http://linux.bkbits.net/linux-2.5
torvalds@ppc970.osdl.org|ChangeSet|20040623175909|50581 torvalds
# This is a BitKeeper generated diff -Nru style patch.
#
# drivers/scsi/scsiiom.c
#   2021/06/14 15:59:00-05:00 g.liakhovetski@gmx.de +1 -1
#   tmscsim: 64-bit cleanup
# 
# net/core/dev.c
#   2004/06/23 08:05:38-07:00 davem@nuts.davemloft.net +0 -0
#   SCCS merged
# 
# net/core/dev.c
#   2004/06/22 10:05:28-07:00 torvalds@ppc970.osdl.org +0 -3
#   Auto merged
# 
# net/core/dev.c
#   2004/06/22 09:28:45-07:00 torvalds@ppc970.osdl.org +3 -4
#   Fix C99'ism that breaks older gcc's.
#   
#   Also clean it all up - use get_cpu()/put_cpu() instead of
#   playing games by hand with preemption.
# 
# net/core/dev.c
#   2004/06/21 09:32:30-07:00 akm@osdl.org +3 -4
#   [NET]: Fix dev_queue_xmit build with older gcc.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/core/dev.c
#   2004/06/20 17:35:52-07:00 akepner@sgi.com +40 -15
#   [NET]: Lockless loopback patch (version 2).
# 
# net/core/dev.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +81 -0
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/core/dev.c
#   2004/06/17 12:11:17-07:00 davem@nuts.davemloft.net +2 -0
#   [NET]: In unregister_netdevice(), do synchronize_net() before final dev_put().
#   
#   This way we make sure that all destination cache updates
#   to remove references to this device are seen by entire
#   system before final destruction of the device.
# 
# include/linux/sysfs.h
#   2004/06/03 10:27:09-07:00 mochel@digitalimplant.org +1 -1
#   [sysfs] Add attr_name() macro
# 
# include/linux/sysfs.h
#   2004/06/02 17:01:56-07:00 mochel@digitalimplant.org +21 -0
#   [Driver Model] Consolidate object attribute definition.
# 
# drivers/base/class.c
#   2004/06/10 02:35:56-07:00 greg@kroah.com +18 -18
#   Driver Core: more whitespace fixups
#   
#   This catches the files I had to do by hand as Dmitry's patch differed from my tree.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/base/class.c
#   2004/06/03 10:41:22-07:00 mochel@digitalimplant.org +75 -6
#   [Driver Model] Add default attributes for classes class devices.
# 
# ChangeSet
#   2004/06/23 10:55:18-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] bug in V-link handling (arch/i386/pci/irq.c)
#   
#   	Via southbridges use register 0x3c of the on-board devices (USB and
#   AC97) to control interrupt routing for those.  In drivers/pci/quirks.c we
#   set it correctly (dev->irq & 15).  However, in pirq_enable_irq() where the
#   second half of that stuff lives, we forget to apply the mask.
#   
#   	That's what causes problems with ioapic on via motherboards in 2.6.
#   One-liner below ACKed by Alan, verified on via-based boxen here, obviously
#   doesn't affect non-via ones (we only set interrupt_line_quirk for via
#   chipsets). 
# 
# arch/i386/pci/irq.c
#   2004/06/22 12:40:53-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1
#   bug in V-link handling (arch/i386/pci/irq.c)
# 
# ChangeSet
#   2004/06/23 08:05:47-07:00 davem@nuts.davemloft.net 
#   Merge
# 
# net/sched/Kconfig
#   2004/06/23 08:04:20-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/core/skbuff.c
#   2004/06/23 08:04:20-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# include/net/pkt_sched.h
#   2004/06/23 08:04:19-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# include/linux/skbuff.h
#   2004/06/23 08:04:19-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# include/linux/pkt_sched.h
#   2004/06/23 08:04:19-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# include/linux/netdevice.h
#   2004/06/23 08:04:19-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/23 07:44:19-07:00 yoshfuji@linux-ipv6.org 
#   [NETFILTER]: Fix iptable_raw.c build with older gcc.
# 
# net/ipv4/netfilter/iptable_raw.c
#   2004/06/23 07:44:05-07:00 yoshfuji@linux-ipv6.org +11 -5
#   [NETFILTER]: Fix iptable_raw.c build with older gcc.
# 
# ChangeSet
#   2004/06/22 19:53:47-07:00 jbarnes@engr.sgi.com 
#   [PATCH] ppc32: Support for new Apple laptop models
#   
#   This adds sound support for some of the newer PowerBooks.  It appears
#   that this chip supports the AWACS sample rates, but has a snapper-style
#   mixer.  Tested and works on my PowerBook5,4. 
#   
#   Signed-off-by: Jesse Barnes <jbarnes@sgi.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2004/06/22 19:52:14-07:00 paulus@samba.org 
#   [PATCH] Handle altivec assist exception properly
#   
#   This is the PPC64 counterpart of the PPC32 Altivec assist exception
#   handler that went in recently.
#   
#   On PPC64 machines with Altivec (i.e.  machines that use the PPC970 chip,
#   such as the G5 powermac), the altivec floating-point instructions can
#   operate in two modes: one where denormalized inputs or outputs are
#   truncated to zero, and one where they aren't.  In the latter mode the
#   processor can take an exception when it encounters denormalized
#   floating-point inputs or outputs rather than dealing with them in
#   hardware.
#   
#   This patch adds code to deal properly with the exception, by emulating
#   the instruction that caused the exception.  Previously the kernel just
#   switched the altivec unit into the truncate-to-zero mode, which works
#   but is a bit gross.  Fortunately there are only a limited set of altivec
#   instructions which can generate the assist exception, so we don't have
#   to emulate the whole altivec instruction set.
#   
#   Note that Altivec is Motorola's name for the PowerPC vector/SIMD
#   instructions; IBM calls the same thing VMX, and currently only IBM makes
#   64-bit PowerPC CPU chips.  Nevertheless, I have used the term Altivec in
#   the PPC64 code for consistency with the PPC32 code.
#   
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2004/06/22 19:52:02-07:00 benh@kernel.crashing.org 
#   [PATCH] radeonfb: Fix panel detection on some laptops
#   
#   The code in radeonfb looking for the BIOS image currently uses the BIOS
#   ROM if any, and falls back to the RAM image if not found.  This is
#   unfortunatly not correct for a bunch of laptops where the real panel
#   data are only present in the RAM image.
#   
#   This works around this problem by preferring the RAM image on mobility
#   chipsets.  This is definitely not the best workaround, we need some arch
#   support for linking the RAM image to the PCI ID (preferrably by having
#   the arch snapshot it during boot, isolating us completely from the
#   details of where this image is in memory).  I'll see how we can get such
#   an improvement later.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2004/06/22 19:51:52-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc32: Support for new Apple laptop models
#   
#   This adds support for newer Apple laptop models.  It adds the basic
#   identification for the new motherboards and the cpufreq support for
#   models using the new 7447A CPU from Motorola.
#   
#   This is mostly the work of John Steele Scott <toojays@toojays.net> with
#   some bits from Sebastian Henschel <linux@kodeaffe.de> and some rework by
#   myself.  Please apply,
#   
#   Signed-off-by: John Steele Scott <toojays@toojays.net>
#   Signed-off-by: Sebastian Henschel <linux@kodeaffe.de>
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2004/06/22 19:51:41-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc32: oprofile support
#   
#   This adds basic oprofile support to ppc32.  Originally from Anton
#   Blanchard, I just re-diffed it against current kernels.
#   
#   Signed-off-by: Anton Blanchard <anton@samba.org>
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2004/06/22 19:51:29-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc32: Cleanups & warning fixes of traps.c
#   
#   This cleans up arch/ppc/kernel/traps.c and vecemu.c to use the same
#   formatting style for all functions, and fixes 2 warnings in the altivec
#   floating point emulation code.  No functional change. 
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/ppc/pmac.c
#   2004/06/22 14:40:39-07:00 jbarnes@engr.sgi.com +7 -0
#   ppc32: Support for new Apple laptop models
# 
# arch/ppc64/kernel/vector.S
#   2004/06/22 19:52:07-07:00 paulus@samba.org +172 -0
#   Handle altivec assist exception properly
# 
# include/asm-ppc64/system.h
#   2004/06/22 19:52:07-07:00 paulus@samba.org +1 -0
#   Handle altivec assist exception properly
# 
# arch/ppc64/kernel/vector.S
#   2004/06/22 19:52:07-07:00 paulus@samba.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vector.S
# 
# arch/ppc64/kernel/vecemu.c
#   2004/06/22 19:52:07-07:00 paulus@samba.org +346 -0
#   Handle altivec assist exception properly
# 
# arch/ppc64/kernel/traps.c
#   2004/06/22 16:05:33-07:00 paulus@samba.org +32 -2
#   Handle altivec assist exception properly
# 
# arch/ppc64/kernel/Makefile
#   2004/06/22 19:52:07-07:00 paulus@samba.org +2 -0
#   Handle altivec assist exception properly
# 
# arch/ppc64/kernel/vecemu.c
#   2004/06/22 19:52:07-07:00 paulus@samba.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vecemu.c
# 
# drivers/video/aty/radeon_base.c
#   2004/06/22 13:11:16-07:00 benh@kernel.crashing.org +16 -2
#   radeonfb: Fix panel detection on some laptops
# 
# include/asm-ppc/uninorth.h
#   2004/06/22 13:04:07-07:00 benh@kernel.crashing.org +6 -0
#   ppc32: Support for new Apple laptop models
# 
# include/asm-ppc/reg.h
#   2004/06/22 13:04:07-07:00 benh@kernel.crashing.org +1 -0
#   ppc32: Support for new Apple laptop models
# 
# include/asm-ppc/pmac_feature.h
#   2004/06/22 13:04:07-07:00 benh@kernel.crashing.org +6 -0
#   ppc32: Support for new Apple laptop models
# 
# arch/ppc/platforms/pmac_feature.c
#   2004/06/22 13:04:07-07:00 benh@kernel.crashing.org +32 -0
#   ppc32: Support for new Apple laptop models
# 
# arch/ppc/platforms/pmac_cpufreq.c
#   2004/06/22 13:04:07-07:00 benh@kernel.crashing.org +193 -118
#   ppc32: Support for new Apple laptop models
# 
# arch/ppc/kernel/misc.S
#   2004/06/22 13:04:07-07:00 benh@kernel.crashing.org +18 -0
#   ppc32: Support for new Apple laptop models
# 
# arch/ppc/oprofile/init.c
#   2004/06/22 12:05:08-07:00 benh@kernel.crashing.org +23 -0
#   ppc32: oprofile support
# 
# arch/ppc/oprofile/Makefile
#   2004/06/22 12:05:08-07:00 benh@kernel.crashing.org +9 -0
#   ppc32: oprofile support
# 
# arch/ppc/oprofile/Kconfig
#   2004/06/22 12:05:08-07:00 benh@kernel.crashing.org +23 -0
#   ppc32: oprofile support
# 
# arch/ppc/oprofile/init.c
#   2004/06/22 12:05:08-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/oprofile/init.c
# 
# arch/ppc/oprofile/Makefile
#   2004/06/22 12:05:08-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/oprofile/Makefile
# 
# arch/ppc/oprofile/Kconfig
#   2004/06/22 12:05:08-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/oprofile/Kconfig
# 
# arch/ppc/kernel/time.c
#   2004/06/22 12:05:08-07:00 benh@kernel.crashing.org +15 -7
#   ppc32: oprofile support
# 
# arch/ppc/Makefile
#   2004/06/22 12:05:08-07:00 benh@kernel.crashing.org +2 -0
#   ppc32: oprofile support
# 
# arch/ppc/Kconfig
#   2004/06/22 12:05:08-07:00 benh@kernel.crashing.org +1 -0
#   ppc32: oprofile support
# 
# include/asm-ppc/processor.h
#   2004/06/22 12:04:49-07:00 benh@kernel.crashing.org +2 -0
#   ppc32: Cleanups & warning fixes of traps.c
# 
# arch/ppc/kernel/vecemu.c
#   2004/06/22 12:04:49-07:00 benh@kernel.crashing.org +1 -2
#   ppc32: Cleanups & warning fixes of traps.c
# 
# arch/ppc/kernel/traps.c
#   2004/06/22 12:04:49-07:00 benh@kernel.crashing.org +18 -35
#   ppc32: Cleanups & warning fixes of traps.c
# 
# ChangeSet
#   2004/06/22 20:42:16-04:00 jgarzik@pobox.com 
#   [libata sata_sil] Re-fix mod15write bug
#   
#   Certain early SATA drives have problems with write requests whose
#   length satisfy the equation "sectors % 15 == 1", on the SiI 3112.
#   Other drives, and other SiI controllers, are not affected.
#   
#   The fix for this problem is to avoid such requests, in one of three
#   ways, for the affect drive+controller combos:
#   1) Limit all writes to 15 sectors
#   2) Use block layer features to avoid creating requests whose
#      length satisfies the above equation.
#   3) When a request satisfies the above equation, split the request
#      into two writes, neither of which satisfies the equation.
#   
#   I chose fix #1, the most simple to implement.  After discussion with
#   Silicon Image and others regarding the impact of this fix, I have
#   decided to remain with fix #1, and will not be implementing a
#   "better fix".  This means that the affected SATA drives will see
#   decreased performance, but set of affected drives is small and will
#   never grow larger.
#   
#   Further, the complexity of implementing solution #2 or
#   solution #3 is rather large.
#   
#   When implementing lba48 'large request' support, I unintentionally
#   broke the fix for these affected drives.  Kudos to Ricky Beam for
#   noticing this.
#   
#   This change restores the fix, by adding a flag ATA_DFLAG_LOCK_SECTORS
#   to indicate that the max_sectors value set by the low-level driver
#   should never be changed.
# 
# include/linux/libata.h
#   2004/06/22 20:42:10-04:00 jgarzik@pobox.com +1 -0
#   [libata sata_sil] Re-fix mod15write bug
#   
#   Certain early SATA drives have problems with write requests whose
#   length satisfy the equation "sectors % 15 == 1", on the SiI 3112.
#   Other drives, and other SiI controllers, are not affected.
#   
#   The fix for this problem is to avoid such requests, in one of three
#   ways, for the affect drive+controller combos:
#   1) Limit all writes to 15 sectors
#   2) Use block layer features to avoid creating requests whose
#      length satisfies the above equation.
#   3) When a request satisfies the above equation, split the request
#      into two writes, neither of which satisfies the equation.
#   
#   I chose fix #1, the most simple to implement.  After discussion with
#   Silicon Image and others regarding the impact of this fix, I have
#   decided to remain with fix #1, and will not be implementing a
#   "better fix".  This means that the affected SATA drives will see
#   decreased performance, but set of affected drives is small and will
#   never grow larger.
#   
#   Further, the complexity of implementing solution #2 or
#   solution #3 is rather large.
#   
#   When implementing lba48 'large request' support, I unintentionally
#   broke the fix for these affected drives.  Kudos to Ricky Beam for
#   noticing this.
#   
#   This change restores the fix, by adding a flag ATA_DFLAG_LOCK_SECTORS
#   to indicate that the max_sectors value set by the low-level driver
#   should never be changed.
# 
# drivers/scsi/sata_sil.c
#   2004/06/22 20:42:10-04:00 jgarzik@pobox.com +1 -0
#   [libata sata_sil] Re-fix mod15write bug
#   
#   Certain early SATA drives have problems with write requests whose
#   length satisfy the equation "sectors % 15 == 1", on the SiI 3112.
#   Other drives, and other SiI controllers, are not affected.
#   
#   The fix for this problem is to avoid such requests, in one of three
#   ways, for the affect drive+controller combos:
#   1) Limit all writes to 15 sectors
#   2) Use block layer features to avoid creating requests whose
#      length satisfies the above equation.
#   3) When a request satisfies the above equation, split the request
#      into two writes, neither of which satisfies the equation.
#   
#   I chose fix #1, the most simple to implement.  After discussion with
#   Silicon Image and others regarding the impact of this fix, I have
#   decided to remain with fix #1, and will not be implementing a
#   "better fix".  This means that the affected SATA drives will see
#   decreased performance, but set of affected drives is small and will
#   never grow larger.
#   
#   Further, the complexity of implementing solution #2 or
#   solution #3 is rather large.
#   
#   When implementing lba48 'large request' support, I unintentionally
#   broke the fix for these affected drives.  Kudos to Ricky Beam for
#   noticing this.
#   
#   This change restores the fix, by adding a flag ATA_DFLAG_LOCK_SECTORS
#   to indicate that the max_sectors value set by the low-level driver
#   should never be changed.
# 
# drivers/scsi/libata-scsi.c
#   2004/06/22 20:42:10-04:00 jgarzik@pobox.com +2 -1
#   [libata sata_sil] Re-fix mod15write bug
#   
#   Certain early SATA drives have problems with write requests whose
#   length satisfy the equation "sectors % 15 == 1", on the SiI 3112.
#   Other drives, and other SiI controllers, are not affected.
#   
#   The fix for this problem is to avoid such requests, in one of three
#   ways, for the affect drive+controller combos:
#   1) Limit all writes to 15 sectors
#   2) Use block layer features to avoid creating requests whose
#      length satisfies the above equation.
#   3) When a request satisfies the above equation, split the request
#      into two writes, neither of which satisfies the equation.
#   
#   I chose fix #1, the most simple to implement.  After discussion with
#   Silicon Image and others regarding the impact of this fix, I have
#   decided to remain with fix #1, and will not be implementing a
#   "better fix".  This means that the affected SATA drives will see
#   decreased performance, but set of affected drives is small and will
#   never grow larger.
#   
#   Further, the complexity of implementing solution #2 or
#   solution #3 is rather large.
#   
#   When implementing lba48 'large request' support, I unintentionally
#   broke the fix for these affected drives.  Kudos to Ricky Beam for
#   noticing this.
#   
#   This change restores the fix, by adding a flag ATA_DFLAG_LOCK_SECTORS
#   to indicate that the max_sectors value set by the low-level driver
#   should never be changed.
# 
# ChangeSet
#   2004/06/23 01:07:38+01:00 dvrabel@com.rmk.(none) 
#   [ARM PATCH] 1940/1: asm-arm/checksum.h - missing include
#   
#   Patch from David Vrabel
#   
#   Missing include (cf. include/asm-i386/checksum.h) in include/asm-arm/checksum.h.
# 
# include/asm-arm/checksum.h
#   2004/06/21 15:17:39+01:00 dvrabel@com.rmk.(none) +2 -0
#   [PATCH] 1940/1: asm-arm/checksum.h - missing include
# 
# ChangeSet
#   2004/06/23 01:03:51+01:00 icampbell@com.rmk.(none) 
#   [ARM PATCH] 1939/1: SA1100 watchdog driver also works on PXA2xx
#   
#   Patch from Ian Campbell
#   
#   The SA1100 watchdog driver also works fine on the PXA2xx. Tested on 
#   a PXA255 based platform.
# 
# drivers/char/watchdog/sa1100_wdt.c
#   2004/06/23 01:00:00+01:00 icampbell@com.rmk.(none) +4 -4
#   [PATCH] 1939/1: SA1100 watchdog driver also works on PXA2xx
# 
# drivers/char/watchdog/Kconfig
#   2004/06/23 01:00:00+01:00 icampbell@com.rmk.(none) +6 -5
#   [PATCH] 1939/1: SA1100 watchdog driver also works on PXA2xx
# 
# ChangeSet
#   2004/06/23 00:59:35+01:00 jelenz@edu.rmk.(none) 
#   [ARM PATCH] 1936/1: Update collie fb entries to use new style initializers
#   
#   Patch from John Lenz
#   
#   Switches the collie framebuffer mach_info structure to use
#   the new initializers.
#   
#   Signed-off-by: John Lenz <jelenz@students.wisc.edu>
# 
# drivers/video/sa1100fb.c
#   2004/06/22 01:00:00+01:00 jelenz@edu.rmk.(none) +8 -8
#   [PATCH] 1936/1: Update collie fb entries to use new style initializers
# 
# ChangeSet
#   2004/06/23 00:55:42+01:00 jelenz@edu.rmk.(none) 
#   [ARM PATCH] 1935/1: Fix bug in sa1111 driver
#   
#   Patch from John Lenz
#   
#   The __sa1111_probe function is declared __init, and it is called from
#   the sa1111_probe function, which is not declared __init.
#   
#   Signed-off-by: John Lenz <jelenz@students.wisc.edu>
# 
# arch/arm/common/sa1111.c
#   2004/06/22 01:00:00+01:00 jelenz@edu.rmk.(none) +1 -1
#   [PATCH] 1935/1: Fix bug in sa1111 driver
# 
# ChangeSet
#   2004/06/23 00:48:22+01:00 icampbell@com.rmk.(none) 
#   [ARM PATCH] 1933/1: Convert PXA serial driver to device model and implement suspend and resume
#   
#   Patch from Ian Campbell
#   
#   Patch 1848/1 removed the hack for preserving FFUART over sleep.
#   
#   This patch adds back that support in the correct place by converting
#   the PXA serial driver to use the driver model and hooking up the 
#   suspend and resume methods.
# 
# drivers/serial/pxa.c
#   2004/06/22 01:00:00+01:00 icampbell@com.rmk.(none) +62 -11
#   [PATCH] 1933/1: Convert PXA serial driver to device model and implement suspend and resume
# 
# arch/arm/mach-pxa/generic.c
#   2004/06/22 01:00:00+01:00 icampbell@com.rmk.(none) +16 -0
#   [PATCH] 1933/1: Convert PXA serial driver to device model and implement suspend and resume
# 
# ChangeSet
#   2004/06/23 00:44:18+01:00 elf@com.rmk.(none) 
#   [ARM PATCH] 1913/1: lh7a40x #3 (1/2) serial
#   
#   Patch from Marc Singer
#   
#   Serial console and port driver for the LH7a40x CPUs.  The only change
#   made since the last patch was to change the PORT_ID (again).  This
#   patch superceeds two serial driver patches.
#   
# 
# include/linux/serial_core.h
#   2004/06/05 11:30:48+01:00 elf@com.rmk.(none) +3 -0
#   [PATCH] 1913/1: lh7a40x #3 (1/2) serial
# 
# drivers/serial/Makefile
#   2004/06/05 11:30:48+01:00 elf@com.rmk.(none) +1 -0
#   [PATCH] 1913/1: lh7a40x #3 (1/2) serial
# 
# drivers/serial/Kconfig
#   2004/06/05 11:30:48+01:00 elf@com.rmk.(none) +23 -0
#   [PATCH] 1913/1: lh7a40x #3 (1/2) serial
# 
# drivers/serial/serial_lh7a40x.c
#   2004/06/05 11:30:48+01:00 elf@com.rmk.(none) +708 -0
#   [PATCH] 1913/1: lh7a40x #3 (1/2) serial
# 
# drivers/serial/serial_lh7a40x.c
#   2004/06/05 11:30:48+01:00 elf@com.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-serial/drivers/serial/serial_lh7a40x.c
# 
# ChangeSet
#   2004/06/22 23:54:18+01:00 rmk@flint.arm.linux.org.uk 
#   Merge bk://dsaxena.bkbits.net/linux-2.6-for-rmk
#   into flint.arm.linux.org.uk:/usr/src/bk/linux-2.6-rmk
# 
# arch/arm/mach-integrator/integrator_cp.c
#   2004/06/22 23:53:14+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/22 14:07:48-07:00 akepner@sgi.com 
#   [NET]: In loopback, make get_stats() get correct per-cpu stats.
#   
#   Signed-off-by: Arthur Kepner <akepner@sgi.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/loopback.c
#   2004/06/22 14:07:33-07:00 akepner@sgi.com +1 -2
#   [NET]: In loopback, make get_stats() get correct per-cpu stats.
#   
#   Signed-off-by: Arthur Kepner <akepner@sgi.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/22 13:54:22-07:00 davem@nuts.davemloft.net 
#   [IPSEC]: In ESP, do not put scatterlist array on stack.
#   
#   Put it in per-esp data instead.  Noticed by Linus.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv6/esp6.c
#   2004/06/22 13:53:57-07:00 davem@nuts.davemloft.net +6 -10
#   [IPSEC]: In ESP, do not put scatterlist array on stack.
#   
#   Put it in per-esp data instead.  Noticed by Linus.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/esp4.c
#   2004/06/22 13:53:57-07:00 davem@nuts.davemloft.net +6 -10
#   [IPSEC]: In ESP, do not put scatterlist array on stack.
#   
#   Put it in per-esp data instead.  Noticed by Linus.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/net/esp.h
#   2004/06/22 13:53:57-07:00 davem@nuts.davemloft.net +5 -0
#   [IPSEC]: In ESP, do not put scatterlist array on stack.
#   
#   Put it in per-esp data instead.  Noticed by Linus.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/22 12:59:56-07:00 davem@nuts.davemloft.net 
#   Merge bk://kernel.bkbits.net/acme/net-2.6
#   into nuts.davemloft.net:/disk1/BK/net-2.6
# 
# net/ipv4/tcp_input.c
#   2004/06/22 12:59:47-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv4/tcp.c
#   2004/06/22 12:59:46-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/22 10:20:50-07:00 torvalds@ppc970.osdl.org 
#   Merge bk://gkernel.bkbits.net/libata-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# drivers/scsi/Makefile
#   2004/06/22 10:20:47-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/scsi/Kconfig
#   2004/06/22 10:20:47-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/ide/Kconfig
#   2004/06/22 10:20:47-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/22 10:18:32-07:00 torvalds@ppc970.osdl.org 
#   sparse: clean up warning in swapfile.c
# 
# mm/swapfile.c
#   2004/06/22 10:18:26-07:00 torvalds@ppc970.osdl.org +1 -1
#   sparse: clean up warning in swapfile.c
# 
# ChangeSet
#   2004/06/22 10:05:31-07:00 torvalds@ppc970.osdl.org 
#   Merge bk://kernel.bkbits.net/davem/net-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# ChangeSet
#   2004/06/22 13:02:35-04:00 jgarzik@pobox.com 
#   [blk carmel] s/carmel/sx8/ in the driver itself
# 
# drivers/block/sx8.c
#   2004/06/22 13:02:29-04:00 jgarzik@pobox.com +3 -3
#   [blk carmel] s/carmel/sx8/ in the driver itself
# 
# ChangeSet
#   2004/06/22 09:28:50-07:00 torvalds@ppc970.osdl.org 
#   Fix C99'ism that breaks older gcc's.
#   
#   Also clean it all up - use get_cpu()/put_cpu() instead of
#   playing games by hand with preemption.
# 
# ChangeSet
#   2004/06/22 09:25:34-07:00 khali@linux-fr.org 
#   [PATCH] I2C: Drop out-of-date code in w83781d and w83627hf
#   
#   Here is a simple patch which drops some out-of-date code in the w83781d
#   and w83627hf i2c chip drivers. These bits are left over from the times
#   when chip drivers were setting default limits at init.
#   
#   
#   Signed-off-by: Jean Delvare <khali at linux-fr dot org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/w83781d.c
#   2004/06/19 11:22:05-07:00 khali@linux-fr.org +2 -9
#   I2C: Drop out-of-date code in w83781d and w83627hf
# 
# drivers/i2c/chips/w83627hf.c
#   2004/06/19 11:21:06-07:00 khali@linux-fr.org +1 -4
#   I2C: Drop out-of-date code in w83781d and w83627hf
# 
# ChangeSet
#   2004/06/22 09:20:30-07:00 greg@kroah.com 
#   [PATCH] USB: sparse fixups for devio.c
# 
# drivers/usb/core/devio.c
#   2004/06/22 02:09:36-07:00 greg@kroah.com +10 -9
#   USB: sparse fixups for devio.c
# 
# ChangeSet
#   2004/06/22 08:27:43-07:00 rddunlap@osdl.org 
#   [PATCH] sparse: make sys_quotactl() prototype match function
#   
#   Al missed this one in his sparse fixes
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/syscalls.h
#   2004/06/21 21:31:11-07:00 rddunlap@osdl.org +1 -1
#   sparse: make sys_quotactl() prototype match function
# 
# ChangeSet
#   2004/06/22 08:27:32-07:00 rddunlap@osdl.org 
#   [PATCH] Fix sparse warning in drivers/block/ll_rw_blk.c
#   
#   From: Mika Kukkonen <mika@osdl.org>
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/ll_rw_blk.c
#   2004/06/21 19:20:21-07:00 rddunlap@osdl.org +1 -1
#   Fix sparse warning in drivers/block/ll_rw_blk.c
# 
# ChangeSet
#   2004/06/22 08:27:21-07:00 rddunlap@osdl.org 
#   [PATCH] Fix sparse warning in fs/proc/base.c
#   
#   From: Mika Kukkonen <mika@osdl.org>
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/proc/base.c
#   2004/06/19 22:42:40-07:00 rddunlap@osdl.org +6 -3
#   Fix sparse warning in fs/proc/base.c
# 
# ChangeSet
#   2004/06/22 08:27:10-07:00 rddunlap@osdl.org 
#   [PATCH] Fix sparse warning in fs/devfs/base.c
#   
#   From: Mika Kukkonen <mika@osdl.org>
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/devfs/base.c
#   2004/06/19 22:30:39-07:00 rddunlap@osdl.org +2 -1
#   Fix sparse warning in fs/devfs/base.c
# 
# ChangeSet
#   2004/06/22 16:23:52+01:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Correct MMCI clock rate on Integrator/CP.
# 
# arch/arm/mach-integrator/integrator_cp.c
#   2004/06/22 16:21:27+01:00 rmk@flint.arm.linux.org.uk +2 -2
#   MMCI clock is 14.7456MHz not 33MHz.
# 
# ChangeSet
#   2004/06/22 14:55:39+01:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Move cpu_switch_mm() and cpu_get_pgd() to asm/proc-fns.h
# 
# include/asm-arm/proc-fns.h
#   2004/06/22 14:53:15+01:00 rmk@flint.arm.linux.org.uk +16 -0
#   Move cpu_switch_mm() and cpu_get_pgd() to asm/proc-fns.h
# 
# include/asm-arm/cpu-single.h
#   2004/06/22 14:53:15+01:00 rmk@flint.arm.linux.org.uk +2 -19
#   Move cpu_switch_mm() and cpu_get_pgd() to asm/proc-fns.h
# 
# include/asm-arm/cpu-multi32.h
#   2004/06/22 14:53:15+01:00 rmk@flint.arm.linux.org.uk +1 -16
#   Move cpu_switch_mm() and cpu_get_pgd() to asm/proc-fns.h
# 
# ChangeSet
#   2004/06/22 03:52:32-03:00 acme@conectiva.com.br 
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_timer.c
#   2004/06/22 03:52:20-03:00 acme@conectiva.com.br +2 -2
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_output.c
#   2004/06/22 03:52:20-03:00 acme@conectiva.com.br +19 -17
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_minisocks.c
#   2004/06/22 03:52:19-03:00 acme@conectiva.com.br +1 -1
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_input.c
#   2004/06/22 03:52:19-03:00 acme@conectiva.com.br +12 -13
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/22 03:52:19-03:00 acme@conectiva.com.br +10 -10
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/sock.c
#   2004/06/22 03:52:19-03:00 acme@conectiva.com.br +2 -0
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/tcp.h
#   2004/06/22 03:52:19-03:00 acme@conectiva.com.br +5 -12
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/22 03:52:19-03:00 acme@conectiva.com.br +8 -0
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/linux/tcp.h
#   2004/06/22 03:52:19-03:00 acme@conectiva.com.br +0 -1
#   [NET] move send_head from tcp private area to struct sock
#   
#   The poor cousins also need this, LLC will be the first to use it.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/22 02:12:28-04:00 jgarzik@pobox.com 
#   [libata ata_piix] combined mode bug fix; improved ICH6 support
# 
# drivers/scsi/ata_piix.c
#   2004/06/22 02:12:22-04:00 jgarzik@pobox.com +14 -11
#   [libata ata_piix] combined mode bug fix; improved ICH6 support
# 
# ChangeSet
#   2004/06/22 00:54:50-04:00 jgarzik@pobox.com 
#   [libata] fix build error, minor cleanups
# 
# include/linux/libata.h
#   2004/06/22 00:54:44-04:00 jgarzik@pobox.com +0 -5
#   [libata] fix build error, minor cleanups
# 
# drivers/scsi/libata-core.c
#   2004/06/22 00:54:44-04:00 jgarzik@pobox.com +2 -3
#   [libata] fix build error, minor cleanups
# 
# ChangeSet
#   2004/06/21 21:39:50-07:00 torvalds@ppc970.osdl.org 
#   Fix up permissions of some files that were not readable
#   by "other". The normal permissions for the kernel tree
#   should be -rw-r--r--.
# 
# Documentation/scsi/ChangeLog.megaraid
#   2004/06/21 21:36:23-07:00 torvalds@ppc970.osdl.org +0 -0
#   Change mode to -rw-r--r--
# 
# Documentation/networking/netif-msg.txt
#   2004/06/21 21:36:17-07:00 torvalds@ppc970.osdl.org +0 -0
#   Change mode to -rw-r--r--
# 
# ChangeSet
#   2004/06/22 00:36:09-04:00 jgarzik@pobox.com 
#   [libata] move some code around
#   
#   Split ata_eng_timeout into the main part (ata_qc_timeout)
#   and the part called by the SCSI layer (ata_eng_timeout).
#   
#   Zero behavior changes.
# 
# drivers/input/joystick/grip_mp.c
#   2004/06/21 21:36:04-07:00 torvalds@ppc970.osdl.org +0 -0
#   Change mode to -rw-r--r--
# 
# drivers/scsi/libata-core.c
#   2004/06/22 00:36:02-04:00 jgarzik@pobox.com +42 -12
#   [libata] move some code around
#   
#   Split ata_eng_timeout into the main part (ata_qc_timeout)
#   and the part called by the SCSI layer (ata_eng_timeout).
#   
#   Zero behavior changes.
# 
# drivers/char/drm/drm_irq.h
#   2004/06/21 21:35:57-07:00 torvalds@ppc970.osdl.org +0 -0
#   Change mode to -rw-r--r--
# 
# drivers/char/agp/isoch.c
#   2004/06/21 21:34:47-07:00 torvalds@ppc970.osdl.org +0 -0
#   Change mode to -rw-r--r--
# 
# ChangeSet
#   2004/06/22 01:20:08-03:00 acme@conectiva.com.br 
#   [NET] generalise tcp_moderate_sndbuf
#   
#   Renaming it to sk_stream_moderate_sndbuf, further patches will move
#   all the tcp memory pressure handling support into net/core/stream.c
#   to make them usable by the poor cousins, starting with LLC.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/22 01:19:56-03:00 acme@conectiva.com.br +1 -1
#   [NET] generalise tcp_moderate_sndbuf
#   
#   Renaming it to sk_stream_moderate_sndbuf, further patches will move
#   all the tcp memory pressure handling support into net/core/stream.c
#   to make them usable by the poor cousins, starting with LLC.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/tcp.h
#   2004/06/22 01:19:56-03:00 acme@conectiva.com.br +2 -10
#   [NET] generalise tcp_moderate_sndbuf
#   
#   Renaming it to sk_stream_moderate_sndbuf, further patches will move
#   all the tcp memory pressure handling support into net/core/stream.c
#   to make them usable by the poor cousins, starting with LLC.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/22 01:19:56-03:00 acme@conectiva.com.br +8 -0
#   [NET] generalise tcp_moderate_sndbuf
#   
#   Renaming it to sk_stream_moderate_sndbuf, further patches will move
#   all the tcp memory pressure handling support into net/core/stream.c
#   to make them usable by the poor cousins, starting with LLC.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/21 23:47:16-04:00 bunk@fs.tum.de 
#   [PATCH] 2.6.7-mm1: drivers/scsi/hosts.h -> scsi/scsi_host.h
#   
#   On Sun, Jun 20, 2004 at 05:46:32PM -0700, Andrew Morton wrote:
#   >...
#   > All 226 patches:
#   >...
#   > bk-libata.patch
#   >...
#   
#   drivers/scsi/hosts.h is obsolete, use scsi/scsi_host.h.
#   
#   Please apply
#   Adrian
# 
# drivers/scsi/sata_nv.c
#   2004/06/20 21:51:17-04:00 bunk@fs.tum.de +1 -1
#   2.6.7-mm1: drivers/scsi/hosts.h -> scsi/scsi_host.h
# 
# ChangeSet
#   2004/06/22 00:46:47-03:00 acme@conectiva.com.br 
#   [NET] generalise tcp_free_skb, renaming it to sk_stream_free_skb
#   
#   Will be used by the poor cousins
#   
#   Signed-of-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_output.c
#   2004/06/22 00:46:35-03:00 acme@conectiva.com.br +2 -2
#   [NET] generalise tcp_free_skb, renaming it to sk_stream_free_skb
#   
#   Will be used by the poor cousins
#   
#   Signed-of-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_input.c
#   2004/06/22 00:46:35-03:00 acme@conectiva.com.br +4 -6
#   [NET] generalise tcp_free_skb, renaming it to sk_stream_free_skb
#   
#   Will be used by the poor cousins
#   
#   Signed-of-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/22 00:46:35-03:00 acme@conectiva.com.br +1 -1
#   [NET] generalise tcp_free_skb, renaming it to sk_stream_free_skb
#   
#   Will be used by the poor cousins
#   
#   Signed-of-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/tcp.h
#   2004/06/22 00:46:35-03:00 acme@conectiva.com.br +1 -9
#   [NET] generalise tcp_free_skb, renaming it to sk_stream_free_skb
#   
#   Will be used by the poor cousins
#   
#   Signed-of-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/22 00:46:35-03:00 acme@conectiva.com.br +11 -0
#   [NET] generalise tcp_free_skb, renaming it to sk_stream_free_skb
#   
#   Will be used by the poor cousins
#   
#   Signed-of-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/linux/tcp.h
#   2004/06/22 00:46:35-03:00 acme@conectiva.com.br +1 -1
#   [NET] generalise tcp_free_skb, renaming it to sk_stream_free_skb
#   
#   Will be used by the poor cousins
#   
#   Signed-of-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/21 20:26:23-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: the rest of ieee1394 annotation
# 
# drivers/ieee1394/video1394.c
#   2004/06/21 07:11:51-07:00 viro@www.linux.org.uk +10 -9
#   sparse: the rest of ieee1394 annotation
# 
# drivers/ieee1394/dv1394.c
#   2004/06/21 07:11:51-07:00 viro@www.linux.org.uk +6 -5
#   sparse: the rest of ieee1394 annotation
# 
# drivers/ieee1394/amdtp.c
#   2004/06/21 07:11:51-07:00 viro@www.linux.org.uk +2 -2
#   sparse: the rest of ieee1394 annotation
# 
# ChangeSet
#   2004/06/21 20:26:12-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: hd.c annotation
# 
# drivers/firmware/efivars.c
#   2004/06/21 07:11:51-07:00 viro@www.linux.org.uk +1 -1
#   sparse: hd.c annotation
# 
# ChangeSet
#   2004/06/21 20:26:01-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: quota annotation
# 
# fs/quota.c
#   2004/06/21 07:11:50-07:00 viro@www.linux.org.uk +2 -2
#   sparse: quota annotation
# 
# ChangeSet
#   2004/06/21 20:25:50-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: sock_fprog sanitized
#   
#   sock_fprog instances that had kernel pointer in ->filter (both of them -
#   in ppp_generic and isdn_ppp) replaced with explicit pairs len + kernel
#   pointer.  Copying of userland sock_fprog (with its __user ->filter)
#   cleaned up and sanitized.
#   
#   Trivial annotation done in the rest of ->ioctl() in ppp_generic and
#   isdn_ppp.
# 
# include/linux/isdn_ppp.h
#   2004/06/21 07:11:52-07:00 viro@www.linux.org.uk +3 -2
#   sparse: sock_fprog sanitized
# 
# drivers/net/ppp_generic.c
#   2004/06/21 07:11:52-07:00 viro@www.linux.org.uk +100 -70
#   sparse: sock_fprog sanitized
# 
# drivers/isdn/i4l/isdn_ppp.h
#   2004/06/21 07:11:52-07:00 viro@www.linux.org.uk +2 -2
#   sparse: sock_fprog sanitized
# 
# drivers/isdn/i4l/isdn_ppp.c
#   2004/06/21 07:11:52-07:00 viro@www.linux.org.uk +103 -82
#   sparse: sock_fprog sanitized
# 
# ChangeSet
#   2004/06/21 20:25:39-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: raw1394 annotation
# 
# drivers/ieee1394/raw1394.h
#   2004/06/21 07:11:51-07:00 viro@www.linux.org.uk +5 -5
#   sparse: raw1394 annotation
# 
# drivers/ieee1394/raw1394.c
#   2004/06/21 07:11:51-07:00 viro@www.linux.org.uk +41 -48
#   sparse: raw1394 annotation
# 
# drivers/ieee1394/raw1394-private.h
#   2004/06/21 07:11:51-07:00 viro@www.linux.org.uk +2 -2
#   sparse: raw1394 annotation
# 
# ChangeSet
#   2004/06/21 20:25:28-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: drivers/net/wan annotation
# 
# include/linux/if.h
#   2004/06/21 07:22:34-07:00 viro@www.linux.org.uk +7 -7
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/x25_asy.c
#   2004/06/21 07:22:00-07:00 viro@www.linux.org.uk +1 -1
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/pci200syn.c
#   2004/06/21 07:21:53-07:00 viro@www.linux.org.uk +2 -1
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/n2.c
#   2004/06/21 07:21:44-07:00 viro@www.linux.org.uk +2 -1
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/lmc/lmc_ioctl.h
#   2004/06/21 07:22:15-07:00 viro@www.linux.org.uk +2 -2
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/hdlc_raw_eth.c
#   2004/06/21 07:21:35-07:00 viro@www.linux.org.uk +1 -1
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/hdlc_raw.c
#   2004/06/21 07:21:19-07:00 viro@www.linux.org.uk +1 -1
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/hdlc_fr.c
#   2004/06/21 07:21:15-07:00 viro@www.linux.org.uk +1 -1
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/hdlc_cisco.c
#   2004/06/21 07:21:08-07:00 viro@www.linux.org.uk +1 -1
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/dscc4.c
#   2004/06/21 07:20:51-07:00 viro@www.linux.org.uk +1 -1
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/cosa.h
#   2004/06/21 07:20:41-07:00 viro@www.linux.org.uk +1 -1
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/cosa.c
#   2004/06/21 07:20:40-07:00 viro@www.linux.org.uk +21 -20
#   sparse: drivers/net/wan annotation
# 
# drivers/net/wan/c101.c
#   2004/06/21 07:20:33-07:00 viro@www.linux.org.uk +2 -1
#   sparse: drivers/net/wan annotation
# 
# ChangeSet
#   2004/06/21 20:25:16-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: efivars.c initializer fix
# 
# drivers/ide/legacy/hd.c
#   2004/06/21 07:11:51-07:00 viro@www.linux.org.uk +1 -1
#   sparse: efivars.c initializer fix
# 
# ChangeSet
#   2004/06/21 20:25:05-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: zlib stray extern removal
# 
# lib/zlib_deflate/deflate.c
#   2004/06/21 07:11:50-07:00 viro@www.linux.org.uk +1 -1
#   sparse: zlib stray extern removal
# 
# ChangeSet
#   2004/06/21 20:24:54-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: ncpfs/ioctl.c annotation
# 
# include/linux/ncp_fs.h
#   2004/06/21 07:11:50-07:00 viro@www.linux.org.uk +3 -3
#   sparse: ncpfs/ioctl.c annotation
# 
# fs/ncpfs/ioctl.c
#   2004/06/21 07:11:50-07:00 viro@www.linux.org.uk +37 -45
#   sparse: ncpfs/ioctl.c annotation
# 
# ChangeSet
#   2004/06/21 20:24:44-07:00 viro@www.linux.org.uk 
#   [PATCH] ibmtr missing include
# 
# drivers/net/tokenring/ibmtr.c
#   2004/06/21 07:19:31-07:00 viro@www.linux.org.uk +1 -0
#   ibmtr missing include
# 
# ChangeSet
#   2004/06/21 19:56:37-07:00 torvalds@ppc970.osdl.org 
#   Merge bk://linux-acpi.bkbits.net/linux-acpi-release-2.6.7
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# arch/i386/kernel/mpparse.c
#   2004/06/21 19:56:34-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/21 23:01:24-03:00 acme@conectiva.com.br 
#   [NET] generalise tcp_error, renaming it to sk_stream_error
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/21 23:01:13-03:00 acme@conectiva.com.br +2 -11
#   [NET] generalise tcp_error, renaming it to sk_stream_error
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/stream.c
#   2004/06/21 23:01:13-03:00 acme@conectiva.com.br +11 -0
#   [NET] generalise tcp_error, renaming it to sk_stream_error
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/21 23:01:13-03:00 acme@conectiva.com.br +1 -0
#   [NET] generalise tcp_error, renaming it to sk_stream_error
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/21 20:59:09-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.7
#   into intel.com:/home/lenb/bk/linux-acpi-test-2.6.7
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/21 20:59:06-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# arch/i386/kernel/mpparse.c
#   2004/06/21 20:59:06-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/21 20:53:04-04:00 len.brown@intel.com 
#   [ACPI] re-factor previous mpparse IRQ override fix (Linus Torvalds)
#   Reflect that only the dstirq depends on the dstapic.
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/21 20:52:49-04:00 len.brown@intel.com +13 -7
#   re-factor previous patch to reflect that only the dstirq
#   depends on the dstapic
# 
# arch/i386/kernel/mpparse.c
#   2004/06/21 20:52:49-04:00 len.brown@intel.com +16 -8
#   re-factor previous patch to reflect that only the dstirq
#   depends on the dstapic
# 
# ChangeSet
#   2004/06/21 17:04:23-07:00 greg@kroah.com 
#   merge fixups.
# 
# drivers/scsi/scsi_debug.c
#   2004/06/21 17:04:10-07:00 greg@kroah.com +1 -1
#   merge fixups.
# 
# ChangeSet
#   2004/06/21 16:04:04-07:00 hadi@zynx.com 
#   [PKT_SCHED]: C99'ify act_police_ops.
# 
# net/sched/police.c
#   2004/06/21 16:03:41-07:00 hadi@zynx.com +13 -13
#   [PKT_SCHED]: C99'ify act_police_ops.
# 
# ChangeSet
#   2004/06/21 15:14:21-07:00 greg@kroah.com 
#   merge 
# 
# drivers/scsi/scsi_debug.c
#   2004/06/21 15:14:13-07:00 greg@kroah.com +2 -7
#   merge 
# 
# ChangeSet
#   2004/06/21 14:39:33-07:00 kaber@trash.net 
#   [NETFILTER]: ip_table_raw C99 initialization
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/iptable_raw.c
#   2004/06/21 14:39:19-07:00 kaber@trash.net +58 -37
#   [NETFILTER]: ip_table_raw C99 initialization
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:38:44-07:00 kaber@trash.net 
#   [NETFILTER]: Add realm match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/Kconfig
#   2004/06/21 14:38:11-07:00 kaber@trash.net +2 -2
#   [NETFILTER]: Add realm match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/Makefile
#   2004/06/21 14:38:11-07:00 kaber@trash.net +1 -0
#   [NETFILTER]: Add realm match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/Kconfig
#   2004/06/21 14:38:11-07:00 kaber@trash.net +14 -0
#   [NETFILTER]: Add realm match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ipt_realm.c
#   2004/06/21 14:37:59-07:00 kaber@trash.net +76 -0
#   [NETFILTER]: Add realm match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ipt_realm.c
#   2004/06/21 14:37:59-07:00 kaber@trash.net +0 -0
#   BitKeeper file /disk1/BK/nf-2.6/net/ipv4/netfilter/ipt_realm.c
# 
# include/linux/netfilter_ipv4/ipt_realm.h
#   2004/06/21 14:37:58-07:00 kaber@trash.net +10 -0
#   [NETFILTER]: Add realm match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/netfilter_ipv4/ipt_realm.h
#   2004/06/21 14:37:58-07:00 kaber@trash.net +0 -0
#   BitKeeper file /disk1/BK/nf-2.6/include/linux/netfilter_ipv4/ipt_realm.h
# 
# kernel/module.c
#   2004/06/21 14:37:39-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# drivers/scsi/scsi_transport_spi.c
#   2004/06/21 14:37:38-07:00 greg@kroah.com +0 -1
#   Auto merged
# 
# MAINTAINERS
#   2004/06/21 14:37:38-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/21 14:36:31-07:00 kaber@trash.net 
#   [NETFILTER]: Add addrtype match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/Makefile
#   2004/06/21 14:36:07-07:00 kaber@trash.net +1 -0
#   [NETFILTER]: Add addrtype match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/Kconfig
#   2004/06/21 14:36:07-07:00 kaber@trash.net +10 -0
#   [NETFILTER]: Add addrtype match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ipt_addrtype.c
#   2004/06/21 14:35:54-07:00 kaber@trash.net +77 -0
#   [NETFILTER]: Add addrtype match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ipt_addrtype.c
#   2004/06/21 14:35:54-07:00 kaber@trash.net +0 -0
#   BitKeeper file /disk1/BK/nf-2.6/net/ipv4/netfilter/ipt_addrtype.c
# 
# include/linux/netfilter_ipv4/ipt_addrtype.h
#   2004/06/21 14:35:52-07:00 kaber@trash.net +11 -0
#   [NETFILTER]: Add addrtype match
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/netfilter_ipv4/ipt_addrtype.h
#   2004/06/21 14:35:52-07:00 kaber@trash.net +0 -0
#   BitKeeper file /disk1/BK/nf-2.6/include/linux/netfilter_ipv4/ipt_addrtype.h
# 
# ChangeSet
#   2004/06/21 14:34:20-07:00 kaber@trash.net 
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv6/sit.c
#   2004/06/21 14:34:06-07:00 kaber@trash.net +2 -14
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv6/ip6_tunnel.c
#   2004/06/21 14:34:06-07:00 kaber@trash.net +1 -7
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ipt_REJECT.c
#   2004/06/21 14:34:06-07:00 kaber@trash.net +1 -5
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/ipmr.c
#   2004/06/21 14:34:06-07:00 kaber@trash.net +3 -12
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/ipip.c
#   2004/06/21 14:34:06-07:00 kaber@trash.net +2 -14
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/ip_input.c
#   2004/06/21 14:34:06-07:00 kaber@trash.net +1 -5
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/ip_gre.c
#   2004/06/21 14:34:06-07:00 kaber@trash.net +2 -14
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/skbuff.h
#   2004/06/21 14:34:06-07:00 kaber@trash.net +12 -3
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:33:48-07:00 kaber@trash.net 
#   [NETFILTER]: Relax hook check in ipt_CLASSIFY
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ipt_CLASSIFY.c
#   2004/06/21 14:33:34-07:00 kaber@trash.net +7 -5
#   [NETFILTER]: Relax hook check in ipt_CLASSIFY
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:33:13-07:00 kaber@trash.net 
#   [NETFILTER]: Fix offset calculation in amanda conntrack helper
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ip_conntrack_amanda.c
#   2004/06/21 14:32:59-07:00 kaber@trash.net +1 -1
#   [NETFILTER]: Fix offset calculation in amanda conntrack helper
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:32:37-07:00 kaber@trash.net 
#   [NETFILTER]: Fix expectation eviction order
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ip_nat_core.c
#   2004/06/21 14:32:23-07:00 kaber@trash.net +1 -1
#   [NETFILTER]: Fix expectation eviction order
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ip_conntrack_core.c
#   2004/06/21 14:32:23-07:00 kaber@trash.net +7 -16
#   [NETFILTER]: Fix expectation eviction order
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:32:04-07:00 kaber@trash.net 
#   [NETFILTER]: Don't reroute on nfmark change in mangle table when routing by nfmark is not enabled
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/iptable_mangle.c
#   2004/06/21 14:31:50-07:00 kaber@trash.net +2 -0
#   [NETFILTER]: Don't reroute on nfmark change in mangle table when routing by nfmark is not enabled
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:31:28-07:00 kaber@trash.net 
#   [NETFILTER]: 'any' matching in ipt_helper
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ipt_helper.c
#   2004/06/21 14:31:14-07:00 kaber@trash.net +5 -6
#   [NETFILTER]: 'any' matching in ipt_helper
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:30:52-07:00 kaber@trash.net 
#   [NETFILTER]: Fix inverted matching in ipt_helper
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ipt_helper.c
#   2004/06/21 14:30:38-07:00 kaber@trash.net +5 -6
#   [NETFILTER]: Fix inverted matching in ipt_helper
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:30:19-07:00 kaber@trash.net 
#   [NETFILTER]: skip internal targets in iptables proc listing
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv6/netfilter/ip6_tables.c
#   2004/06/21 14:30:05-07:00 kaber@trash.net +10 -1
#   [NETFILTER]: skip internal targets in iptables proc listing
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ip_tables.c
#   2004/06/21 14:30:05-07:00 kaber@trash.net +10 -1
#   [NETFILTER]: skip internal targets in iptables proc listing
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:29:41-07:00 kaber@trash.net 
#   [NETFILTER]: Change permissions of /proc/net/ip_conntrack to 0440
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ip_conntrack_standalone.c
#   2004/06/21 14:29:27-07:00 kaber@trash.net +1 -1
#   [NETFILTER]: Change permissions of /proc/net/ip_conntrack to 0440
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:28:57-07:00 kaber@trash.net 
#   [NETFILTER]: complain about brokeness on SMP for pid, sid and command matching in ipt_owner
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv6/netfilter/ip6t_owner.c
#   2004/06/21 14:28:43-07:00 kaber@trash.net +8 -1
#   [NETFILTER]: complain about brokeness on SMP for pid, sid and command matching in ipt_owner
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ipt_owner.c
#   2004/06/21 14:28:43-07:00 kaber@trash.net +9 -1
#   [NETFILTER]: complain about brokeness on SMP for pid, sid and command matching in ipt_owner
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:28:23-07:00 kaber@trash.net 
#   [NETFILTER]: Fix non-existant config option for IP_NF_ASSERT, fix some broken assertions
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ip_nat_core.c
#   2004/06/21 14:28:09-07:00 kaber@trash.net +3 -2
#   [NETFILTER]: Fix non-existant config option for IP_NF_ASSERT, fix some broken assertions
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv4/netfilter/ip_conntrack_core.c
#   2004/06/21 14:28:09-07:00 kaber@trash.net +1 -3
#   [NETFILTER]: Fix non-existant config option for IP_NF_ASSERT, fix some broken assertions
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/netfilter_ipv4/ip_conntrack.h
#   2004/06/21 14:28:09-07:00 kaber@trash.net +1 -1
#   [NETFILTER]: Fix non-existant config option for IP_NF_ASSERT, fix some broken assertions
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 14:07:06-07:00 herbert@gondor.apana.org.au 
#   [NET]: In sungem driver, keep track of rx buffer alloc size based upon MTU.
# 
# drivers/net/sungem.h
#   2004/06/21 14:06:52-07:00 herbert@gondor.apana.org.au +2 -1
#   [NET]: In sungem driver, keep track of rx buffer alloc size based upon MTU.
# 
# drivers/net/sungem.c
#   2004/06/21 14:06:52-07:00 herbert@gondor.apana.org.au +8 -4
#   [NET]: In sungem driver, keep track of rx buffer alloc size based upon MTU.
# 
# ChangeSet
#   2004/06/21 15:22:34-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.7
#   into intel.com:/home/lenb/bk/linux-acpi-test-2.6.7
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/21 15:22:31-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# arch/i386/kernel/mpparse.c
#   2004/06/21 15:22:31-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/21 15:20:51-04:00 len.brown@intel.com 
#   [ACPI] fix double timer interrupt mapping (Hans-Frieder Vogt)
#   caused by errant fix for OSDL 2835
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/21 15:20:45-04:00 len.brown@intel.com +1 -1
#   fix previous fix that caused double timer interrupts (Hans-Frieder Vogt)
# 
# arch/i386/kernel/mpparse.c
#   2004/06/21 15:20:45-04:00 len.brown@intel.com +1 -1
#   fix previous fix that caused double timer interrupts (Hans-Frieder Vogt)
# 
# ChangeSet
#   2004/06/21 14:52:56-04:00 jgarzik@pobox.com 
#   Rename 'carmel' block driver to 'sx8'.
#   
#   Requested by Promise.  The hardware isn't widely deployed yet,
#   with almost all users being early evaluators, so this should be OK.
# 
# drivers/block/Makefile
#   2004/06/21 14:52:50-04:00 jgarzik@pobox.com +1 -1
#   Rename 'carmel' block driver to 'sx8'.
#   
#   Requested by Promise.  The hardware isn't widely deployed yet,
#   with almost all users being early evaluators, so this should be OK.
# 
# drivers/block/Kconfig
#   2004/06/21 14:52:50-04:00 jgarzik@pobox.com +4 -4
#   Rename 'carmel' block driver to 'sx8'.
#   
#   Requested by Promise.  The hardware isn't widely deployed yet,
#   with almost all users being early evaluators, so this should be OK.
# 
# Documentation/devices.txt
#   2004/06/21 14:52:50-04:00 jgarzik@pobox.com +14 -14
#   Rename 'carmel' block driver to 'sx8'.
#   
#   Requested by Promise.  The hardware isn't widely deployed yet,
#   with almost all users being early evaluators, so this should be OK.
# 
# drivers/block/sx8.c
#   2004/06/21 14:49:55-04:00 jgarzik@pobox.com +0 -0
#   Rename: drivers/block/carmel.c -> drivers/block/sx8.c
# 
# ChangeSet
#   2004/06/21 09:34:33-07:00 akpm@osdl.org 
#   [NET]: Loopback, allocate per-cpu stats statically and fix cpu refcounting.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/loopback.c
#   2004/06/21 09:34:19-07:00 akpm@osdl.org +18 -17
#   [NET]: Loopback, allocate per-cpu stats statically and fix cpu refcounting.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 09:32:44-07:00 akm@osdl.org 
#   [NET]: Fix dev_queue_xmit build with older gcc.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/21 13:14:12-03:00 acme@conectiva.com.br 
#   [NET] generalise tcp_set_owner_r and tcp_rfree
#   
#   Will be used by the poor cousins
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_input.c
#   2004/06/21 13:14:00-03:00 acme@conectiva.com.br +4 -4
#   [NET] generalise tcp_set_owner_r and tcp_rfree
#   
#   Will be used by the poor cousins
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/21 13:14:00-03:00 acme@conectiva.com.br +0 -8
#   [NET] generalise tcp_set_owner_r and tcp_rfree
#   
#   Will be used by the poor cousins
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/stream.c
#   2004/06/21 13:14:00-03:00 acme@conectiva.com.br +10 -0
#   [NET] generalise tcp_set_owner_r and tcp_rfree
#   
#   Will be used by the poor cousins
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/tcp.h
#   2004/06/21 13:14:00-03:00 acme@conectiva.com.br +0 -10
#   [NET] generalise tcp_set_owner_r and tcp_rfree
#   
#   Will be used by the poor cousins
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/21 13:14:00-03:00 acme@conectiva.com.br +10 -0
#   [NET] generalise tcp_set_owner_r and tcp_rfree
#   
#   Will be used by the poor cousins
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/20 23:44:05-07:00 axboe@suse.de 
#   [PATCH] only clear ->last_merge when appropriate
#   
#   Make sure we only clear q->last_merge hint, if it matches the request
#   currently passed in.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/ll_rw_blk.c
#   2004/06/20 23:39:06-07:00 axboe@suse.de +8 -4
#   only clear ->last_merge when appropriate
# 
# ChangeSet
#   2004/06/20 20:46:32-07:00 sam@ravnborg.org 
#   [PATCH] kbuild: add deb-pkg target
#   
#   To prepare kbuild for more kernel packaging formats move all packaging support
#   to scripts/package.
#   
#   In top-level Makefile introduce generic support for all package formats using
#   target names *-pkg.  Included the old rpm target for backward compatibility.
#   
#   A new variable KBUILD_IMAGE is used to specify what kernel image will be part
#   of the final package, and is to be set by the arch specific makefile.
#   KBUILD_IMAGE may be overridden from command line or environment.  KBUILD_IMAGE
#   will see wider usage later, mainly when installing kernel images.
#   
#   Introducing KBUILD_IMAGE allowed arch specific details to be deleted from the
#   mkspec and builddeb scripts.
#   
#   While in the process added the deb packet format.  Script is From: Wichert
#   Akkerman <wichert@wiggy.net>
#   
#   To create a RPM packet use 'make rpm-pkg'.
#   To create a deb packet use 'make deb-pkg'.
#   Both targets are included in 'make help'
#   
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# scripts/package/mkspec
#   2004/06/20 18:23:45-07:00 sam@ravnborg.org +7 -16
#   kbuild: add deb-pkg target
# 
# scripts/package/builddeb
#   2004/06/20 20:46:25-07:00 sam@ravnborg.org +79 -0
# 
# scripts/package/Makefile
#   2004/06/20 20:46:25-07:00 sam@ravnborg.org +71 -0
# 
# scripts/Makefile
#   2004/06/20 18:23:45-07:00 sam@ravnborg.org +1 -1
#   kbuild: add deb-pkg target
# 
# arch/i386/Makefile
#   2004/06/20 18:23:45-07:00 sam@ravnborg.org +7 -6
#   kbuild: add deb-pkg target
# 
# Makefile
#   2004/06/20 18:23:45-07:00 sam@ravnborg.org +25 -37
#   kbuild: add deb-pkg target
# 
# scripts/package/builddeb
#   2004/06/20 20:46:25-07:00 sam@ravnborg.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/scripts/package/builddeb
# 
# scripts/package/Makefile
#   2004/06/20 20:46:25-07:00 sam@ravnborg.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/scripts/package/Makefile
# 
# ChangeSet
#   2004/06/20 20:46:14-07:00 sam@ravnborg.org 
#   [PATCH] Avoid rebuild of IKCFG when using O=
#   
#   When using a separate output directory the in-kernel config wiere rebuild
#   each time the kernel was compiled.  Fix this by specifying correct path to
#   Makefile in the prerequisite to the ikconfig.h file.
#   
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/Makefile
#   2004/06/20 18:23:45-07:00 sam@ravnborg.org +1 -1
#   Avoid rebuild of IKCFG when using O=
# 
# ChangeSet
#   2004/06/20 20:46:03-07:00 sam@ravnborg.org 
#   [PATCH] wanxl firware build fix
#   
#   allmodconfig and allyesconfig are currently failing because they select
#   wanxl firmware rebuild, and that requires an m68k assembler toolchain.
#   
#   Add a new generic option to the "Generic Driver Options" menu.  The option
#   is defaul equals y and prevents us from building firmware unless really
#   needed.
#   
#   Firmware is usually provided in separate filer '_shipped', and there is no
#   need to rebuild them unless strictly required.  First user is WanXL - which
#   otherwise required a m68k tool-set to compile.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/wan/Kconfig
#   2004/06/20 18:23:45-07:00 sam@ravnborg.org +1 -1
#   wanxl firware build fix
# 
# drivers/base/Kconfig
#   2004/06/20 18:23:45-07:00 sam@ravnborg.org +9 -0
#   wanxl firware build fix
# 
# ChangeSet
#   2004/06/20 20:45:52-07:00 geert@linux-m68k.org 
#   [PATCH] Fix idr.h comment
#   
#   Fix path in <linux/idr.h> header file.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/idr.h
#   2004/06/20 18:23:45-07:00 geert@linux-m68k.org +1 -1
#   Fix idr.h comment
# 
# ChangeSet
#   2004/06/20 20:45:41-07:00 juhl-lkml@dif.dk 
#   [PATCH] Fix warning in tdfxfb.c
#   
#   drivers/video/tdfxfb.c:1104: warning: initialization discards qualifiers from pointer target type
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/tdfxfb.c
#   2004/06/20 18:23:45-07:00 juhl-lkml@dif.dk +1 -1
#   Fix warning in tdfxfb.c
# 
# ChangeSet
#   2004/06/20 20:45:30-07:00 nickpiggin@yahoo.com.au 
#   [PATCH] lindent rwsem
#   
#   Lindent rwsem.c and rwsem-spinlock.c and fix a few things by hand.  Also
#   added a couple of comments for the memory barriers.  Added the __sched
#   annotation that was left out of rwsem-spinlock.c.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/rwsem.c
#   2004/06/20 18:23:45-07:00 nickpiggin@yahoo.com.au +59 -50
#   lindent rwsem
# 
# lib/rwsem-spinlock.c
#   2004/06/20 18:23:45-07:00 nickpiggin@yahoo.com.au +51 -46
#   lindent rwsem
# 
# ChangeSet
#   2004/06/20 20:45:19-07:00 akpm@osdl.org 
#   [PATCH] jfs warning fix
#   
#   On ppc64, s64 is `long'.
#   
#   In file included from fs/jfs/jfs_xtree.h:25,
#                    from fs/jfs/jfs_incore.h:26,
#                    from fs/jfs/super.c:29:
#   fs/jfs/jfs_btree.h: In function `BT_STACK_DUMP':
#   fs/jfs/jfs_btree.h:151: warning: long long unsigned int format, s64 arg (arg 2)
#   
#   Cc: Dave Kleikamp <shaggy@austin.ibm.com>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/jfs/jfs_btree.h
#   2004/06/20 18:23:45-07:00 akpm@osdl.org +1 -1
#   jfs warning fix
# 
# ChangeSet
#   2004/06/20 20:45:08-07:00 ralf@linux-mips.org 
#   [PATCH] Add M48T35 RTC driver
#   
#   Add M48T35 RTC driver for the SGI IP27 aka Origin 200, Origin 2000 and
#   Onyx 2.
#   
#   Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/ip27-rtc.c
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +327 -0
#   Add M48T35 RTC driver
# 
# drivers/char/Makefile
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +1 -0
#   Add M48T35 RTC driver
# 
# drivers/char/Kconfig
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +11 -0
#   Add M48T35 RTC driver
# 
# drivers/char/ip27-rtc.c
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/char/ip27-rtc.c
# 
# ChangeSet
#   2004/06/20 20:44:57-07:00 ralf@linux-mips.org 
#   [PATCH] Cobalt LCD Driver update
#   
#   Mostly reformatting to get the sometimes random formatting style of the LCD
#   driver to something Linux compliant.  Use module_init/exit for module
#   initialization and cleanup.
#   
#   Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/lcd.h
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +184 -0
#   Cobalt LCD Driver update
# 
# drivers/char/lcd.h
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/char/lcd.h
# 
# drivers/char/lcd.c
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +375 -327
#   Cobalt LCD Driver update
# 
# drivers/char/Makefile
#   2004/06/20 18:30:54-07:00 ralf@linux-mips.org +1 -0
#   Cobalt LCD Driver update
# 
# drivers/char/Kconfig
#   2004/06/20 18:30:54-07:00 ralf@linux-mips.org +7 -0
#   Cobalt LCD Driver update
# 
# arch/mips/configs/cobalt_defconfig
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +1 -1
#   Cobalt LCD Driver update
# 
# arch/mips/Kconfig
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +0 -5
#   Cobalt LCD Driver update
# 
# ChangeSet
#   2004/06/20 20:44:45-07:00 ralf@linux-mips.org 
#   [PATCH] DS1286 cleanups
#   
#   Remove #ifdef'ed hooks for the DS1286 driver through the kernel.  While
#   cleaning make it work as a module also and add back the core of the driver
#   got lost when drivers/sgi/ was shredded.
#   
#   Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/ds1286.h
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +54 -0
#   DS1286 cleanups
# 
# include/linux/ds1286.h
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/linux/ds1286.h
# 
# fs/proc/proc_misc.c
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +0 -15
#   DS1286 cleanups
# 
# drivers/char/misc.c
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +0 -4
#   DS1286 cleanups
# 
# drivers/char/ds1286.c
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +578 -0
#   DS1286 cleanups
# 
# drivers/char/Makefile
#   2004/06/20 18:30:55-07:00 ralf@linux-mips.org +1 -0
#   DS1286 cleanups
# 
# drivers/char/Kconfig
#   2004/06/20 18:30:55-07:00 ralf@linux-mips.org +11 -0
#   DS1286 cleanups
# 
# arch/mips/defconfig
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +1 -1
#   DS1286 cleanups
# 
# arch/mips/configs/ip22_defconfig
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +1 -1
#   DS1286 cleanups
# 
# drivers/char/ds1286.c
#   2004/06/20 18:23:44-07:00 ralf@linux-mips.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/char/ds1286.c
# 
# ChangeSet
#   2004/06/20 20:44:34-07:00 ralf@linux-mips.org 
#   [PATCH] mips: remove old junk
#   
#   Remove old, unused initialization stuff.
#   
#   Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/misc.c
#   2004/06/20 18:30:55-07:00 ralf@linux-mips.org +0 -13
#   mips: remove old junk
# 
# ChangeSet
#   2004/06/20 20:44:23-07:00 bjoern@j3e.de 
#   [PATCH] NLS support for ASCII
#   
#   I created an ASCII NSL module manually based on the ISO-8859-1 NLS module.
#   
#   This might be of use for people who do not want any charset conversion to
#   take place.  fs modules like vfat for example then could be forced to
#   display any non-ASCII character in the uni_xlate escaped form.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nls/nls_ascii.c
#   2004/06/20 18:23:44-07:00 bjoern@j3e.de +167 -0
#   NLS support for ASCII
# 
# fs/nls/nls_ascii.c
#   2004/06/20 18:23:44-07:00 bjoern@j3e.de +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/fs/nls/nls_ascii.c
# 
# fs/nls/Makefile
#   2004/06/20 18:23:44-07:00 bjoern@j3e.de +1 -0
#   NLS support for ASCII
# 
# fs/nls/Kconfig
#   2004/06/20 18:23:44-07:00 bjoern@j3e.de +8 -0
#   NLS support for ASCII
# 
# ChangeSet
#   2004/06/20 20:44:11-07:00 emoenke@gwdg.de 
#   [PATCH] CREDITS update
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# CREDITS
#   2004/06/20 18:23:44-07:00 emoenke@gwdg.de +2 -2
#   CREDITS update
# 
# ChangeSet
#   2004/06/20 20:44:00-07:00 akpm@osdl.org 
#   [PATCH] move as documentation
#   
#   Move the anticipatory scheduler documentation into Documentation/block.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/block/as-iosched.txt
#   2004/06/20 18:23:43-07:00 akpm@osdl.org +1 -1
#   move as documentation
# 
# ChangeSet
#   2004/06/20 23:57:54-03:00 acme@conectiva.com.br 
#   [NET] generalise wait_for_tcp_memory
#   
#   Renaming it to sk_stream_wait_memory
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/sctp/socket.c
#   2004/06/20 23:57:40-03:00 acme@conectiva.com.br +1 -1
#   [NET] generalise wait_for_tcp_memory
#   
#   Renaming it to sk_stream_wait_memory
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/20 23:57:40-03:00 acme@conectiva.com.br +2 -63
#   [NET] generalise wait_for_tcp_memory
#   
#   Renaming it to sk_stream_wait_memory
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/stream.c
#   2004/06/20 23:57:40-03:00 acme@conectiva.com.br +63 -0
#   [NET] generalise wait_for_tcp_memory
#   
#   Renaming it to sk_stream_wait_memory
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/20 23:57:40-03:00 acme@conectiva.com.br +1 -0
#   [NET] generalise wait_for_tcp_memory
#   
#   Renaming it to sk_stream_wait_memory
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/20 23:47:17-03:00 acme@conectiva.com.br 
#   [NET] introduce sk_stream_wait_close, from tcp code
#   
#   Will be used by the poor cousins.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/20 23:46:55-03:00 acme@conectiva.com.br +1 -27
#   [NET] introduce sk_stream_wait_close, from tcp code
#   
#   Will be used by the poor cousins.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/stream.c
#   2004/06/20 23:46:55-03:00 acme@conectiva.com.br +28 -0
#   [NET] introduce sk_stream_wait_close, from tcp code
#   
#   Will be used by the poor cousins.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/20 23:46:55-03:00 acme@conectiva.com.br +1 -0
#   [NET] introduce sk_stream_wait_close, from tcp code
#   
#   Will be used by the poor cousins.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/20 23:33:23-03:00 acme@conectiva.com.br 
#   [NET] generalise wait_for_tcp_connect
#   
#   This will be used by the poor cousins, look, for instance, at
#   x25_wait_for_connection_establishment :-)
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_input.c
#   2004/06/20 23:33:12-03:00 acme@conectiva.com.br +1 -1
#   [NET] generalise wait_for_tcp_connect
#   
#   This will be used by the poor cousins, look, for instance, at
#   x25_wait_for_connection_establishment :-)
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/20 23:33:12-03:00 acme@conectiva.com.br +4 -39
#   [NET] generalise wait_for_tcp_connect
#   
#   This will be used by the poor cousins, look, for instance, at
#   x25_wait_for_connection_establishment :-)
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/stream.c
#   2004/06/20 23:33:12-03:00 acme@conectiva.com.br +37 -0
#   [NET] generalise wait_for_tcp_connect
#   
#   This will be used by the poor cousins, look, for instance, at
#   x25_wait_for_connection_establishment :-)
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/sock.c
#   2004/06/20 23:33:12-03:00 acme@conectiva.com.br +1 -0
#   [NET] generalise wait_for_tcp_connect
#   
#   This will be used by the poor cousins, look, for instance, at
#   x25_wait_for_connection_establishment :-)
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/20 23:33:12-03:00 acme@conectiva.com.br +4 -0
#   [NET] generalise wait_for_tcp_connect
#   
#   This will be used by the poor cousins, look, for instance, at
#   x25_wait_for_connection_establishment :-)
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/linux/tcp.h
#   2004/06/20 23:33:12-03:00 acme@conectiva.com.br +0 -2
#   [NET] generalise wait_for_tcp_connect
#   
#   This will be used by the poor cousins, look, for instance, at
#   x25_wait_for_connection_establishment :-)
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/20 18:58:22-07:00 axboe@suse.de 
#   [PATCH] deadline I/O scheduler documentation
#   
#   Document the deadline scheduler and its tunables.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/block/deadline-iosched.txt
#   2004/06/20 18:23:43-07:00 axboe@suse.de +78 -0
#   deadline I/O scheduler documentation
# 
# Documentation/block/deadline-iosched.txt
#   2004/06/20 18:23:43-07:00 axboe@suse.de +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/block/deadline-iosched.txt
# 
# ChangeSet
#   2004/06/20 18:58:10-07:00 juhl-lkml@dif.dk 
#   [PATCH] isp16 check_region() removal
#   
#   Convert check_region to request_region and clean up some parentheses in
#   return statements for drivers/cdrom/isp16.c.
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/cdrom/isp16.c
#   2004/06/20 18:23:43-07:00 juhl-lkml@dif.dk +27 -18
#   isp16 check_region() removal
# 
# ChangeSet
#   2004/06/20 18:57:59-07:00 ak@suse.de 
#   [PATCH] NUMA API updates
#   
#   This patch three issues in NUMA API
#   
#   - When 1 was passed to set_mempolicy or mbind as maxnodes argument
#     get_nodes could corrupt the stack and cause a crash.  Fix that.
#   
#   - Remove the restriction to do interleaving only for order 0.  Together
#     with the patch that went in previously to use interleaving policy at boot
#     time this should give back the original behaviour of distributing the big
#     hash tables.
#   
#   - Fix some bad white space in comments
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/mempolicy.c
#   2004/06/20 18:23:43-07:00 ak@suse.de +13 -10
#   NUMA API updates
# 
# ChangeSet
#   2004/06/20 18:57:48-07:00 mason@suse.com 
#   [PATCH] fix possible stack corruption during reiserfs_file_write
#   
#   With preallocation turned on, reiserfs_allocate_blocks_for_region wasn't
#   sending a large enough array to hold all the blocks it was asking the block
#   allocator to find.  This can result in stack corruption.
#   
#   The fix is to kmalloc an array to hold the blocks, making sure to allocate
#   something large enough.
#   
#   There was also a recent optimization to force the allocator to find a free
#   region large enough to hold the entire preallocation size.  This was
#   sometimes causing more blocks to be allocated then had been requested,
#   which would also overflow the array.  Something more elegant is required
#   here, until then just disable the optimization.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/reiserfs/file.c
#   2004/06/20 18:23:43-07:00 mason@suse.com +15 -10
#   fix possible stack corruption during reiserfs_file_write
# 
# fs/reiserfs/bitmap.c
#   2004/06/20 18:23:43-07:00 mason@suse.com +1 -4
#   fix possible stack corruption during reiserfs_file_write
# 
# ChangeSet
#   2004/06/20 18:57:37-07:00 fabian.frederick@skynet.be 
#   [PATCH] sparse annotation for sys_quotactl()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/quota.c
#   2004/06/20 18:23:43-07:00 fabian.frederick@skynet.be +1 -1
#   sparse annotation for sys_quotactl()
# 
# ChangeSet
#   2004/06/20 18:57:26-07:00 hugh@veritas.com 
#   [PATCH] mprotect propagate anon_vma
#   
#   When mprotect shifts the boundary between vmas (merging the reprotected
#   area into the vma before or the vma after), make sure that the expanding
#   vma has anon_vma if the shrinking vma had, to cover anon pages imported.
#   Thanks to Andrea for alerting us to this oversight.
#   
#   Cc: <andrea@suse.de>
#   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/mmap.c
#   2004/06/20 18:23:42-07:00 hugh@veritas.com +14 -1
#   mprotect propagate anon_vma
# 
# ChangeSet
#   2004/06/20 18:57:15-07:00 jbarnes@engr.sgi.com 
#   [PATCH] export sys_ioctl to modules
#   
#   Small patch to export sys_ioctl if CONFIG_COMPAT is set.  This allows
#   platforms to implement 32 bit compatibility ioctl handlers in modules.
#   
#   Submitted-by: Jesse Barnes <jbarnes@sgi.com>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ioctl.c
#   2004/06/20 18:23:42-07:00 jbarnes@engr.sgi.com +10 -0
#   export sys_ioctl to modules
# 
# arch/x86_64/kernel/x8664_ksyms.c
#   2004/06/20 18:23:42-07:00 jbarnes@engr.sgi.com +0 -1
#   export sys_ioctl to modules
# 
# arch/sparc64/kernel/sparc64_ksyms.c
#   2004/06/20 18:23:42-07:00 jbarnes@engr.sgi.com +0 -1
#   export sys_ioctl to modules
# 
# arch/s390/kernel/s390_ksyms.c
#   2004/06/20 18:23:42-07:00 jbarnes@engr.sgi.com +0 -1
#   export sys_ioctl to modules
# 
# arch/ppc64/kernel/ppc_ksyms.c
#   2004/06/20 18:23:42-07:00 jbarnes@engr.sgi.com +0 -1
#   export sys_ioctl to modules
# 
# ChangeSet
#   2004/06/20 18:57:04-07:00 hch@lst.de 
#   [PATCH] fix isdn to not assume mem*io return values
#   
#   These are defined like the normal ISO C mem* routines although x86 happens
#   to return void by accident.  Fix isdn to not assume a return value.
#   
#   Sent to the isdn list, but as usual I didn't get any reply.
#   
#   The patch is from the Debian kernel package and really old.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/isdn/sc/shmem.c
#   2004/06/20 18:23:42-07:00 hch@lst.de +12 -21
#   fix isdn to not assume mem*io return values
# 
# drivers/isdn/sc/packet.c
#   2004/06/20 18:23:42-07:00 hch@lst.de +2 -2
#   fix isdn to not assume mem*io return values
# 
# drivers/isdn/sc/message.c
#   2004/06/20 18:23:42-07:00 hch@lst.de +0 -1
#   fix isdn to not assume mem*io return values
# 
# ChangeSet
#   2004/06/20 18:56:53-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: radio-zoltrix fix.
#   
#   From: Paul Focke <paul.focke@pandora.be>
#   
#   I recently upgraded from 2.4 to kernel 2.6 & noticed that the zoltrix radio
#   driver was not working.  Seems like a little typo.  I tested this on my system
#   and it's working fine now.  I doubt there are any other linux users in the
#   world who still use this card ;-)
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/radio/radio-zoltrix.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +1 -1
#   v4l: radio-zoltrix fix.
# 
# ChangeSet
#   2004/06/20 18:56:42-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: cx88 driver update
#   
#   This is a update for the cx88 tv card driver.  Changes:
#   
#   * finally make it build with gcc 2.95 ;)
#   
#   * add new tv cards.
#   
#   * plenty of fixes for the TV sound code.
#   
#   * use v4l2 API for communication with tuner + tda9887
#   
#   * misc other minor stuff.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/cx88/cx88.h
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +21 -13
#   v4l: cx88 driver update
# 
# drivers/media/video/cx88/cx88-video.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +99 -76
#   v4l: cx88 driver update
# 
# drivers/media/video/cx88/cx88-vbi.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +5 -8
#   v4l: cx88 driver update
# 
# drivers/media/video/cx88/cx88-tvaudio.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +240 -157
#   v4l: cx88 driver update
# 
# drivers/media/video/cx88/cx88-reg.h
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +10 -0
#   v4l: cx88 driver update
# 
# drivers/media/video/cx88/cx88-i2c.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +0 -2
#   v4l: cx88 driver update
# 
# drivers/media/video/cx88/cx88-cards.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +162 -14
#   v4l: cx88 driver update
# 
# ChangeSet
#   2004/06/20 18:56:31-07:00 kraxel@bytesex.org 
#   [PATCH] saa7134 driver update
#   
#   This is an update for the saa7134 driver.  Changes:
#   
#   
#   * add support for more TV cards, as usual ;)
#   
#   * add support for image cropping.
#   
#   * use v4l2 API to talk to the tuner chips (thus it depends on the
#     tuner/tda9887 patch).
#   
#   * fixes for the audio carrier scan.
#   
#   * make transport stream packet size configurable.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/saa7134/saa7134.h
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +5 -1
#   saa7134 driver update
# 
# drivers/media/video/saa7134/saa7134-video.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +114 -87
#   saa7134 driver update
# 
# drivers/media/video/saa7134/saa7134-tvaudio.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +103 -69
#   saa7134 driver update
# 
# drivers/media/video/saa7134/saa7134-ts.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +17 -10
#   saa7134 driver update
# 
# drivers/media/video/saa7134/saa7134-oss.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +3 -2
#   saa7134 driver update
# 
# drivers/media/video/saa7134/saa7134-input.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +65 -3
#   saa7134 driver update
# 
# drivers/media/video/saa7134/saa7134-core.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +12 -4
#   saa7134 driver update
# 
# drivers/media/video/saa7134/saa7134-cards.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +102 -20
#   saa7134 driver update
# 
# drivers/media/video/saa7134/saa6752hs.c
#   2004/06/20 18:23:42-07:00 kraxel@bytesex.org +0 -1
#   saa7134 driver update
# 
# ChangeSet
#   2004/06/20 18:56:19-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: IR input driver update.
#   
#   This patch updates the ir-kbd-gpio and ir-kbd-i2c drivers.  Nothing major,
#   just some keytable fixes and support for more hardware.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/ir-kbd-i2c.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +106 -16
#   v4l: IR input driver update.
# 
# drivers/media/video/ir-kbd-gpio.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +41 -41
#   v4l: IR input driver update.
# 
# ChangeSet
#   2004/06/20 18:56:08-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: bttv driver update
#   
#   This is a update of the bttv driver.  Changes:
#   
#   * some card-specific fixes + new cards.
#   
#   * separate buffer switching for video frames and vbi data, that should make
#     bttv less sensitive to high irq latencies.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/bttvp.h
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +8 -5
#   v4l: bttv driver update
# 
# drivers/media/video/bttv.h
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +2 -0
#   v4l: bttv driver update
# 
# drivers/media/video/bttv-vbi.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +4 -1
#   v4l: bttv driver update
# 
# drivers/media/video/bttv-risc.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +18 -10
#   v4l: bttv driver update
# 
# drivers/media/video/bttv-driver.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +95 -36
#   v4l: bttv driver update
# 
# drivers/media/video/bttv-cards.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +92 -3
#   v4l: bttv driver update
# 
# ChangeSet
#   2004/06/20 18:55:57-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: tuner + tda9887 updates
#   
#   This is a big update for the tuner and tda9887 modules which are used for TV
#   card tuning.
#   
#   The tda9887 module is basically completely rewritten and understands all the
#   config bits now instead of having just some fixed config presets.  Some of
#   these config bits can be changed by insmod options now.
#   
#   The other big change is that both modules allow to use the V4L2 API for
#   inter-module communication (i.e.  when bttv/saa7134/...  pass through the
#   tuning ioctls to the modules).  That allows to specify the TV norm more
#   precisely (not just PAL but PAL-I, PAL-BG, ...), which is needed in some cases
#   to make TV audio work correctly.  Using the old v4l1 API is still possible so
#   this shouldn't break any users of these two modules.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/tuner.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +173 -68
#   v4l: tuner + tda9887 updates
# 
# drivers/media/video/tda9887.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +414 -202
#   v4l: tuner + tda9887 updates
# 
# ChangeSet
#   2004/06/20 18:55:46-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: ir-common update
#   
#   Some minor changes for the ir-common module: Update for the RC5 keytable and
#   increase the IR_KEYTAB_SIZE #define.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/media/ir-common.h
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +1 -1
#   v4l: ir-common update
# 
# drivers/media/common/ir-common.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +2 -2
#   v4l: ir-common update
# 
# ChangeSet
#   2004/06/20 18:55:35-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: msp3400 cleanup.
#   
#   This patch has some cleanups for the msp3400 module: Balance is used directly
#   now instead of maintaining the state as left/right volume and calculate the
#   balance from that.  The msp3400 did that only for historical reasons and it
#   isn't needed any more ...
#   
#   Credits for that go to Perry Gilfillan.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/msp3400.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +29 -33
#   v4l: msp3400 cleanup.
# 
# ChangeSet
#   2004/06/20 18:55:24-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: video-buf fixes.
#   
#   This patch has some minor bugfixes for the video-buf module.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/media/video-buf.h
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +0 -2
#   v4l: video-buf fixes.
# 
# drivers/media/video/video-buf.c
#   2004/06/20 18:23:41-07:00 kraxel@bytesex.org +11 -4
#   v4l: video-buf fixes.
# 
# ChangeSet
#   2004/06/20 18:55:13-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: video-buf magic numbers
#   
#   This patch adds some magic IDs and checks for them to the data structs of the
#   video-buf module.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/media/video-buf.h
#   2004/06/20 18:30:58-07:00 kraxel@bytesex.org +4 -0
#   v4l: video-buf magic numbers
# 
# drivers/media/video/video-buf.c
#   2004/06/20 18:30:58-07:00 kraxel@bytesex.org +26 -6
#   v4l: video-buf magic numbers
# 
# ChangeSet
#   2004/06/20 18:55:02-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: update video-buf for per-frame input switching.
#   
#   This patch updates the video-buf module to support the per-frame input
#   switching added by the v4l2 API patch.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/media/video-buf.h
#   2004/06/20 18:30:58-07:00 kraxel@bytesex.org +5 -1
#   v4l: update video-buf for per-frame input switching.
# 
# drivers/media/video/video-buf.c
#   2004/06/20 18:30:58-07:00 kraxel@bytesex.org +14 -0
#   v4l: update video-buf for per-frame input switching.
# 
# ChangeSet
#   2004/06/20 18:54:51-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: v4l2 API updates
#   
#   This patch has some minor updates to v4l2 API:
#   
#   * A new pixel format (V4L2_PIX_FMT_SBGGR8).
#   
#   * Adds some #defines for tv norms for convenience.
#   
#   * Allow to specify the video source to capture from on a per-frame basis.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/videodev2.h
#   2004/06/20 18:23:40-07:00 kraxel@bytesex.org +12 -5
#   v4l: v4l2 API updates
# 
# ChangeSet
#   2004/06/20 18:54:40-07:00 axboe@suse.de 
#   [PATCH] iommu max segment size
#   
#   This patch is from James, I've changed it slightly only.
#   
#   The problem is that some IOMMU implementations have a maximum limit to the
#   size of the number of contiguously mappable pages (admittedly, this limit
#   is mostly in the resource management algorithms rather than the IOMMUs
#   themselves).
#   
#   This patch adds this concept to the bio layer via the parameter
#   
#   BIO_VMERGE_MAX_SIZE
#   
#   which architectures can define in asm/io.h (if undefined, we assume it to
#   be infinite, which is current behaviour).
#   
#   While adding this, I noticed several places where bio was making incorrect
#   assumptions about virtual mergeability (none of which was a bug: bio was
#   overestimating rather than underestimating).
#   
#   - The worst offender was bio_add_page(), which seemed never to check for
#     virtual mergeability
#   
#   - I also fixed blk_hw_contig_segments() not to check the QUEUE_CLUSTER
#     flag, and not to check the phys segment boundary.
#   
#   In order to track the hw segment size across bios, I had to introduce two
#   extra bio parameters: bi_hw_front_size and bi_hw_back_size which store the
#   sizes of the front and back hw contiguous segments (and which will be equal
#   if there's only one hw segment).  When the bio is merged into a request,
#   these fields are updated with the total hw contig size so they can always
#   be used to assess if the merger would violate the BIO_VMERGE_MAX_SIZE
#   parameter.
#   
#   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/linux/bio.h
#   2004/06/20 18:23:40-07:00 axboe@suse.de +18 -0
#   iommu max segment size
# 
# fs/bio.c
#   2004/06/20 18:23:40-07:00 axboe@suse.de +11 -3
#   iommu max segment size
# 
# drivers/block/ll_rw_blk.c
#   2004/06/20 18:23:40-07:00 axboe@suse.de +80 -24
#   iommu max segment size
# 
# ChangeSet
#   2004/06/20 18:54:29-07:00 dcn@sgi.com 
#   [PATCH] add wait_event_interruptible_exclusive() macro
#   
#   This patch defines a macro that does exactly what
#   wait_event_interruptible() does except that it adds the current task to the
#   wait queue as an exclusive task (i.e., sets the WQ_FLAG_EXCLUSIVE flag)
#   rather than as a non-exclusive task as wait_event_interruptible() does.
#   
#   This allows one to do a wake_up_nr() to wake up a specific number of tasks.
#    I'm in the process of submitting a patch to linux-ia64 that requires this
#   capability.  (Its subject line is "[PATCH 3/4] SGI Altix cross partition
#   functionality".)
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/wait.h
#   2004/06/20 18:23:40-07:00 dcn@sgi.com +30 -1
#   add wait_event_interruptible_exclusive() macro
# 
# ChangeSet
#   2004/06/20 18:54:18-07:00 mika@osdl.org 
#   [PATCH] Uninline machine_specific_memory_setup()
#   
#   Cleanup arch/i386/kernel/setup.c a little bit by:
#   
#   * un-inlining machine_specific_memory_setup() (it's implementations are
#     pretty big to be inlined anyway)
#   
#   * remove setup_memory_region() by moving the code inside setup_arch()
#   
#   I would also recommend BK-renaming all four files
#   (include/asm-i386/*/setup_arch_post.h) to ".c" and moving them into
#   arch/i386/*/, but that obviously is not needed in anyway.  But IMHO they
#   are clearly ".c" files, not ".h" files.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/mach-voyager/setup_arch_post.h
#   2004/06/20 18:23:40-07:00 mika@osdl.org +1 -1
#   Uninline machine_specific_memory_setup()
# 
# include/asm-i386/mach-visws/setup_arch_post.h
#   2004/06/20 18:23:40-07:00 mika@osdl.org +1 -1
#   Uninline machine_specific_memory_setup()
# 
# include/asm-i386/mach-default/setup_arch_post.h
#   2004/06/20 18:23:40-07:00 mika@osdl.org +1 -1
#   Uninline machine_specific_memory_setup()
# 
# arch/i386/kernel/setup.c
#   2004/06/20 18:23:40-07:00 mika@osdl.org +6 -12
#   Uninline machine_specific_memory_setup()
# 
# ChangeSet
#   2004/06/20 18:54:07-07:00 mark@alpha.dyndns.org 
#   [PATCH] Add ovcamchip driver
#   
#   This patch adds a new driver for the OmniVision OV6xx0 and OV7xx0 series of
#   CMOS image sensors.  It is currently used by the w9968cf USB webcam driver,
#   which is already in mainline 2.6.  Up until now it had to be compiled
#   outside the kernel tree, which is clearly suboptimal.
#   
#   It is also used by version 2 of the ov511 USB webcam driver, which will be
#   merged in the near future.  That will reduce some code duplication, since
#   the existing ov511 has much of this code built-in.
#   
#   This was previously submitted to Linux-USB-Devel, and I have fixed the
#   concerns that came up at that time.
#   
#   Developer's Certificate of Origin 1.0
#   
#   By making a contribution to this project, I certify that:
#   
#   (a) The contribution was created in whole or in part by me and I
#           have the right to submit it under the open source license
#           indicated in the file; or
#   
#   (b) The contribution is based upon previous work that, to the best
#           of my knowledge, is covered under an appropriate open source
#           license and I have the right under that license to submit that
#           work with modifications, whether created in whole or in part
#           by me, under the same open source license (unless I am
#           by me, under the same open source license (unless I am
#           permitted to submit under a different license), as indicated
#           in the file; or
#   
#   (c) The contribution was provided directly to me by some other
#           person who certified (a), (b) or (c) and I have not modified
#           it.
#   
#   Signed-off-by: Mark McClelland <mark@alpha.dyndns.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/media/ovcamchip.h
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +104 -0
#   Add ovcamchip driver
# 
# drivers/media/video/ovcamchip/ovcamchip_priv.h
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +87 -0
#   Add ovcamchip driver
# 
# drivers/media/video/ovcamchip/ovcamchip_core.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +446 -0
#   Add ovcamchip driver
# 
# drivers/media/video/ovcamchip/ov7x20.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +455 -0
#   Add ovcamchip driver
# 
# drivers/media/video/ovcamchip/ov7x10.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +335 -0
#   Add ovcamchip driver
# 
# drivers/media/video/ovcamchip/ov76be.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +303 -0
#   Add ovcamchip driver
# 
# drivers/media/video/ovcamchip/ov6x30.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +374 -0
#   Add ovcamchip driver
# 
# drivers/media/video/ovcamchip/ov6x20.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +415 -0
#   Add ovcamchip driver
# 
# drivers/media/video/ovcamchip/Makefile
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +4 -0
#   Add ovcamchip driver
# 
# include/media/ovcamchip.h
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/media/ovcamchip.h
# 
# drivers/media/video/ovcamchip/ovcamchip_priv.h
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h
# 
# drivers/media/video/ovcamchip/ovcamchip_core.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/ovcamchip/ovcamchip_core.c
# 
# drivers/media/video/ovcamchip/ov7x20.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/ovcamchip/ov7x20.c
# 
# drivers/media/video/ovcamchip/ov7x10.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/ovcamchip/ov7x10.c
# 
# drivers/media/video/ovcamchip/ov76be.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/ovcamchip/ov76be.c
# 
# drivers/media/video/ovcamchip/ov6x30.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/ovcamchip/ov6x30.c
# 
# drivers/media/video/ovcamchip/ov6x20.c
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/ovcamchip/ov6x20.c
# 
# drivers/media/video/ovcamchip/Makefile
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/ovcamchip/Makefile
# 
# drivers/media/video/Makefile
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +1 -0
#   Add ovcamchip driver
# 
# drivers/media/video/Kconfig
#   2004/06/20 18:23:40-07:00 mark@alpha.dyndns.org +11 -0
#   Add ovcamchip driver
# 
# ChangeSet
#   2004/06/20 18:53:55-07:00 akpm@osdl.org 
#   [PATCH] swapoff: activate pages
#   
#   People like to use swapoff/swapon as a way of restoring their VM to a
#   predictable "preconditional" state.
#   
#   Problem is, swapoff leaves mapped anon/pagecache pages on the inactive list,
#   so they immediately get swapped out again when swapspace becomes available.
#   
#   Let's move these pages onto the active list to the VM has to again decide
#   whether to swap them out.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/swapfile.c
#   2004/06/20 18:21:45-07:00 akpm@osdl.org +7 -0
#   swapoff: activate pages
# 
# ChangeSet
#   2004/06/20 18:53:44-07:00 shaggy@austin.ibm.com 
#   [PATCH] jfs build fix
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/jfs/jfs_dtree.c
#   2004/06/20 18:21:45-07:00 shaggy@austin.ibm.com +2 -1
#   jfs build fix
# 
# ChangeSet
#   2004/06/20 18:53:33-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] airo.c broke
#   
#   But Al fixed it again.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/wireless/airo.c
#   2004/06/20 18:21:44-07:00 viro@parcelfarce.linux.theplanet.co.uk +2 -0
#   airo.c broke
# 
# ChangeSet
#   2004/06/20 18:53:22-07:00 paulkf@microgate.com 
#   [PATCH] ppp_synctty.c receive/write_wakeup fix
#   
#   Allow receive and write_wakeup callbacks to be called at hard interrupt
#   context and/or with interrupts disabled (removes softirq warning).
#   
#   This mirrors changes by Paul Mackerras to ppp_async.c for the same purpose.
#   Patch has been previously posted for comments and has been tested with
#   success by multiple persons.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/ppp_synctty.c
#   2004/06/20 18:20:58-07:00 paulkf@microgate.com +92 -69
#   ppp_synctty.c receive/write_wakeup fix
# 
# ChangeSet
#   2004/06/20 18:53:11-07:00 cesarb@nitnet.com.br 
#   [PATCH] O_NOATIME support
#   
#   This patch adds support for the O_NOATIME open flag (GNU extension):
#   
#   int O_NOATIME  	Macro
#     If this bit is set, read will not update the access time of the file.
#     See File Times. This is used by programs that do backups, so that
#     backing a file up does not count as reading it. Only the owner of the
#     file or the superuser may use this bit.
#   
#   It is useful if you want to do something with the file atime (for instance,
#   moving files that have not been accessed in a while to somewhere else, or
#   something like Debian's popularity-contest) but you also want to read all
#   files periodically (for instance, tripwire or debsums).
#   
#   Currently, the program that reads all files periodically has to use utimes,
#   which can race with the atime update:
#   
#       A               B
#     open
#     fstat
#     read
#                     open
#                     read
#                     close
#     close
#     utimes
#   
#   And the file still has the old atime, instead of the new one from when B
#   did the read from it.  This problem does not happen if A uses O_NOATIME
#   instead of utimes to preserve the atime.
#   
#   This patch adds the O_NOATIME constant for all architectures, but it would
#   also be possible to add it one architecture at a time by defining it to 0
#   when not defined in asm-*.
#   
#   Based on patch by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl> at
#   http://www.uwsg.iu.edu/hypermail/linux/kernel/9811.2/0118.html
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fs.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +2 -1
#   O_NOATIME support
# 
# include/asm-x86_64/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-v850/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-sparc64/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-sparc/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-sh/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-s390/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-ppc64/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-ppc/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-parisc/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-mips/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-m68k/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-ia64/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-i386/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-h8300/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-cris/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-arm26/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-arm/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# include/asm-alpha/fcntl.h
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +1 -0
#   O_NOATIME support
# 
# fs/namei.c
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +5 -0
#   O_NOATIME support
# 
# fs/fcntl.c
#   2004/06/20 18:20:57-07:00 cesarb@nitnet.com.br +6 -1
#   O_NOATIME support
# 
# ChangeSet
#   2004/06/20 18:52:59-07:00 dhowells@redhat.com 
#   [PATCH] Permit inode & dentry hash tables to be allocated > MAX_ORDER size
#   
#   Here's a patch to allocate memory for big system hash tables with the
#   bootmem allocator rather than with main page allocator.
#   
#   It is needed for three reasons:
#   
#   (1) So that the size can be bigger than MAX_ORDER.  IBM have done some
#       testing on their big PPC64 systems (64GB of RAM) with linux-2.4 and found
#       that they get better performance if the sizes of the inode cache hash,
#       dentry cache hash, buffer head hash and page cache hash are increased
#       beyond MAX_ORDER (order 11).
#   
#        Now the main allocator can't allocate anything larger than MAX_ORDER, but
#        the bootmem allocator can.
#   
#        In 2.6 it appears that only the inode and dentry hashes remain of those
#        four, but there are other hash tables that could use this service.
#   
#   (2) Changing MAX_ORDER appears to have a number of effects beyond just
#       limiting the maximum size that can be allocated in one go.
#   
#   (3) Should someone want a hash table in which each bucket isn't a power of
#       two in size, memory will be wasted as the chunk of memory allocated will
#       be a power of two in size (to hold a power of two number of buckets).
#   
#       On the other hand, using the bootmem allocator means the allocation
#       will only take up sufficient pages to hold it, rather than the next power
#       of two up.
#   
#       Admittedly, this point doesn't apply to the dentry and inode hashes,
#       but it might to another hash table that might want to use this service.
#   
#   
#   I've coelesced the meat of the inode and dentry allocation routines into
#   one such routine in mm/page_alloc.c that the the respective initialisation
#   functions now call before mem_init() is called.
#   
#   This routine gets it's approximation of memory size by counting up the
#   ZONE_NORMAL and ZONE_DMA pages (and ZONE_HIGHMEM if requested) in all the
#   nodes passed to the main allocator by paging_init() (or wherever the arch
#   does it).  It does not use max_low_pfn as that doesn't seem to be available
#   on all archs, and it doesn't use num_physpages since that includes highmem
#   pages not available to the kernel for allocating data structures upon -
#   which may not be appropriate when calculating hash table size.
#   
#   On the off chance that the size of each hash bucket may not be exactly a
#   power of two, the routine will only allocate as many pages as is necessary
#   to ensure that the number of buckets is exactly a power of two, rather than
#   allocating the smallest power-of-two sized chunk of memory that will hold
#   the same array of buckets.
#   
#   The maximum size of any single hash table is given by
#   MAX_SYS_HASH_TABLE_ORDER, as is now defined in linux/mmzone.h.
#   
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: David Howells <dhowells@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/page_alloc.c
#   2004/06/20 18:20:10-07:00 dhowells@redhat.com +73 -0
#   Permit inode & dentry hash tables to be allocated > MAX_ORDER size
# 
# init/main.c
#   2004/06/20 18:19:55-07:00 dhowells@redhat.com +1 -0
#   Permit inode & dentry hash tables to be allocated > MAX_ORDER size
# 
# include/linux/mmzone.h
#   2004/06/20 18:19:55-07:00 dhowells@redhat.com +12 -0
#   Permit inode & dentry hash tables to be allocated > MAX_ORDER size
# 
# include/linux/kernel.h
#   2004/06/20 18:20:10-07:00 dhowells@redhat.com +9 -0
#   Permit inode & dentry hash tables to be allocated > MAX_ORDER size
# 
# include/linux/fs.h
#   2004/06/20 18:31:00-07:00 dhowells@redhat.com +7 -4
#   Permit inode & dentry hash tables to be allocated > MAX_ORDER size
# 
# include/linux/bootmem.h
#   2004/06/20 18:19:55-07:00 dhowells@redhat.com +8 -0
#   Permit inode & dentry hash tables to be allocated > MAX_ORDER size
# 
# fs/inode.c
#   2004/06/20 18:20:10-07:00 dhowells@redhat.com +18 -42
#   Permit inode & dentry hash tables to be allocated > MAX_ORDER size
# 
# fs/dcache.c
#   2004/06/20 18:20:10-07:00 dhowells@redhat.com +24 -44
#   Permit inode & dentry hash tables to be allocated > MAX_ORDER size
# 
# ChangeSet
#   2004/06/20 18:52:48-07:00 daniel.ritz@gmx.ch 
#   [PATCH] pcmcia: enable read prefetch on o2micro bridges to fix HDSP
#   
#   enable read prefetching on O2micro bridges. It fixes the problems
#   seen with the RME Hammerfall DSP.
#   Thanks to Eric Still from O2micro for the input.
#   
#   Cc: Russell King <rmk@arm.linux.org.uk>
#   Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/pcmcia/yenta_socket.c
#   2004/06/20 18:19:18-07:00 daniel.ritz@gmx.ch +9 -1
#   pcmcia: enable read prefetch on o2micro bridges to fix HDSP
# 
# drivers/pcmcia/o2micro.h
#   2004/06/20 18:19:18-07:00 daniel.ritz@gmx.ch +26 -0
#   pcmcia: enable read prefetch on o2micro bridges to fix HDSP
# 
# drivers/pcmcia/i82365.c
#   2004/06/20 18:19:18-07:00 daniel.ritz@gmx.ch +0 -1
#   pcmcia: enable read prefetch on o2micro bridges to fix HDSP
# 
# ChangeSet
#   2004/06/20 18:52:36-07:00 pazke@donpac.ru 
#   [PATCH] use new DMI API for HP Pavilion
#   
#   Example code for the new DMI APU - port HP Pavilion irq workaround to new
#   DMI probing.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/pci/visws.c
#   2004/06/20 18:17:56-07:00 pazke@donpac.ru +0 -2
#   use new DMI API for HP Pavilion
# 
# arch/i386/pci/irq.c
#   2004/06/20 18:19:08-07:00 pazke@donpac.ru +31 -1
#   use new DMI API for HP Pavilion
# 
# arch/i386/kernel/dmi_scan.c
#   2004/06/20 18:18:45-07:00 pazke@donpac.ru +0 -25
#   use new DMI API for HP Pavilion
# 
# ChangeSet
#   2004/06/20 18:52:25-07:00 pazke@donpac.ru 
#   [PATCH] export DMI check functions
#   
#   This patch creates and exports 2 functions which can be used by the rest of
#   kernel code to perform DMI data checks:
#   
#   - dmi_check_system() function checks system DMI data against given blacklist
#     table and on each match runs corresponding callback function;
#   
#   - dmi_get_system_info() function returns DMI data value.  Useful for people
#     wanting more complex DMI data check than simple string match.
#   
#   Also filling unused match entries with NO_MATCH made optional, but existing
#   NO_MATCH occurences are left intact, so people are free to continue dmi_scan.c
#   patching without massive reject problems.
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/dmi.h
#   2004/06/20 18:17:49-07:00 pazke@donpac.ru +47 -0
#   export DMI check functions
# 
# include/linux/dmi.h
#   2004/06/20 18:17:49-07:00 pazke@donpac.ru +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/linux/dmi.h
# 
# arch/i386/kernel/dmi_scan.c
#   2004/06/20 18:31:01-07:00 pazke@donpac.ru +55 -56
#   export DMI check functions
# 
# ChangeSet
#   2004/06/20 18:52:14-07:00 akpm@osdl.org 
#   [PATCH] ppc64: eeh.h warning-fix
#   
#   In file included from include/asm/io.h:365,
#                    from drivers/video/kyro/STG4000Reg.h:23,
#                    from drivers/video/kyro/STG4000Ramdac.c:16:
#   include/asm/eeh.h:58: warning: `struct device_node' declared inside parameter list
#   include/asm/eeh.h:58: warning: its scope is only this definition or declaration, which is probably not what you want
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/eeh.h
#   2004/06/20 18:15:35-07:00 akpm@osdl.org +1 -0
#   ppc64: eeh.h warning-fix
# 
# ChangeSet
#   2004/06/20 18:52:03-07:00 akpm@osdl.org 
#   [PATCH] ppc64 CONFIG_ALTIVEC=n build fix
#   
#   With CONFIG_ALTIVEC=n, flush_altivec_to_thread() has no implementation.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/system.h
#   2004/06/20 18:15:35-07:00 akpm@osdl.org +9 -1
#   ppc64 CONFIG_ALTIVEC=n build fix
# 
# ChangeSet
#   2004/06/20 18:27:13-07:00 dsaxena@omelas.(none) 
#   Merge bk://bk.arm.linux.org.uk/linux-2.6-rmk
#   into omelas.(none):/home/dsaxena/src/linux-2.6-for-rmk
# 
# BitKeeper/deleted/.del-core.c~9e662b6895b788f2
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-core.c~714a718aec4a2c30
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# arch/arm/kernel/entry-armv.S
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# arch/arm/common/Makefile
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# arch/arm/Makefile
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# arch/arm/Kconfig
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-time.h~e839fe4bcd9e4cf9
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-time.h~730e38fa47912a2c
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-core.c~9e662b6895b788f2
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Merge rename: arch/arm/mach-ftvpci/core.c -> BitKeeper/deleted/.del-core.c~9e662b6895b788f2
# 
# BitKeeper/deleted/.del-core.c~714a718aec4a2c30
#   2004/06/20 18:27:07-07:00 dsaxena@omelas.(none) +0 -0
#   Merge rename: arch/arm/mach-tbox/core.c -> BitKeeper/deleted/.del-core.c~714a718aec4a2c30
# 
# ChangeSet
#   2004/06/20 17:40:34-07:00 akpm@osdl.org 
#   [SPARC64]: bug.h needs compiler.h
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/asm-sparc64/bug.h
#   2004/06/20 17:40:08-07:00 akpm@osdl.org +2 -0
#   [SPARC64]: bug.h needs compiler.h
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/20 17:36:21-07:00 akepner@sgi.com 
#   [NET]: Lockless loopback patch (version 2).
# 
# net/sched/sch_generic.c
#   2004/06/20 17:35:53-07:00 akepner@sgi.com +29 -14
#   [NET]: Lockless loopback patch (version 2).
# 
# net/sched/sch_api.c
#   2004/06/20 17:35:53-07:00 akepner@sgi.com +3 -0
#   [NET]: Lockless loopback patch (version 2).
# 
# include/net/pkt_sched.h
#   2004/06/20 17:35:52-07:00 akepner@sgi.com +2 -0
#   [NET]: Lockless loopback patch (version 2).
# 
# include/linux/netdevice.h
#   2004/06/20 17:35:52-07:00 akepner@sgi.com +1 -0
#   [NET]: Lockless loopback patch (version 2).
# 
# drivers/net/loopback.c
#   2004/06/20 17:35:52-07:00 akepner@sgi.com +33 -8
#   [NET]: Lockless loopback patch (version 2).
# 
# ChangeSet
#   2004/06/20 17:06:07-07:00 davem@nuts.davemloft.net 
#   Merge bk://kernel.bkbits.net/acme/net-2.6
#   into nuts.davemloft.net:/disk1/BK/net-2.6
# 
# net/ipv4/tcp.c
#   2004/06/20 17:05:59-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/20 20:54:15-03:00 acme@conectiva.com.br 
#   [NET] move tcp_memory_free to sk_stream_memory_free
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/20 20:54:04-03:00 acme@conectiva.com.br +5 -10
#   [NET] move tcp_memory_free to sk_stream_memory_free
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/20 20:54:04-03:00 acme@conectiva.com.br +5 -0
#   [NET] move tcp_memory_free to sk_stream_memory_free
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/20 16:38:03-07:00 davem@nuts.davemloft.net 
#   Merge bk://kernel.bkbits.net/acme/net-2.6-1.1768
#   into nuts.davemloft.net:/disk1/BK/acme-2.6
# 
# net/ipv6/udp.c
#   2004/06/20 16:37:54-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv6/tcp_ipv6.c
#   2004/06/20 16:37:54-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv6/raw.c
#   2004/06/20 16:37:54-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv6/ndisc.c
#   2004/06/20 16:37:54-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv6/mcast.c
#   2004/06/20 16:37:53-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv4/tcp.c
#   2004/06/20 16:37:53-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv4/netfilter/ip_conntrack_core.c
#   2004/06/20 16:37:53-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# include/linux/skbuff.h
#   2004/06/20 16:37:53-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/20 19:45:03-03:00 acme@conectiva.com.br 
#   [NET] move skb_can_coalesce to skbuff.h
#   
#   This one also removes the duplicate can_coalesce in tcp.c and makes it
#   use skb_can_coalesce.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/20 19:44:45-03:00 acme@conectiva.com.br +2 -13
#   [NET] move skb_can_coalesce to skbuff.h
#   
#   This one also removes the duplicate can_coalesce in tcp.c and makes it
#   use skb_can_coalesce.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/ip_output.c
#   2004/06/20 19:44:45-03:00 acme@conectiva.com.br +0 -11
#   [NET] move skb_can_coalesce to skbuff.h
#   
#   This one also removes the duplicate can_coalesce in tcp.c and makes it
#   use skb_can_coalesce.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/linux/skbuff.h
#   2004/06/20 19:44:45-03:00 acme@conectiva.com.br +12 -0
#   [NET] move skb_can_coalesce to skbuff.h
#   
#   This one also removes the duplicate can_coalesce in tcp.c and makes it
#   use skb_can_coalesce.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/20 14:18:46-07:00 hadi@zynx.com 
#   [NET]: Fix module refcounting of TC actions.
# 
# net/sched/sch_prio.c
#   2004/06/20 14:18:14-07:00 hadi@zynx.com +2 -1
#   [NET]: Fix module refcounting of TC actions.
# 
# net/sched/police.c
#   2004/06/20 14:18:14-07:00 hadi@zynx.com +15 -12
#   [NET]: Fix module refcounting of TC actions.
# 
# net/sched/cls_u32.c
#   2004/06/20 14:18:14-07:00 hadi@zynx.com +12 -13
#   [NET]: Fix module refcounting of TC actions.
# 
# net/sched/act_api.c
#   2004/06/20 14:18:14-07:00 hadi@zynx.com +54 -16
#   [NET]: Fix module refcounting of TC actions.
# 
# net/sched/Kconfig
#   2004/06/20 14:18:14-07:00 hadi@zynx.com +8 -4
#   [NET]: Fix module refcounting of TC actions.
# 
# include/net/pkt_sched.h
#   2004/06/20 14:18:14-07:00 hadi@zynx.com +10 -5
#   [NET]: Fix module refcounting of TC actions.
# 
# include/net/pkt_act.h
#   2004/06/20 14:18:14-07:00 hadi@zynx.com +7 -7
#   [NET]: Fix module refcounting of TC actions.
# 
# include/linux/pkt_sched.h
#   2004/06/20 14:18:14-07:00 hadi@zynx.com +6 -0
#   [NET]: Fix module refcounting of TC actions.
# 
# include/linux/pkt_cls.h
#   2004/06/20 14:18:14-07:00 hadi@zynx.com +19 -8
#   [NET]: Fix module refcounting of TC actions.
# 
# ChangeSet
#   2004/06/20 12:32:43-07:00 davem@nuts.davemloft.net 
#   [SPARC64]: Check _TIF_SYSCALL_SUCCESS before syscall return value.
#   
#   We might have to clear the flag, and if we do not
#   then subsequent syscalls can get confused.
#   
#   Bug easily triggered by suspending emacs in a pty
#   and then resuming, select() returns due to a pending
#   signal but because _TIF_SYSCALL_SUCCESS is erroneously
#   set by a previous syscall -514 ends up slipping into
#   userspace.  Oops.
# 
# arch/sparc64/kernel/entry.S
#   2004/06/20 12:32:28-07:00 davem@nuts.davemloft.net +18 -16
#   [SPARC64]: Check _TIF_SYSCALL_SUCCESS before syscall return value.
#   
#   We might have to clear the flag, and if we do not
#   then subsequent syscalls can get confused.
#   
#   Bug easily triggered by suspending emacs in a pty
#   and then resuming, select() returns due to a pending
#   signal but because _TIF_SYSCALL_SUCCESS is erroneously
#   set by a previous syscall -514 ends up slipping into
#   userspace.  Oops.
# 
# ChangeSet
#   2004/06/20 10:39:30-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: I/O abstraction updates
#   
#   M68k I/O abstraction updates:
#     - Make I/O ports and addresses `unsigned long'
#     - Add casts to make operations warning-compatible with other archs
#     - Add {in,out}[wl]_p() and {in,out}l(), which are needed for some drivers
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-m68k/io.h
#   2004/04/12 04:56:00-07:00 geert@linux-m68k.org +32 -14
#   m68k: I/O abstraction updates
# 
# ChangeSet
#   2004/06/20 10:39:19-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: atomic op fixups
#   
#   M68k: Add missing atomic operations (from Roman Zippel and me) and replace
#   `__inline__' by `inline' while we're at it.
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-m68k/atomic.h
#   2004/06/20 02:09:03-07:00 geert@linux-m68k.org +91 -7
#   m68k: atomic op fixups
# 
# ChangeSet
#   2004/06/20 10:39:08-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: Mac IOP fix
#   
#   Mac IOP: Fix copy-and-paste bug (found by OPERA, reported by Zhenmin Li,
#   confirmed by Brad Boyer)
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68k/mac/iop.c
#   2004/05/26 05:49:09-07:00 geert@linux-m68k.org +1 -1
#   m68k: Mac IOP fix
# 
# ChangeSet
#   2004/06/20 10:38:57-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: sparse infrastructure
#   
#   M68k: Make sparse work
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68k/Makefile
#   2004/06/20 01:49:05-07:00 geert@linux-m68k.org +2 -0
#   m68k: sparse infrastructure
# 
# ChangeSet
#   2004/06/20 10:38:46-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: Mac Sonic Ethernet
#   
#   Mac Sonic Ethernet: Kill duplicate `MODULE_LICENSE("GPL");' (already defined in
#   included sonic.c) which causes a compile failure
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/macsonic.c
#   2004/05/04 13:42:38-07:00 geert@linux-m68k.org +0 -1
#   m68k: Mac Sonic Ethernet
# 
# ChangeSet
#   2004/06/20 10:38:35-07:00 geert@linux-m68k.org 
#   [PATCH] affs remount fixes
#   
#   AFFS: Fix oops on write after remount (from Roman Zippel):
#     - Allocate/free bitmap as necessary
#     - Remove last uses of SF_READONLY
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/affs_fs_sb.h
#   2004/06/18 02:18:33-07:00 geert@linux-m68k.org +0 -1
#   affs remount fixes
# 
# include/linux/affs_fs.h
#   2004/06/18 02:18:33-07:00 geert@linux-m68k.org +2 -1
#   affs remount fixes
# 
# fs/affs/super.c
#   2004/06/18 02:17:49-07:00 geert@linux-m68k.org +12 -14
#   affs remount fixes
# 
# fs/affs/bitmap.c
#   2004/06/18 02:17:49-07:00 geert@linux-m68k.org +21 -8
#   affs remount fixes
# 
# fs/affs/amigaffs.c
#   2004/06/18 02:17:49-07:00 geert@linux-m68k.org +0 -1
#   affs remount fixes
# 
# ChangeSet
#   2004/06/20 10:38:24-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: use set_page_count()
#   
#   M68k: From 2.6.7-rc1 on, it's no longer allowed to access page->count directly
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68k/mm/memory.c
#   2004/05/24 06:55:41-07:00 geert@linux-m68k.org +1 -1
#   m68k: use set_page_count()
# 
# ChangeSet
#   2004/06/20 10:38:13-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: bus error handling
#   
#   M68k: Allow to catch a bus error via the exception mechanism (from Roman
#   Zippel)
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68k/kernel/traps.c
#   2004/05/23 01:55:54-07:00 geert@linux-m68k.org +4 -3
#   m68k: bus error handling
# 
# ChangeSet
#   2004/06/20 10:38:02-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: new gcc optimizations
#   
#   M68k compiler updates from Roman Zippel:
#     - Fix various lvalue warnings from newer gcc
#     - Remove unnecessary volatile declarations
#     - Change some constraints from "a" to "m" to generate slightly better code
#     - Use "o" constraint for bitfield instructions
#     - Use generic bitmap functions for some of the ext2/minix bitmap functions
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-m68k/string.h
#   2004/05/23 01:56:37-07:00 geert@linux-m68k.org +8 -9
#   m68k: new gcc optimizations
# 
# include/asm-m68k/page.h
#   2004/05/23 01:56:37-07:00 geert@linux-m68k.org +8 -10
#   m68k: new gcc optimizations
# 
# include/asm-m68k/bitops.h
#   2004/05/23 10:50:20-07:00 geert@linux-m68k.org +54 -103
#   m68k: new gcc optimizations
# 
# include/asm-m68k/atomic.h
#   2004/05/23 01:56:37-07:00 geert@linux-m68k.org +16 -12
#   m68k: new gcc optimizations
# 
# ChangeSet
#   2004/06/20 10:37:51-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: handle new gcc's
#   
#   M68k: Fixes for when compiling with modern gcc (from Roman Zippel):
#     - Avoid warning 'use of memory input without lvalue in asm operand 0 is
#       deprecated' of newer gcc
#     - Replace some '%/' with offical '%%' to escape a '%'
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-m68k/ucontext.h
#   2004/05/23 01:56:37-07:00 geert@linux-m68k.org +2 -4
#   m68k: handle new gcc's
# 
# arch/m68k/kernel/signal.c
#   2004/05/23 01:55:54-07:00 geert@linux-m68k.org +17 -17
#   m68k: handle new gcc's
# 
# ChangeSet
#   2004/06/20 10:37:41-07:00 geert@linux-m68k.org 
#   [PATCH] m68k: IFPSP060 update
#   
#   IFPSP060: Make sure that the destination address of a misaligned cas access is
#   properly mapped in, so the kernel won't oops in the emulation handler (from
#   Roman Zippel).
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68k/ifpsp060/iskeleton.S
#   2004/05/23 01:55:54-07:00 geert@linux-m68k.org +47 -5
#   m68k: IFPSP060 update
# 
# ChangeSet
#   2004/06/20 09:59:33-07:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: don't use "utf8" charset and NLS_DEFAULT
#   
#   Recently, some distributors have set "utf8" to NLS_DEFAULT, therefore,
#   FAT uses the "iocharset=utf8" as default.  But, since "iocharset=utf8"
#   doesn't provide the function (lower <-> upper conversion) which FAT
#   needs, so FAT can't provide suitable behavior.
#   
#   This patch does:
#   
#        - doesn't recognize "utf8" as "iocharset"
#        - doesn't use NLS_DEFAULT as default "iocharset"
#        - instead of NLS_DEFAULT, adds FAT_DEFAULT_CODEPAGE and
#          FAT_DEFAULT_IOCHARSET
#      
#   NOTE: the following looks like buggy, so it's not recommended
#   
#       "codepage=437,iocharset=iso8859-1,utf8"
#   
#   however, some utf8 file name can handle. (in this case, it uses the
#   table of iso8859-1 for lower <-> upper conversion)
#   
#   
#   Sign-off-by: Jesse Barnes <jbarnes@engr.sgi.com>
#   Sign-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Sign-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/fat/inode.c
#   2004/06/19 11:30:39-07:00 hirofumi@mail.parknet.co.jp +46 -42
#   FAT: don't use "utf8" charset and NLS_DEFAULT
# 
# fs/Kconfig
#   2004/06/19 11:30:39-07:00 hirofumi@mail.parknet.co.jp +19 -0
#   FAT: don't use "utf8" charset and NLS_DEFAULT
# 
# ChangeSet
#   2004/06/20 09:56:58-07:00 torvalds@ppc970.osdl.org 
#   Follow 2.4.x semantics for in-kernel signal sending.
# 
# kernel/signal.c
#   2004/06/20 09:56:52-07:00 torvalds@ppc970.osdl.org +7 -0
#   Follow 2.4.x semantics for in-kernel signal sending.
# 
# ChangeSet
#   2004/06/20 09:33:28-07:00 arjanv@redhat.com 
#   [PATCH] fix amd64 boot breakage
#   
#   This fixes a bug that prevent my amd64 box from booting;
#   numa_default_policy was __init however it's called like this in
#   init/main.c:
#   
#           free_initmem();
#           unlock_kernel();
#           system_state = SYSTEM_RUNNING;
#           numa_default_policy();
#   
#   
#   eg after free_initmem(). This resulted in it being reused/freed and that
#   gives a nasty oops.
# 
# mm/mempolicy.c
#   2004/06/20 02:29:33-07:00 arjanv@redhat.com +1 -1
#   fix amd64 boot breakage
# 
# ChangeSet
#   2004/06/20 07:00:13-05:00 stevef@steveft21.ltcsamba 
#   Do not kill cifsd thread until last smb session on tcp session is
#   SMBulogged off.  Fixes umounting bug (pointed out by Nick Millington)
#   when multiple mounts with different userids are mounted to the same
#   server from the client.  
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/connect.c
#   2004/06/20 06:59:52-05:00 stevef@steveft21.ltcsamba +18 -10
#   Do not kill cifsd thread until last smb session on tcp session is
#   SMBulogged off.
# 
# fs/cifs/cifssmb.c
#   2004/06/20 06:59:51-05:00 stevef@steveft21.ltcsamba +1 -0
#   return unique error, when last smb session on a tcp session is logged off.
# 
# fs/cifs/CHANGES
#   2004/06/20 06:59:51-05:00 stevef@steveft21.ltcsamba +3 -0
#   update cifs change log
# 
# fs/cifs/AUTHORS
#   2004/06/20 06:59:51-05:00 stevef@steveft21.ltcsamba +1 -1
#   update list of contributors of bug reports
# 
# ChangeSet
#   2004/06/20 03:03:06-03:00 acme@toy.kerneljanitors.org 
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/ip6_checksum.h
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +94 -0
# 
# net/ipv6/udp.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv6/tcp_ipv6.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv6/raw.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +2 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv6/ndisc.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv6/mcast.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv6/icmp.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_output.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +0 -64
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -48
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/netfilter/ipt_MASQUERADE.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/netfilter/ip_nat_standalone.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/netfilter/ip_fw_compat_redir.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/netfilter/ip_conntrack_standalone.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/netfilter/ip_conntrack_core.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/skbuff.c
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +76 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/tcp.h
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +24 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/ip6_checksum.h
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +0 -0
#   BitKeeper file /home/acme/bk/net-2.6/include/net/ip6_checksum.h
# 
# include/net/ip.h
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/checksum.h
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +1 -69
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/linux/skbuff.h
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +24 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/linux/errqueue.h
#   2004/06/20 03:02:54-03:00 acme@toy.kerneljanitors.org +4 -0
#   [NET] generalise tcp_add_data, skb_split and tcp_copy_to_page
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/19 21:20:36-07:00 akpm@osdl.org 
#   [NET]: Fix warning in farsync WAN driver.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/wan/farsync.c
#   2004/06/19 21:20:21-07:00 akpm@osdl.org +1 -1
#   [NET]: Fix warning in farsync WAN driver.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/19 16:47:14-07:00 yoshfuji@linux-ipv6.org 
#   [ECONET]: Fix some warnings.
# 
# net/econet/af_econet.c
#   2004/06/19 16:46:52-07:00 yoshfuji@linux-ipv6.org +10 -4
#   [ECONET]: Fix some warnings.
# 
# ChangeSet
#   2004/06/19 17:45:27-04:00 ralf@linux-mips.org 
#   [PATCH] hdlcdrv needs to stop queueing
#   
#   We better stop the queue in the close call.
#   
#   Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
# 
# drivers/net/hamradio/hdlcdrv.c
#   2004/05/10 10:13:02-04:00 ralf@linux-mips.org +2 -0
#   hdlcdrv needs to stop queueing
# 
# ChangeSet
#   2004/06/19 17:45:19-04:00 ralf@linux-mips.org 
#   [PATCH] Cosmetic cleanups to sb1250-mac.c
#   
#   Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
# 
# drivers/net/sb1250-mac.c
#   2004/06/09 08:33:56-04:00 ralf@linux-mips.org +2 -2
#   Cosmetic cleanups to sb1250-mac.c
# 
# ChangeSet
#   2004/06/19 17:45:10-04:00 ralf@linux-mips.org 
#   [PATCH] Reformat
#   
#   Pure microcosmetic.
#   
#   Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
# 
# drivers/net/tc35815.c
#   2004/04/21 20:35:51-04:00 ralf@linux-mips.org +1 -1
#   Reformat
# 
# ChangeSet
#   2004/06/19 17:45:01-04:00 ralf@linux-mips.org 
#   [PATCH] Use netdev_priv in sgiseeq
#   
#   The combined allocation of of receive and transmit rings and driver data
#   so far made the use of netdev_priv impossible.  Split the allocation
#   and use netdev_priv to access the non-ring driver_private data.
#   
#   Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
# 
# drivers/net/sgiseeq.c
#   2004/05/10 10:13:02-04:00 ralf@linux-mips.org +75 -70
#   Use netdev_priv in sgiseeq
# 
# ChangeSet
#   2004/06/19 17:41:19-04:00 arjanv@redhat.com 
#   [PATCH] sk98lin pci id
# 
# drivers/net/sk98lin/h/skdrv2nd.h
#   2004/06/18 20:00:00-04:00 arjanv@redhat.com +2 -1
#   sk98lin pci id
# 
# ChangeSet
#   2004/06/19 17:36:14-04:00 ryan@michonline.com 
#   [PATCH] orinoco.c rate limit lost information frame message
#   
#   Rate limit a (apparently) harmless warning in orinoco.c
#   
#   (My laptop remained connected with active X applications running over
#   ssh while this message was hitting every second, since I patched my
#   driver to include this the problem hasn't recurred.)
#   
#   Signed-Off-By: Ryan Anderson <ryan@michonline.com>
# 
# drivers/net/wireless/orinoco.c
#   2004/06/13 17:20:20-04:00 ryan@michonline.com +2 -1
#   orinoco.c rate limit lost information frame message
# 
# ChangeSet
#   2004/06/19 17:12:57-04:00 brazilnut@us.ibm.com 
#   [PATCH] pcnet32: cleanup IRQ limitation.
#   
#   Cleanup pcnet32 IRQ handling based on suggestions from Ralf Baechle
#   <ralf@linux-mips.org>, and Brian Murphy <brian@murphy.dk>
#   
#   Tested by myself and Brian Murphy.
#   
#   Please also apply to 2.4.27-pre6.
#   
#   Signed-off-by: Don Fry <brazilnut@us.ibm.com>
# 
# drivers/net/pcnet32.c
#   2004/06/17 09:14:53-04:00 brazilnut@us.ibm.com +12 -14
#   pcnet32: cleanup IRQ limitation.
# 
# ChangeSet
#   2004/06/19 17:12:48-04:00 brazilnut@us.ibm.com 
#   [PATCH] pcnet32: recover after rx hang.
#   
#   This patch fixes a receive hang that occasionally occurs after a Tx
#   FIFO underrun.  The receive dma remains in a hung state sometimes.  The
#   transmit operations continue to occur, but no receive activity.
#   
#   This was reproduced on several ppc64 systems and the fix has been verified
#   there.  The patch has been tested as well on an ia32 system, which did
#   not experience the hang because it did not have fifo underruns, which is
#   a preqrequisite for the hang.  The memory barriers decreased the frequency
#   of occurrence.  The final change to reset the chip instead of just stopping
#   it eliminated the last hangs.
#   
#   Please also apply against 2.4.7 (with offset of -1), tested ia32.
#   
#   Signed-off by: brazilnut@us.ibm.com
# 
# drivers/net/pcnet32.c
#   2004/06/15 06:00:17-04:00 brazilnut@us.ibm.com +30 -10
#   pcnet32: recover after rx hang.
# 
# ChangeSet
#   2004/06/19 17:12:39-04:00 brazilnut@us.ibm.com 
#   [PATCH] pcnet32: discard oversize rx packets
#   
#   This patch will discard received frames that are larger than one buffer.
#   This has been tested on ia32 and ppc64 systems.
#   
#   Please also apply to 2.4.7 (with offset of -3), tested ia32.
#   
#   Signed-off by: brazilnut@us.ibm.com
# 
# drivers/net/pcnet32.c
#   2004/06/15 05:36:43-04:00 brazilnut@us.ibm.com +10 -3
#   pcnet32: discard oversize rx packets
# 
# ChangeSet
#   2004/06/19 17:09:31-04:00 davem@redhat.com 
#   [PATCH] hamachi DMA
#   
#   Let's get this thing not using bus_to_virt() anymore,
#   as follows.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
#   
#   ===== drivers/net/hamachi.c 1.35 vs edited =====
# 
# drivers/net/hamachi.c
#   2004/06/16 14:15:20-04:00 davem@redhat.com +1 -3
#   hamachi DMA
# 
# ChangeSet
#   2004/06/19 17:08:21-04:00 fenlason@redhat.com 
#   [PATCH] sunhme patch
#   
#   Without this patch, insmod-ing the sunhme module crashes on my fc2
#   box.
#   
#   		-- JF
# 
# drivers/net/sunhme.c
#   2004/06/16 20:29:23-04:00 fenlason@redhat.com +2 -1
#   hme patch
# 
# ChangeSet
#   2004/06/19 17:07:34-04:00 jeb.j.cramer@intel.com 
#   [PATCH] e1000 management reset fix
#   
#   * Resetting the adapter blew away management settings.  So we save the
#   important bits before performing a reset.
# 
# drivers/net/e1000/e1000_main.c
#   2004/06/18 20:00:00-04:00 jeb.j.cramer@intel.com +9 -1
#   e1000 management reset fix
# 
# drivers/net/e1000/e1000_hw.h
#   2004/06/18 20:00:00-04:00 jeb.j.cramer@intel.com +2 -0
#   e1000 management reset fix
# 
# drivers/net/e1000/e1000_hw.c
#   2004/06/18 20:00:00-04:00 jeb.j.cramer@intel.com +35 -0
#   e1000 management reset fix
# 
# drivers/net/e1000/e1000.h
#   2004/06/18 20:00:00-04:00 jeb.j.cramer@intel.com +1 -0
#   e1000 management reset fix
# 
# ChangeSet
#   2004/06/19 17:07:25-04:00 shemminger@osdl.org 
#   [PATCH] convert sk fddi driver to ANSI C
#   
#   Sparse does not handle K&R at all, and I think I saw Linus saying that
#   he has no intention of adding it to sparse while ago. So here is a blob
#   of patch to convert drivers/net/skfp/* from K&R to ANSI-C. Compile
#   tested with "make allmodconfig" on x86, as I obviously don't have the
#   HW.
#   
#   Mika
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/skfp/srf.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +11 -23
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/smttimer.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +9 -26
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/smtparse.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +9 -17
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/smtinit.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +5 -6
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/smtdef.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +10 -21
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/smt.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +142 -265
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/skfddi.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +2 -15
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/rmt.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +25 -45
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/queue.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +6 -18
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/pmf.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +24 -54
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/pcmplc.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +47 -117
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/lnkstat.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +5 -10
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/hwt.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +9 -18
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/hwmtm.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +99 -122
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/h/smtstate.h
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +6 -0
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/h/cmtdef.h
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +144 -178
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/fplustm.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +61 -129
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/ess.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +21 -41
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/ecm.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +11 -22
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/drvfbi.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +49 -132
#   convert sk fddi driver to ANSI C
# 
# drivers/net/skfp/cfm.c
#   2004/06/17 17:49:49-04:00 shemminger@osdl.org +10 -25
#   convert sk fddi driver to ANSI C
# 
# ChangeSet
#   2004/06/19 17:06:09-04:00 akpm@osdl.org 
#   [PATCH] H8/300: smc9194 driver
#   
#   From: Yoshinori Sato <ysato@users.sourceforge.jp>
#   
#   - H8/300 target support
#   - fixed irq support
#   - high address (>0xffff) i/o fix
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/smc9194.c
#   2004/06/18 01:19:59-04:00 akpm@osdl.org +65 -9
#   H8/300: smc9194 driver
# 
# ChangeSet
#   2004/06/19 17:04:50-04:00 herbert@gondor.apana.org.au 
#   [PATCH] Re: linux-2.6.7 Equalizer Load-balancer.  eql.c. local non-privileged DoS
#   
#   Vitaly V. Bursov <vitalyvb@ukr.net> wrote:
#   >
#   > there are multiple vulns in drivers/net/eql.c
#   >
#   > if there is no such device, dev_get_by_name returns NULL and everything dies.
#   > Exploiting this is trivial.
#   
#   Thanks for the report.  This patch should fix them.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   
#   Cheers,
#   --
#   Visit Openswan at http://www.openswan.org/
#   Email:  Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
#   Home Page: http://gondor.apana.org.au/~herbert/
#   PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
#   --
#   ===== drivers/net/eql.c 1.13 vs edited =====
# 
# drivers/net/eql.c
#   2004/06/18 07:30:49-04:00 herbert@gondor.apana.org.au +4 -0
#   Re: linux-2.6.7 Equalizer Load-balancer.  eql.c. local non-privileged DoS
# 
# ChangeSet
#   2004/06/19 17:00:28-04:00 achirica@telefonica.net 
#   [wireless airo] Clean initialization of Mini-PCI cards even from suspend
# 
# drivers/net/wireless/airo.c
#   2004/06/18 16:56:26-04:00 achirica@telefonica.net +28 -12
#   Clean initialization of Mini-PCI cards even from suspend
# 
# ChangeSet
#   2004/06/19 12:48:23-07:00 davem@nuts.davemloft.net 
#   [IPV6]: Export necessary xfrm6_tunnel functions.
# 
# net/ipv6/xfrm6_tunnel.c
#   2004/06/19 12:48:05-07:00 davem@nuts.davemloft.net +11 -0
#   [IPV6]: Export necessary xfrm6_tunnel functions.
# 
# ChangeSet
#   2004/06/19 11:55:24-07:00 yoshfuji@linux-ipv6.org 
#   [NET]: Fix some userland header bustage.
# 
# include/linux/netfilter_ipv6/ip6_tables.h
#   2004/06/19 11:55:10-07:00 yoshfuji@linux-ipv6.org +3 -0
#   [NET]: Fix some userland header bustage.
# 
# include/linux/netfilter_ipv4/ip_tables.h
#   2004/06/19 11:55:10-07:00 yoshfuji@linux-ipv6.org +2 -1
#   [NET]: Fix some userland header bustage.
# 
# include/linux/netfilter_arp/arp_tables.h
#   2004/06/19 11:55:10-07:00 yoshfuji@linux-ipv6.org +1 -1
#   [NET]: Fix some userland header bustage.
# 
# include/linux/netfilter.h
#   2004/06/19 11:55:10-07:00 yoshfuji@linux-ipv6.org +1 -0
#   [NET]: Fix some userland header bustage.
# 
# ChangeSet
#   2004/06/19 11:36:58-07:00 akpm@osdl.org 
#   [NET]: Fix econet build bustage.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/econet/af_econet.c
#   2004/06/19 11:36:43-07:00 akpm@osdl.org +2 -2
#   [NET]: Fix econet build bustage.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/19 07:50:55-07:00 mikulas@artax.karlin.mff.cuni.cz 
#   [PATCH] HPFS fixes for 2.6.7 kernel
#   
#   This contains hpfs fixes from my source ported to 2.6.7 kernel:
#   
#   updates:
#   - allocator fragments files less
#   - OS/2 Warp Server filesystem can be mounted read/only
#   - added reschedule points so that it doesn't hog CPU
#   
#   bug fixes:
#   - filesystem error message when syncing or fsyncing deleted file (or when
#     system just writes it on its own)
#   - filesystem error on extremly fragmented files
#   - corrupted disk structures could possibly corrupt memory
# 
# fs/hpfs/super.c
#   2004/06/18 18:13:55-07:00 mikulas@artax.karlin.mff.cuni.cz +1 -0
#   HPFS fixes for 2.6.7 kernel
# 
# fs/hpfs/map.c
#   2004/06/18 18:09:05-07:00 mikulas@artax.karlin.mff.cuni.cz +4 -2
#   HPFS fixes for 2.6.7 kernel
# 
# fs/hpfs/inode.c
#   2004/06/18 18:13:20-07:00 mikulas@artax.karlin.mff.cuni.cz +9 -7
#   HPFS fixes for 2.6.7 kernel
# 
# fs/hpfs/hpfs_fn.h
#   2004/06/18 18:01:00-07:00 mikulas@artax.karlin.mff.cuni.cz +3 -2
#   HPFS fixes for 2.6.7 kernel
# 
# fs/hpfs/hpfs.h
#   2004/06/18 17:58:08-07:00 mikulas@artax.karlin.mff.cuni.cz +1 -1
#   HPFS fixes for 2.6.7 kernel
# 
# fs/hpfs/ea.c
#   2004/06/18 17:57:50-07:00 mikulas@artax.karlin.mff.cuni.cz +3 -5
#   HPFS fixes for 2.6.7 kernel
# 
# fs/hpfs/buffer.c
#   2004/06/18 17:55:53-07:00 mikulas@artax.karlin.mff.cuni.cz +8 -0
#   HPFS fixes for 2.6.7 kernel
# 
# fs/hpfs/anode.c
#   2004/06/18 17:49:38-07:00 mikulas@artax.karlin.mff.cuni.cz +1 -2
#   HPFS fixes for 2.6.7 kernel
# 
# fs/hpfs/alloc.c
#   2004/06/18 18:44:32-07:00 mikulas@artax.karlin.mff.cuni.cz +44 -26
#   HPFS fixes for 2.6.7 kernel
# 
# Documentation/filesystems/hpfs.txt
#   2004/06/18 18:17:43-07:00 mikulas@artax.karlin.mff.cuni.cz +10 -2
#   HPFS fixes for 2.6.7 kernel
# 
# ChangeSet
#   2004/06/19 07:50:44-07:00 akpm@osdl.org 
#   [PATCH] mptctl.c build fix
#   
#   drivers/message/fusion/mptctl.c:89:24: asm/compat.h: No such file or directory
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/message/fusion/mptctl.c
#   2004/06/19 00:22:47-07:00 akpm@osdl.org +1 -1
#   mptctl.c build fix
# 
# ChangeSet
#   2004/06/19 07:49:02-07:00 torvalds@ppc970.osdl.org 
#   Merge http://lia64.bkbits.net/to-linus-2.5
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# include/asm-ia64/pgtable.h
#   2004/06/19 07:48:59-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# arch/ia64/kernel/iosapic.c
#   2004/06/19 07:48:59-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# arch/ia64/ia32/ia32_entry.S
#   2004/06/19 07:48:59-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/18 21:52:08-07:00 yanmin.zhang@intel.com 
#   [PATCH] ia64: fix free_huge_page() call in hugetlb_prefault()
#   
#   In base kernel 2.6.7, there is bug in function hugetlb_prefault().  The
#   call to free_huge_page() is incorrect and should be replaced with a call
#   to page_cache_release().
#   
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# arch/ia64/mm/hugetlbpage.c
#   2004/06/18 00:26:02-07:00 yanmin.zhang@intel.com +1 -1
#   ia64: fix free_huge_page() call in hugetlb_prefault()
# 
# ChangeSet
#   2004/06/18 21:49:12-07:00 eranian@hpl.hp.com 
#   [PATCH] ia64: perfmon stack consumption fix
#   
#   This patch moves the pfm_ovfl_arg_t structure from the kernel stack
#   into the pfm_context_t structure. This minimizes kernel stack space
#   consumption.
#   
#   Signed-off-by: Stephane Eranian <eranian@hpl.hp.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# arch/ia64/kernel/perfmon.c
#   2004/06/18 09:17:04-07:00 eranian@hpl.hp.com +20 -18
#   ia64: perfmon stack consumption fix
# 
# ChangeSet
#   2004/06/18 21:45:35-07:00 ashok.raj@intel.com 
#   [PATCH] ia64: move move_irq() from iosapic.c to irq.c
#   
#   This patch moves move_irq() from ioaspic.c to irq.c to make this common
#   for ia64 subarches.
#   
#   Signed-off-by: Ashok Raj <ashok.raj@intel.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# include/asm-ia64/irq.h
#   2004/06/18 15:22:57-07:00 ashok.raj@intel.com +6 -0
#   ia64: move move_irq() from iosapic.c to irq.c
# 
# arch/ia64/kernel/irq.c
#   2004/06/18 15:22:57-07:00 ashok.raj@intel.com +16 -0
#   ia64: move move_irq() from iosapic.c to irq.c
# 
# arch/ia64/kernel/iosapic.c
#   2004/06/18 15:22:57-07:00 ashok.raj@intel.com +0 -16
#   ia64: move move_irq() from iosapic.c to irq.c
# 
# ChangeSet
#   2004/06/18 21:42:42-07:00 arun.sharma@intel.com 
#   [PATCH] ia64: fix ia32 partial-page map support for overlapping mmaps
#   
#   - Handle the overlapping mmaps in the MAP_FIXED case
#   - Handle unmaps correctly i.e. call __ia32_delete_pp_range()
#   - There are now three clear entry points into the pp manipulation code
#           - ia32_set_pp
#           - ia32_unset_pp
#           - ia32_compare_pp
#   - Rename internal functions to __ia32_*pp_*
#   - Grab mmap_sem just once at the main entry point
#   
#   Signed-off-by: Gordon Jin <gordon.jin@intel.com>
#   Signed-off-by: Arun Sharma <arun.sharma@intel.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# arch/ia64/ia32/sys_ia32.c
#   2004/06/18 04:55:20-07:00 arun.sharma@intel.com +184 -134
#   ia64: fix ia32 partial-page map support for overlapping mmaps
# 
# ChangeSet
#   2004/06/18 23:02:41-05:00 stevef@smfhome1.smfdom 
#   check better for free files on writepage retry
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/file.c
#   2004/06/18 23:02:34-05:00 stevef@smfhome1.smfdom +21 -7
#   check better for free files on writepage retry
# 
# ChangeSet
#   2004/06/18 22:01:37-05:00 stevef@smfhome1.smfdom 
#   Do not send junk in bcc area of oplock break SMB Lock request, and always let oplock break release
#   through even if requests are ahead of it waiting for responses to complete.
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/transport.c
#   2004/06/18 22:01:30-05:00 stevef@smfhome1.smfdom +20 -15
#   do not count oplock breaks against in flight count
# 
# fs/cifs/connect.c
#   2004/06/18 22:01:30-05:00 stevef@smfhome1.smfdom +1 -1
#   do not reset inFlight count on reconnection so it does not go negative
# 
# fs/cifs/cifssmb.c
#   2004/06/18 22:01:30-05:00 stevef@smfhome1.smfdom +14 -8
#   Do not send junk in bcc area of oplock break SMB Lock request
# 
# fs/cifs/CHANGES
#   2004/06/18 22:01:30-05:00 stevef@smfhome1.smfdom +2 -1
#   update cifs vfs change log for 1.19
# 
# ChangeSet
#   2004/06/18 18:26:37-07:00 rddunlap@osdl.org 
#   [PATCH] sparse: lib/string.c sparse fix
#   
#   A classic..
#   
#     lib/string.c:165:19: warning: assignment expression in conditional
#   
#   From: Mika Kukkonen <mika@osdl.org>
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
# 
# lib/string.c
#   2004/06/09 12:58:48-07:00 rddunlap@osdl.org +1 -1
#   sparse: lib/string.c sparse fix
# 
# ChangeSet
#   2004/06/18 18:26:26-07:00 rddunlap@osdl.org 
#   [PATCH] sparse: kernel/module.c sparse fix
#   
#   Add __user annotation for !CONFIG_MODULE_UNLOAD case.
#   
#   From: Mika Kukkonen <mika@osdl.org>
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
# 
# kernel/module.c
#   2004/06/09 13:11:44-07:00 rddunlap@osdl.org +1 -1
#   sparse: kernel/module.c sparse fix
# 
# ChangeSet
#   2004/06/18 16:46:25-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: drivers/video/sis annotation
# 
# drivers/video/sis/sis_main.c
#   2004/06/18 09:43:52-07:00 viro@www.linux.org.uk +16 -15
#   sparse: drivers/video/sis annotation
# 
# ChangeSet
#   2004/06/18 16:37:47-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: drivers/video/aty annotation
# 
# drivers/video/aty/radeon_base.c
#   2004/06/18 09:36:48-07:00 viro@www.linux.org.uk +4 -4
#   sparse: drivers/video/aty annotation
# 
# ChangeSet
#   2004/06/18 16:35:56-07:00 torvalds@ppc970.osdl.org 
#   Merge ppc970.osdl.org:/home/torvalds/v2.6/v2.6.7
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# include/linux/ipmi.h
#   2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# include/linux/fb.h
#   2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# fs/binfmt_aout.c
#   2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/video/fbmem.c
#   2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/char/ipmi/ipmi_watchdog.c
#   2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/char/ipmi/ipmi_devintf.c
#   2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/18 16:35:04-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: autofs annotation
# 
# fs/autofs/root.c
#   2004/06/18 11:14:07-07:00 viro@www.linux.org.uk +7 -6
#   sparse: autofs annotation
# 
# ChangeSet
#   2004/06/18 16:34:54-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: synclinkmp annotation
# 
# drivers/char/synclinkmp.c
#   2004/06/18 11:19:11-07:00 viro@www.linux.org.uk +22 -21
#   sparse: synclinkmp annotation
# 
# ChangeSet
#   2004/06/18 16:34:45-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: cyclades annotation
# 
# drivers/char/cyclades.c
#   2004/06/18 11:16:10-07:00 viro@www.linux.org.uk +29 -30
#   sparse: cyclades annotation
# 
# ChangeSet
#   2004/06/18 16:34:35-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: ipmi annotation
# 
# include/linux/ipmi.h
#   2004/06/18 11:18:12-07:00 viro@www.linux.org.uk +2 -2
#   sparse: ipmi annotation
# 
# drivers/char/ipmi/ipmi_watchdog.c
#   2004/06/18 11:18:46-07:00 viro@www.linux.org.uk +10 -13
#   sparse: ipmi annotation
# 
# drivers/char/ipmi/ipmi_devintf.c
#   2004/06/18 11:18:33-07:00 viro@www.linux.org.uk +14 -13
#   sparse: ipmi annotation
# 
# ChangeSet
#   2004/06/18 16:34:24-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: amd64 bits
#   
#    - added define of __x86_64__ to sparse arguments on amd64
#    - switched amd64 uaccess.h to __chk_user_ptr()
# 
# include/asm-x86_64/uaccess.h
#   2004/06/18 11:15:18-07:00 viro@www.linux.org.uk +34 -44
#   sparse: amd64 bits
# 
# arch/x86_64/Makefile
#   2004/06/18 11:15:02-07:00 viro@www.linux.org.uk +2 -0
#   sparse: amd64 bits
# 
# ChangeSet
#   2004/06/18 16:34:14-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: applicom annotation
# 
# drivers/char/applicom.c
#   2004/06/18 11:19:50-07:00 viro@www.linux.org.uk +10 -9
#   sparse: applicom annotation
# 
# ChangeSet
#   2004/06/18 16:34:03-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: udf cleanups
#   
#   removed bogus externs from declarations in fs/udf/*
# 
# fs/udf/misc.c
#   2004/06/18 11:12:57-07:00 viro@www.linux.org.uk +6 -6
#   sparse: udf cleanups
# 
# fs/udf/crc.c
#   2004/06/18 11:12:52-07:00 viro@www.linux.org.uk +1 -1
#   sparse: udf cleanups
# 
# ChangeSet
#   2004/06/18 16:33:52-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: drivers/video/matrox annotation
# 
# drivers/video/matrox/matroxfb_crtc2.c
#   2004/06/18 11:08:45-07:00 viro@www.linux.org.uk +5 -5
#   sparse: drivers/video/matrox annotation
# 
# drivers/video/matrox/matroxfb_base.c
#   2004/06/18 11:08:34-07:00 viro@www.linux.org.uk +16 -15
#   sparse: drivers/video/matrox annotation
# 
# ChangeSet
#   2004/06/18 16:33:41-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: drivers/video/kyro annotation
# 
# drivers/video/kyro/fbdev.c
#   2004/06/18 11:07:54-07:00 viro@www.linux.org.uk +6 -6
#   sparse: drivers/video/kyro annotation
# 
# ChangeSet
#   2004/06/18 16:33:31-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: drivers/video partial annotation
#   
#   misc annotation in drivers/video/* (nowhere near complete)
# 
# include/linux/fb.h
#   2004/06/18 11:11:09-07:00 viro@www.linux.org.uk +2 -2
#   sparse: drivers/video partial annotation
# 
# drivers/video/sstfb.c
#   2004/06/18 11:10:17-07:00 viro@www.linux.org.uk +2 -2
#   sparse: drivers/video partial annotation
# 
# drivers/video/radeonfb.c
#   2004/06/18 11:10:06-07:00 viro@www.linux.org.uk +2 -2
#   sparse: drivers/video partial annotation
# 
# drivers/video/imsttfb.c
#   2004/06/18 11:10:31-07:00 viro@www.linux.org.uk +10 -9
#   sparse: drivers/video partial annotation
# 
# drivers/video/fbmem.c
#   2004/06/18 11:10:53-07:00 viro@www.linux.org.uk +2 -2
#   sparse: drivers/video partial annotation
# 
# ChangeSet
#   2004/06/18 16:33:20-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: nfs partial annotation
# 
# include/linux/nfs4_mount.h
#   2004/06/18 11:11:45-07:00 viro@www.linux.org.uk +3 -3
#   sparse: nfs partial annotation
# 
# fs/nfs/idmap.c
#   2004/06/18 11:12:29-07:00 viro@www.linux.org.uk +6 -5
#   sparse: nfs partial annotation
# 
# fs/nfs/direct.c
#   2004/06/18 11:12:14-07:00 viro@www.linux.org.uk +1 -1
#   sparse: nfs partial annotation
# 
# ChangeSet
#   2004/06/18 16:33:09-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: mwave annotation
# 
# drivers/char/mwave/tp3780i.h
#   2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +2 -2
#   sparse: mwave annotation
# 
# drivers/char/mwave/tp3780i.c
#   2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +2 -2
#   sparse: mwave annotation
# 
# drivers/char/mwave/mwavedd.c
#   2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +17 -20
#   sparse: mwave annotation
# 
# drivers/char/mwave/3780i.h
#   2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +5 -5
#   sparse: mwave annotation
# 
# drivers/char/mwave/3780i.c
#   2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +10 -10
#   sparse: mwave annotation
# 
# ChangeSet
#   2004/06/18 16:32:59-07:00 viro@www.linux.org.uk 
#   [PATCH] sparse: binfmt_aout annotation
# 
# fs/binfmt_aout.c
#   2004/06/18 11:13:43-07:00 viro@www.linux.org.uk +13 -12
#   sparse: binfmt_aout annotation
# 
# ChangeSet
#   2004/06/18 14:14:17-07:00 akpm@osdl.org 
#   [NET]: Fix eql.c failed dev_get_by_name() return value check.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/eql.c
#   2004/06/18 14:14:03-07:00 akpm@osdl.org +5 -1
#   [NET]: Fix eql.c failed dev_get_by_name() return value check.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/18 14:12:29-07:00 yoshfuji@linux-ipv6.org 
#   [IPV6]: Fix autoconf description in ip-sysctl.txt.
# 
# Documentation/networking/ip-sysctl.txt
#   2004/06/18 14:12:15-07:00 yoshfuji@linux-ipv6.org +4 -2
#   [IPV6]: Fix autoconf description in ip-sysctl.txt.
# 
# ChangeSet
#   2004/06/18 14:11:36-07:00 wli@holomorphy.com 
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/irda/irda_device.c
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +2 -2
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/net/irda/irda_device.h
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -1
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/w83977af_ir.h
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -0
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/w83977af_ir.c
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +19 -12
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/via-ircc.h
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -0
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/via-ircc.c
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +18 -10
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/smsc-ircc2.c
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +20 -11
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/nsc-ircc.h
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -0
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/nsc-ircc.c
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +19 -11
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/ali-ircc.h
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -0
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/ali-ircc.c
#   2004/06/18 14:11:22-07:00 wli@holomorphy.com +19 -11
#   [IRDA]: Remove usage of isa_virt_to_bus()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/18 14:09:17-07:00 dlstevens@us.ibm.com 
#   [IPV6]: Handle user asking for any device in mcast calls.
# 
# net/ipv6/mcast.c
#   2004/06/18 14:09:03-07:00 dlstevens@us.ibm.com +1 -1
#   [IPV6]: Handle user asking for any device in mcast calls.
# 
# ChangeSet
#   2004/06/18 13:54:52-07:00 shemminger@osdl.org 
#   [PKT_SCHED]: Add loss option to network delay scheduler.
#   
#   This enhances the network simulation scheduler to do simple random loss.
#   
#   The loss parameter is a simple 32 bit value such that 0 means no loss, and
#   0xffffffff is always drop.  I have a new version of the tc command which takes
#   care of conversion from percent to this value.
#   
#   Same patch for 2.4 and 2.6
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_delay.c
#   2004/06/18 13:54:39-07:00 shemminger@osdl.org +9 -0
#   [PKT_SCHED]: Add loss option to network delay scheduler.
#   
#   This enhances the network simulation scheduler to do simple random loss.
#   
#   The loss parameter is a simple 32 bit value such that 0 means no loss, and
#   0xffffffff is always drop.  I have a new version of the tc command which takes
#   care of conversion from percent to this value.
#   
#   Same patch for 2.4 and 2.6
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/pkt_sched.h
#   2004/06/18 13:54:39-07:00 shemminger@osdl.org +2 -1
#   [PKT_SCHED]: Add loss option to network delay scheduler.
#   
#   This enhances the network simulation scheduler to do simple random loss.
#   
#   The loss parameter is a simple 32 bit value such that 0 means no loss, and
#   0xffffffff is always drop.  I have a new version of the tc command which takes
#   care of conversion from percent to this value.
#   
#   Same patch for 2.4 and 2.6
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/18 13:51:42-07:00 davem@nuts.davemloft.net 
#   [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver.
#   
#   Based upon a patch from Stephen Hemminger.
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_tbf.c
#   2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +5 -7
#   [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver.
#   
#   Based upon a patch from Stephen Hemminger.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_htb.c
#   2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +0 -1
#   [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver.
#   
#   Based upon a patch from Stephen Hemminger.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_hfsc.c
#   2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +1 -2
#   [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver.
#   
#   Based upon a patch from Stephen Hemminger.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_delay.c
#   2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +5 -7
#   [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver.
#   
#   Based upon a patch from Stephen Hemminger.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_cbq.c
#   2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +1 -1
#   [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver.
#   
#   Based upon a patch from Stephen Hemminger.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/18 13:50:35-07:00 torvalds@ppc970.osdl.org 
#   sparse: fix up fusion/mptctl.c after merge
# 
# drivers/message/fusion/mptctl.c
#   2004/06/18 13:50:29-07:00 torvalds@ppc970.osdl.org +8 -7
#   sparse: fix up fusion/mptctl.c after merge
# 
# ChangeSet
#   2004/06/18 13:46:11-07:00 torvalds@ppc970.osdl.org 
#   Merge
# 
# drivers/message/fusion/mptctl.c
#   2004/06/18 13:46:06-07:00 torvalds@ppc970.osdl.org +0 -2
#   Merge
# 
# drivers/scsi/scsi_syms.c
#   2004/06/18 13:44:28-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/scsi/scsi_ioctl.c
#   2004/06/18 13:44:28-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/scsi/fdomain.c
#   2004/06/18 13:44:28-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/scsi/fd_mcs.c
#   2004/06/18 13:44:28-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/18 13:43:51-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sparse: drivers/message/fusion annotations and fixes
#   
#   Sigh...  First of all, LSI folks have very quaint idea of existing
#   platforms and word sizes on those.  Their definitions of U32 and S32
#   should really be reserved for posterity (preferably chiseled into the
#   rock they have between the ears), but kernel is the wrong place for
#   that.  Fixed.
#   
#   mptctl_do_mpt_command() was always called on userland pointers;
#   kernel/userland argument removed along with dead code, function
#   annotated, callers updated.
#   
#   The rest is trivial annotations in mptctl.c and in its ioctl structures
#   - nothing fancy there.
# 
# drivers/message/fusion/mptctl.h
#   2004/06/18 08:09:14-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -5
#   sparse: drivers/message/fusion annotations and fixes
# 
# drivers/message/fusion/mptctl.c
#   2004/06/18 08:09:16-07:00 viro@parcelfarce.linux.theplanet.co.uk +68 -77
#   sparse: drivers/message/fusion annotations and fixes
# 
# drivers/message/fusion/lsi/mpi_type.h
#   2004/06/18 08:09:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +6 -11
#   sparse: drivers/message/fusion annotations and fixes
# 
# ChangeSet
#   2004/06/18 13:43:40-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] crapectomy - last users of kernel_scsi_ioctl() gone
#   
#   Last 3 users of kernel_scsi_ioctl() eliminated; two of them used to read
#   partition table by issuing a READ6 via ioctl (instead of just calling
#   scsi_bios_ptable() as every other ->biosparam() instance does).
#   
#   The last one was doing a very quaint access to fields of scsi_device by
#   issuing SCSI_IOCLT_GET_LUN and then shuffling bits in the result.  Down
#   with that insanity...
# 
# ChangeSet
#   2004/06/18 13:40:49-07:00 shemminger@osdl.org 
#   [PKT_SCHED]: Delay scheduler should retry if requeue fails.
#   
#   If delay scheduler decides not to send the packet right away, it requeues
#   it.  If the requeue fails, it should go and look again rather than waking
#   up prematurely.
#   
#   Same patch should apply to both 2.6 and 2.4
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_delay.c
#   2004/06/18 13:40:35-07:00 shemminger@osdl.org +9 -5
#   [PKT_SCHED]: Delay scheduler should retry if requeue fails.
#   
#   If delay scheduler decides not to send the packet right away, it requeues
#   it.  If the requeue fails, it should go and look again rather than waking
#   up prematurely.
#   
#   Same patch should apply to both 2.6 and 2.4
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/scsi/scsi_ioctl.h
#   2004/06/18 07:38:19-07:00 viro@parcelfarce.linux.theplanet.co.uk +0 -1
#   crapectomy - last users of kernel_scsi_ioctl() gone
# 
# drivers/scsi/scsi_syms.c
#   2004/06/18 07:36:48-07:00 viro@parcelfarce.linux.theplanet.co.uk +0 -1
#   crapectomy - last users of kernel_scsi_ioctl() gone
# 
# drivers/scsi/scsi_ioctl.c
#   2004/06/18 07:36:38-07:00 viro@parcelfarce.linux.theplanet.co.uk +0 -16
#   crapectomy - last users of kernel_scsi_ioctl() gone
# 
# drivers/scsi/pcmcia/nsp_cs.c
#   2004/06/18 07:37:49-07:00 viro@parcelfarce.linux.theplanet.co.uk +4 -4
#   crapectomy - last users of kernel_scsi_ioctl() gone
# 
# drivers/scsi/fdomain.c
#   2004/06/18 07:37:05-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -16
#   crapectomy - last users of kernel_scsi_ioctl() gone
# 
# drivers/scsi/fd_mcs.c
#   2004/06/18 07:37:16-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -14
#   crapectomy - last users of kernel_scsi_ioctl() gone
# 
# ChangeSet
#   2004/06/18 13:37:04-07:00 rmk+lkml@arm.linux.org.uk 
#   [PATCH] Couple of sysfs patches
#   
#   On Wed, Jun 16, 2004 at 05:51:03PM -0500, Dmitry Torokhov wrote:
#   > What about freeing the resources? Can it be put in platform_device_unregister
#   > or is it release handler task? I'd put it in unregister because when I call
#   > unregister I expect device be half-dead and release as much resources as it
#   > can.
#   
#   
#   Here's the updated patch - to be applied on top of the
#   platform_get_resource() patch sent previously.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/18 13:36:39-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sparse: ibmasmfs annotations
#   
#   Trivial annotations + couple of missing (void) in prototypes
# 
# include/linux/device.h
#   2004/06/10 12:15:03-07:00 rmk+lkml@arm.linux.org.uk +0 -1
#   Couple of sysfs patches
# 
# drivers/base/platform.c
#   2004/06/18 13:24:02-07:00 rmk+lkml@arm.linux.org.uk +52 -39
#   Couple of sysfs patches
# 
# drivers/misc/ibmasm/ibmasmfs.c
#   2004/06/18 08:05:56-07:00 viro@parcelfarce.linux.theplanet.co.uk +14 -14
#   sparse: ibmasmfs annotations
# 
# ChangeSet
#   2004/06/18 13:36:27-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sparse: ide-tape annotation
# 
# drivers/ide/ide-tape.c
#   2004/06/18 08:04:58-07:00 viro@parcelfarce.linux.theplanet.co.uk +11 -9
#   sparse: ide-tape annotation
# 
# ChangeSet
#   2004/06/18 13:36:16-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sparse: drivers/input annotations
#   
#   Trivial annotations in drivers/input
# 
# drivers/input/tsdev.c
#   2004/06/18 08:04:18-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1
#   sparse: drivers/input annotations
# 
# drivers/input/misc/uinput.c
#   2004/06/18 08:04:24-07:00 viro@parcelfarce.linux.theplanet.co.uk +3 -3
#   sparse: drivers/input annotations
# 
# drivers/input/joydev.c
#   2004/06/18 08:04:15-07:00 viro@parcelfarce.linux.theplanet.co.uk +21 -20
#   sparse: drivers/input annotations
# 
# ChangeSet
#   2004/06/18 13:36:05-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sparse: drivers/char/watchdog annotation
#   
#   Trivial annotations in drivers/char/watchdog/*
# 
# drivers/char/watchdog/wdt_pci.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -7
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -7
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/wafer5823wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -7
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/w83877f_wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/w83627hf_wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/softdog.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -5
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/scx200_wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -6
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/sc520_wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/sc1200wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -7
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/sbc60xxwdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/pcwd_usb.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +11 -9
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/pcwd_pci.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +11 -9
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/mixcomwd.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -4
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/machzwd.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -4
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/ib700wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -5
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/i8xx_tco.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/eurotechwdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -8
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/cpu5wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -4
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/alim7101_wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/alim1535_wdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/advantechwdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6
#   sparse: drivers/char/watchdog annotation
# 
# drivers/char/watchdog/acquirewdt.c
#   2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -5
#   sparse: drivers/char/watchdog annotation
# 
# ChangeSet
#   2004/06/18 13:35:54-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sparse: ixj annotated
#   
#   drivers/telephony (aka ixj.c) annotated, IXJ_CADENCE split into kernel
#   and userland variants, ioctl structures got __user on pointers.
# 
# include/linux/ixjuser.h
#   2004/06/18 07:40:16-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1
#   sparse: ixj annotated
# 
# drivers/telephony/ixj.h
#   2004/06/18 07:39:46-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -2
#   sparse: ixj annotated
# 
# drivers/telephony/ixj.c
#   2004/06/18 07:39:48-07:00 viro@parcelfarce.linux.theplanet.co.uk +61 -45
#   sparse: ixj annotated
# 
# ChangeSet
#   2004/06/18 13:35:42-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sparse: vm86.c annotated
#   
#   vm86.c annotated; vm86old(2) and vm86(2) switched to explicit
#   
#   	int <fn>(struct pt_regs regs)
#   
#   format.
# 
# arch/i386/kernel/vm86.c
#   2004/06/18 07:35:47-07:00 viro@parcelfarce.linux.theplanet.co.uk +19 -13
#   sparse: vm86.c annotated
# 
# ChangeSet
#   2004/06/18 13:35:31-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sparse: rt_sigsuspend/sigaltstack sanitized
#   
#   rt_sigsuspend() and sigaltstack() prototype changed; instead of
#   playing games with casts of argument address to struct pt_regs * and
#   digging through it, we declare them as
#   
#   	int <fn>(struct pt_regs regs)
#   
#   instead.
# 
# arch/i386/kernel/signal.c
#   2004/06/18 07:35:29-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -9
#   sparse: rt_sigsuspend/sigaltstack sanitized
# 
# ChangeSet
#   2004/06/18 13:35:20-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sparse: i387 math-emu annotation
#   
#   arch/i386/math-emu/* annotated.
# 
# arch/i386/math-emu/reg_ld_str.c
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +75 -75
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/reg_compare.c
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +6 -6
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/load_store.c
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +26 -26
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/get_address.c
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +15 -15
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/fpu_system.h
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/fpu_proto.h
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +21 -21
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/fpu_etc.c
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/fpu_entry.c
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +17 -16
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/fpu_aux.c
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +10 -10
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/fpu_arith.c
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +18 -18
#   sparse: i387 math-emu annotation
# 
# arch/i386/math-emu/errors.c
#   2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -5
#   sparse: i387 math-emu annotation
# 
# ChangeSet
#   2004/06/18 13:18:34-07:00 shemminger@osdl.org 
#   [PKT_SCHED]: Delay scheduler enqueue always succeeds.
#   
#   If underlying fifo enqueue fails, return the status not 0.
#   Same patch should apply to both 2.6 and 2.4
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_delay.c
#   2004/06/18 13:18:20-07:00 shemminger@osdl.org +1 -1
#   [PKT_SCHED]: Delay scheduler enqueue always succeeds.
#   
#   If underlying fifo enqueue fails, return the status not 0.
#   Same patch should apply to both 2.6 and 2.4
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/18 13:15:58-07:00 shemminger@osdl.org 
#   [BRIDGE]: Kill sysfs hotplug avoidance hacks.
#   
#   The whole effort to avoid hotplug was misguided.  If it is really a problem
#   (which it doesn't appear to be) then it can more easily be addressed by smarter
#   hotplug scripts in user space.
#   
#   This patch gets rid of the whole subsystem hack for bridge kobjects.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/bridge/br_sysfs_if.c
#   2004/06/18 13:15:34-07:00 shemminger@osdl.org +1 -1
#   [BRIDGE]: Kill sysfs hotplug avoidance hacks.
#   
#   The whole effort to avoid hotplug was misguided.  If it is really a problem
#   (which it doesn't appear to be) then it can more easily be addressed by smarter
#   hotplug scripts in user space.
#   
#   This patch gets rid of the whole subsystem hack for bridge kobjects.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/bridge/br_sysfs_br.c
#   2004/06/18 13:15:34-07:00 shemminger@osdl.org +1 -18
#   [BRIDGE]: Kill sysfs hotplug avoidance hacks.
#   
#   The whole effort to avoid hotplug was misguided.  If it is really a problem
#   (which it doesn't appear to be) then it can more easily be addressed by smarter
#   hotplug scripts in user space.
#   
#   This patch gets rid of the whole subsystem hack for bridge kobjects.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/bridge/br_private.h
#   2004/06/18 13:15:34-07:00 shemminger@osdl.org +0 -5
#   [BRIDGE]: Kill sysfs hotplug avoidance hacks.
#   
#   The whole effort to avoid hotplug was misguided.  If it is really a problem
#   (which it doesn't appear to be) then it can more easily be addressed by smarter
#   hotplug scripts in user space.
#   
#   This patch gets rid of the whole subsystem hack for bridge kobjects.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/bridge/br.c
#   2004/06/18 13:15:34-07:00 shemminger@osdl.org +0 -3
#   [BRIDGE]: Kill sysfs hotplug avoidance hacks.
#   
#   The whole effort to avoid hotplug was misguided.  If it is really a problem
#   (which it doesn't appear to be) then it can more easily be addressed by smarter
#   hotplug scripts in user space.
#   
#   This patch gets rid of the whole subsystem hack for bridge kobjects.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/18 19:53:46+01:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Remove NexusPCI/FTVPCI platform.
#   
#   This platform is no longer maintained, and its maintainer says that
#   the hardware is obsolete and out of circulation.
# 
# arch/arm/common/Makefile
#   2004/06/18 19:51:33+01:00 rmk@flint.arm.linux.org.uk +0 -1
#   Remove FTVPCI PCI host driver.
# 
# arch/arm/Makefile
#   2004/06/18 19:51:33+01:00 rmk@flint.arm.linux.org.uk +0 -2
#   Remove FTVPCI.
# 
# arch/arm/Kconfig
#   2004/06/18 19:51:32+01:00 rmk@flint.arm.linux.org.uk +4 -9
#   Remove FTVPCI.
# 
# ChangeSet
#   2004/06/18 19:45:27+01:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Remove TBOX.
#   
#   This platform is no longer maintained, and its maintainer says that
#   the hardware is obsolete and out of circulation.
# 
# ChangeSet
#   2004/06/18 11:43:35-07:00 torvalds@ppc970.osdl.org 
#   Merge bk://kernel.bkbits.net/davem/net-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# security/selinux/ss/services.c
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/selinux/ss/policydb.c
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/selinux/include/security.h
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/selinux/include/flask.h
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/selinux/include/class_to_string.h
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/selinux/include/av_permissions.h
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/selinux/include/av_perm_to_string.h
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/selinux/include/av_inherit.h
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/selinux/hooks.c
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/selinux/Makefile
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# security/dummy.c
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# net/netlink/af_netlink.c
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# include/linux/security.h
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# include/asm-ppc64/system.h
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# Documentation/filesystems/proc.txt
#   2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# arch/arm/Makefile
#   2004/06/18 19:42:57+01:00 rmk@flint.arm.linux.org.uk +0 -1
#   Remove TBOX.
# 
# BitKeeper/deleted/.del-plx90x0.c~6e00d8c4651bebd
#   2004/06/18 19:22:53+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: arch/arm/common/plx90x0.c
# 
# BitKeeper/deleted/.del-Makefile~743b0b21d18f48a3
#   2004/06/18 19:21:48+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: arch/arm/mach-tbox/Makefile
# 
# BitKeeper/deleted/.del-Makefile~1bcec227c3749c2b
#   2004/06/18 19:21:42+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: arch/arm/mach-ftvpci/Makefile
# 
# BitKeeper/deleted/.del-vmalloc.h~6fe84d89a4fe0487
#   2004/06/18 19:20:44+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/vmalloc.h
# 
# BitKeeper/deleted/.del-uncompress.h~d86deb706ce0af8c
#   2004/06/18 19:20:41+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/uncompress.h
# 
# BitKeeper/deleted/.del-timex.h~e40ee87eef3b5d82
#   2004/06/18 19:20:39+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/timex.h
# 
# BitKeeper/deleted/.del-time.h~730e38fa47912a2c
#   2004/06/18 19:20:37+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/time.h
# 
# BitKeeper/deleted/.del-system.h~13cdaece381624c5
#   2004/06/18 19:20:34+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/system.h
# 
# BitKeeper/deleted/.del-param.h~43f147e81e4d4aa
#   2004/06/18 19:20:32+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/param.h
# 
# BitKeeper/deleted/.del-memory.h~a8036cb472d809fd
#   2004/06/18 19:20:31+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/memory.h
# 
# BitKeeper/deleted/.del-irqs.h~4b397f62f210ba4a
#   2004/06/18 19:20:29+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/irqs.h
# 
# BitKeeper/deleted/.del-io.h~dad3ba234da9ed44
#   2004/06/18 19:20:28+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/io.h
# 
# BitKeeper/deleted/.del-hardware.h~e2ae6d2a73466d92
#   2004/06/18 19:20:26+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/hardware.h
# 
# BitKeeper/deleted/.del-dma.h~7c79d144ee7126
#   2004/06/18 19:20:25+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-nexuspci/dma.h
# 
# BitKeeper/deleted/.del-vmalloc.h~9cc411fb2236e832
#   2004/06/18 19:20:24+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/vmalloc.h
# 
# BitKeeper/deleted/.del-uncompress.h~ba1125271f695d9a
#   2004/06/18 19:20:22+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/uncompress.h
# 
# BitKeeper/deleted/.del-timex.h~21cf937463373e34
#   2004/06/18 19:20:20+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/timex.h
# 
# BitKeeper/deleted/.del-time.h~e839fe4bcd9e4cf9
#   2004/06/18 19:20:18+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/time.h
# 
# BitKeeper/deleted/.del-system.h~cd0858e052bb3f86
#   2004/06/18 19:20:16+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/system.h
# 
# BitKeeper/deleted/.del-serial.h~4a4898b286343b2a
#   2004/06/18 19:20:15+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/serial.h
# 
# BitKeeper/deleted/.del-param.h~220f433111a13232
#   2004/06/18 19:20:13+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/param.h
# 
# BitKeeper/deleted/.del-memory.h~32316a4b360340b5
#   2004/06/18 19:20:11+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/memory.h
# 
# BitKeeper/deleted/.del-irqs.h~f8419d051722d58a
#   2004/06/18 19:20:09+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/irqs.h
# 
# BitKeeper/deleted/.del-io.h~62e0d6286c3e19bc
#   2004/06/18 19:20:08+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/io.h
# 
# BitKeeper/deleted/.del-hardware.h~7238d94368669e11
#   2004/06/18 19:20:05+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/hardware.h
# 
# BitKeeper/deleted/.del-dma.h~4cb7553c767afee5
#   2004/06/18 19:20:03+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: include/asm-arm/arch-tbox/dma.h
# 
# BitKeeper/deleted/.del-core.c~714a718aec4a2c30
#   2004/06/18 19:20:01+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: arch/arm/mach-tbox/core.c
# 
# BitKeeper/deleted/.del-pci.c~550e56da56112be2
#   2004/06/18 19:19:59+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: arch/arm/mach-ftvpci/pci.c
# 
# BitKeeper/deleted/.del-leds.c~78050371c0248352
#   2004/06/18 19:19:58+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: arch/arm/mach-ftvpci/leds.c
# 
# BitKeeper/deleted/.del-core.c~9e662b6895b788f2
#   2004/06/18 19:19:57+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   Delete: arch/arm/mach-ftvpci/core.c
# 
# ChangeSet
#   2004/06/18 12:43:06-05:00 stevef@stevef95.austin.ibm.com 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into stevef95.austin.ibm.com:/home/stevef/linux-2.5cifs
# 
# fs/Kconfig
#   2004/06/18 12:42:54-05:00 stevef@stevef95.austin.ibm.com +0 -1
#   Auto merged
# 
# ChangeSet
#   2004/06/18 10:32:19-07:00 greg@kroah.com 
#   Merge kroah.com:/home/greg/linux/BK/bleed-2.6
#   into kroah.com:/home/greg/linux/BK/usb-2.6
# 
# drivers/usb/storage/scsiglue.c
#   2004/06/18 10:32:14-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/18 10:06:37-07:00 torvalds@ppc970.osdl.org 
#   Merge bk://linux-scsi.bkbits.net/scsi-for-linus-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# include/linux/pci_ids.h
#   2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/scsi/sr.c
#   2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/scsi/ide-scsi.c
#   2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/scsi/Makefile
#   2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/scsi/Kconfig
#   2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-scsi_pc98.c~63183f0558d43fc2
#   2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-pc980155.c~e29865f8a9a6ed50
#   2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/06/18 10:06:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-scsi_pc98.c~63183f0558d43fc2
#   2004/06/18 10:06:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Merge rename: drivers/scsi/scsi_pc98.c -> BitKeeper/deleted/.del-scsi_pc98.c~63183f0558d43fc2
# 
# BitKeeper/deleted/.del-pc980155.c~e29865f8a9a6ed50
#   2004/06/18 10:06:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Merge rename: drivers/scsi/pc980155.c -> BitKeeper/deleted/.del-pc980155.c~e29865f8a9a6ed50
# 
# ChangeSet
#   2004/06/18 10:04:39-07:00 greg@kroah.com 
#   USB: mark pwc driver broken again, as it still is :(
# 
# drivers/usb/media/Kconfig
#   2004/06/18 03:03:21-07:00 greg@kroah.com +1 -1
#   USB: mark pwc driver broken again, as it still is :(
# 
# ChangeSet
#   2004/06/18 17:58:33+01:00 tony@com.rmk.(none) 
#   [ARM PATCH] 1931/1: Allow device address translation in dma-mapping, version 3
#   
#   Patch from Tony Lindgren
#   
#   Allows translation of shared memory addresses for devices using 
#   dma-mapping. In some cases the device DMA address is different
#   from the ARM DMA address, for example with some USB OHCI 
#   controllers.
#   
#   For more background information, please see the ARM Linux mailing
#   list thread "OHCI controller".
# 
# include/asm-arm/memory.h
#   2004/06/18 00:11:37+01:00 tony@com.rmk.(none) +10 -1
#   [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3
# 
# include/asm-arm/dma-mapping.h
#   2004/06/18 00:11:37+01:00 tony@com.rmk.(none) +4 -4
#   [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3
# 
# include/asm-arm/arch-omap/memory.h
#   2004/06/18 00:11:37+01:00 tony@com.rmk.(none) +20 -4
#   [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3
# 
# arch/arm/mm/consistent.c
#   2004/06/18 00:11:02+01:00 tony@com.rmk.(none) +1 -1
#   [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3
# 
# arch/arm/common/dmabounce.c
#   2004/06/18 00:11:01+01:00 tony@com.rmk.(none) +5 -5
#   [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3
# 
# ChangeSet
#   2004/06/18 17:53:15+01:00 nico@org.rmk.(none) 
#   [ARM PATCH] 1932/1: fix comment about cache handling syscall
#   
#   Patch from Nicolas Pitre
#   
#   Let's make it coherent with what the actual code is doing and has
#   always done, even in 2.4.  Nobody complained about this so let's
#   just fix the comment.  The most natural usage pattern for this is
#   a base address and a size so it's more efficient to have an exclusive
#   end address anyway.
# 
# ChangeSet
#   2004/06/18 09:52:38-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: dummy_hcd shouldn't reject SET-ADDRESS requests
#   
#   This patch for the dummy_hcd driver prevents it from rejecting SET-ADDRESS
#   requests when the address is already set.  The USB 2.0 spec states that if
#   a device is in the ADDRESS state, it should accept and start using the new
#   address.  Behavior in the CONFIGURED state is undefined, but since
#   dummy_hcd doesn't keep track of the difference between the two states we
#   might as well accept the new address in any case.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/dummy_hcd.c
#   2004/06/18 03:18:28-07:00 stern@rowland.harvard.edu +0 -5
#   USB: dummy_hcd shouldn't reject SET-ADDRESS requests
# 
# arch/arm/kernel/traps.c
#   2004/06/18 02:01:40+01:00 nico@org.rmk.(none) +1 -1
#   [PATCH] 1932/1: fix comment about cache handling syscall
# 
# ChangeSet
#   2004/06/18 09:50:41-07:00 axboe@suse.de 
#   [PATCH] cfq direct io alias problem
#   
#   This is a fix for when we encounter an alias during insert. When that
#   happens we move the request to dispatch, but it may happen that this
#   request is also the ->last_merge hint. So we may attempt to merge with
#   this later, when it's either in progress or already freed. Rearrange the
#   logic a bit so we clear the merge hint there as well. It looks more
#   complex than it is, the only real code change is the addition of a
#   cfq_remove_merge_hints() in cfq_dispatch_sort().
#   
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/cfq-iosched.c
#   2004/06/17 10:37:34-07:00 axboe@suse.de +14 -8
#   cfq direct io alias problem
# 
# ChangeSet
#   2004/06/18 09:50:31-07:00 axboe@suse.de 
#   [PATCH] cfq allocation race
#   
#   It's possible under unlucky circumstances for this race to trigger. I
#   described it with a comment in the code.
#   
#   Signed-Off-By: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/cfq-iosched.c
#   2004/05/24 06:35:01-07:00 axboe@suse.de +19 -0
#   cfq allocation race
# 
# ChangeSet
#   2004/06/18 09:50:20-07:00 axboe@suse.de 
#   [PATCH] cfq sysfs support
#   
#   This makes the CFQ tunables available in sysfs, like AS and deadline.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/cfq-iosched.c
#   2004/05/24 06:06:17-07:00 axboe@suse.de +113 -2
#   cfq sysfs support
# 
# ChangeSet
#   2004/06/18 17:49:27+01:00 icampbell@com.rmk.(none) 
#   [ARM PATCH] 1934/2:  Consolidate code to set CKEN on PXA
#   
#   Patch from Ian Campbell
#   
#   I've seen comments several times that various PXA drivers
#   update CKEN in an unsafe manner. This patch consolidates
#   this code into a single function pxa_set_cken() and updates
#   all the in tree drivers to use it.
# 
# ChangeSet
#   2004/06/18 09:48:38-07:00 torvalds@ppc970.osdl.org 
#   Remove old stale header files that aren't referenced anywhere.
#   
#   Noted by Alexey Dobriyan.
# 
# BitKeeper/deleted/.del-netfilter_x25.h~5e2c13d4592d8c13
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/netfilter_x25.h
# 
# BitKeeper/deleted/.del-netfilter_ipx.h~7e5cd8fa9a3985ac
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/netfilter_ipx.h
# 
# BitKeeper/deleted/.del-netfilter_ddp.h~2153f0da7220ca38
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/netfilter_ddp.h
# 
# BitKeeper/deleted/.del-netbeui.h~1cf2e2f4793bcad1
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/netbeui.h
# 
# BitKeeper/deleted/.del-mpp.h~8ebce3fa907ece97
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/mpp.h
# 
# BitKeeper/deleted/.del-isdn_lzscomp.h~99cfe6e36b994a1
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/isdn_lzscomp.h
# 
# BitKeeper/deleted/.del-in_systm.h~268bf1b1642e1ee5
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/in_systm.h
# 
# BitKeeper/deleted/.del-fsfilter.h~5fc8d5fdaaa381a
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/fsfilter.h
# 
# BitKeeper/deleted/.del-atapi.h~8a1b1aeca6c26a7
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/atapi.h
# 
# BitKeeper/deleted/.del-adb_mouse.h~d5f39849c4abbd6e
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/adb_mouse.h
# 
# BitKeeper/deleted/.del-acpi_serial.h~d839323d8907296b
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/acpi_serial.h
# 
# BitKeeper/deleted/.del-802_11.h~9b6bd4cff8af7a90
#   2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/linux/802_11.h
# 
# include/asm-arm/arch-pxa/hardware.h
#   2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +5 -0
#   [PATCH] 1934/2:  Consolidate code to set CKEN on PXA
# 
# drivers/video/pxafb.c
#   2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +1 -4
#   [PATCH] 1934/2:  Consolidate code to set CKEN on PXA
# 
# drivers/usb/gadget/pxa2xx_udc.c
#   2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +2 -2
#   [PATCH] 1934/2:  Consolidate code to set CKEN on PXA
# 
# drivers/serial/pxa.c
#   2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +2 -7
#   [PATCH] 1934/2:  Consolidate code to set CKEN on PXA
# 
# arch/arm/mach-pxa/generic.c
#   2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +18 -0
#   [PATCH] 1934/2:  Consolidate code to set CKEN on PXA
# 
# ChangeSet
#   2004/06/18 09:46:06-07:00 torvalds@ppc970.osdl.org 
#   Merge
# 
# drivers/net/at1700.c
#   2004/06/18 09:46:04-07:00 torvalds@ppc970.osdl.org +0 -0
#   SCCS merged
# 
# ChangeSet
#   2004/06/18 17:43:22+01:00 icampbell@com.rmk.(none) 
#   [ARM PATCH] 1930/1: Allocate correct number of pseudo palette entries in pxafb
#   
#   Patch from Ian Campbell
#   
#   The pxafb driver incorrectly allocates 17 u32's for a 16 entry 
#   pseudo palette.
# 
# drivers/net/Makefile
#   2004/06/18 09:43:07-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-ne2k_cbus.c~db2bde9191a8ce9a
#   2004/06/18 09:43:06-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/06/18 09:43:06-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/net/82596.c
#   2004/06/18 09:43:06-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-ne2k_cbus.c~db2bde9191a8ce9a
#   2004/06/18 09:43:06-07:00 torvalds@ppc970.osdl.org +0 -0
#   Merge rename: drivers/net/ne2k_cbus.c -> BitKeeper/deleted/.del-ne2k_cbus.c~db2bde9191a8ce9a
# 
# drivers/video/pxafb.c
#   2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +1 -1
#   [PATCH] 1930/1: Allocate correct number of pseudo palette entries in pxafb
# 
# ChangeSet
#   2004/06/18 09:36:50-07:00 davem@nuts.davemloft.net 
#   Merge
# 
# security/selinux/hooks.c
#   2004/06/18 09:36:41-07:00 davem@nuts.davemloft.net +0 -101
#   SCCS merged
# 
# security/selinux/ss/services.c
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -12
#   Auto merged
# 
# security/selinux/ss/policydb.c
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -9
#   Auto merged
# 
# security/selinux/include/security.h
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -5
#   Auto merged
# 
# security/selinux/include/flask.h
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -21
#   Auto merged
# 
# security/selinux/include/class_to_string.h
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -21
#   Auto merged
# 
# security/selinux/include/av_permissions.h
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -573
#   Auto merged
# 
# security/selinux/include/av_perm_to_string.h
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -101
#   Auto merged
# 
# security/selinux/include/av_inherit.h
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -9
#   Auto merged
# 
# security/selinux/Makefile
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -1
#   Auto merged
# 
# security/dummy.c
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -1
#   Auto merged
# 
# net/netlink/af_netlink.c
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -4
#   Auto merged
# 
# include/linux/security.h
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -11
#   Auto merged
# 
# include/asm-ppc64/system.h
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# Documentation/filesystems/proc.txt
#   2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/18 09:33:53-07:00 torvalds@ppc970.osdl.org 
#   This removes the files orphaned by the earlier PC9800 removal
# 
# BitKeeper/deleted/.del-smpboot_hooks.h~5940f4c36bed59b4
#   2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/smpboot_hooks.h
# 
# BitKeeper/deleted/.del-setup_arch_pre.h~1aa05e47e2ae5d10
#   2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/setup_arch_pre.h
# 
# BitKeeper/deleted/.del-setup_arch_post.h~c1ce95fa8d614f4d
#   2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/setup_arch_post.h
# 
# BitKeeper/deleted/.del-pci-functions.h~930f4ea96f69d14
#   2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/pci-functions.h
# 
# BitKeeper/deleted/.del-mach_wakecpu.h~de206fda8667a7e7
#   2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/mach_wakecpu.h
# 
# BitKeeper/deleted/.del-mach_traps.h~db7e527be9d0d95b
#   2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/mach_traps.h
# 
# BitKeeper/deleted/.del-mach_timer.h~6faf9e0362bc9cad
#   2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/mach_timer.h
# 
# BitKeeper/deleted/.del-mach_time.h~4ec98fea93568edd
#   2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/mach_time.h
# 
# BitKeeper/deleted/.del-mach_reboot.h~666bd1054bae0a25
#   2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/mach_reboot.h
# 
# BitKeeper/deleted/.del-irq_vectors.h~5a325ee32bbed31
#   2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/irq_vectors.h
# 
# BitKeeper/deleted/.del-io_ports.h~8f892217bfd99be4
#   2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/io_ports.h
# 
# BitKeeper/deleted/.del-do_timer.h~e73335e43b11ea32
#   2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/do_timer.h
# 
# BitKeeper/deleted/.del-bios_ebda.h~4a870d9833986305
#   2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/bios_ebda.h
# 
# BitKeeper/deleted/.del-apm.h~324fabc1c2354803
#   2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/mach-pc9800/apm.h
# 
# BitKeeper/deleted/.del-video.S~284da1c1c2e38aa8
#   2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/boot98/video.S
# 
# BitKeeper/deleted/.del-setup.S~bd07a5b2361060c
#   2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/boot98/setup.S
# 
# BitKeeper/deleted/.del-mtools.conf.in~3346efde195fa35
#   2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/boot98/mtools.conf.in
# 
# BitKeeper/deleted/.del-install.sh~6441f5459fde0cb0
#   2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/boot98/install.sh
# 
# BitKeeper/deleted/.del-bootsect.S~aa4f19a632039843
#   2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/boot98/bootsect.S
# 
# BitKeeper/deleted/.del-Makefile~2700a53f2e1fb469
#   2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/boot98/Makefile
# 
# BitKeeper/deleted/.del-topology.c~607813b1b960974f
#   2004/06/18 09:32:43-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/mach-pc9800/topology.c
# 
# BitKeeper/deleted/.del-std_resources.c~54f4a08a759f2f5f
#   2004/06/18 09:32:43-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/mach-pc9800/std_resources.c
# 
# BitKeeper/deleted/.del-setup.c~161f6c99c14ddb5d
#   2004/06/18 09:32:43-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/mach-pc9800/setup.c
# 
# BitKeeper/deleted/.del-Makefile~c002abb789b0791f
#   2004/06/18 09:32:43-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: arch/i386/mach-pc9800/Makefile
# 
# BitKeeper/deleted/.del-sound_pc9800.h~d8dde13c75b5753b
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: sound/isa/cs423x/sound_pc9800.h
# 
# BitKeeper/deleted/.del-pc9801_118_magic.h~479c5fdd78d01b7a
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: sound/isa/cs423x/pc9801_118_magic.h
# 
# BitKeeper/deleted/.del-pc9800_sca.h~b52752436ddb82ea
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/pc9800_sca.h
# 
# BitKeeper/deleted/.del-pc9800.h~e8f7c13f33846c88
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: include/asm-i386/pc9800.h
# 
# BitKeeper/deleted/.del-pc9800.c~1af765dbb1c51b76
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/ide/legacy/pc9800.c
# 
# BitKeeper/deleted/.del-pc98.c~e5a92ca5f2b01d36
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: sound/isa/cs423x/pc98.c
# 
# BitKeeper/deleted/.del-nec98.h~a0b8de1e822fa884
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: fs/partitions/nec98.h
# 
# BitKeeper/deleted/.del-nec98.c~2e65e92f56ce9a56
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: fs/partitions/nec98.c
# 
# BitKeeper/deleted/.del-hd98.c~fc4a0b69729bf7c1
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/ide/legacy/hd98.c
# 
# BitKeeper/deleted/.del-98spkr.c~a1a91856da60a088
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/input/misc/98spkr.c
# 
# BitKeeper/deleted/.del-98busmouse.c~ca244def94322735
#   2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/input/mouse/98busmouse.c
# 
# BitKeeper/deleted/.del-serial98.c~c69c28b9984f1cca
#   2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/serial/serial98.c
# 
# BitKeeper/deleted/.del-scsi_pc98.c~63183f0558d43fc2
#   2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/scsi/scsi_pc98.c
# 
# BitKeeper/deleted/.del-pc980155.h~f12bd20496e02379
#   2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/scsi/pc980155.h
# 
# BitKeeper/deleted/.del-pc980155.c~e29865f8a9a6ed50
#   2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/scsi/pc980155.c
# 
# BitKeeper/deleted/.del-lp_old98.c~fc58ff5b2fa5c998
#   2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/char/lp_old98.c
# 
# BitKeeper/deleted/.del-floppy98.c~12864e155d00fa0e
#   2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/block/floppy98.c
# 
# BitKeeper/deleted/.del-98kbd.c~fcb070eb5c330ed3
#   2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/input/keyboard/98kbd.c
# 
# BitKeeper/deleted/.del-98kbd-io.c~37d03ba23bb15415
#   2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/input/serio/98kbd-io.c
# 
# BitKeeper/deleted/.del-upd4990a.c~6da2f3423f9a74f
#   2004/06/18 09:32:23-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/char/upd4990a.c
# 
# BitKeeper/deleted/.del-ne2k_cbus.h~b1e2c6c8f1caf542
#   2004/06/18 09:32:23-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/net/ne2k_cbus.h
# 
# BitKeeper/deleted/.del-ne2k_cbus.c~db2bde9191a8ce9a
#   2004/06/18 09:32:23-07:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/net/ne2k_cbus.c
# 
# ChangeSet
#   2004/06/18 09:31:40-07:00 torvalds@ppc970.osdl.org 
#   Merge
# 
# arch/i386/kernel/acpi/boot.c
#   2004/06/18 09:31:38-07:00 torvalds@ppc970.osdl.org +0 -0
#   SCCS merged
# 
# arch/i386/kernel/mpparse.c
#   2004/06/18 09:29:48-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/18 09:24:59-07:00 torvalds@ppc970.osdl.org 
#   Merge duplicate selinux network hooks
# 
# security/selinux/hooks.c
#   2004/06/18 09:24:54-07:00 torvalds@ppc970.osdl.org +0 -101
#   Merge duplicate selinux hooks
# 
# security/selinux/ss/services.c
#   2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -12
#   Auto merged
# 
# security/selinux/ss/policydb.c
#   2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -9
#   Auto merged
# 
# security/selinux/include/security.h
#   2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -5
#   Auto merged
# 
# security/selinux/include/flask.h
#   2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -21
#   Auto merged
# 
# security/selinux/include/class_to_string.h
#   2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -21
#   Auto merged
# 
# security/selinux/include/av_permissions.h
#   2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -573
#   Auto merged
# 
# security/selinux/include/av_perm_to_string.h
#   2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -101
#   Auto merged
# 
# security/selinux/include/av_inherit.h
#   2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -9
#   Auto merged
# 
# security/selinux/Makefile
#   2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -1
#   Auto merged
# 
# security/dummy.c
#   2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -1
#   Auto merged
# 
# net/netlink/af_netlink.c
#   2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -4
#   Auto merged
# 
# include/linux/security.h
#   2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -11
#   Auto merged
# 
# include/asm-ppc64/system.h
#   2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# Documentation/filesystems/proc.txt
#   2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/18 08:25:41-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: remove unused queued_signals global accounting
#   
#   Remove unused queued_signals global accounting.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sysctl.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +0 -18
#   RLIM: remove unused queued_signals global accounting
# 
# kernel/signal.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +0 -3
#   RLIM: remove unused queued_signals global accounting
# 
# ChangeSet
#   2004/06/18 08:25:30-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: enforce rlimits on queued signals
#   
#   Add a user_struct pointer to the sigqueue structure.  Charge sigqueue
#   allocation and destruction to the user_struct rather than a global pool.  This
#   per user rlimit accounting obsoletes the global queued_signals accouting.
#   
#   The patch as charges the sigqueue struct allocation to the queue that it's
#   pending on (the receiver of the signal).  So the owner of the queue is charged
#   for whoever writes to it (much like quota for a 777 file).
#   
#   The patch started out charging the task which allocated the sigqueue struct.
#   In most cases, these are always the same user (permission for sending a
#   signal), so those cases are moot.  In the cases where it isn't the same user,
#   it's a privileged user sending a signal to another user.
#   
#   It seems wrong to charge the allocation to the privleged user, when the other
#   user could block receipt as long as it feels.  The flipside is, someone else
#   can fill your queue (expectation is that someone else is privileged).  I think
#   it's right the way it is.  The change to revert is very small.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/signal.c
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +11 -6
#   RLIM: enforce rlimits on queued signals
# 
# include/linux/signal.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: enforce rlimits on queued signals
# 
# ChangeSet
#   2004/06/18 08:25:20-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: pass task_struct in send_signal()
#   
#   Update send_signal() api to allow passing the task receiving the signal.  This
#   is necessary to ensure signals generated out of process context can be charged
#   to the correct user.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/signal.c
#   2004/06/18 00:32:25-07:00 chrisw@osdl.org +4 -3
#   RLIM: pass task_struct in send_signal()
# 
# ChangeSet
#   2004/06/18 08:23:45-07:00 torvalds@ppc970.osdl.org 
#   Fix kill_pg_info(): return success if _any_ signal succeeded.
# 
# kernel/signal.c
#   2004/06/18 08:23:40-07:00 torvalds@ppc970.osdl.org +7 -11
#   Fix kill_pg_info(): return success if _any_ signal succeeded.
# 
# ChangeSet
#   2004/06/18 08:17:04-07:00 kszysiu@iceberg.elsat.net.pl 
#   [PATCH] cmpci oops on rmmod + fix
#   
#   The cmpci driver included in Linux 2.6.7 causes an oops on rmmod, I believe
#   cm_remove should be marked __devexit rather than __devinit.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/cmpci.c
#   2004/06/18 00:06:08-07:00 kszysiu@iceberg.elsat.net.pl +2 -2
#   cmpci oops on rmmod + fix
# 
# ChangeSet
#   2004/06/18 08:16:53-07:00 ysato@users.sourceforge.jp 
#   [PATCH] H8/300: io.h cleanup
#   
#   - optimize byteswap
#   - add noswap io mode
#   - cleanup var type
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-h8300/io.h
#   2004/06/18 00:06:08-07:00 ysato@users.sourceforge.jp +68 -24
#   H8/300: io.h cleanup
# 
# ChangeSet
#   2004/06/18 08:16:42-07:00 ysato@users.sourceforge.jp 
#   [PATCH] H8/300: ptrace fix
#   
#   - Kconfig typo fix
#   - PTRACE_PEEKUSER read process info support
#   - exr restore fix
#   - ptrace register offset fix
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/h8300/platform/h8s/ptrace_h8s.c
#   2004/06/18 00:06:07-07:00 ysato@users.sourceforge.jp +1 -1
#   H8/300: ptrace fix
# 
# arch/h8300/platform/h8s/entry.S
#   2004/06/18 00:06:07-07:00 ysato@users.sourceforge.jp +1 -1
#   H8/300: ptrace fix
# 
# arch/h8300/kernel/ptrace.c
#   2004/06/18 00:06:07-07:00 ysato@users.sourceforge.jp +23 -5
#   H8/300: ptrace fix
# 
# arch/h8300/Kconfig
#   2004/06/18 00:06:07-07:00 ysato@users.sourceforge.jp +1 -1
#   H8/300: ptrace fix
# 
# ChangeSet
#   2004/06/18 08:16:33-07:00 kaos@ocs.com.au 
#   [PATCH] contify some scheduler functions
#   
#   Several scheduler macros only read from the task struct, mark them const.
#   It may help the compiler generate better code.
#   
#   Signed-off-by: Keith Owens <kaos@ocs.com.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sched.c
#   2004/06/18 00:06:07-07:00 kaos@ocs.com.au +3 -3
#   contify some scheduler functions
# 
# kernel/exit.c
#   2004/06/18 00:06:07-07:00 kaos@ocs.com.au +3 -3
#   contify some scheduler functions
# 
# include/linux/sched.h
#   2004/06/18 00:06:07-07:00 kaos@ocs.com.au +6 -6
#   contify some scheduler functions
# 
# ChangeSet
#   2004/06/18 08:16:21-07:00 greg@kroah.com 
#   [PATCH] remove EXPORT_SYMBOL(kallsyms_lookup)
#   
#   Distros have started to ship kernels with this patch, as it seems that some
#   unnamed binary module authors are already abusing this function (as well as
#   some open source modules, like the openib code.) I could not find any valid
#   reason why this symbol should be exported, so here's a patch against 2.6.7
#   that removes it.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/kallsyms.c
#   2004/06/18 00:06:07-07:00 greg@kroah.com +0 -1
#   remove EXPORT_SYMBOL(kallsyms_lookup)
# 
# ChangeSet
#   2004/06/18 08:16:11-07:00 rddunlap@osdl.org 
#   [PATCH] remove blank line in show_trace()
#   
#   Delete a blank line for more error reporting on-screen.
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/traps.c
#   2004/06/18 00:06:07-07:00 rddunlap@osdl.org +0 -1
#   remove blank line in show_trace()
# 
# ChangeSet
#   2004/06/18 08:16:00-07:00 kenneth.w.chen@intel.com 
#   [PATCH] Hugetlb page bug fix for i386 in PAE mode
#   
#   Hit a bug check when unmap a hugetlb vma in PAE mode on i386 (and x86-64).
#   
#    Bad page state at free_hot_cold_page (in process 'a.out', page c165cc40)
#    flags:0x20000000 mapping:f75e1d00 mapped:0 count:0
#    Backtrace:
#    Call Trace:
#     [<c0133e0d>] bad_page+0x79/0x9e
#     [<c0134550>] free_hot_cold_page+0x71/0xfa
#     [<c0115d60>] unmap_hugepage_range+0xa3/0xbf
#     [<c013d375>] unmap_vmas+0xac/0x252
#     [<c0117691>] default_wake_function+0x0/0xc
#     [<c0140bea>] unmap_region+0xd8/0x145
#     [<c0140f2d>] do_munmap+0xfc/0x14d
#     [<c01b8a56>] sys_shmdt+0xa5/0x126
#     [<c010a2ad>] sys_ipc+0x23c/0x27f
#     [<c014a85e>] sys_write+0x38/0x59
#     [<c0103e1b>] syscall_call+0x7/0xb
#   
#   It turns out there is a bug in hugetlb_prefault(): with 3 level page table,
#   huge_pte_alloc() might return a pmd that points to a PTE page.  It happens
#   if the virtual address for hugetlb mmap is recycled from previously used
#   normal page mmap.  free_pgtables() might not scrub the pmd entry on munmap
#   and hugetlb_prefault skips on any pmd presence regardless what type it is. 
#   Patch to fix the bug.
#   
#   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>
# 
# arch/i386/mm/hugetlbpage.c
#   2004/06/18 00:06:07-07:00 kenneth.w.chen@intel.com +9 -2
#   Hugetlb page bug fix for i386 in PAE mode
# 
# ChangeSet
#   2004/06/18 08:15:49-07:00 minyard@acm.org 
#   [PATCH] IPMI base patch to fix channel handling and add polling
#   
#   This patch fixes some problems with handling of channel detection in the
#   driver.  Some systems that are IPMI 1.5 do not implement the channel query
#   command.  Also, the interface has to be fully up before the command is
#   ready.
#   
#   This patch also adds a polling interface; this is required for situations
#   where interrupts are not running, but the system must still issue IPMI
#   commands, like when taking a crash dump.
#   
#   It also updates the driver version to v32.
#   
#   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
#   2004/06/18 00:06:07-07:00 minyard@acm.org +4 -0
#   IPMI base patch to fix channel handling and add polling
# 
# include/linux/ipmi_msgdefs.h
#   2004/06/18 00:06:07-07:00 minyard@acm.org +1 -0
#   IPMI base patch to fix channel handling and add polling
# 
# include/linux/ipmi.h
#   2004/06/18 00:06:07-07:00 minyard@acm.org +10 -0
#   IPMI base patch to fix channel handling and add polling
# 
# drivers/char/ipmi/ipmi_watchdog.c
#   2004/06/18 00:06:07-07:00 minyard@acm.org +3 -5
#   IPMI base patch to fix channel handling and add polling
# 
# drivers/char/ipmi/ipmi_smic_sm.c
#   2004/06/18 00:06:07-07:00 minyard@acm.org +1 -1
#   IPMI base patch to fix channel handling and add polling
# 
# drivers/char/ipmi/ipmi_si_intf.c
#   2004/06/18 00:06:07-07:00 minyard@acm.org +45 -16
#   IPMI base patch to fix channel handling and add polling
# 
# drivers/char/ipmi/ipmi_msghandler.c
#   2004/06/18 00:06:07-07:00 minyard@acm.org +29 -2
#   IPMI base patch to fix channel handling and add polling
# 
# drivers/char/ipmi/ipmi_kcs_sm.c
#   2004/06/18 00:06:07-07:00 minyard@acm.org +1 -1
#   IPMI base patch to fix channel handling and add polling
# 
# drivers/char/ipmi/ipmi_devintf.c
#   2004/06/18 00:06:07-07:00 minyard@acm.org +1 -1
#   IPMI base patch to fix channel handling and add polling
# 
# drivers/char/ipmi/ipmi_bt_sm.c
#   2004/06/18 00:06:07-07:00 minyard@acm.org +1 -1
#   IPMI base patch to fix channel handling and add polling
# 
# ChangeSet
#   2004/06/18 08:15:37-07:00 jmorris@redhat.com 
#   [PATCH] SELinux: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Cc: David S. Miller <davem@redhat.com>
#   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/nlmsgtab.c
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +153 -0
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/ss/services.c
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +12 -0
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/ss/policydb.c
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +9 -1
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/nlmsgtab.c
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/security/selinux/nlmsgtab.c
# 
# security/selinux/include/security.h
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +5 -4
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/include/flask.h
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +9 -0
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/include/class_to_string.h
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +9 -0
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/include/av_permissions.h
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +223 -0
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/include/av_perm_to_string.h
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +12 -0
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/include/av_inherit.h
#   2004/06/18 00:06:06-07:00 jmorris@redhat.com +9 -0
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/hooks.c
#   2004/06/18 00:06:06-07:00 jmorris@redhat.com +80 -22
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# security/selinux/Makefile
#   2004/06/18 00:06:07-07:00 jmorris@redhat.com +1 -1
#   SELinux: Fine-grained Netlink support - SELinux changes
# 
# ChangeSet
#   2004/06/18 08:15:25-07:00 jmorris@redhat.com 
#   [PATCH] SELinux: Fine-grained Netlink support - add sk to netlink_send hook
#   
#   Modifies the LSM netlink_send() hook so that it takes a struct sock parameter.
#    SELinux will use this parameter to lookup the class of socket, which was
#   assigned during socket security initialization.
#   
#   Cc: David S. Miller <davem@redhat.com>
#   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
#   2004/06/18 00:32:07-07:00 jmorris@redhat.com +1 -1
#   SELinux: Fine-grained Netlink support - add sk to netlink_send hook
# 
# security/dummy.c
#   2004/06/18 00:06:06-07:00 jmorris@redhat.com +1 -1
#   SELinux: Fine-grained Netlink support - add sk to netlink_send hook
# 
# net/netlink/af_netlink.c
#   2004/06/18 00:06:06-07:00 jmorris@redhat.com +1 -1
#   SELinux: Fine-grained Netlink support - add sk to netlink_send hook
# 
# include/linux/security.h
#   2004/06/18 00:06:06-07:00 jmorris@redhat.com +11 -8
#   SELinux: Fine-grained Netlink support - add sk to netlink_send hook
# 
# ChangeSet
#   2004/06/18 08:15:14-07:00 jmorris@redhat.com 
#   [PATCH] SELinux: Fine-grained Netlink support - move security_netlink_send() hook
#   
#   This patch moves the security_netlink_send() LSM hook after the user copy, so
#   that LSM modules can safely examine skb payload content.  For SELinux, we need
#   to look at the Netlink message type.
#   
#   Cc: David S. Miller <davem@redhat.com>
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/netlink/af_netlink.c
#   2004/06/18 00:32:07-07:00 jmorris@redhat.com +4 -4
#   SELinux: Fine-grained Netlink support - move security_netlink_send() hook
# 
# ChangeSet
#   2004/06/18 08:15:04-07:00 jmorris@redhat.com 
#   [PATCH] SELinux: Fine-grained Netlink support - SELinux headers update
#   
#   This patch regenerates the SELinux module headers to reflect new class and
#   access vectors definitions.  The size of the diff is misleading; much of it is
#   simply a change in the ordering of the automatically generated definitions.
#   The corresponding generation script has been changed to ensure a stable order
#   in the future.  Please apply.
#   
#   Author: Stephen Smalley <sds@epoch.ncsc.mil>
#   Cc: David S. Miller <davem@redhat.com>
#   Signed-off-by:  Stephen Smalley <sds@epoch.ncsc.mil>
#   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/include/flask.h
#   2004/06/18 00:32:07-07:00 jmorris@redhat.com +12 -0
#   SELinux: Fine-grained Netlink support - SELinux headers update
# 
# security/selinux/include/class_to_string.h
#   2004/06/18 00:32:07-07:00 jmorris@redhat.com +12 -0
#   SELinux: Fine-grained Netlink support - SELinux headers update
# 
# security/selinux/include/av_permissions.h
#   2004/06/18 00:32:07-07:00 jmorris@redhat.com +350 -250
#   SELinux: Fine-grained Netlink support - SELinux headers update
# 
# security/selinux/include/av_perm_to_string.h
#   2004/06/18 00:32:07-07:00 jmorris@redhat.com +89 -3
#   SELinux: Fine-grained Netlink support - SELinux headers update
# 
# ChangeSet
#   2004/06/18 08:14:53-07:00 chrisw@osdl.org 
#   [PATCH] fix simple_strtoul base 16 handling
#   
#   I know it's simple_strtoul, but is it meant to be that simple?  Fix up for
#   both simple_strtoul and simple_strtoull.
#   
#   simple_strtoul(0x401b, NULL, 0) = 0x401b
#   simple_strtoul(0X401b, NULL, 0) = 0x0
#   simple_strtoul(0x401b, NULL, 16) = 0x0
#   simple_strtoul(0X401b, NULL, 16) = 0x0
#   
#   simple_strtoull(0x401b, NULL, 0) = 0x401b
#   simple_strtoull(0X401b, NULL, 0) = 0x0
#   simple_strtoull(0x401b, NULL, 16) = 0x0
#   simple_strtoull(0X401b, NULL, 16) = 0x0
#   
#   Signed-off-by: Chris Wright <chrisw@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/vsprintf.c
#   2004/06/18 00:06:06-07:00 chrisw@osdl.org +8 -2
#   fix simple_strtoul base 16 handling
# 
# ChangeSet
#   2004/06/18 08:14:42-07:00 eger@havoc.gtf.org 
#   [PATCH] rivafb: fb accel capabilities
#   
#   Here's the fb accel capabilities patch for rivafb.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/riva/fbdev.c
#   2004/06/18 00:06:06-07:00 eger@havoc.gtf.org +6 -1
#   rivafb: fb accel capabilities
# 
# ChangeSet
#   2004/06/18 08:14:31-07:00 geert@linux-m68k.org 
#   [PATCH] fix warning in fbmem.c
#   
#   Fix a const/non-const warning.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fb.h
#   2004/06/18 00:06:06-07:00 geert@linux-m68k.org +1 -1
#   fix warning in fbmem.c
# 
# drivers/video/fbmem.c
#   2004/06/18 00:06:06-07:00 geert@linux-m68k.org +13 -9
#   fix warning in fbmem.c
# 
# ChangeSet
#   2004/06/18 08:14:20-07:00 eger@havoc.gtf.org 
#   [PATCH] fix radeonfb panning and make it play nice with copyarea()
#   
#   radeonfb: fix panning corruption on a large virtual screen, Make panning
#   and copyarea() play nicely with each other.
#   
#   Signed-off-by: David Eger <eger@havoc.gtf.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/aty/radeon_base.c
#   2004/06/18 00:06:05-07:00 eger@havoc.gtf.org +13 -0
#   fix radeonfb panning and make it play nice with copyarea()
# 
# drivers/video/aty/radeon_accel.c
#   2004/06/18 00:06:05-07:00 eger@havoc.gtf.org +4 -4
#   fix radeonfb panning and make it play nice with copyarea()
# 
# ChangeSet
#   2004/06/18 08:14:09-07:00 lethal@Linux-SH.ORG 
#   [PATCH] asiliantfb init fix
#   
#   asiliantfb seems to have only been partially merged (the fbmem.c bits in
#   particular seem to have been missed entirely).  This adds them back in,
#   though they do seem to be present in the fbdev tree, at least they were the
#   last time I looked.
#   
#   These are the last bit of outstanding changes I have in the LinuxSH
#   tree for asiliantfb, so it would be nice to get this out of the way.
#   
#   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/fbmem.c
#   2004/06/18 00:32:08-07:00 lethal@Linux-SH.ORG +4 -0
#   asiliantfb init fix
# 
# ChangeSet
#   2004/06/18 08:13:58-07:00 adaplas@hotpop.com 
#   [PATCH] More updates to rivafb driver
#   
#   1.  pass info->monspecs.modedb and info->monspecs.modedb_len to
#      fb_find_mode() instead of NULL, 0 since its contents are specific to the
#      attached display.  Anyway, if info->monspecs.modedb == NULL,
#      fb_find_mode() will use the default database.
#   
#   2.  Added best fit algo to fb_find_mode().
#   
#   3.  Use snprintf instead of sprintf.
#   
#   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/modedb.c
#   2004/06/18 00:06:05-07:00 adaplas@hotpop.com +19 -2
#   More updates to rivafb driver
# 
# drivers/video/console/fbcon.c
#   2004/06/18 00:06:05-07:00 adaplas@hotpop.com +4 -3
#   More updates to rivafb driver
# 
# ChangeSet
#   2004/06/18 08:13:47-07:00 adaplas@hotpop.com 
#   [PATCH] Updates to rivafb driver
#   
#   The patch updates rivafb to the following:
#   
#   1.  Fixed cursor corruption and simplified cursor code.
#   
#   2.  Maximized var->yres_virtual on initial mode setting.  Scrolling,
#      therefore, defaults to y-panning which is significantly faster.
#   
#   3.  Restricted var->xres_virtual and var->yres_virtual to 0x7fff
#      (hardware limitation?).  Otherwise, var->yres_virtual > 0x7fff + panning
#      will hang the GPU.
#   
#   4.  Added I2C/DDC support.  This feature enables independent mode setup
#      to rivafb.  'stty rows n cols n' should now work correctly.  This is a
#      configurable option.
#   
#   5. Various/minor fixes to drawing code.
#   
#   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
#   2004/06/18 00:06:05-07:00 adaplas@hotpop.com +209 -0
#   Updates to rivafb driver
# 
# drivers/video/riva/rivafb.h
#   2004/06/18 00:06:05-07:00 adaplas@hotpop.com +24 -9
#   Updates to rivafb driver
# 
# drivers/video/riva/rivafb-i2c.c
#   2004/06/18 00:06:05-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/riva/rivafb-i2c.c
# 
# drivers/video/riva/fbdev.c
#   2004/06/18 00:32:08-07:00 adaplas@hotpop.com +188 -148
#   Updates to rivafb driver
# 
# drivers/video/riva/Makefile
#   2004/06/18 00:06:05-07:00 adaplas@hotpop.com +6 -2
#   Updates to rivafb driver
# 
# drivers/video/Kconfig
#   2004/06/18 00:06:05-07:00 adaplas@hotpop.com +5 -0
#   Updates to rivafb driver
# 
# ChangeSet
#   2004/06/18 08:13:36-07:00 eger@havoc.gtf.org 
#   [PATCH] fbcon: prefer pan when available
#   
#   Improve heuristics to favor panning over copyarea() thanks to pseudocode
#   from Antonino Daplas <adaplas@hotpop.com>
#   
#   Signed-off-by: David Eger <eger@havoc.gtf.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/console/fbcon.c
#   2004/06/18 00:32:09-07:00 eger@havoc.gtf.org +19 -15
#   fbcon: prefer pan when available
# 
# ChangeSet
#   2004/06/18 08:13:25-07:00 eger@havoc.gtf.org 
#   [PATCH] fb accel capabilities
#   
#   Baseline patch to make framebuffer/fbcon interaction more sane by basing the
#   fbcon heuristics on capabilities advertized by underlying framebuffer via the
#   fb_info.flags field.
#   
#   This patch updates fbcon, fb.h, and skeletonfb.c.  It does *not* yet update
#   the drivers themselves.  They should compile and work, but their hinting is
#   not correct yet, meaning most fb drivers will be slow until I set the flags to
#   the right hinting driver-by-driver
#   
#   Signed-off-by: David Eger <eger@havoc.gtf.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fb.h
#   2004/06/18 00:32:08-07:00 eger@havoc.gtf.org +46 -6
#   fb accel capabilities
# 
# drivers/video/skeletonfb.c
#   2004/06/18 00:06:05-07:00 eger@havoc.gtf.org +7 -1
#   fb accel capabilities
# 
# drivers/video/console/fbcon.h
#   2004/06/18 00:06:05-07:00 eger@havoc.gtf.org +19 -32
#   fb accel capabilities
# 
# drivers/video/console/fbcon.c
#   2004/06/18 00:32:09-07:00 eger@havoc.gtf.org +50 -47
#   fb accel capabilities
# 
# ChangeSet
#   2004/06/18 08:13:13-07:00 daniel@osdl.org 
#   [PATCH] handle partial DIO write
#   
#   The fsx-linux hole fill failure problem was caused by
#   generic_file_aio_write_nolock() not handling the partial DIO write
#   correctly.  Here's a patch lets DIO do the partial write, and the fallback
#   to buffered is done (correctly) for what is left.  This fixes the hole
#   filling without retrying the entire i/o.  This patch also applies to
#   2.6.7-rc3 with some offset.
#   
#   I tested this (on ext3) with
#   fsx-linux -l 500000 -r 4096 -t 4096 -w 4096 -Z -N 10000 junk  -R -W
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/filemap.c
#   2004/06/18 00:06:05-07:00 daniel@osdl.org +1 -1
#   handle partial DIO write
# 
# fs/direct-io.c
#   2004/06/18 00:06:05-07:00 daniel@osdl.org +7 -7
#   handle partial DIO write
# 
# ChangeSet
#   2004/06/18 08:13:02-07:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: lost dirty bits
#   
#   The SetPageUptodate function is called for pages that are already up to
#   date.  The arch_set_page_uptodate function of s390 may not clear the dirty
#   bit in that case otherwise a dirty bit which is set between the start of an
#   i/o for a writeback and a following call to SetPageUptodate is lost.
#   
#   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/linux/page-flags.h
#   2004/06/18 00:06:04-07:00 schwidefsky@de.ibm.com +3 -9
#   s390: lost dirty bits
# 
# include/asm-s390/pgtable.h
#   2004/06/18 00:06:04-07:00 schwidefsky@de.ibm.com +4 -2
#   s390: lost dirty bits
# 
# ChangeSet
#   2004/06/18 08:12:51-07:00 hch@lst.de 
#   [PATCH] fix standalone inclusion of asm-i386/dma-mapping.h
#   
#   Without this a usb-storage patch I sent fails on x86 because dma-mapping.h
#   uses struct device and various VM stuff without proper includes.  It's fine
#   on ppc at least.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/dma-mapping.h
#   2004/06/18 00:06:04-07:00 hch@lst.de +3 -0
#   fix standalone inclusion of asm-i386/dma-mapping.h
# 
# ChangeSet
#   2004/06/18 08:12:41-07:00 jmorris@redhat.com 
#   [PATCH] Fix sock_orphan race.
#   
#   The patch below fixes a race between sock_orphan() and
#   selinux_socket_sock_rcv_skb() which can lead to a null pointer deref oops
#   under heavy load.  The sk_callback_lock is used in the patch to synchronize
#   access to the incoming socket's inode security state.
#   
#   This patch has been under test in the Fedora kernel for over a month
#   without incident.
#   
#   Author:  Stephen Smalley <sds@epoch.ncsc.mil>
#   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
#   2004/06/18 00:32:07-07:00 jmorris@redhat.com +21 -16
#   Fix sock_orphan race.
# 
# ChangeSet
#   2004/06/18 08:12:29-07:00 marcelo.tosatti@cyclades.com 
#   [PATCH] update Marcelo CREDITS info
#   
#   Update my CREDITS information.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# CREDITS
#   2004/06/18 00:06:04-07:00 marcelo.tosatti@cyclades.com +7 -6
#   update Marcelo CREDITS info
# 
# ChangeSet
#   2004/06/18 08:12:18-07:00 jmorris@redhat.com 
#   [PATCH] Add security_file_permission() to AIO paths.
#   
#   Currently, there are no LSM hooks in the AIO codepaths, which means that
#   LSM based access controls are not revalidated upon AIO read and write
#   operations.  The patch below adds the security_file_permission() LSM hook
#   prior to the VFS aio_read()/aio_write() calls.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/aio.c
#   2004/06/18 00:06:04-07:00 jmorris@redhat.com +7 -0
#   Add security_file_permission() to AIO paths.
# 
# ChangeSet
#   2004/06/18 08:12:08-07:00 linux@dominikbrodowski.de 
#   [PATCH] add 1 in __const_udelay()
#   
#   The "mull" instruction in __const_udelay() cuts off the lower 32 bits --
#   so, it is "rounding down".  This is both an issue for small ndelay()s for
#   _all_ values for loops_per_jiffy and for certain {n,u}delay()s for many
#   loops_per_jiffy values.
#   
#   Assuming
#   
#   LPJ = 1501115
#   
#   udelay(87)
#   
#   results in
#   
#   130597 loops to be spent.
#   
#   However, 1000 * 130597 / 1501115 is 86.999997 us, so we're actually
#   _rounding down_.  1000 * 130598 / 1501115 is 87.000662841, which would be
#   the technically correct thing to do.  Of course, for the TSC case this
#   won't matter as the maths take some time, so the actual delay is
#   
#   1000 * __udelay(x) / lpj + __OVERHEAD(x)
#   
#   Anybody worried about both the additional overhead and the fact that the
#   overhead takes some time to run should add a check
#   
#           if (unlikely(xloops < OVERHEAD))
#                   return;
#           xloops -= OVERHEAD;
#   
#   to the delay() routines in arch/i386/kernel/timers/*.c and determine
#   what the OVERHEAD is.
#   
#   Signed-off-by: Dominik Brodowski <linux@brodo.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/lib/delay.c
#   2004/06/18 00:06:04-07:00 linux@dominikbrodowski.de +1 -1
#   add 1 in __const_udelay()
# 
# ChangeSet
#   2004/06/18 08:11:56-07:00 linux@dominikbrodowski.de 
#   [PATCH] round up  in __udelay()
#   
#   Round up in __udelay(): 2**32 / 100000 is 4294.97, so it's more intuitive
#   to round up, and it causes more predictable results:
#   
#   n usec delay on a 1500000 BogoMIPS system:
#   
#     n 	   before	  -mull		after
#     1	 1000 ticks	 1499 ticks	 1500 ticks
#    10	14000 ticks	14999 ticks	15000 ticks
#   
#   n usec delay on a 100000 BogoMIPS system: 
#   
#    n 	   before	  -mull		after
#     1	    0 ticks	   99 ticks	  100 ticks
#    10	    0 ticks	  999 ticks	 1000 ticks
#   100	 9000 ticks	 9999 ticks	10000 ticks
#   
#   While it can be argued that some time is also spent in the delay functions,
#   it's better to spend _at least_ the specified time sleeping, in my humble
#   opinion.  And the overhead of a specific ->delay() implementation should be
#   substracted in the specific ->delay() implementation.
#   
#   Signed-off-by: Dominik Brodowski <linux@brodo.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/delay.h
#   2004/06/18 00:06:04-07:00 linux@dominikbrodowski.de +1 -1
#   round up  in __udelay()
# 
# arch/i386/lib/delay.c
#   2004/06/18 00:32:10-07:00 linux@dominikbrodowski.de +1 -1
#   round up  in __udelay()
# 
# ChangeSet
#   2004/06/18 08:11:46-07:00 linux@dominikbrodowski.de 
#   [PATCH] mull'ify multiplication with HZ in __const_udelay()
#   
#   John Stultz mentioned on lkml ( http://lkml.org/lkml/2004/6/5/15 ) that
#   calls to udelay() don't delay long enough, causing trouble e.g.  in the USB
#   subsystem.  The following patches address this issue.
#   
#   Move the multiplication of (loops_per_jiffy * xloops) with HZ into the
#   "mull" asm operation.  This increases the accuracy of the delay functions
#   largely:
#   
#   n usec delay on a system with loops_per_jiffy = 1500000 :
#   
#     n 	   before	  after
#     1	 1000 ticks	 1499 ticks
#    10	14000 ticks	14999 ticks
#   
#   n usec delay on a system with loops_per_jiffy = 100000 : 
#   
#    n 	   before	  after
#     1	    0 ticks	   99 ticks
#    10	    0 ticks	  999 ticks
#   100	 9000 ticks	 9999 ticks
#   
#   As noted by Kurt Garloff, it's necessary to adjust for large
#   loops_per_jiffies, as the multiplication of it with HZ fails for 4GHz or
#   larger.  So, John Stultz suggested multiplying xloops with 4 first, and
#   multiplying with (HZ/4).
#   
#   Signed-off-by: Dominik Brodowski <linux@brodo.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/lib/delay.c
#   2004/06/18 00:32:10-07:00 linux@dominikbrodowski.de +3 -2
#   mull'ify multiplication with HZ in __const_udelay()
# 
# ChangeSet
#   2004/06/18 08:11:35-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] Fix raid1 read_balancing code.
#   
#   The meaning of mddev->in_sync changed subtly a while ago, and raid1 wasn't
#   changed to match.  This results in raid1 read_balancing not working
#   properly.  This patch corrects the relevant test.
#   
#   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/raid1.c
#   2004/06/18 00:06:03-07:00 neilb@cse.unsw.edu.au +2 -1
#   Fix raid1 read_balancing code.
# 
# ChangeSet
#   2004/06/18 08:11:24-07:00 alex@clusterfs.com 
#   [PATCH] ext3: htree readdir fix
#   
#   I've observed that ext3_htree_fill_tree() doesn't ignore empty records
#   (de->inode == 0).  test case is very simple: turn htree on, create several
#   hundreds of files, remove them and look at strace ls:
#   
#   [root@victim tests]# ls -a /test/1
#   .  ..
#   
#   [root@victim tests]# strace ls /test/1/
#   ....
#   getdents64(3, /* 18 entries */, 4096)   = 432
#   getdents64(3, /* 0 entries */, 4096)    = 0
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ext3/namei.c
#   2004/06/18 00:06:03-07:00 alex@clusterfs.com +2 -0
#   ext3: htree readdir fix
# 
# ChangeSet
#   2004/06/18 08:11:13-07:00 wli@holomorphy.com 
#   [PATCH] fix isofs ignoring noexec and mode mount options
#   
#    * Removed period check for executables in fs/isofs/inode.c
#   This fixes Debian BTS #162190
#   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=162190
#   
#   	From: Jan Gregor <gregor_jan@seznam.cz>
#   	To: Debian Bug Tracking System <submit@bugs.debian.org>
#   	Subject: kernel-source-2.4.18: kernel ignores noexec and mode option in cdrom case
#   	Message-ID: <20020924162129.A328@pisidlo>
#   
#   In /etc/fstab i have following line:
#   /dev/cdrom      /cdrom          iso9660  gid=100,noauto,ro,noexec,mode=0444,user      0       0
#   
#   I found on one CD that some files have exec bit set. From brief view
#   those files has no extension (filename.ext).
#   
#   My drive is asus-1610a (ATAPI writer) connected throught scsi-emulation.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/isofs/inode.c
#   2004/06/18 00:06:03-07:00 wli@holomorphy.com +0 -8
#   fix isofs ignoring noexec and mode mount options
# 
# ChangeSet
#   2004/06/18 08:11:04-07:00 wli@holomorphy.com 
#   [PATCH] fix handling of '/' embedded in filenames in isofs
#   
#    * Fix slashes in broken Acorn ISO9660 images in fs/isofs/dir.c (Darren Salt)
#   This fixes Debian BTS #141660.
#   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=141660
#   
#   	From: Darren Salt <linux@youmustbejoking.demon.co.uk>
#   	Message-ID: <4B238BA09A%linux@youmustbejoking.demon.co.uk>
#   	To: submit@bugs.debian.org
#   	Subject: Handle '/' in filenames in broken ISO9660 images
#   
#   [Also applicable to 2.2.x]
#   
#   There has been for some time a problem with certain CD-ROMs whose images
#   were generated using a particular tool on Acorn RISC OS.  The problem is
#   that in certain catalogue entries, the extension separator character '/'
#   (RISC OS uses '.' and '/' the other way round) was not replaced with '.';
#   thus Linux cannot properly parse this without this patch, thinking that it
#   is a directory separator.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/isofs/dir.c
#   2004/06/18 00:06:03-07:00 wli@holomorphy.com +2 -1
#   fix handling of '/' embedded in filenames in isofs
# 
# ChangeSet
#   2004/06/18 08:10:53-07:00 wli@holomorphy.com 
#   [PATCH] fix duplicate environment variables passed to init
#   
#    * Fixed argument processing bug in init/main.c (Eric Delaunay)
#   This fixes Debian BTS #58566.
#   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=58566
#   
#   	From: Eric Delaunay <delaunay@lix.polytechnique.fr>
#   	Message-Id: <200002201918.UAA02327@jazz.pontchartrain.fr>
#   	Subject: pb in handling parameters on kernel command line
#   	To: submit@bugs.debian.org (debian bug tracking system)
#   
#   Hello, I found some bugs in kernel command line parser.  AFAIK, they are not
#   Debian nor sparc specific but I'm not subscribed to linux-kernel mailing list
#   and since I'm involved with boot-floppies (mainly for sparc), I think I'm right
#   to report it here.  Feel free to forward it upstream (I checked the latest
#   2.3.46 sources and it seems these bugs are still there).
#   
#   These bugs are not release critical.  The latter just not gives the user a
#   chance to overwrite TERM env var at boot time.  It could be just
#   inconvenient for serial console boot, and in this case, our busybox' init is
#   already enforcing TERM=vt102.
#   Nevertheless if it could not be fixed before the release, I could even write a
#   workaround in busybox' init (it's just a matter of rewriting getenv()).
#   
#   At last, it does not affect sysvinit package because serial console tty is
#   controlled by a getty process which is reading terminal settings on its command
#   line (take a look in inittab for T0 entries, if any).
#   
#   Ok, here is my modest contribution to kernel hacking.  I don't know much about
#   kernel internals but it seems that argument parsing is a bit broken.
#   
#   One trivial patch for command line like "init=/bin/sh console=prom" where
#   console=prom is replaced by lot of spaces in previous call to setup_arch() on
#   sparc, therefore the line parsed by parse_options() is really
#   "init=/bin/sh            " and a lot of null args are pushed into argv_init.
#   
#   The other patch is for command line like "TERM=vt100" where both default & user
#   TERM entries are pushed into the env array.
#   Taking a look into /proc/1/environ, it shows up:
#   HOME=/
#   TERM=linux
#   TERM=vt100
#   
#   It appears that ash (maybe other shells too) is giving the latter entry but
#   glibc getenv() is giving the former.  It is therefore impossible to get entry
#   from the user in a C program like busybox' init (used in Debian boot-floppies).
#   
#   I guess getenv() is not written to support duplicate entries, therefore the
#   kernel should avoid such construct.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# init/main.c
#   2004/06/18 00:06:03-07:00 wli@holomorphy.com +2 -0
#   fix duplicate environment variables passed to init
# 
# ChangeSet
#   2004/06/18 08:10:43-07:00 wli@holomorphy.com 
#   [PATCH] unregister driver if probing fails in sb_card.c
#   
#    * Unregister driver if probing fails in sound/oss/sb_card.c
#   This fixes Debian BTS #218845.
#   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=218845
#   
#   	From: Robin Gerard <robin.jag@free.fr>
#   	To: submit@bugs.debian.org
#   	Subject: no sound with kernel-image-2.6.0-test9-1-386
#   	Message-ID: <20031103004939.GA2071@mauritius>
#   
#   I downlaoded the kernel-image-2.6.0-test9-1-386_2.6.0-test9-1_i386.deb
#   and I installed it successfully. Everything works fine, except the sound.
#   (I run also the kernel-image-2.4.20 and the sound is ok with this kernel)
#   My sound card is a sb.
#   
#   First I launched modconf but no module was displayed.
#   
#   I did: modprobe sb
#   and I got:
#   
#   sb: Init: Done
#   sb: Init: Starting Probe...
#   kobject_register failed for OSS SndBlstr (-17)
#   Call Trace:
#   [<c0191cda>] kobject_register+0x3a/0x40
#   [<c01d9bcc>] bus_add_driver+0x30/0x64
#   [<c01d9e51>] driver_register+0x2d/0x34
#   [<c011a24a>] preempt_schedule+0x2a/0x48
#   [<c01b6f84>] pnp_register_driver+0x28/0x58
#   [<c01b6c5e>] pnp_register_card_driver+0x5e/0x98
#   [<c488f063>] sb_init+0x63/0xb5 [sb]
#   [<c0130bf4>] sys_init_module+0xe8/0x1f0
#   [<c010b577>] syscall_call+0x7/0xb
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/sb_card.c
#   2004/06/18 00:06:03-07:00 wli@holomorphy.com +7 -1
#   unregister driver if probing fails in sb_card.c
# 
# ChangeSet
#   2004/06/18 08:10:32-07:00 wli@holomorphy.com 
#   [PATCH] lower priority of "too many keys" msg in atkbd.c
#   
#   From: "Jon Thackray" <jgt@pobox.com>
#   
#    * Lowered priority of "too many keys" message in drivers/input/keyboard/atkbd.c
#   This fixes Debian BTS #239036.
#   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=239036
#   
#   
#   The keyboard under 2.6.4 seems to be behaving strangely, reporting unknown
#   key codes and too many keys pressed, even when no keys have been pressed.
#   The keyboard is connected via an 8 way KVM switch, but was working quite
#   acceptably under 2.4.25 with no such messages.  Trying 2.6.3 is not an
#   option as it doesn't support the hardware properly, as previously reported.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/input/keyboard/atkbd.c
#   2004/06/18 00:48:49-07:00 wli@holomorphy.com +1 -1
#   lower priority of "too many keys" msg in atkbd.c
# 
# ChangeSet
#   2004/06/18 08:10:21-07:00 rddunlap@osdl.org 
#   [PATCH] istallion printk fix
#   
#   istallion: Remove duplicate "%d" in printk();
#   
#   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/char/istallion.c
#   2004/06/18 00:06:03-07:00 rddunlap@osdl.org +1 -1
#   istallion printk fix
# 
# ChangeSet
#   2004/06/18 08:10:10-07:00 egmont@uhulinux.hu 
#   [PATCH] Shift+PgUp if nr of scrolled lines is < 4
#   
#   Using the vga console driver, if the number of the lines scrolled out is
#   less than four, then Shift+PageUp doesn't work.
#   
#   The bug is closely related to the 'margin' feature of scrolling, which
#   means that if less than four lines should remain unvisible in the direction
#   we are scrolling to, then we scroll a little bit more just to see those few
#   lines.  Kind of two small magnets at the borders of the buffer.
#   
#   This bug was also reported with maybe a less clear description by Stepan
#   Koltsov (cc'ed just for fun) back in 2001 and he got no answer.  I found it
#   at http://seclists.org/lists/linux-kernel/2001/Nov/0080.html
#   
#   His patch simply disables margin support and hence everythings becomes
#   okay, but you lose a nice feature.
#   
#   Here's a patch that retains margin support and fixes the bug.  Works for
#   me, tested for a week.  No guarantee.  As I don't fully understand the code
#   (see also my previous mail) I'm not 100% sure that I'm doing the right
#   thing, so I'd prefer if someone would take a closer look at it.
#   
#   At least 2.4 and 2.6 are affected, maybe older ones too.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/console/vgacon.c
#   2004/06/18 00:06:02-07:00 egmont@uhulinux.hu +2 -0
#   Shift+PgUp if nr of scrolled lines is < 4
# 
# ChangeSet
#   2004/06/18 08:09:59-07:00 davidel@xmailserver.org 
#   [PATCH] epoll: replace the file lookup hash with rbtrees
#   
#   The epoll allocation for the fd lookup hash used to allocate up to 1MB
#   (depending on the "hint" size passed to epoll_create()) with
#   __get_free_pages(0), and this might lead to a "malicious" user to do
#   something like:
#   
#       for (i = 0; i < 1024; i++)
#           epoll_create(BIG-NUM);
#   
#   You can replace "malicious user" with IBM-ltp test suite, and the meaning
#   does not change.  The above code might exhaust memory badly, even before
#   the file creation limit is topped.  Also, the allocation was independent
#   from the number of fds pushed into the epoll fd hash.  Using an rb-tree
#   ther will be not pre-allocation of the hash, and the size of the memory
#   used will be proportional to the number of fds pushed into the epoll fd.
#   The patch also removes 100 lines of code, that is never a bad thing ;)
#   
#   Signed-off-by: Davide Libenzi <davidel@xmailserver.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/eventpoll.c
#   2004/06/18 00:06:02-07:00 davidel@xmailserver.org +93 -187
#   epoll: replace the file lookup hash with rbtrees
# 
# ChangeSet
#   2004/06/18 08:09:48-07:00 rtjohnso@eecs.berkeley.edu 
#   [PATCH] drivers/char/ipmi/ipmi_devintf.c: user/kernel pointer typo
#   
#   Judging from context, I think there's a misplaced "&" in this code that can
#   cause stack overflows and other nasty problems.  Perhaps it's left over
#   from when msgdata was an array instead of a pointer?
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/ipmi/ipmi_devintf.c
#   2004/06/18 00:32:07-07:00 rtjohnso@eecs.berkeley.edu +1 -1
#   drivers/char/ipmi/ipmi_devintf.c: user/kernel pointer typo
# 
# ChangeSet
#   2004/06/18 08:09:37-07:00 akpm@osdl.org 
#   [PATCH] Make update_one_process() static
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/timer.c
#   2004/06/17 23:59:01-07:00 akpm@osdl.org +1 -1
#   Make update_one_process() static
# 
# include/linux/sched.h
#   2004/06/18 00:32:06-07:00 akpm@osdl.org +0 -2
#   Make update_one_process() static
# 
# ChangeSet
#   2004/06/18 08:09:26-07:00 vandrove@vc.cvut.cz 
#   [PATCH] Decrease stack usage in ncpfs's ioctl
#   
#   It decreases stack consumption in one of ncpfs's paths from 3000 to 2200
#   bytes (and stack portion in ncpfs ioctl code from 1336 to 452 bytes).
#   
#   - some code used large structure (with embeded 256 bytes for filename)
#     while it never passed filename around.  Use something smaller in
#     ncp_conn_logged_in.  Decrease 616 => 300.
#   
#   - gcc-3.3 is very bad when it comes to parallel blocks in ioctl.  Split
#     some branches from large switch to separate functions.  ncp_ioctl now
#     uses 152 bytes of stack (instead of 720) and biggest child 64.
#   
#   Signed-off-by: Petr Vandrovec <vandrove@vc.cvut.cz>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ncpfs/ncplib_kernel.h
#   2004/06/17 23:59:01-07:00 vandrove@vc.cvut.cz +5 -3
#   Decrease stack usage in ncpfs's ioctl
# 
# fs/ncpfs/ncplib_kernel.c
#   2004/06/17 23:59:01-07:00 vandrove@vc.cvut.cz +27 -15
#   Decrease stack usage in ncpfs's ioctl
# 
# fs/ncpfs/ioctl.c
#   2004/06/17 23:59:01-07:00 vandrove@vc.cvut.cz +160 -157
#   Decrease stack usage in ncpfs's ioctl
# 
# fs/ncpfs/dir.c
#   2004/06/17 23:59:01-07:00 vandrove@vc.cvut.cz +5 -5
#   Decrease stack usage in ncpfs's ioctl
# 
# ChangeSet
#   2004/06/18 08:09:16-07:00 herbert@gondor.apana.org.au 
#   [PATCH] swsusp: remove copy_pagedir
#   
#   It can be replaced by a simple memcpy.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/swsusp.c
#   2004/06/17 23:59:00-07:00 herbert@gondor.apana.org.au +3 -16
#   swsusp: remove copy_pagedir
# 
# kernel/power/pmdisk.c
#   2004/06/17 23:59:00-07:00 herbert@gondor.apana.org.au +4 -16
#   swsusp: remove copy_pagedir
# 
# ChangeSet
#   2004/06/18 08:09:05-07:00 herbert@gondor.apana.org.au 
#   [PATCH] remove unnecessary memsets from swsusp and pmdisk
#   
#   Here's the patch that removes the memset calls from both pmdisk and swsusp.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/swsusp.c
#   2004/06/18 00:32:12-07:00 herbert@gondor.apana.org.au +0 -1
#   remove unnecessary memsets from swsusp and pmdisk
# 
# kernel/power/pmdisk.c
#   2004/06/18 00:32:12-07:00 herbert@gondor.apana.org.au +0 -1
#   remove unnecessary memsets from swsusp and pmdisk
# 
# ChangeSet
#   2004/06/18 08:08:54-07:00 herbert@gondor.apana.org.au 
#   [PATCH] omdisk memory leak fix
#   
#   Fix a couple of memory leaks in the pmdisk driver.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/pmdisk.c
#   2004/06/18 00:32:13-07:00 herbert@gondor.apana.org.au +11 -11
#   omdisk memory leak fix
# 
# ChangeSet
#   2004/06/18 08:08:43-07:00 pavel@ucw.cz 
#   [PATCH] Fix memory leak in swsusp
#   
#   This fixes 2 memory leaks in swsusp: during relocating pagedir, eaten pages
#   were not properly freed in error path and even regular freeing path was
#   freeing one page too little.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/swsusp.c
#   2004/06/18 00:32:13-07:00 pavel@ucw.cz +16 -11
#   Fix memory leak in swsusp
# 
# ChangeSet
#   2004/06/18 08:08:32-07:00 axboe@suse.de 
#   [PATCH] blk: move threshold unplugging
#   
#   The 'unplug on queued exceeding unplug threshold' logic only works for file
#   system requests currently, since it's in __make_request().  Move it where
#   it belongs, in elv_add_request().  This way it works for queued block sg
#   requests as well.
#   
#   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/linux/blkdev.h
#   2004/06/18 08:08:26-07:00 axboe@suse.de +1 -0
#   blk: move threshold unplugging
# 
# drivers/block/ll_rw_blk.c
#   2004/06/18 08:08:26-07:00 axboe@suse.de +4 -7
#   blk: move threshold unplugging
# 
# drivers/block/elevator.c
#   2004/06/18 08:08:26-07:00 axboe@suse.de +8 -0
#   blk: move threshold unplugging
# 
# ChangeSet
#   2004/06/18 08:08:21-07:00 axboe@suse.de 
#   [PATCH] fix cdrom mt rainier probe
#   
#   Mt rainier probe must be deferred to media load time, since it requires a
#   valid media (the drive may present a different capability based on what
#   media is loaded).  This fixes that for ide-cd and sr.
#   
#   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/sr.c
#   2004/06/18 08:08:15-07:00 axboe@suse.de +1 -15
#   fix cdrom mt rainier probe
# 
# drivers/ide/ide-cd.h
#   2004/06/18 08:08:15-07:00 axboe@suse.de +0 -2
#   fix cdrom mt rainier probe
# 
# drivers/ide/ide-cd.c
#   2004/06/18 08:08:15-07:00 axboe@suse.de +1 -22
#   fix cdrom mt rainier probe
# 
# drivers/cdrom/cdrom.c
#   2004/06/18 08:08:15-07:00 axboe@suse.de +30 -2
#   fix cdrom mt rainier probe
# 
# ChangeSet
#   2004/06/18 08:08:10-07:00 mikem@beardog.cca.cpqcorp.net 
#   [PATCH] cciss ioctl32 update
#   
#   This patch provides a conversion routine for 32-bit user space apps that
#   call into a 64-bit kernel on x86_64 architectures.  This is required for
#   the HP Array Configuration utility and the HP management agents.  Without
#   this patch the apps will not function.
#   
#   The 2 ioctls affected are the cciss pass thru ioctls.  Caveat: it spits out
#   2 warnings during compilation.  I've tried everything I can think of to
#   clean them up, but...  If anyone has any helpful suggestions I'm all ears.
#   
#   Code by Stephen Cameron
#   Tested by Stephen Cameron & Mike Miller
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/cciss_ioctl.h
#   2004/06/18 08:08:04-07:00 mikem@beardog.cca.cpqcorp.net +28 -0
#   cciss ioctl32 update
# 
# drivers/block/cciss.c
#   2004/06/18 08:08:04-07:00 mikem@beardog.cca.cpqcorp.net +144 -0
#   cciss ioctl32 update
# 
# ChangeSet
#   2004/06/18 08:07:59-07:00 andrea@suse.de 
#   [PATCH] remap_file_pages() speedup
#   
#   Avoid taking down_write(mmap_sem) unless we really need it.
#   
#   Seems that the only reason we're taking it for writing is to protect
#   vma->vm_flags.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/fremap.c
#   2004/06/17 23:58:59-07:00 andrea@suse.de +12 -5
#   remap_file_pages() speedup
# 
# ChangeSet
#   2004/06/18 08:07:48-07:00 arun.sharma@intel.com 
#   [PATCH] sys_getdents64 needs compat wrapper
#   
#   Due to different structure alignment rules in the ABI between ia32 and
#   ia64, certain members of the dirent structure are not guaranteed to be 8
#   byte aligned on ia64.  This requires a compat wrapper around these 32 bit
#   system calls.  Other architectures may or may not have the problem,
#   depending on the alignment rules.
#   
#   This was observed by running /emul/ia32-linux/bin/ls on 2.6.6 which produces
#   kernel mode unaligned faults.
#   
#   Original patch by: Arnd Bergmann <arnd@arndb.de>
#   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>
# 
# fs/compat.c
#   2004/06/17 23:58:59-07:00 arun.sharma@intel.com +255 -0
#   sys_getdents64 needs compat wrapper
# 
# arch/ia64/ia32/ia32_entry.S
#   2004/06/17 23:58:59-07:00 arun.sharma@intel.com +2 -2
#   sys_getdents64 needs compat wrapper
# 
# ChangeSet
#   2004/06/18 08:07:37-07:00 tvignaud@mandrakesoft.com 
#   [PATCH] checksatck.pl fixes
#   
#   - "\<" and "\>" can be safely replaced with "<" and ">"
#   
#   - "$var =~ /^string$/" is better written "$var eq 'string'"
#   
#   - $i is better written without the double quotes
#   
#   - it's not safe to use for without "my"ing the iteration variable
#   
#   - "print foreach @array" is better written "print @array"
#   
#   - declare variables
#   
#   - ".*" is useless at the end of a regexp
#   
#   - "$a[@a] = $foo" is a rather obfuscated syntax for "push @a, $foo"...
#     let's not opencoding language basic operators...
#   
#   - ignoring return value from a regexp is very bad: this can results in
#     working on previous value of $1, $2, ...
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# scripts/checkstack.pl
#   2004/06/17 23:58:59-07:00 tvignaud@mandrakesoft.com +14 -15
#   checksatck.pl fixes
# 
# ChangeSet
#   2004/06/18 08:07:26-07:00 ashok.raj@intel.com 
#   [PATCH] don't create cpu/online sysfs file
#   
#   This file provides ability for caller of register_cpu() to either create a
#   control file, or not.  This can be handy if a particular platform decides
#   that certain CPU's are not removable.  Hence would like to not create a
#   control file.
#   
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Ashok Raj <ashok.raj@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/cpu.h
#   2004/06/17 23:58:59-07:00 ashok.raj@intel.com +1 -0
#   don't create cpu/online sysfs file
# 
# drivers/base/cpu.c
#   2004/06/17 23:58:59-07:00 ashok.raj@intel.com +3 -1
#   don't create cpu/online sysfs file
# 
# arch/ppc64/kernel/sysfs.c
#   2004/06/17 23:58:59-07:00 ashok.raj@intel.com +10 -0
#   don't create cpu/online sysfs file
# 
# ChangeSet
#   2004/06/18 08:07:15-07:00 umka@namesys.com 
#   [PATCH] memory allocation checks in cs46xx_dsp_proc_register_scb_desc()
#   
#   Adds memory allocation checks in cs46xx_dsp_proc_register_scb_desc()
#   
#   Signed-off-by: Yury Umanets <torque@ukrpost.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/pci/cs46xx/dsp_spos_scb_lib.c
#   2004/06/17 23:57:06-07:00 umka@namesys.com +7 -1
#   memory allocation checks in cs46xx_dsp_proc_register_scb_desc()
# 
# ChangeSet
#   2004/06/18 08:07:05-07:00 torque@ukrpost.net 
#   [PATCH] memory allocation checks in mtdblock_open()
#   
#   Fixes memory allocation check in mtdblock_open()
#   
#   Signed-off-by: Yury Umanets <torque@ukrpost.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/mtd/mtdblock.c
#   2004/06/17 23:57:06-07:00 torque@ukrpost.net +1 -1
#   memory allocation checks in mtdblock_open()
# 
# ChangeSet
#   2004/06/18 08:06:54-07:00 torque@ukrpost.net 
#   [PATCH] memory allocation checks in eth1394_update()
#   
#   Adds memory allocation checks in eth1394_update().
#   
#   Signed-off-by: Yury Umanets <torque@ukrpost.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/ieee1394/eth1394.c
#   2004/06/17 23:57:06-07:00 torque@ukrpost.net +4 -1
#   memory allocation checks in eth1394_update()
# 
# ChangeSet
#   2004/06/18 08:06:43-07:00 ak@suse.de 
#   [PATCH] Use numa policy API for boot time policy
#   
#   Suggested by Manfred Spraul.
#   
#   __get_free_pages had a hack to do node interleaving allocation at boot
#   time.  This patch sets an interleave process policy using the NUMA API for
#   init and the idle threads instead.  Before entering the user space init the
#   policy is reset to default again.  Result is the same.
#   
#   Advantage is less code and removing of a check from a fast path.
#   
#   Removes more code than it adds.
#   
#   I verified that the memory distribution after boot is roughly the same.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/page_alloc.c
#   2004/06/17 23:57:05-07:00 ak@suse.de +0 -41
#   Use numa policy API for boot time policy
# 
# mm/mempolicy.c
#   2004/06/17 23:57:05-07:00 ak@suse.de +15 -3
#   Use numa policy API for boot time policy
# 
# init/main.c
#   2004/06/18 00:32:11-07:00 ak@suse.de +4 -0
#   Use numa policy API for boot time policy
# 
# include/linux/mempolicy.h
#   2004/06/17 23:57:05-07:00 ak@suse.de +11 -0
#   Use numa policy API for boot time policy
# 
# ChangeSet
#   2004/06/18 08:06:32-07:00 wli@holomorphy.com 
#   [PATCH] apic: make mach_default compile again
#   
#   While sweeping the APIC code two points were missed.  The first is getting
#   the definition of BAD_APICID available to
#   include/asm-i386/mach-default/mach_apic.h by #including the right header,
#   and the second is UP local APIC without UP IO-APIC linking in
#   get_broadcast_physid().
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/mach-default/mach_apic.h
#   2004/06/17 23:56:25-07:00 wli@holomorphy.com +1 -0
#   apic: make mach_default compile again
# 
# arch/i386/kernel/io_apic.c
#   2004/06/17 23:56:25-07:00 wli@holomorphy.com +0 -11
#   apic: make mach_default compile again
# 
# arch/i386/kernel/apic.c
#   2004/06/17 23:56:25-07:00 wli@holomorphy.com +11 -0
#   apic: make mach_default compile again
# 
# ChangeSet
#   2004/06/18 08:06:21-07:00 wli@holomorphy.com 
#   [PATCH] apic: remove marking of non-present physids in phys_cpu_present_map
#   
#   Marking invalid APIC ID's in phys_cpu_present_map was intended to generate
#   "collisions" between APIC ID's in order to assist the ordinary bounds
#   checking against the broadcast physical APIC ID.  However, this is bounds
#   checked everywhere it's necessary, and it's also not even possible to
#   properly bounds-check everywhere.  So this patch removes that marking of
#   non-present physical APIC ID's.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mach-visws/mpparse.c
#   2004/06/17 23:56:23-07:00 wli@holomorphy.com +0 -8
#   apic: remove marking of non-present physids in phys_cpu_present_map
# 
# arch/i386/kernel/mpparse.c
#   2004/06/17 23:56:23-07:00 wli@holomorphy.com +1 -13
#   apic: remove marking of non-present physids in phys_cpu_present_map
# 
# ChangeSet
#   2004/06/18 08:06:09-07:00 wli@holomorphy.com 
#   [PATCH] apic: fix kicking of non-present cpus
#   
#   The following patch repairs kicking of non-present cpus by making
#   cpu_present_to_apicid() bounds-check its argument.  It also corrects the
#   same issue on NUMA-Q by correctly passing the generated artificial APIC ID
#   instead of the raw value discovered in the MP table.
#   
#   A miscellaneous compilefix for CONFIG_ACPI_BOOT is also included for
#   completeness.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/mach-visws/mach_apic.h
#   2004/06/17 23:55:40-07:00 wli@holomorphy.com +4 -1
#   apic: fix kicking of non-present cpus
# 
# include/asm-i386/mach-default/mach_apic.h
#   2004/06/18 00:32:15-07:00 wli@holomorphy.com +4 -1
#   apic: fix kicking of non-present cpus
# 
# include/asm-i386/apic.h
#   2004/06/17 23:55:40-07:00 wli@holomorphy.com +2 -0
#   apic: fix kicking of non-present cpus
# 
# arch/i386/kernel/mpparse.c
#   2004/06/18 00:32:15-07:00 wli@holomorphy.com +4 -4
#   apic: fix kicking of non-present cpus
# 
# arch/i386/kernel/io_apic.c
#   2004/06/18 00:32:15-07:00 wli@holomorphy.com +1 -1
#   apic: fix kicking of non-present cpus
# 
# ChangeSet
#   2004/06/18 08:05:58-07:00 wli@holomorphy.com 
#   [PATCH] APIC enumeration fixes
#   
#   The following patch appears sound according to an audit to ensure that all
#   of the codepaths where it was introduced were called after the APIC
#   fixmappings were set up.
#   
#   This patch introduces get_physical_broadcast(), which checks the version ID
#   of the local APIC to determine whether it's a serial APIC or xAPIC, and
#   returns the correct physical broadcast ID.  It replaces all uses of
#   APIC_BROADCAST_ID and IO_APIC_MAX_ID with this in order to ensure.  It also
#   changes the checks during MP table parsing so the APIC ID is checked in
#   tandem with the version number.
#   
#   I'm holding out for some kind of testing to get an idea of whether this
#   covers the cases or introduces regressions, or whatever.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/mpspec_def.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +1 -0
#   APIC enumeration fixes
# 
# include/asm-i386/mach-visws/mach_apic.h
#   2004/06/18 00:32:15-07:00 wli@holomorphy.com +0 -1
#   APIC enumeration fixes
# 
# include/asm-i386/mach-summit/mach_mpspec.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5
#   APIC enumeration fixes
# 
# include/asm-i386/mach-summit/mach_apic.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1
#   APIC enumeration fixes
# 
# include/asm-i386/mach-numaq/mach_mpspec.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5
#   APIC enumeration fixes
# 
# include/asm-i386/mach-numaq/mach_apic.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1
#   APIC enumeration fixes
# 
# include/asm-i386/mach-generic/mach_mpspec.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5
#   APIC enumeration fixes
# 
# include/asm-i386/mach-generic/mach_apic.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1
#   APIC enumeration fixes
# 
# include/asm-i386/mach-es7000/mach_mpspec.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5
#   APIC enumeration fixes
# 
# include/asm-i386/mach-es7000/mach_apic.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1
#   APIC enumeration fixes
# 
# include/asm-i386/mach-default/mach_mpspec.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5
#   APIC enumeration fixes
# 
# include/asm-i386/mach-default/mach_apic.h
#   2004/06/18 00:32:15-07:00 wli@holomorphy.com +0 -6
#   APIC enumeration fixes
# 
# include/asm-i386/mach-bigsmp/mach_mpspec.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5
#   APIC enumeration fixes
# 
# include/asm-i386/mach-bigsmp/mach_apic.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1
#   APIC enumeration fixes
# 
# include/asm-i386/genapic.h
#   2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -2
#   APIC enumeration fixes
# 
# arch/i386/mach-visws/mpparse.c
#   2004/06/18 00:32:15-07:00 wli@holomorphy.com +10 -2
#   APIC enumeration fixes
# 
# arch/i386/kernel/mpparse.c
#   2004/06/18 00:32:15-07:00 wli@holomorphy.com +30 -2
#   APIC enumeration fixes
# 
# arch/i386/kernel/io_apic.c
#   2004/06/18 00:32:15-07:00 wli@holomorphy.com +18 -9
#   APIC enumeration fixes
# 
# ChangeSet
#   2004/06/18 08:05:47-07:00 akpm@osdl.org 
#   [PATCH] i386 uninline some bitops
#   
#   Uninline the non-leaf bit search functions.  Saves 9 kbytes from my vmlinux.
#   
#   And gratuitously s/__inline__/inline/
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/lib/bitops.c
#   2004/06/17 23:55:22-07:00 akpm@osdl.org +70 -0
#   i386 uninline some bitops
# 
# include/asm-i386/bitops.h
#   2004/06/17 23:55:22-07:00 akpm@osdl.org +27 -77
#   i386 uninline some bitops
# 
# arch/i386/lib/bitops.c
#   2004/06/17 23:55:22-07:00 akpm@osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/i386/lib/bitops.c
# 
# arch/i386/lib/Makefile
#   2004/06/17 23:55:22-07:00 akpm@osdl.org +2 -3
#   i386 uninline some bitops
# 
# ChangeSet
#   2004/06/18 08:05:36-07:00 wli@holomorphy.com 
#   [PATCH] x86_64 numa cpumask build fix
#   
#   arch/x86_64/mm/numa.c: In function `numa_initmem_init':
#   arch/x86_64/mm/numa.c:185: error: incompatible types in assignment
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/x86_64/mm/numa.c
#   2004/06/17 23:53:45-07:00 wli@holomorphy.com +1 -1
#   x86_64 numa cpumask build fix
# 
# ChangeSet
#   2004/06/18 08:05:25-07:00 tom.l.nguyen@intel.com 
#   [PATCH] msi TARGET_CPUS fix
#   
#   Somehow the change in TARGET_CPUS generated this error in UP environment.
#   Patch below will fix it.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/msi.h
#   2004/06/17 23:53:44-07:00 tom.l.nguyen@intel.com +1 -1
#   msi TARGET_CPUS fix
# 
# ChangeSet
#   2004/06/18 08:05:14-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: dm-raid1.c: Use list_for_each_entry_safe
#   
#   dm-raid1.c: In rh_exit(), use list_for_each_entry_safe instead of
#   list_for_each_safe.
#   
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-raid1.c
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +2 -4
#   dm: dm-raid1.c: Use list_for_each_entry_safe
# 
# ChangeSet
#   2004/06/18 08:05:03-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: dm-raid1.c: Make delayed_bios a bio_list
#   
#   dm-raid1.c: Make struct region::delayed_bios a bio_list instead of a bio*.
#   This will ensure the queued bios are kept in the proper order.
#   
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-raid1.c
#   2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +7 -10
#   dm: dm-raid1.c: Make delayed_bios a bio_list
# 
# ChangeSet
#   2004/06/18 08:04:52-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: dm-io: Error handling
#   
#   dm-io: Proper error handling when someone is trying to read from multiple
#   regions.
#   
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-io.c
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +12 -2
#   dm: dm-io: Error handling
# 
# ChangeSet
#   2004/06/18 08:04:41-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: Use structure assignments instead of memcpy
#   
#   Use structure assignments instead of memcpy's.
#   [Suggested by akpm during kcopyd review.]
#   
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/kcopyd.c
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +2 -2
#   dm: Use structure assignments instead of memcpy
# 
# drivers/md/dm.c
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +1 -1
#   dm: Use structure assignments instead of memcpy
# 
# drivers/md/dm-table.c
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +2 -2
#   dm: Use structure assignments instead of memcpy
# 
# drivers/md/dm-snap.c
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +1 -1
#   dm: Use structure assignments instead of memcpy
# 
# drivers/md/dm-raid1.c
#   2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +2 -2
#   dm: Use structure assignments instead of memcpy
# 
# ChangeSet
#   2004/06/18 08:04:32-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: Create/destroy kcopyd on demand.
#   
#   Create/destroy kcopyd on demand.
#   
#   This changes kcopyd to initialize its mempool and workqueue only when a
#   client specifically needs to use it.
#   
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/kcopyd.h
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -3
#   dm: Create/destroy kcopyd on demand.
# 
# drivers/md/kcopyd.c
#   2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +61 -27
#   dm: Create/destroy kcopyd on demand.
# 
# drivers/md/dm.h
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -3
#   dm: Create/destroy kcopyd on demand.
# 
# drivers/md/dm.c
#   2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +0 -1
#   dm: Create/destroy kcopyd on demand.
# 
# ChangeSet
#   2004/06/18 08:04:21-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: Documentation
#   
#   Device-Mapper documentation.
#   
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/device-mapper/zero.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +37 -0
#   dm: Documentation
# 
# Documentation/device-mapper/striped.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +58 -0
#   dm: Documentation
# 
# Documentation/device-mapper/linear.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +61 -0
#   dm: Documentation
# 
# Documentation/device-mapper/kcopyd.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +47 -0
#   dm: Documentation
# 
# Documentation/device-mapper/dm-io.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +75 -0
#   dm: Documentation
# 
# Documentation/device-mapper/zero.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/zero.txt
# 
# Documentation/device-mapper/striped.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/striped.txt
# 
# Documentation/device-mapper/linear.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/linear.txt
# 
# Documentation/device-mapper/kcopyd.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/kcopyd.txt
# 
# Documentation/device-mapper/dm-io.txt
#   2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/dm-io.txt
# 
# ChangeSet
#   2004/06/18 08:04:10-07:00 christophe@saout.de 
#   [PATCH] Device-mapper: dm-zero flushing fix
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-zero.c
#   2004/06/17 23:53:43-07:00 christophe@saout.de +2 -1
#   Device-mapper: dm-zero flushing fix
# 
# ChangeSet
#   2004/06/18 08:03:59-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: dm-zero version
#   
#   Add missing dm-zero version number.
#   
#   From: Alasdair Kergon <agk@redhat.com>
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-zero.c
#   2004/06/18 00:32:17-07:00 kevcorry@us.ibm.com +1 -0
#   dm: dm-zero version
# 
# ChangeSet
#   2004/06/18 08:03:48-07:00 agk@redhat.com 
#   [PATCH] Device-mapper: dm-zero
#   
#   Add dm-zero target
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-zero.c
#   2004/06/18 00:32:17-07:00 agk@redhat.com +96 -0
#   Device-mapper: dm-zero
# 
# drivers/md/dm-zero.c
#   2004/06/18 00:32:17-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-zero.c
# 
# drivers/md/Makefile
#   2004/06/17 23:53:43-07:00 agk@redhat.com +1 -0
#   Device-mapper: dm-zero
# 
# drivers/md/Kconfig
#   2004/06/17 23:53:43-07:00 agk@redhat.com +7 -0
#   Device-mapper: dm-zero
# 
# ChangeSet
#   2004/06/18 08:03:37-07:00 agk@redhat.com 
#   [PATCH] Device-mapper: mirroring
#   
#   Add mirror target.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-raid1.c
#   2004/06/18 00:32:16-07:00 agk@redhat.com +1283 -0
#   Device-mapper: mirroring
# 
# drivers/md/dm-log.h
#   2004/06/17 23:53:43-07:00 agk@redhat.com +124 -0
#   Device-mapper: mirroring
# 
# drivers/md/dm-log.c
#   2004/06/17 23:53:43-07:00 agk@redhat.com +629 -0
#   Device-mapper: mirroring
# 
# drivers/md/dm-raid1.c
#   2004/06/18 00:32:16-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-raid1.c
# 
# drivers/md/dm-log.h
#   2004/06/17 23:53:43-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-log.h
# 
# drivers/md/dm-log.c
#   2004/06/17 23:53:43-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-log.c
# 
# drivers/md/Makefile
#   2004/06/18 00:32:17-07:00 agk@redhat.com +2 -0
#   Device-mapper: mirroring
# 
# drivers/md/Kconfig
#   2004/06/18 00:32:17-07:00 agk@redhat.com +7 -0
#   Device-mapper: mirroring
# 
# ChangeSet
#   2004/06/18 08:03:25-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: Fix error cleanup in dm_create_persistent()
#   
#   dm-exception-store.c: Fix error cleanup in dm_create_persistent().
#   This was originally found by chrisw during code review.
#   
#   From: Dave Olien <dmo@osdl.org>
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-exception-store.c
#   2004/06/17 23:53:43-07:00 kevcorry@us.ibm.com +2 -2
#   dm: Fix error cleanup in dm_create_persistent()
# 
# ChangeSet
#   2004/06/18 08:03:15-07:00 agk@redhat.com 
#   [PATCH] Device-mapper: snapshots
#   
#   Add snapshot target
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-snap.h
#   2004/06/17 23:53:43-07:00 agk@redhat.com +161 -0
#   Device-mapper: snapshots
# 
# drivers/md/dm-snap.c
#   2004/06/18 00:32:16-07:00 agk@redhat.com +1213 -0
#   Device-mapper: snapshots
# 
# drivers/md/dm-snap.h
#   2004/06/17 23:53:43-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-snap.h
# 
# drivers/md/dm-snap.c
#   2004/06/18 00:32:16-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-snap.c
# 
# drivers/md/dm-exception-store.c
#   2004/06/18 00:32:17-07:00 agk@redhat.com +648 -0
#   Device-mapper: snapshots
# 
# drivers/md/Makefile
#   2004/06/18 00:32:17-07:00 agk@redhat.com +2 -0
#   Device-mapper: snapshots
# 
# drivers/md/Kconfig
#   2004/06/18 00:32:17-07:00 agk@redhat.com +6 -0
#   Device-mapper: snapshots
# 
# drivers/md/dm-exception-store.c
#   2004/06/18 00:32:17-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-exception-store.c
# 
# ChangeSet
#   2004/06/18 08:03:03-07:00 kevcorry@us.ibm.com 
#   [PATCH] kcopyd commentary
#   
#   We're also working on some general documentation which will go in
#   Documentation/device-mapper and will include more detailed information
#   about the core driver and the other sub-modules.  We'll try to submit those
#   patches in the near future.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/kcopyd.h
#   2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +4 -0
#   kcopyd commentary
# 
# drivers/md/kcopyd.c
#   2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +4 -0
#   kcopyd commentary
# 
# ChangeSet
#   2004/06/18 08:02:55-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: kcopyd: No need to lock pages
#   
#   No need to lock kcopyd pages.
#   
#   From: Alasdair Kergon <agk@redhat.com>
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/kcopyd.c
#   2004/06/18 00:32:18-07:00 kevcorry@us.ibm.com +0 -2
#   dm: kcopyd: No need to lock pages
# 
# ChangeSet
#   2004/06/18 08:02:44-07:00 kevcorry@us.ibm.com 
#   [PATCH] dm: kcopyd: remove superfluous INIT_LIST_HEADs
#   
#   Remove superfluous kcopyd INIT_LIST_HEAD.
#   
#   From: Alasdair Kergon <agk@redhat.com>
#   Signed-off-by: Kevin Corry <kevcorry@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/kcopyd.c
#   2004/06/18 00:32:18-07:00 kevcorry@us.ibm.com +0 -4
#   dm: kcopyd: remove superfluous INIT_LIST_HEADs
# 
# ChangeSet
#   2004/06/18 08:02:33-07:00 agk@redhat.com 
#   [PATCH] Device-mapper: kcopyd
#   
#   Add kcopyd - a daemon for copying regions of block devices around in an
#   efficient manner.  Multiple destinations can be specified for a copy.
#   Designed to perform well both with many small chunks or few large chunks.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/kcopyd.h
#   2004/06/18 00:32:18-07:00 agk@redhat.com +41 -0
#   Device-mapper: kcopyd
# 
# drivers/md/kcopyd.c
#   2004/06/18 00:32:18-07:00 agk@redhat.com +667 -0
#   Device-mapper: kcopyd
# 
# drivers/md/kcopyd.h
#   2004/06/18 00:32:18-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/kcopyd.h
# 
# drivers/md/kcopyd.c
#   2004/06/18 00:32:18-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/kcopyd.c
# 
# drivers/md/dm.h
#   2004/06/18 00:32:16-07:00 agk@redhat.com +3 -0
#   Device-mapper: kcopyd
# 
# drivers/md/dm.c
#   2004/06/18 00:32:16-07:00 agk@redhat.com +1 -0
#   Device-mapper: kcopyd
# 
# drivers/md/Makefile
#   2004/06/18 00:32:17-07:00 agk@redhat.com +1 -1
#   Device-mapper: kcopyd
# 
# ChangeSet
#   2004/06/18 08:02:21-07:00 agk@redhat.com 
#   [PATCH] dm-io: device-mapper i/o library for kcopyd
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-io.h
#   2004/06/17 23:53:42-07:00 agk@redhat.com +77 -0
#   dm-io: device-mapper i/o library for kcopyd
# 
# mm/mempool.c
#   2004/06/17 23:53:42-07:00 agk@redhat.com +0 -6
#   dm-io: device-mapper i/o library for kcopyd
# 
# drivers/md/dm-io.h
#   2004/06/17 23:53:42-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-io.h
# 
# drivers/md/dm-io.c
#   2004/06/18 00:32:16-07:00 agk@redhat.com +637 -0
#   dm-io: device-mapper i/o library for kcopyd
# 
# drivers/md/Makefile
#   2004/06/18 00:32:18-07:00 agk@redhat.com +1 -1
#   dm-io: device-mapper i/o library for kcopyd
# 
# drivers/md/dm-io.c
#   2004/06/18 00:32:16-07:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-io.c
# 
# ChangeSet
#   2004/06/18 08:02:10-07:00 bogdan.costescu@iwr.uni-heidelberg.de 
#   [PATCH] 3c59x: support for ATI Radeon 9100 IGP
#   
#   The following patch adds support for the 3Com networking core found in the
#   ATI Radeon 9100 IGP southbridge used on boards like Asus P4R800-VM.
#   
#   The main point of this patch is using HAS_MII instead of HAS_NWAY for the
#   definition of the board.  All the previous trials since the end of last
#   year used HAS_NWAY which disables the Tx part of the transceiver; using
#   HAS_NWAY was the way all 3Com Cyclone and Tornado chips worked, as they had
#   the transceiver integrated.  The ATI solution has an external transceiver
#   and I had to physically see the different chip on the board (the board was
#   provided by ATI) to finally understand that it needs the HAS_MII
#   definition...  I'm still waiting for some docs from ATI to clarify if this
#   is the correct way of handling this chip and if there are any differences
#   w.r.t EEPROM handling, but as it appears to work and was also confirmed by
#   other testers, I don't want to keep owners of such boards away from their
#   networks :-)
#   
#   The textual identification was a bit hard to decide; it's called
#   "3c920B-EMB-WNM" in the Windows .INF file that Asus provides for their
#   boards.  As this name was already used for PCI ID 9210, I added the
#   paranthesis which specifies where this chip is found.
#   
#   The Scyld driver defines FEATURE_TORNADO to include HAS_NWAY.  This board
#   would then probably need to not be defined with FEATURE_TORNADO, but the
#   same as in this patch.
#   
#   I would like to publicly thank Tyson Vickers for both ideas and patience
#   during the last few weeks.  He managed to get the driver working by
#   randomly setting driver parameters :-) But then he contacted me and worked
#   with me towards the solution.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/3c59x.c
#   2004/06/17 23:53:42-07:00 bogdan.costescu@iwr.uni-heidelberg.de +8 -4
#   3c59x: support for ATI Radeon 9100 IGP
# 
# ChangeSet
#   2004/06/18 08:01:58-07:00 thomas@winischhofer.net 
#   [PATCH] sisfb update 1.7.10
#   
#   attached is an update for the sisfb driver to version 1.7.10.
#   
#   This update includes
#   
#   - fixes for pure 64bit and 32/64bit mixed systems (add ioctl conversion;
#     fix variable sizes, etc; REQUIRED for current X.org/XFree86 on 64bit
#     systems, even if pure 64bit),
#   
#   - fixes for 301C video bridge, (scales TV output correctly now)
#   
#   - fixes for 1600x1200 and 1400x1050 LCD panels,
#   
#   - many fixes for 661/741/760 (amongst others, proper LFB support for the
#     760 and corrections for SiS' new BIOS data layout; would lead to display
#     corruption with old driver)
#   
#   - add support for many modes for LCD which were unsupported previously,
#   
#   - add support for HiVision and YPbPr HDTV
#   
#   - "vga=" statement now honoured properly (sisfb will set the same mode as
#     the kernel did by default)
#   
#   - use LCD native resolution mode if no mode is given
#   
#   - a major clean up of main driver code,
#   
#   - radical removal of duplicate (or nearly duplicate) code,
#   
#   - switched to 2.6 module_param macros,
#   
#   - enhanced communication with the X driver,
#   
#   - added eventual POSTing of SiS300/305 card for non-x86 archs,
#   
#   - added ability to relocate the image on the TV screen using a userland
#     tool,
#   
#   - added Documentation/fb/sisfb.txt (why the heck was this missing?!)
#   
#   - small fix for SiS DRM driver (match 32/64bit fixes mentioned above)
#     (cast the data passed to sis_free as u32)
#   
#   - make driver re-entrant by avoiding static structures and variables.
#   
#   As usual, heavily tested.  The mode switching code is even lab-tested by
#   SiS (although 100% written by me).  Please apply asap (especially since
#   64bit systems were not properly supported previously; as mentioned, current
#   X.org/XFree86 needs this update for proper communication with the
#   framebuffer driver on 64bit systems.  X crashes on such systems with the
#   old driver).
#   
#   Signed-off-by: Thomas Winischhofer <thomas@winischhofer.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/video/sisfb.h
#   2004/06/17 23:53:42-07:00 thomas@winischhofer.net +80 -171
#   sisfb update 1.7.10
# 
# drivers/video/sis/vstruct.h
#   2004/06/17 23:53:42-07:00 thomas@winischhofer.net +58 -100
#   sisfb update 1.7.10
# 
# drivers/video/sis/vgatypes.h
#   2004/06/17 23:53:42-07:00 thomas@winischhofer.net +62 -103
#   sisfb update 1.7.10
# 
# drivers/video/sis/sis_main.h
#   2004/06/17 23:53:42-07:00 thomas@winischhofer.net +365 -704
#   sisfb update 1.7.10
# 
# drivers/video/sis/sis_main.c
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +3762 -3016
#   sisfb update 1.7.10
# 
# drivers/video/sis/sis_accel.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +140 -264
#   sisfb update 1.7.10
# 
# drivers/video/sis/sis_accel.c
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +188 -187
#   sisfb update 1.7.10
# 
# drivers/video/sis/sis.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +497 -2
#   sisfb update 1.7.10
# 
# drivers/video/sis/osdef.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +45 -65
#   sisfb update 1.7.10
# 
# drivers/video/sis/oem310.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +32 -196
#   sisfb update 1.7.10
# 
# drivers/video/sis/oem300.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +3 -5
#   sisfb update 1.7.10
# 
# drivers/video/sis/initdef.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +85 -37
#   sisfb update 1.7.10
# 
# drivers/video/sis/init301.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +132 -60
#   sisfb update 1.7.10
# 
# drivers/video/sis/init.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +198 -607
#   sisfb update 1.7.10
# 
# drivers/video/sis/init.c
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +961 -1060
#   sisfb update 1.7.10
# 
# Documentation/fb/sisfb.txt
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +158 -0
#   sisfb update 1.7.10
# 
# drivers/video/sis/init301.c
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +3425 -4113
#   sisfb update 1.7.10
# 
# drivers/video/sis/310vtbl.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +507 -1122
#   sisfb update 1.7.10
# 
# drivers/video/sis/300vtbl.h
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +346 -458
#   sisfb update 1.7.10
# 
# drivers/char/drm/sis_mm.c
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +2 -2
#   sisfb update 1.7.10
# 
# Documentation/ioctl-number.txt
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +2 -0
#   sisfb update 1.7.10
# 
# Documentation/fb/sisfb.txt
#   2004/06/17 23:53:41-07:00 thomas@winischhofer.net +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/fb/sisfb.txt
# 
# ChangeSet
#   2004/06/18 08:01:45-07:00 paul@serice.net 
#   [PATCH] iso9660: NFS fix
#   
#   Make all inode numbers unique for images less than 128GB in size.  Required
#   for knfsd.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/iso_fs.h
#   2004/06/17 23:53:41-07:00 paul@serice.net +6 -12
#   iso9660: NFS fix
# 
# fs/isofs/inode.c
#   2004/06/18 00:32:11-07:00 paul@serice.net +4 -2
#   iso9660: NFS fix
# 
# fs/isofs/dir.c
#   2004/06/18 00:32:11-07:00 paul@serice.net +12 -3
#   iso9660: NFS fix
# 
# ChangeSet
#   2004/06/18 08:01:34-07:00 paul@serice.net 
#   [PATCH] iso9660: fix handling of inodes beyond 4GB
#   
#   This is my fourth attempt to patch the isofs code.  It is similar to the last
#   posting except this one implements the NFS get_parent() method which has
#   always been missing.
#   
#   The original problem I set out to addresses is that the current iso9660 file
#   system cannot reach inodes located beyond the 4GB barrier.  This is caused by
#   using the inode number as the byte offset of the inode data.  Being 32-bits
#   wide, the inode number is unable to reach inode data that does not reside on
#   the first 4GB of the file system.
#   
#   This causes real problems with "growisofs"
#   
#         http://fy.chalmers.se/~appro/linux/DVD+RW/#isofs4gb
#   
#   and my pet project "shunt"
#   
#         http://www.serice.net/shunt/
#   
#   This patch switches the isofs code from iget() to iget5_locked() which allows
#   extra data to be passed into isofs_read_inode() so that inode data anywhere on
#   the disk can be reached.
#   
#   The inode number scheme was also changed.  Continuing to use the byte offset
#   would have resulted in non-unique inodes in many common situations, but
#   because the inode number no longer plays any role in reading the meta-data off
#   the disk, I was free to set the inode number to some unique characteristic of
#   the file.  I have chosen to use the block offset which is also 32-bits wide.
#   
#   Lastly, the pre-patch code uses the default export_operations to handle
#   accessing the file system through NFS.  The problem with this is that the
#   default NFS operations assume that iget() works which is no longer the case
#   because of the necessity of switching to iget5_locked().  So, I had to
#   implement the NFS operations too.  As a bonus, I went ahead and implemented
#   the NFS get_parent() method which has always been missing.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/isofs/export.c
#   2004/06/17 23:53:41-07:00 paul@serice.net +228 -0
#   iso9660: fix handling of inodes beyond 4GB
# 
# include/linux/iso_fs_i.h
#   2004/06/17 23:53:41-07:00 paul@serice.net +4 -1
#   iso9660: fix handling of inodes beyond 4GB
# 
# include/linux/iso_fs.h
#   2004/06/18 00:32:20-07:00 paul@serice.net +66 -0
#   iso9660: fix handling of inodes beyond 4GB
# 
# fs/isofs/rock.c
#   2004/06/17 23:53:41-07:00 paul@serice.net +7 -8
#   iso9660: fix handling of inodes beyond 4GB
# 
# fs/isofs/namei.c
#   2004/06/17 23:53:41-07:00 paul@serice.net +21 -9
#   iso9660: fix handling of inodes beyond 4GB
# 
# fs/isofs/inode.c
#   2004/06/18 00:32:20-07:00 paul@serice.net +104 -53
#   iso9660: fix handling of inodes beyond 4GB
# 
# fs/isofs/export.c
#   2004/06/17 23:53:41-07:00 paul@serice.net +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/fs/isofs/export.c
# 
# fs/isofs/dir.c
#   2004/06/18 00:32:20-07:00 paul@serice.net +3 -3
#   iso9660: fix handling of inodes beyond 4GB
# 
# fs/isofs/Makefile
#   2004/06/17 23:53:41-07:00 paul@serice.net +1 -1
#   iso9660: fix handling of inodes beyond 4GB
# 
# ChangeSet
#   2004/06/18 08:01:23-07:00 tim@physik3.uni-rostock.de 
#   [PATCH] BSD accounting format rework
#   
#   BSD accounting format rework:
#   
#   Use all explicit and implicit padding in struct acct to
#   
#    - correctly report 32 bit uid/gid,
#    - correctly report jobs (e.g., daemons) running longer than 497 days,
#    - increase the precision of ac_etime from 2^-13 to 2^-20
#      (i.e., from ~6 hours to ~1 min. after a year)
#    - store the current AHZ value.
#    - allow cross-platform processing of the accounting file
#      (limited for m68k which has a different size struct acct).
#    - introduce versioning for smooth transition to incompatible formats in
#      the future. Currently the following version numbers are defined:
#        0: old format (until 2.6.7) with 16 bit uid/gid
#        1: extended variant (binary compatible to v0 on M68K)
#        2: extended variant (binary compatible to v0 on everything except M68K)
#        3: a new binary incompatible format (64 bytes)
#        4: new binary incompatible format (128 bytes).
#           layout of its first 64 bytes is the same as for v3.
#        5: marks second half of new binary incompatible format (128 bytes)
#           (layout is not yet defined)
#   
#   All this is accomplished without breaking binary compatibility.  32 bit
#   uid/gid support is compatible with the patch previously floating around and
#   used e.g.  by Red Hat.
#   
#   This patch also introduces a config option for a new, binary incompatible
#   "version 3" format that
#   
#    - is uniform across and properly aligned on all platforms
#    - stores pid and ppid
#    - uses AHZ==100 on all platforms (allows to report longer times)
#   
#   Much of the compatibility glue goes away when v1/v2 support is removed from
#   the kernel.  Such a patch is at
#   
#     http://www.physik3.uni-rostock.de/tim/kernel/2.7/acct-cleanup-04.patch
#   
#   and might be applied in the 2.7 timeframe.
#   
#   The new v3 format is source compatible with current GNU acct tools (6.3.5).
#   However, current GNU acct tools can be compiled for only one format.  As there
#   is no way to pass the kernel configuration to userspace, with my patch it will
#   still only support the old v2 format.  Only if v1/v2 support is removed from
#   the kernel, recompiling GNU acct tools will yield v3 support.
#   
#   A preliminary take at the corresponding work on cross-platform userspace tools
#   (GNU acct package) is at
#   
#     http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/
#   
#   This version of the package is able to read any of the v0/v2/v3 formats,
#   regardless of byte-order (untested), even within the same file.
#   Cross-platform compatibility with m68k (v1 format) is not yet implemented, but
#   native use on m68k should work (untested).  pid and ppid are currently only
#   shown by the dump-acct utility.
#   
#   Thanks to Arthur Corliss, Albert Cahalan and Ragnar Kjørstad for their
#   comments, and to Albert Cahalan for the u64->IEEE float conversion code.
#   
#   Signed-off-by: Tim Schmielau <tim@physik3.uni-rostock.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/acct.c
#   2004/06/17 23:53:41-07:00 tim@physik3.uni-rostock.de +97 -8
#   BSD accounting format rework
# 
# init/Kconfig
#   2004/06/17 23:53:41-07:00 tim@physik3.uni-rostock.de +12 -0
#   BSD accounting format rework
# 
# include/linux/acct.h
#   2004/06/17 23:53:41-07:00 tim@physik3.uni-rostock.de +120 -25
#   BSD accounting format rework
# 
# ChangeSet
#   2004/06/18 08:01:12-07:00 alan@redhat.com 
#   [PATCH] make the 3c59x/3c90x driver somewhat more reliable
#   
#   The existing driver violates basic PCI rules in several places making it
#   unusable for basic things like DHCP in Fedora Core.  This patch removes all
#   the situations I can find where it writes to the device while in D3 state
#   and breaks stuff.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/3c59x.c
#   2004/06/18 00:32:18-07:00 alan@redhat.com +34 -9
#   make the 3c59x/3c90x driver somewhat more reliable
# 
# ChangeSet
#   2004/06/18 08:01:01-07:00 bwindle@fint.org 
#   [PATCH] fix 3c59x.c to allow 3c905c 100bT-FD
#   
#   Fix the 3c905C 10/100 transceiver initialisation woes.
#   
#   (This was reverted from 2.6.7-rcX, but the bug reporter said the failure
#   turned out to be unrepeatable).
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/3c59x.c
#   2004/06/18 00:32:20-07:00 bwindle@fint.org +1 -1
#   fix 3c59x.c to allow 3c905c 100bT-FD
# 
# ChangeSet
#   2004/06/18 08:00:52-07:00 joris@eljakim.nl 
#   [PATCH] Validate PM-Timer rate at boot time
#   
#   Add a check to the PM-Timer initialization code.  It validates the PM-Timer
#   rate against PIT channel 2 and rejects the PM-Timer if its rate is not
#   withing 5% of the expected number.
#   
#   Rationale:
#   
#   The PMTMR timers of certain (older) mainboards are running at invalid
#   rates, often much faster than the rate expected by the PM-Timer code.  This
#   causes the system clock to run much too fast.  See also
#   http://bugme.osdl.org/show_bug.cgi?id=2375
#   
#   Possible workarounds are disabling the PM-Timer in the kernel config or
#   disabling the PM-Timer at boot time through the "clock=tsc" parameter.
#   However, we believe it is more user friendly to automatically validate the
#   PM-Timer rate at boot time before using it as the system time source.
#   
#   Tested by me (with broken timer) and John Stultz (with good timer) and
#   believed to be ok.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/timers/timer_pm.c
#   2004/06/17 23:53:40-07:00 joris@eljakim.nl +38 -0
#   Validate PM-Timer rate at boot time
# 
# ChangeSet
#   2004/06/18 08:00:41-07:00 willy@debian.org 
#   [PATCH] ahc1542 !CONFIG_MCA build fix
#   
#   The old 1542 scsi driver is both ISA and MCA.  The MCA portions are disabled
#   when !CONFIG_MCA through the typical wrapper scheme (a la pci.h and
#   !CONFIG_PCI).  However...  the driver unconditionally includes linux/mca.h
#   which in turn unconditionally includes asm/mca.h.
#   
#   This breaks drivers on platforms with ISA but not MCA, like alpha.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/mca.h
#   2004/06/17 23:53:40-07:00 willy@debian.org +2 -0
#   ahc1542 !CONFIG_MCA build fix
# 
# ChangeSet
#   2004/06/18 08:00:30-07:00 mingo@elte.hu 
#   [PATCH] x86: remove io_apic_sync
#   
#   The patch below gets rid of io_apic_sync().
#   
#   io_apic_sync() was introduced in 2.1.104 and it was originally done for
#   masking and unmasking as well.  Later the unmasking use got removed but the
#   masking use lingered around.  I dont think it was ever justified to do it
#   and clearly since the lack of io_apic_sync() didnt break some of the other
#   writes we do to the IO-APIC registers, it must be unnecessary in the
#   masking case too.
#   
#   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-i386/io_apic.h
#   2004/06/17 23:49:30-07:00 mingo@elte.hu +0 -9
#   x86: remove io_apic_sync
# 
# arch/i386/kernel/io_apic.c
#   2004/06/18 00:32:15-07:00 mingo@elte.hu +0 -3
#   x86: remove io_apic_sync
# 
# ChangeSet
#   2004/06/18 08:00:20-07:00 mingo@elte.hu 
#   [PATCH] x86: remove APIC_LOCKUP_DEBUG
#   
#   the patch below gets rid of APIC_LOCKUP_DEBUG.  It has been in the kernel
#   for more than 3 years and the message was only reported once during that
#   period of time - and even in that case it was a side-effect of a really bad
#   crash.  The lockup workaround works, the debugging code can be moved out.
#   
#   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/kernel/io_apic.c
#   2004/06/18 00:32:21-07:00 mingo@elte.hu +0 -21
#   x86: remove APIC_LOCKUP_DEBUG
# 
# ChangeSet
#   2004/06/18 08:00:09-07:00 pavel@ucw.cz 
#   [PATCH] io_apic.c code consolidation
#   
#   This cleans up io_apic.c a bit -- I do not really like 4 copies of same
#   code.
#   
#   Ingo said:
#   
#      yeah, agreed - i checked & test it, it's ok.  I made a small
#      modification (see the patch below) to uninline the __modify_IO_APIC_irq()
#      function - shaving 0.5K off the kernel's size.
#   
#   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/kernel/io_apic.c
#   2004/06/18 00:32:21-07:00 pavel@ucw.cz +16 -51
#   io_apic.c code consolidation
# 
# ChangeSet
#   2004/06/18 07:59:58-07:00 nickpiggin@yahoo.com.au 
#   [PATCH] Fix read() vs truncate race
#   
#   do_generic_mapping_read()
#   {
#   	isize1 = i_size_read();
#   	...
#   	readpage
#   	copy_to_user up to isize1;
#   }
#   
#   readpage()
#   {
#   	isize2 = i_size_read();
#   	...
#   	read blocks
#   	...
#   	zero-fill all blocks past isize2
#   }
#   
#   If a second thread runs truncate and shrinks i_size, so isize1 and isize2 are
#   different, the read can return up to a page of zero-fill that shouldn't really
#   exist.
#   
#   The trick is to read isize1 after doing the readpage.  I realised this is the
#   right way to do it without having to change the readpage API.
#   
#   The patch should not cost any cycles when reading from pagecache.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/filemap.c
#   2004/06/18 00:32:09-07:00 nickpiggin@yahoo.com.au +50 -26
#   Fix read() vs truncate race
# 
# ChangeSet
#   2004/06/18 07:59:47-07:00 akpm@osdl.org 
#   [PATCH] invalidate_inodes2(): mark pages not uptodate
#   
#   Andrea Arcangeli <andrea@suse.de> points out that invalidate_inode_pages2() is
#   supposed to mark mapped-into-pagetable pages as not uptodate so that next time
#   someone faults the page in we will go get a new version from backing store.
#   
#   The callers are the direct-io code and the NFS "something changed on the
#   server" code.  In both these cases we do need to go and re-read the page.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/truncate.c
#   2004/06/17 23:49:30-07:00 akpm@osdl.org +8 -2
#   invalidate_inodes2(): mark pages not uptodate
# 
# ChangeSet
#   2004/06/18 07:59:36-07:00 herbert@gondor.apana.org.au 
#   [PATCH] Check return status of register calls in i82365
#   
#   i82365 calls driver_register and platform_device_register without checking
#   their return values.  This patch fixes that.
#   
#   It also runs platform_device_register() prior to isa_probe() so we don't have
#   to undo ise_probe()'s effects if platform_device_register() ends up failing.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/pcmcia/i82365.c
#   2004/06/17 23:49:30-07:00 herbert@gondor.apana.org.au +10 -4
#   Check return status of register calls in i82365
# 
# ChangeSet
#   2004/06/18 07:59:25-07:00 tol@stacken.kth.se 
#   [PATCH] getgroups16() fix
#   
#   sys_getgroups16 (or rather groups16_to_user()) returns large gids
#   truncated.  Needs to be fixed, one way or another.  Don't know why the
#   other similar casts are still there.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/uid16.c
#   2004/06/17 23:49:29-07:00 tol@stacken.kth.se +6 -6
#   getgroups16() fix
# 
# include/linux/sched.h
#   2004/06/18 00:32:12-07:00 tol@stacken.kth.se +9 -1
#   getgroups16() fix
# 
# ChangeSet
#   2004/06/18 07:59:14-07:00 rene.herman@keyaccess.nl 
#   [PATCH] same small resource tweaks, x86_64 version
#   
#   The same small tweaks for x86_64.  Just to keep the two in sync.  One
#   additional wrinkle: vram_resource was exported to e820.c, which didn't
#   actually use it.  Undo that.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/x86_64/kernel/setup.c
#   2004/06/17 23:49:29-07:00 rene.herman@keyaccess.nl +11 -9
#   same small resource tweaks, x86_64 version
# 
# arch/x86_64/kernel/e820.c
#   2004/06/17 23:49:29-07:00 rene.herman@keyaccess.nl +1 -1
#   same small resource tweaks, x86_64 version
# 
# ChangeSet
#   2004/06/18 07:59:03-07:00 rene.herman@keyaccess.nl 
#   [PATCH] small tweaks to standard resource stuff
#   
#   Various small tweaks. Compiled and booted.
#   
#   1. add IORESOURCE_BUSY | IORESOURCE_MEM also for the kernel code and
#        data resources. I don't believe this actually matters one bit, but
#        they're hooked into a BUSY/MEM parent ("System RAM") and marking
#        them busy seems to make sense.
#   
#   2. delete the .start = 1M default for the kernel code resource. This
#        isn't actually a change; it's set to virt_to_phys(_text) in
#        setup_arch() overriding any default anyways.
#   
#   3. s/vram_resource/video_ram_resource/. Lines up much nicer with
#        video_rom_resource...
#   
#   4. s/checksum/romchecksum/. setup.c is a fairly large file, and
#        "checksum" pollutes the namespace.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/setup.c
#   2004/06/17 23:49:29-07:00 rene.herman@keyaccess.nl +11 -9
#   small tweaks to standard resource stuff
# 
# ChangeSet
#   2004/06/18 07:58:52-07:00 hpa@zytor.com 
#   [PATCH] Use first-fit for pty allocation
#   
#   (With Andrew Morton).
#   
#   The current dynamic pty allocation scheme has a few problems:
#   
#   - pty numbers grow to be very large, causing wtmp file bloat.
#   
#   - Seems to break libc5 and some old applications
#   
#   So change it to do first-fit.  An IDR tree is used to provide a
#   logarithmic-time search.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/tty_io.c
#   2004/06/17 23:49:29-07:00 hpa@zytor.com +64 -19
#   Use first-fit for pty allocation
# 
# ChangeSet
#   2004/06/18 07:58:40-07:00 tytso@mit.edu 
#   [PATCH] Ext3: Retry allocation after transaction commit (v2)
#   
#   Here is a reworked version of my patch to ext3 to retry certain filesystem
#   operations after an ENOSPC error.  The ext3_should_retry_alloc() function will
#   not wait on the currently running transaction if there is a currently active
#   handle; hence this should avoid deadlocks in the Lustre use case.  The patch
#   is versus BK-recent.
#   
#   I've also included a simple, reliable test case which demonstrates the problem
#   this patch is intended to fix.  (Note that BK-recent is not sufficient to
#   address this test case, and waiting on the commiting transaction in
#   ext3_new_block is also not sufficient.  Been there, tried that, didn't work.
#   We need to do the full-bore retry from the top level.  The
#   ext3_should_retry_alloc() will only wait on the committing transaction if
#   there is an active handle; hence Lustre will probably also need to use
#   ext3_should_retry_alloc() if it wants to reliably avoid this particular
#   problem.)
#   
#   #!/bin/sh
#   #
#   #
#   TEST_DIR=/tmp
#   IMAGE=$TEST_DIR/retry.img
#   MNTPT=$TEST_DIR/retry.mnt
#   TEST_SRC=/usr/projects/e2fsprogs/e2fsprogs/build
#   MKE2FS_OPTS=""
#   IMAGE_SIZE=8192
#   
#   umount $MNTPT
#   dd if=/dev/zero of=$IMAGE bs=4k count=$IMAGE_SIZE
#   mke2fs -j -F $MKE2FS_OPTS $IMAGE 
#   
#   function test_log ()
#   {
#   	echo $*
#   	logger -p local4.notice $*
#   }
#   
#   mkdir -p $MNTPT
#   mount -o loop -t ext3 $IMAGE $MNTPT
#   test_log Retry test: BEGIN
#   for i in `seq 1 3`
#   do
#   	test_log "Retry test: Loop $i"
#   	echo 2 > /proc/sys/fs/jbd-debug
#   	while ! mkdir -p $MNTPT/foo/bar
#   	do
#   		test_log "Retry test: mkdir failed"
#   		sleep 1
#   	done
#   	echo 0 > /proc/sys/fs/jbd-debug
#   	cp -r $TEST_SRC $MNTPT/foo/bar 2> /dev/null
#   	rm -rf $MNTPT/*
#   done
#   umount $MNTPT
#   test_log "Retry test: END"
#   
#   
#   akpm@osdl.org
#   
#     Rework the code to make it a formal JBD API entry point.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/jbd.h
#   2004/06/17 23:47:53-07:00 tytso@mit.edu +1 -0
#   Ext3: Retry allocation after transaction commit (v2)
# 
# include/linux/ext3_fs.h
#   2004/06/17 23:47:53-07:00 tytso@mit.edu +1 -0
#   Ext3: Retry allocation after transaction commit (v2)
# 
# fs/jbd/journal.c
#   2004/06/17 23:47:53-07:00 tytso@mit.edu +34 -0
#   Ext3: Retry allocation after transaction commit (v2)
# 
# fs/ext3/xattr.c
#   2004/06/17 23:47:53-07:00 tytso@mit.edu +5 -1
#   Ext3: Retry allocation after transaction commit (v2)
# 
# fs/ext3/namei.c
#   2004/06/18 00:32:11-07:00 tytso@mit.edu +20 -5
#   Ext3: Retry allocation after transaction commit (v2)
# 
# fs/ext3/inode.c
#   2004/06/17 23:47:53-07:00 tytso@mit.edu +5 -14
#   Ext3: Retry allocation after transaction commit (v2)
# 
# fs/ext3/balloc.c
#   2004/06/17 23:49:23-07:00 tytso@mit.edu +32 -6
#   Ext3: Retry allocation after transaction commit (v2)
# 
# fs/ext3/acl.c
#   2004/06/17 23:47:53-07:00 tytso@mit.edu +9 -1
#   Ext3: Retry allocation after transaction commit (v2)
# 
# ChangeSet
#   2004/06/18 07:58:28-07:00 rene.herman@keyaccess.nl 
#   [PATCH] pc9800: merge std_resources.c back into setup.c
#   
#   std_resources.{c,h} was only split off due to pc9800 wanting to override it.
#   With it gone, it might as well be merged back in.  Doesn't change any code.
#   It was compiled and booted.
#   
#   This time this also actually doesn't break compilation of any of the
#   subarches.  That's to say, any further.  I guess it might have been my .config
#   (my regular PC config, with just the subarch switched through menuconfig) or
#   O=, but only ELAN actually compiled.  Voyager and VISWS bombed out at the
#   final link and NUMAQ much sooner (with "physnode_map undeclared" during
#   compilation of numaq.c).
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/setup.c
#   2004/06/18 00:32:22-07:00 rene.herman@keyaccess.nl +200 -5
#   pc9800: merge std_resources.c back into setup.c
# 
# arch/i386/kernel/Makefile
#   2004/06/17 23:44:27-07:00 rene.herman@keyaccess.nl +0 -1
#   pc9800: merge std_resources.c back into setup.c
# 
# arch/i386/Kconfig
#   2004/06/17 23:44:27-07:00 rene.herman@keyaccess.nl +0 -6
#   pc9800: merge std_resources.c back into setup.c
# 
# BitKeeper/deleted/.del-std_resources.h~45da2e05d849a20f
#   2004/06/18 07:58:23-07:00 rene.herman@keyaccess.nl +0 -0
#   Delete: include/asm-i386/std_resources.h
# 
# BitKeeper/deleted/.del-std_resources.c~3be5b97880eb064e
#   2004/06/18 07:58:22-07:00 rene.herman@keyaccess.nl +0 -0
#   Delete: arch/i386/kernel/std_resources.c
# 
# ChangeSet
#   2004/06/18 07:58:17-07:00 bunk@fs.tum.de 
#   [PATCH] more PC9800 removal
#   
#   Removes more PC9800 code.
#   
#   Requires:
#   
#     bk rm drivers/char/upd4990a.c
#     bk rm drivers/net/ne2k_cbus.c
#     bk rm drivers/net/ne2k_cbus.h
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/drivers/opl3/opl3_lib.c
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -20
#   more PC9800 removal
# 
# sound/drivers/mpu401/mpu401.c
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -11
#   more PC9800 removal
# 
# sound/core/seq/instr/Makefile
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -1
#   more PC9800 removal
# 
# sound/core/seq/Makefile
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -1
#   more PC9800 removal
# 
# include/linux/serio.h
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -1
#   more PC9800 removal
# 
# include/linux/serial_core.h
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -8
#   more PC9800 removal
# 
# include/linux/ide.h
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +1 -1
#   more PC9800 removal
# 
# include/asm-i386/timex.h
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -4
#   more PC9800 removal
# 
# include/asm-i386/serial.h
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -7
#   more PC9800 removal
# 
# include/asm-i386/processor.h
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -6
#   more PC9800 removal
# 
# include/asm-i386/ide.h
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -34
#   more PC9800 removal
# 
# drivers/serial/8250_pnp.c
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -3
#   more PC9800 removal
# 
# drivers/pnp/isapnp/core.c
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -5
#   more PC9800 removal
# 
# drivers/net/at1700.c
#   2004/06/17 23:44:24-07:00 bunk@fs.tum.de +0 -88
#   more PC9800 removal
# 
# drivers/net/Space.c
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +2 -2
#   more PC9800 removal
# 
# drivers/net/3c509.c
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +9 -36
#   more PC9800 removal
# 
# drivers/ide/ide-proc.c
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -1
#   more PC9800 removal
# 
# drivers/char/keyboard.c
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +2 -3
#   more PC9800 removal
# 
# arch/i386/kernel/i8259.c
#   2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -5
#   more PC9800 removal
# 
# ChangeSet
#   2004/06/18 07:58:05-07:00 rddunlap@osdl.org 
#   [PATCH] Remove PC9800 support
#   
#   PC9800 sub-arch is incomplete, hackish (at least in IDE), maintainers don't
#   reply to emails and haven't touched it in awhile.  Can't even config it to
#   try to build it without other patches to the kernel tree.
#   
#   bk-rm-script:
#   
#   #! /bin/sh
#   bk rm -r ./arch/i386/mach-pc9800
#   bk rm -r ./arch/i386/boot98
#   bk rm ./drivers/char/lp_old98.c
#   bk rm ./drivers/serial/serial98.c
#   bk rm ./drivers/scsi/scsi_pc98.c
#   bk rm ./drivers/scsi/pc980155.c
#   bk rm ./drivers/scsi/pc980155.h
#   bk rm ./drivers/block/floppy98.c
#   bk rm ./drivers/input/keyboard/98kbd.c
#   bk rm ./drivers/input/serio/98kbd-io.c
#   bk rm ./drivers/input/misc/98spkr.c
#   bk rm ./drivers/input/mouse/98busmouse.c
#   bk rm ./drivers/ide/legacy/pc9800.c
#   bk rm ./drivers/ide/legacy/hd98.c
#   bk rm -r ./include/asm-i386/mach-pc9800
#   bk rm ./include/asm-i386/pc9800_sca.h
#   bk rm ./include/asm-i386/pc9800.h
#   bk rm ./fs/partitions/nec98.c
#   bk rm ./fs/partitions/nec98.h
#   bk rm ./sound/isa/cs423x/pc98.c
#   bk rm ./sound/isa/cs423x/pc9801_118_magic.h
#   bk rm ./sound/isa/cs423x/sound_pc9800.h
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/isa/cs423x/Makefile
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -2
#   Remove PC9800 support
# 
# sound/isa/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -10
#   Remove PC9800 support
# 
# fs/partitions/check.c
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1
#   Remove PC9800 support
# 
# fs/partitions/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -7
#   Remove PC9800 support
# 
# drivers/serial/Makefile
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1
#   Remove PC9800 support
# 
# drivers/serial/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -13
#   Remove PC9800 support
# 
# drivers/scsi/Makefile
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -2
#   Remove PC9800 support
# 
# drivers/scsi/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -12
#   Remove PC9800 support
# 
# drivers/net/Makefile
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1
#   Remove PC9800 support
# 
# drivers/net/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +1 -51
#   Remove PC9800 support
# 
# drivers/input/serio/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -10
#   Remove PC9800 support
# 
# drivers/input/mouse/Makefile
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1
#   Remove PC9800 support
# 
# drivers/input/mouse/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -11
#   Remove PC9800 support
# 
# drivers/input/misc/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -4
#   Remove PC9800 support
# 
# drivers/input/keyboard/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -12
#   Remove PC9800 support
# 
# drivers/ide/Makefile
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1
#   Remove PC9800 support
# 
# drivers/ide/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +1 -19
#   Remove PC9800 support
# 
# drivers/char/Makefile
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1
#   Remove PC9800 support
# 
# drivers/char/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +1 -21
#   Remove PC9800 support
# 
# drivers/block/Kconfig
#   2004/06/17 23:43:53-07:00 rddunlap@osdl.org +1 -8
#   Remove PC9800 support
# 
# ChangeSet
#   2004/06/18 07:57:53-07:00 Robert.Picco@hp.com 
#   [PATCH] HPET driver
#   
#   The driver supports the High Precision Event Timer.  The driver has adopted
#   a similar API to the Real Time Clock driver.  It can support any number of
#   HPET devices and the maximum number of timers per HPET device.  For further
#   information look at the documentation in the patch.
#   
#   Thanks to Venki at Intel for testing the driver on X86 hardware with HPET.
#   
#   HPET documentation is available at http://www.intel.com/design/chipsets/datashts/252516.htm
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/hpet.h
#   2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +133 -0
#   HPET driver
# 
# drivers/char/hpet.c
#   2004/06/17 23:43:14-07:00 Robert.Picco@hp.com +1076 -0
#   HPET driver
# 
# include/linux/miscdevice.h
#   2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +1 -0
#   HPET driver
# 
# include/linux/hpet.h
#   2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/linux/hpet.h
# 
# include/asm-i386/hpet.h
#   2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +3 -0
#   HPET driver
# 
# drivers/char/rtc.c
#   2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +5 -0
#   HPET driver
# 
# drivers/char/hpet.c
#   2004/06/17 23:43:14-07:00 Robert.Picco@hp.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/char/hpet.c
# 
# drivers/char/Makefile
#   2004/06/18 00:32:23-07:00 Robert.Picco@hp.com +1 -0
#   HPET driver
# 
# drivers/char/Kconfig
#   2004/06/18 00:32:23-07:00 Robert.Picco@hp.com +27 -0
#   HPET driver
# 
# arch/i386/kernel/time_hpet.c
#   2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +46 -0
#   HPET driver
# 
# arch/i386/Kconfig
#   2004/06/18 00:32:22-07:00 Robert.Picco@hp.com +2 -1
#   HPET driver
# 
# Documentation/hpet.txt
#   2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +298 -0
#   HPET driver
# 
# Documentation/filesystems/proc.txt
#   2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +1 -1
#   HPET driver
# 
# Documentation/hpet.txt
#   2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/hpet.txt
# 
# ChangeSet
#   2004/06/18 07:57:41-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: adjust default mqueue sizes
#   
#   Lower default sizes for POSIX mqueue allocation now that rlimits are in place.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ipc/mqueue.c
#   2004/06/17 23:41:40-07:00 chrisw@osdl.org +3 -3
#   RLIM: adjust default mqueue sizes
# 
# ChangeSet
#   2004/06/18 07:57:29-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: enforce rlimits for POSIX mqueue allocation
#   
#   Add a user_struct to the mq_inode_info structure.  Charge the maximum number
#   of bytes that could be allocated to a mqueue to the user who creates the
#   mqueue.  This is checked against the per user rlimit.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ipc/mqueue.c
#   2004/06/18 00:32:23-07:00 chrisw@osdl.org +39 -5
#   RLIM: enforce rlimits for POSIX mqueue allocation
# 
# ChangeSet
#   2004/06/18 07:57:18-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: add mq_attr_ok() helper
#   
#   Add helper function mq_attr_ok() to do mq_attr sanity checking, and do some
#   extra overlow checking.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ipc/mqueue.c
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +23 -10
#   RLIM: add mq_attr_ok() helper
# 
# ChangeSet
#   2004/06/18 07:57:07-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: add mq_bytes to user_struct
#   
#   Add mq_bytes field to user_struct, and make sure it's properly initialized.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/user.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -0
#   RLIM: add mq_bytes to user_struct
# 
# include/linux/sched.h
#   2004/06/18 00:32:22-07:00 chrisw@osdl.org +2 -0
#   RLIM: add mq_bytes to user_struct
# 
# ChangeSet
#   2004/06/18 07:56:56-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: add rlimit entry for POSIX mqueue allocation
#   
#   Add an rlimit entry to control the maximum number of bytes a user can allocate
#   to a POSIX mqueue.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/mqueue.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +2 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-x86_64/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-v850/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-sparc64/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-sparc/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-sh/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-s390/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-ppc64/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-ppc/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-parisc/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-mips/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-m68k/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-ia64/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-i386/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-h8300/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-cris/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-arm26/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-arm/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# include/asm-alpha/resource.h
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/x86_64/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/v850/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/um/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/sparc64/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/sparc/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/sh/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/s390/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/ppc64/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/ppc/kernel/process.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/parisc/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/mips/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/m68knommu/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/m68k/kernel/process.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/ia64/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/i386/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/h8300/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/cris/kernel/process.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/arm26/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/arm/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# arch/alpha/kernel/init_task.c
#   2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0
#   RLIM: add rlimit entry for POSIX mqueue allocation
# 
# ChangeSet
#   2004/06/18 07:56:43-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: add simple get_uid() helper
#   
#   Add simple helper function to grab a reference to a user_struct.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/sched.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +5 -0
#   RLIM: add simple get_uid() helper
# 
# ChangeSet
#   2004/06/18 07:56:32-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: add sigpending field to user_struct
#   
#   Add sigpending field to user_struct, and make sure it's properly initialized.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/user.c
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1
#   RLIM: add sigpending field to user_struct
# 
# include/linux/sched.h
#   2004/06/18 00:32:25-07:00 chrisw@osdl.org +1 -0
#   RLIM: add sigpending field to user_struct
# 
# ChangeSet
#   2004/06/18 07:56:20-07:00 chrisw@osdl.org 
#   [PATCH] RLIM: add rlimit entry for controlling queued signals
#   
#   The following patches introduce per user rlimits for both queued signals and
#   POSIX message queues.  The changes touch all the arches resource.h files as
#   well as init_task.c to get the rlimit defaults setup.
#   
#   Both require caching the user_struct to avoid problems with setuid().
#   
#   The signal changes makes some small changes to send_signal() to pass along the
#   task being signalled to get proper accounting for signals initiated in
#   interrupt.  Thanks to Marcelo for getting this one going.
#   
#   
#   This patch:
#   
#   Add an rlimit entry to control the maximum number of pending signals a user
#   may have.  This is essentially just the resource.h changes.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/signal.h
#   2004/06/18 00:32:25-07:00 chrisw@osdl.org +3 -0
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-x86_64/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-v850/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-sparc64/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +6 -4
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-sparc/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +6 -4
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-sh/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-s390/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-ppc64/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-ppc/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-parisc/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-mips/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-m68k/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-ia64/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-i386/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +5 -2
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-h8300/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-cris/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +5 -3
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-arm26/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-arm/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1
#   RLIM: add rlimit entry for controlling queued signals
# 
# include/asm-alpha/resource.h
#   2004/06/18 00:32:24-07:00 chrisw@osdl.org +5 -3
#   RLIM: add rlimit entry for controlling queued signals
# 
# ChangeSet
#   2004/06/18 07:56:09-07:00 akpm@osdl.org 
#   [PATCH] i2c fixups for idr API change
#   
#   Fix up the i2c code which uses the IDR library.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/i2c/i2c-core.c
#   2004/06/17 23:41:38-07:00 akpm@osdl.org +8 -2
#   i2c fixups for idr API change
# 
# ChangeSet
#   2004/06/18 07:55:58-07:00 minyard@acm.org 
#   [PATCH] IDR fixups
#   
#   There were definately some problems in there.  I've made some changes and
#   tested with a lot of bounds.  I don't have a machine with enough memory to
#   fill it up (it would take ~16GB on a 64-bit machine), but I use the "above"
#   code to simulate a lot of situations.
#   
#   The problems were:
#   
#       * IDR_FULL was not the right value
#       * idr_get_new_above() was not defined in the headers or documented.
#       * idr_alloc() bug-ed if there was a race and not enough memory was
#         allocated.  It should have returned NULL.
#       * id will overflow when you go past the end.
#       * There was a "(id >= (1 << (layers*IDR_BITS)))" comparison, but at
#         the top layer it would overflow the id and be zero.
#       * The allocation should return ENOSPC for an "above" value with
#         nothing above it, but it returned EAGAIN.
#   
#   I have not tested on 64-bits (as I don't have a 64-bit machine).
#   
#   I've included the files, a diff from the previous version, and my test
#   programs.
#   
#   For the test programs, idr_test <size> will just attempt to allocate 
#   <size> elements, check them, free them, and check them again.
#   
#   idr_test2 <size> <incr> will allocate <size> element with <incr> between
#   them.
#   
#   idr_test3 just tests some bounds and tries all values with just a few in
#   the idr.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/idr.c
#   2004/06/17 23:41:38-07:00 minyard@acm.org +31 -14
#   IDR fixups
# 
# include/linux/idr.h
#   2004/06/17 23:41:38-07:00 minyard@acm.org +9 -6
#   IDR fixups
# 
# ChangeSet
#   2004/06/18 07:55:47-07:00 akpm@osdl.org 
#   [PATCH] idr: remove counter bits from id's
#   
#   idr_get_new() currently returns an incrementing counter in the top 8 bits of
#   the counter.  Which means that most users have to mask it off again, and we
#   only have a 24-bit range.
#   
#   So remove that counter.  Also:
#   
#   - Remove the BITS_PER_INT define due to namespace collision risk.
#   
#   - Make MAX_ID_SHIFT 31, so counters have a 0 to 2G-1 range.
#   
#   - Why is MAX_ID_SHIFT using sizeof(int) and not sizeof(long)?  If it's for
#     consistency across 32- and 64-bit machines, why not just make it "31"?
#   
#   - Does this still hold true with the counter removed?
#   
#   /* We can only use half the bits in the top level because there are
#      only four possible bits in the top level (5 bits * 4 levels = 25
#      bits, but you only use 24 bits in the id). */
#   
#     If not, what needs to change?
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/idr.c
#   2004/06/18 00:32:26-07:00 akpm@osdl.org +3 -16
#   idr: remove counter bits from id's
# 
# include/linux/idr.h
#   2004/06/18 00:32:26-07:00 akpm@osdl.org +5 -13
#   idr: remove counter bits from id's
# 
# ChangeSet
#   2004/06/18 07:55:36-07:00 minyard@acm.org 
#   [PATCH] Fixes for idr code
#   
#   * On a 32-bit architecture, the idr code will cease to work if you add
#     more than 2^20 entries.  You will not be able to find many of the
#     entries.  The problem is that the IDR code uses 5-bit chunks of the
#     number and the lower portion used by IDR is 24 bits, so you have one bit
#     that leaks over into the comparisons that should not be there.  The
#     solution is to mask off that bit before doing IDR processing.  This
#     actually causes the POSIX timer code to crash if you create that many
#     timers.  I have included an idr_test.tar.gz file that demonstrates this
#     with and without the fix, in case you need more evidence :).
#   
#   * When the IDR fills up, it returns -1.  However, there was no way to
#     check for this condition.  This patch adds the ability to check for the
#     idr being full and fixes all the users.  It also fixes a problem in
#     fs/super.c where the idr code wasn't checking for -1.
#   
#   * There was a race condition creating POSIX timers.  The timer was added
#     to a task struct for another process then the data for the timer was
#     filled out.  The other task could use/destroy time timer as soon as it is
#     in the task's queue and the lock is released.  This moves settup up the
#     timer data to before the timer is enqueued or (for some data) into the
#     lock.
#   
#   * Change things so that the caller doesn't need to run idr_full() to find
#     out the reason for an idr_get_new() failure.
#   
#     Just return -ENOSPC if the tree was full, or -EAGAIN if the caller needs
#     to re-run idr_pre_get() and try again.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/sctp/sm_make_chunk.c
#   2004/06/17 23:41:37-07:00 minyard@acm.org +15 -10
#   Fixes for idr code
# 
# lib/idr.c
#   2004/06/18 00:32:26-07:00 minyard@acm.org +37 -8
#   Fixes for idr code
# 
# kernel/posix-timers.c
#   2004/06/17 23:41:37-07:00 minyard@acm.org +52 -34
#   Fixes for idr code
# 
# include/linux/idr.h
#   2004/06/18 00:32:26-07:00 minyard@acm.org +7 -1
#   Fixes for idr code
# 
# fs/super.c
#   2004/06/17 23:41:37-07:00 minyard@acm.org +10 -5
#   Fixes for idr code
# 
# fs/proc/generic.c
#   2004/06/17 23:41:37-07:00 minyard@acm.org +6 -4
#   Fixes for idr code
# 
# ChangeSet
#   2004/06/18 07:55:25-07:00 mason@suse.com 
#   [PATCH] reiserfs data logging support
#   
#   Add data=journal support for reiserfs
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/reiserfs_fs_i.h
#   2004/06/17 23:41:37-07:00 mason@suse.com +1 -0
#   reiserfs data logging support
# 
# include/linux/reiserfs_fs.h
#   2004/06/17 23:41:37-07:00 mason@suse.com +8 -0
#   reiserfs data logging support
# 
# fs/reiserfs/tail_conversion.c
#   2004/06/17 23:41:37-07:00 mason@suse.com +0 -41
#   reiserfs data logging support
# 
# fs/reiserfs/stree.c
#   2004/06/17 23:41:37-07:00 mason@suse.com +40 -3
#   reiserfs data logging support
# 
# fs/reiserfs/journal.c
#   2004/06/17 23:41:37-07:00 mason@suse.com +13 -4
#   reiserfs data logging support
# 
# fs/reiserfs/inode.c
#   2004/06/17 23:41:37-07:00 mason@suse.com +49 -10
#   reiserfs data logging support
# 
# fs/reiserfs/file.c
#   2004/06/17 23:41:37-07:00 mason@suse.com +18 -2
#   reiserfs data logging support
# 
# ChangeSet
#   2004/06/18 07:55:13-07:00 mason@suse.com 
#   [PATCH] reiserfs: btree readahead
#   
#   Walking the btree can trigger a number of single block synchronous reads.
#   This patch does btree readahead during operations that are likely to be long
#   and sequential.  So far, that only includes directory reads and truncates, but
#   it can make both much faster.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/reiserfs_fs.h
#   2004/06/18 00:32:26-07:00 mason@suse.com +5 -1
#   reiserfs: btree readahead
# 
# fs/reiserfs/stree.c
#   2004/06/18 00:32:26-07:00 mason@suse.com +68 -25
#   reiserfs: btree readahead
# 
# fs/reiserfs/dir.c
#   2004/06/17 23:41:37-07:00 mason@suse.com +1 -0
#   reiserfs: btree readahead
# 
# ChangeSet
#   2004/06/18 07:55:03-07:00 mason@suse.com 
#   [PATCH] reiserfs: remove debugging warning from block allocator
#   
#   Remove debugging warning from the reiserfs block allocator code
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/reiserfs/bitmap.c
#   2004/06/17 23:41:37-07:00 mason@suse.com +0 -1
#   reiserfs: remove debugging warning from block allocator
# 
# ChangeSet
#   2004/06/18 07:54:52-07:00 mason@suse.com 
#   [PATCH] reiserfs: block allocator should not inherit "packing locality 1"
#   
#   reiserfsck --rebuild-tree expects the only key with a packing locality of 1 to
#   be for the root directory (key [1 2]).  The new block allocator inherited that
#   packing locality down to subdirectories, which triggers failures in reiserfsck
#   --rebuild-tree
#   
#   reiserfsck in readonly check mode doesn't complain about this, thanks to Jeff
#   Mahoney for finding it.
#   
#   The fix is to never inherit packing locality #1
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/reiserfs/bitmap.c
#   2004/06/18 00:32:26-07:00 mason@suse.com +6 -1
#   reiserfs: block allocator should not inherit "packing locality 1"
# 
# ChangeSet
#   2004/06/18 07:54:43-07:00 mason@suse.com 
#   [PATCH] reiserfs: block allocator optimizations
#   
#   From: <mason@suse.com>
#   From: <jeffm@suse.com>
#   
#   The current reiserfs allocator pretty much allocates things sequentially
#   from the start of the disk, it works very nicely for desktop loads but
#   once you've got more then one proc doing io data files can fragment badly.
#   
#   One obvious solution is something like ext2's bitmap groups, which puts
#   file data into different areas of the disk based on which subdirectory
#   they are in.  The problem with bitmap groups is that if you've got a
#   group of subdirectories their contents will be spread out all over the
#   disk, leading to lots of seeks during a sequential read.
#   
#   This allocator patch uses the packing locality to determine which bitmap
#   group to allocate from, but when you create a file it looks in the bitmaps
#   to see how 'full' that packing locality already is.  If it hasn't been
#   heavily used yet, the packing locality is inherited from the parent
#   directory putting files in new subdirs close to the parent subdir,
#   otherwise it is the inode number of the parent directory putting new
#   files far away from the parent subdir.
#   
#   The end result is fewer bitmap groups for the same working set.  For
#   example, one test data set created by 20 procs running in parallel has
#   6822 subdirs.  And with vanilla reiserfs that would mean 6822
#   packing localities.  This patch turns that into 26 packing localities.
#   
#   This makes sequential reads of big directory trees more efficient, but
#   it also makes the btree more efficient in general.  Things end up sorted
#   better because groups of subdirs end up with similar keys in the btree,
#   instead of being spread out all over.
#   
#   The bitmap grouping code tries to use the start of each bitmap group
#   for metadata, and offsets the data slightly.  The data and metadata
#   are still close together, but not completely intermixed like they are
#   in the default allocator.  The end result is that leaf nodes tend to be
#   close to each other, making metadata readahead more effective.
#   
#   The old block allocator had the ability to enforce a minimum
#   allocation size, but did not use it.  It now tries to do a pass looking
#   for larger allocation chunks before falling back to the old behaviour
#   of taking any blocks it can find.
#   
#   The patch changes the defaults to:
#   
#   mount -o alloc=skip_busy:dirid_groups:packing_groups
#   
#   You can get back the old behaviour with mount -o alloc=skip_busy
#   
#   mount -o alloc=dirid_groups will turn on the bitmap groups
#   mount -o alloc=packing_groups turns on the packing locality reduction code
#   mount -o alloc=skip_busy:dirid_groups turns on both dirid_groups and
#   skip_busy
#   
#   Finally the patch adds a mount -o alloc=oid_groups, which puts files into
#   bitmap groups based on a hash of their objectid.  This would be used for
#   databases or other situations where you have a limited number of very
#   large files.
#   
#   This command will tell you how many packing localities are actually in
#   use:
#   
#   debugreiserfs -d /dev/xxx | grep '^|.*SD' | sed 's/^.....//' | awk '{print $1}' | sort -u | wc -l
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/reiserfs_fs.h
#   2004/06/18 00:32:26-07:00 mason@suse.com +10 -1
#   reiserfs: block allocator optimizations
# 
# fs/reiserfs/super.c
#   2004/06/17 23:41:36-07:00 mason@suse.com +7 -6
#   reiserfs: block allocator optimizations
# 
# fs/reiserfs/inode.c
#   2004/06/18 00:32:26-07:00 mason@suse.com +1 -2
#   reiserfs: block allocator optimizations
# 
# fs/reiserfs/file.c
#   2004/06/18 00:32:26-07:00 mason@suse.com +11 -3
#   reiserfs: block allocator optimizations
# 
# fs/reiserfs/bitmap.c
#   2004/06/18 00:32:27-07:00 mason@suse.com +234 -55
#   reiserfs: block allocator optimizations
# 
# ChangeSet
#   2004/06/18 07:54:32-07:00 akpm@osdl.org 
#   [PATCH] ppc64: uninline __pte_free_tlb()
#   
#   The pgalloc.h changes broke ppc64:
#   
#   In file included from include/asm-generic/tlb.h:18,
#                    from include/asm/tlb.h:24,
#                    from arch/ppc64/mm/hash_utils.c:48:
#   include/asm/pgalloc.h: In function `__pte_free_tlb':
#   include/asm/pgalloc.h:110: dereferencing pointer to incomplete type
#   include/asm/pgalloc.h:111: dereferencing pointer to incomplete type
#   
#   Uninlining __pte_free_tlb() fixes that.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/pgalloc.h
#   2004/06/17 23:41:36-07:00 akpm@osdl.org +1 -27
#   ppc64: uninline __pte_free_tlb()
# 
# arch/ppc64/mm/tlb.c
#   2004/06/17 23:41:36-07:00 akpm@osdl.org +27 -0
#   ppc64: uninline __pte_free_tlb()
# 
# ChangeSet
#   2004/06/18 07:54:20-07:00 rmk@arm.linux.org.uk 
#   [PATCH] Clean up asm/pgalloc.h include 3
#   
#   This patch cleans up needless includes of asm/pgalloc.h from the arch/i386/
#   subtree.  Compile tested on x86_pc SMP.
#   
#   [I also tried VISWS + SMP without PM doesn't build in smpboot.c,
#    though I don't believe its caused by this patch.  With PM, fails
#    to link complaining maxcpus is undefined.  Therefore, I presume
#    VISWS + SMP is an invalid configuration.]
#   
#   This patch is part of a larger patch aiming towards getting the include of
#   asm/pgtable.h out of linux/mm.h, so that asm/pgtable.h can sanely get at
#   things like mm_struct and friends.
#   
#   I suggest testing in -mm for a while to ensure there aren't any hidden arch
#   issues.
#   
#   The outstanding list of files for other architectures can be found
#   at http://www.arm.linux.org.uk/misc/pgalloc.txt
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mm/ioremap.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/mm/init.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/mm/hugetlbpage.c
#   2004/06/18 00:32:07-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/mm/fault.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/mach-voyager/voyager_thread.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/mach-voyager/voyager_smp.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/mach-voyager/voyager_basic.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/mach-visws/traps.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/vm86.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/traps.c
#   2004/06/18 00:32:07-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/smpboot.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/smp.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/mpparse.c
#   2004/06/18 00:32:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/irq.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/i386_ksyms.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/efi.c
#   2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/apic.c
#   2004/06/18 00:32:15-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include 3
# 
# arch/i386/kernel/acpi/boot.c
#   2004/06/17 23:41:33-07:00 rmk@arm.linux.org.uk +2 -1
#   Clean up asm/pgalloc.h include 3
# 
# ChangeSet
#   2004/06/18 07:54:08-07:00 rmk@arm.linux.org.uk 
#   [PATCH] Clean up asm/pgalloc.h include
#   
#   This patch cleans up needless includes of asm/pgalloc.h from the drivers/
#   subtree.  drivers/char/mem.c has been compile tested; the others have not,
#   since they are for non-x86 and non-ARM architectures.
#   
#   This patch is part of a larger patch aiming towards getting the include of
#   asm/pgtable.h out of linux/mm.h, so that asm/pgtable.h can sanely get at
#   things like mm_struct and friends.
#   
#   I suggest testing in -mm for a while to ensure there aren't any hidden arch
#   issues.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/dmasound/dmasound_atari.c
#   2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# drivers/video/console/sticore.c
#   2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# drivers/parisc/ccio-rm-dma.c
#   2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# drivers/parisc/ccio-dma.c
#   2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# drivers/net/sun3lance.c
#   2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# drivers/net/macsonic.c
#   2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# drivers/net/lasi_82596.c
#   2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# drivers/net/82596.c
#   2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# drivers/char/mem.c
#   2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# ChangeSet
#   2004/06/18 07:53:57-07:00 rmk@arm.linux.org.uk 
#   [PATCH] Clean up asm/pgalloc.h include
#   
#   This patch cleans up needless includes of asm/pgalloc.h from the fs/
#   kernel/ and mm/ subtrees.  Compile tested on multiple ARM platforms, and
#   x86, this patch appears safe.
#   
#   This patch is part of a larger patch aiming towards getting the include of
#   asm/pgtable.h out of linux/mm.h, so that asm/pgtable.h can sanely get at
#   things like mm_struct and friends.
#   
#   I suggest testing in -mm for a while to ensure there aren't any hidden arch
#   issues.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/vmscan.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# mm/vmalloc.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# mm/nommu.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# mm/msync.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# mm/mremap.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# mm/mprotect.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# mm/mmap.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# mm/mincore.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# mm/highmem.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# kernel/module.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# include/asm-generic/tlb.h
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +1 -0
#   Clean up asm/pgalloc.h include
# 
# include/asm-arm26/tlb.h
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +1 -0
#   Clean up asm/pgalloc.h include
# 
# fs/proc/proc_misc.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# fs/exec.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# fs/binfmt_flat.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# fs/binfmt_elf.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# fs/binfmt_aout.c
#   2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1
#   Clean up asm/pgalloc.h include
# 
# ChangeSet
#   2004/06/18 07:53:45-07:00 yoav.zach@intel.com 
#   [PATCH] binfmt_misc: improve calculation of interpreter's credentials
#   
#   This patch allows for misc binaries to run with credentials and security
#   token that are calculated according to the binaries, and not according to the
#   interpreter, which is the legacy behavior of binfmt_misc.
#   
#   The way it is done is by calling prepare_binprm, which is where these
#   attributes are calculated, before switching the 'file' field in the bprm from
#   the binary to the interpreter.
#   
#   This feature should be used with care, since the interpreter will have root
#   permissions when running a setuid binary owned by root.
#   
#   Please note -
#   
#   - Only root can register an interpreter with binfmt_misc.  The feature is
#     documented and the administrator is advised to handle it with care
#   
#   - The new feature is enabled only with a special flag in the registration
#     string.  When this flag is not specified the current behavior of
#     binfmt_misc is kept
#   
#   - This is the only 'right' way for an interpreter to know the correct
#     AT_SECURE value for the interpreted binary
#   
#   
#   From: Chris Wright <chrisw@osdl.org>
#   
#     This patchset looks OK, except for one problem.  It installs the fd (which
#     could've been unreadable) without unsharing the ->files.  So someone can use
#     this to read unreadable yet executable files.  Here's a patch which fixes
#     that up.  I added one bit that's commented out because I'm not positive if a
#     final steal_locks() is needed.
#   
#     I did a fair amount of rearranging to simplify the error conditions
#     relative to the fd_install(), and unshare_files().
#   
#   From: Chris Wright <chrisw@osdl.org>
#   
#     I found that the intel patchset (and mine as well) leaked i_writecount on
#     the original executed file.  In addition, I verified that the steal_locks()
#     bit is indeed needed.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/binfmt_misc.c
#   2004/06/17 23:41:09-07:00 yoav.zach@intel.com +71 -51
#   binfmt_misc: improve calculation of interpreter's credentials
# 
# Documentation/binfmt_misc.txt
#   2004/06/17 23:41:09-07:00 yoav.zach@intel.com +7 -0
#   binfmt_misc: improve calculation of interpreter's credentials
# 
# ChangeSet
#   2004/06/18 07:53:34-07:00 yoav.zach@intel.com 
#   [PATCH] Handle non-readable binfmt_misc executables
#   
#   <background>
#   
#   I work in a group that works on enabling the IA-32 Execution Layer
#   (http://www.intel.com/pressroom/archive/releases/20040113comp.htm) on Linux.
#   In a few words - this is a dynamic translator for IA-32 binaries on IPF
#   platform.  Following David Mosberger's advice - we use the binfmt_misc
#   mechanism for the invocation of the translator whenever the user tries to
#   exec an IA-32 binary.
#   
#   The EL is meant to help in the migration path from IA-32 to IPF.  From our
#   beta customers we learnt that at first stage - they tend to keep their
#   environment mostly intact, using the legacy IA-32 binaries.
#   
#   Such an environment has, naturally, setuid and non-readable binaries.  It
#   will be useless to ask the administrator to change the settings of such an
#   environment - some of them are very complex, and the administrators are
#   reluctant to make any changes in a system that already proved itself to be
#   robust and secure.  So, our target with these patches is not to enhance the
#   support for scripts but rather to allow a translator to be integrated into a
#   working environment that is not (and should not be) aware to the fact it's
#   being emulated.
#   
#   As I said before - it is practically hopeless to expect an administrator of
#   such a system to change it so that it will suit the current behavior of
#   binfmt_misc.  But, even if we could do that,
#   
#   I'm not sure it would be a good idea - these changes are likely to be less
#   secure than the suggested patches -
#   
#   - In order to execute non-readable binaries the binary will have to be made
#     readable, which is obviously less secure than allowing only a trusted
#     translator to read it
#   
#   - There will be no way for the translator to calculate the accurate
#     AT_SECURE value for the translated process.  This might end up with the
#     translated process running in a non-secured mode when it actually needs to
#     be secured.
#   
#   </background>
#   
#   
#   I prepared a patch that solves a couple of problems that interpreters have
#   when invoked via binfmt_misc.  currently -
#   
#   1) such interpreters cannot open non-readable binaries
#   
#   2) the processes will have their credentials and security attributes
#      calculated according to interpreter permissions and not those of the
#      original binary
#   
#   the proposed patch solves these problems by -
#   
#   1) opening the binary on behalf of the interpreter and passing its fd
#      instead of the path as argv[1] to the interpreter
#   
#   2) calling prepare_binprm with the file struct of the binary and not the
#      one of the interpreter
#   
#   The new functionality is enabled by adding a special flag to the registration
#   string.  If this flag is not added then old behavior is not changed.
#   
#   A preliminary version of this patch was sent to the list on 9/1/2003 with the
#   title "[PATCH]: non-readable binaries - binfmt_misc 2.6.0-test4".  This new
#   version fixes the concerns that were raised by the patch, except of calling
#   unshare_files() before allocating a new fd.  this is because this feature did
#   not enter 2.6 yet.
#   
#   
#   Arun Sharma <arun.sharma@intel.com> says:
#   
#   We were going through an internal review of this patch:
#   
#   http://marc.theaimsgroup.com/?l=linux-kernel&m=107424598901720&w=2
#   
#   which is in your tree already.  I'm not sure if this line of code got
#   sufficient review.
#   
#   +               /* call prepare_binprm before switching to interpreter's file
#   +                * so that all security calculation will be done according to
#   +                * binary and not interpreter */
#   +               retval = prepare_binprm(bprm);
#   
#   The case that concerns me is: unprivileged interpreter and a privileged
#   binary.  One can use binfmt_misc to execute untrusted code (interpreter) with
#   elevated privileges.  One could argue that all binfmt_misc interpreters are
#   trusted, because only root can register them.  But that's a change from the
#   traditional behavior of binfmt_misc (and binfmt_script).
#   
#   
#   (Update):
#   
#   Arun pointed out that calculating the process credentials according to the
#   binary that needs to be translated is a bit risky, since it requires the
#   administrator to pay extra attention not to register an interpreter which is
#   not intended to run with root credentials.
#   
#   After discussing this issue with him, I would like to propose a modified
#   patch: The old patch did 2 things - 1) open the binary for reading and 2)
#   calculate the credentials according to the binary.
#   
#   I removed the riskier part of changing the credentials calculation, so the
#   revised patch only opens the binary for reading.  It also includes few words
#   of warning in the description of the 'open-binary' feature in
#   binfmt_misc.txt, and makes the function entry_status print the flags in use.
#   
#   As for the 'credentials' part of the patch, I will prepare a separate patch
#   for it and send it again to the LKML, describe the problem and ask for people
#   comments.
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/binfmts.h
#   2004/06/17 23:41:09-07:00 yoav.zach@intel.com +4 -0
#   Handle non-readable binfmt_misc executables
# 
# fs/exec.c
#   2004/06/18 00:32:28-07:00 yoav.zach@intel.com +3 -1
#   Handle non-readable binfmt_misc executables
# 
# fs/binfmt_misc.c
#   2004/06/18 00:32:28-07:00 yoav.zach@intel.com +120 -21
#   Handle non-readable binfmt_misc executables
# 
# Documentation/binfmt_misc.txt
#   2004/06/18 00:32:28-07:00 yoav.zach@intel.com +19 -4
#   Handle non-readable binfmt_misc executables
# 
# ChangeSet
#   2004/06/18 07:53:23-07:00 mporter@kernel.crashing.org 
#   [PATCH] Add PPC4xx MAINTAINERS entry, merge CREDITS from 2.4
#   
#   Add myself as the PPC4xx maintainer. Merge CREDITS entry from 2.4
#   
#   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>
# 
# MAINTAINERS
#   2004/06/17 23:41:09-07:00 mporter@kernel.crashing.org +7 -0
#   Add PPC4xx MAINTAINERS entry, merge CREDITS from 2.4
# 
# CREDITS
#   2004/06/18 00:32:10-07:00 mporter@kernel.crashing.org +8 -0
#   Add PPC4xx MAINTAINERS entry, merge CREDITS from 2.4
# 
# ChangeSet
#   2004/06/18 07:53:12-07:00 olh@suse.de 
#   [PATCH] ppc64: avoid multiline /proc/cmdline content on iSeries
#   
#   /proc/cmdline is filled via an OS400 call iSeries_init().  It scans the
#   returned data from the end, instead of the beginning.  This leads to
#   multiple lines in /proc/cmdline
#   
#   Just scan from the beginning and stop at the first newline.  This patch
#   changes also the /proc/iSeries/mf/*/cmdline interface to do the same as the
#   initial setup.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/mf_proc.c
#   2004/06/17 23:41:08-07:00 olh@suse.de +15 -22
#   ppc64: avoid multiline /proc/cmdline content on iSeries
# 
# arch/ppc64/kernel/iSeries_setup.c
#   2004/06/17 23:41:08-07:00 olh@suse.de +6 -7
#   ppc64: avoid multiline /proc/cmdline content on iSeries
# 
# ChangeSet
#   2004/06/18 07:53:00-07:00 mikpe@csd.uu.se 
#   [PATCH] ppc32 irq.c cpumask fix
#   
#   2.6.7-rc3-mm1 changed cpumask_t from ulong to a struct, causing
#   compile-time errors in arch/ppc/kernel/irq.c.
#   
#   Proposed fix below. Tested on a G3.
#   
#   Signed-off-by: Mikael Pettersson <mikpe@csd.uu.se>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/kernel/irq.c
#   2004/06/17 23:41:08-07:00 mikpe@csd.uu.se +3 -1
#   ppc32 irq.c cpumask fix
# 
# ChangeSet
#   2004/06/18 07:52:49-07:00 kumar.gala@freescale.com 
#   [PATCH] ppc32: support for e500 and 85xx
#   
#   Here is both a GNU style and BK patch for adding support for the e500 core and
#   85xx platform to 2.6.  This is pretty much a direct port from 2.4 with a bit
#   of cleanup around the edges.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/mpc85xx.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +128 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/immap_85xx.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +126 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/fsl_ocp.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +54 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/syslib/ppc85xx_setup.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +67 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/syslib/ppc85xx_setup.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +341 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/syslib/ppc85xx_common.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +29 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/syslib/ppc85xx_common.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +46 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/platforms/85xx/mpc85xx_ads_common.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +50 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/platforms/85xx/mpc85xx_ads_common.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +237 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/platforms/85xx/mpc8540_ads.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +30 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/platforms/85xx/mpc8540_ads.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +238 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/platforms/85xx/mpc8540.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +97 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/platforms/85xx/Makefile
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +7 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/platforms/85xx/Kconfig
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +44 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/mm/fsl_booke_mmu.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +236 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/head_e500.S
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +1329 -0
#   ppc32: support for e500 and 85xx
# 
# include/linux/prctl.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +6 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/tlbflush.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +22 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/system.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/serial.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/reg_booke.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +119 -11
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/reg.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +12 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/ptrace.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +5 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/processor.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +16 -9
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/ppcboot.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -2
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/ppc_asm.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +56 -10
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/pgtable.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +37 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/ocp_ids.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -1
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/ocp.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +4 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/mpc85xx.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc/mpc85xx.h
# 
# include/asm-ppc/mmu_context.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +5 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/mmu.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +68 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/io.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -0
#   ppc32: support for e500 and 85xx
# 
# include/asm-ppc/immap_85xx.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc/immap_85xx.h
# 
# include/asm-ppc/fsl_ocp.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc/fsl_ocp.h
# 
# include/asm-ppc/elf.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +1 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/syslib/ppc85xx_setup.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc85xx_setup.h
# 
# arch/ppc/syslib/ppc85xx_setup.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc85xx_setup.c
# 
# arch/ppc/syslib/ppc85xx_common.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc85xx_common.h
# 
# arch/ppc/syslib/ppc85xx_common.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc85xx_common.c
# 
# arch/ppc/syslib/open_pic.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +1 -1
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/syslib/Makefile
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +7 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/platforms/85xx/mpc85xx_ads_common.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
# 
# arch/ppc/platforms/85xx/mpc85xx_ads_common.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
# 
# arch/ppc/platforms/85xx/mpc8540_ads.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc8540_ads.h
# 
# arch/ppc/platforms/85xx/mpc8540_ads.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc8540_ads.c
# 
# arch/ppc/platforms/85xx/mpc8540.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc8540.c
# 
# arch/ppc/platforms/85xx/Makefile
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/Makefile
# 
# arch/ppc/platforms/85xx/Kconfig
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/Kconfig
# 
# arch/ppc/mm/pgtable.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +32 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/mm/mmu_decl.h
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +9 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/mm/init.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +6 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/mm/fsl_booke_mmu.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/mm/fsl_booke_mmu.c
# 
# arch/ppc/mm/fault.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +7 -7
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/mm/Makefile
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +1 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/traps.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +89 -2
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/signal.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +42 -3
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/ptrace.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +84 -3
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/process.c
#   2004/06/18 00:32:24-07:00 kumar.gala@freescale.com +95 -6
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/ppc_ksyms.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +5 -1
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/misc.S
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +37 -3
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/head_e500.S
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/kernel/head_e500.S
# 
# arch/ppc/kernel/entry.S
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +24 -12
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/cputable.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +12 -1
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/asm-offsets.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +7 -1
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/align.c
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +5 -5
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/kernel/Makefile
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +4 -0
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/Makefile
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +8 -2
#   ppc32: support for e500 and 85xx
# 
# arch/ppc/Kconfig
#   2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +33 -4
#   ppc32: support for e500 and 85xx
# 
# ChangeSet
#   2004/06/18 07:52:38-07:00 hugh@veritas.com 
#   [PATCH] mm: pretest pte_young and pte_dirty
#   
#   Test for pte_young before going to the costlier atomic test_and_clear, as
#   asm-generic does.  Test for pte_dirty before going to the costlier atomic
#   test_and_clear, as asm-generic does (I said before that I would not do so for
#   pte_dirty, but was missing the point: there is nothing atomic about deciding
#   to do nothing).  But I've not touched the rather different ppc and ppc64.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-x86_64/pgtable.h
#   2004/06/17 23:41:07-07:00 hugh@veritas.com +15 -2
#   mm: pretest pte_young and pte_dirty
# 
# include/asm-parisc/pgtable.h
#   2004/06/17 23:41:07-07:00 hugh@veritas.com +4 -0
#   mm: pretest pte_young and pte_dirty
# 
# include/asm-ia64/pgtable.h
#   2004/06/17 23:41:07-07:00 hugh@veritas.com +4 -0
#   mm: pretest pte_young and pte_dirty
# 
# include/asm-i386/pgtable.h
#   2004/06/17 23:41:07-07:00 hugh@veritas.com +14 -2
#   mm: pretest pte_young and pte_dirty
# 
# ChangeSet
#   2004/06/18 07:52:27-07:00 hugh@veritas.com 
#   [PATCH] mm: flush TLB when clearing young
#   
#   Traditionally we've not flushed TLB after clearing the young/referenced bit,
#   it has seemed just a waste of time.  Russell King points out that on some
#   architectures, with the move from 2.4 mm sweeping to 2.6 rmap, this may be a
#   serious omission: very frequently referenced pages never re-marked young, and
#   the worst choices made for unmapping.
#   
#   So, replace ptep_test_and_clear_young by ptep_clear_flush_young throughout
#   rmap.c.  Originally I'd imagined making some kind of TLB gather optimization,
#   but don't see what now: whether worth it rather depends on how common
#   cross-cpu flushes are, and whether global or not.
#   
#   ppc and ppc64 have already found this issue, and worked around it by arranging
#   TLB flush from their ptep_test_and_clear_young: with the aid of pgtable rmap
#   pointers.  I'm hoping ptep_clear_flush_young will allow ppc and ppc64 to
#   remove that special code, but won't change them myself.
#   
#   It's worth noting that it is Andrea's anon_vma rmap which makes the vma
#   available for ptep_clear_flush_young in page_referenced_one: anonmm and
#   pte_chains would both need an additional find_vma for that.
#   
#   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/rmap.c
#   2004/06/17 23:41:07-07:00 hugh@veritas.com +3 -3
#   mm: flush TLB when clearing young
# 
# ChangeSet
#   2004/06/18 13:33:48+01:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Add support code for ARM hardware vector floating point
#   
#   This cset adds the code to handle the hardware vector floating point
#   unit found on some ARM926 and later CPUs.  The hardware provides
#   an implementation for the common cases, and bounces exceptions for
#   other cases, which have to be handled in software, and signalling
#   SIGFPE as appropriate.
# 
# include/asm-arm/vfpmacros.h
#   2004/06/18 13:31:34+01:00 rmk@flint.arm.linux.org.uk +25 -0
# 
# include/asm-arm/vfpmacros.h
#   2004/06/18 13:31:33+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/vfpmacros.h
# 
# include/asm-arm/vfp.h
#   2004/06/18 13:31:26+01:00 rmk@flint.arm.linux.org.uk +78 -0
# 
# include/asm-arm/vfp.h
#   2004/06/18 13:31:26+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/vfp.h
# 
# arch/arm/vfp/vfpsingle.c
#   2004/06/18 13:31:18+01:00 rmk@flint.arm.linux.org.uk +1224 -0
# 
# arch/arm/vfp/vfpsingle.c
#   2004/06/18 13:31:18+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfpsingle.c
# 
# arch/arm/vfp/vfpmodule.c
#   2004/06/18 13:31:11+01:00 rmk@flint.arm.linux.org.uk +288 -0
# 
# arch/arm/vfp/vfpmodule.c
#   2004/06/18 13:31:11+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfpmodule.c
# 
# arch/arm/vfp/vfpinstr.h
#   2004/06/18 13:31:03+01:00 rmk@flint.arm.linux.org.uk +88 -0
# 
# arch/arm/vfp/vfpinstr.h
#   2004/06/18 13:31:03+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfpinstr.h
# 
# arch/arm/vfp/vfphw.S
#   2004/06/18 13:30:55+01:00 rmk@flint.arm.linux.org.uk +210 -0
# 
# arch/arm/vfp/vfphw.S
#   2004/06/18 13:30:55+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfphw.S
# 
# arch/arm/vfp/vfpdouble.c
#   2004/06/18 13:30:41+01:00 rmk@flint.arm.linux.org.uk +1186 -0
# 
# arch/arm/vfp/vfpdouble.c
#   2004/06/18 13:30:41+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfpdouble.c
# 
# arch/arm/vfp/vfp.h
#   2004/06/18 13:30:32+01:00 rmk@flint.arm.linux.org.uk +333 -0
# 
# arch/arm/vfp/vfp.h
#   2004/06/18 13:30:32+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfp.h
# 
# arch/arm/vfp/entry.S
#   2004/06/18 13:30:14+01:00 rmk@flint.arm.linux.org.uk +45 -0
# 
# arch/arm/vfp/entry.S
#   2004/06/18 13:30:14+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/entry.S
# 
# arch/arm/vfp/Makefile
#   2004/06/18 13:29:58+01:00 rmk@flint.arm.linux.org.uk +12 -0
# 
# arch/arm/vfp/Makefile
#   2004/06/18 13:29:58+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/Makefile
# 
# Documentation/arm/VFP/release-notes.txt
#   2004/06/18 13:29:51+01:00 rmk@flint.arm.linux.org.uk +55 -0
# 
# include/asm-arm/thread_info.h
#   2004/06/18 13:29:51+01:00 rmk@flint.arm.linux.org.uk +5 -2
#   Add VFP state to thread information structure.
# 
# include/asm-arm/fpstate.h
#   2004/06/18 13:29:51+01:00 rmk@flint.arm.linux.org.uk +32 -0
#   Add VFP hardware structures.
# 
# Documentation/arm/VFP/release-notes.txt
#   2004/06/18 13:29:51+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/Documentation/arm/VFP/release-notes.txt
# 
# arch/arm/kernel/process.c
#   2004/06/18 13:29:50+01:00 rmk@flint.arm.linux.org.uk +6 -0
#   Add VFP calls for releasing VFP state held by a thread and
#   initialising VFP State.
# 
# arch/arm/kernel/entry-armv.S
#   2004/06/18 13:29:50+01:00 rmk@flint.arm.linux.org.uk +13 -0
#   Add VFP calls and additional context switch support.
# 
# arch/arm/Makefile
#   2004/06/18 13:29:50+01:00 rmk@flint.arm.linux.org.uk +1 -0
#   Add VFP directory to build
# 
# arch/arm/Kconfig
#   2004/06/18 13:29:49+01:00 rmk@flint.arm.linux.org.uk +11 -0
#   Add VFP configuration option.
# 
# ChangeSet
#   2004/06/18 15:21:08+09:00 yoshfuji@linux-ipv6.org 
#   [XFRM] fix dependency issues for CONFIG_IPV6=m.
# 
# net/xfrm/xfrm_state.c
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +10 -0
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# net/xfrm/xfrm_export.c
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# net/xfrm/Makefile
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# net/ipv6/ipcomp6.c
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +5 -1
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# net/ipv6/esp6.c
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +8 -5
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# net/ipv6/ah6.c
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +5 -1
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# net/ipv4/ipcomp.c
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +7 -3
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# net/ipv4/esp4.c
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +9 -4
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# net/ipv4/ah4.c
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +4 -1
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# include/net/xfrm.h
#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
# 
# BitKeeper/deleted/.del-xfrm_output.c~af23cc5516e28602
#   2004/06/18 15:10:51+09:00 yoshfuji@linux-ipv6.org +0 -0
#   Delete: net/xfrm/xfrm_output.c
# 
# ChangeSet
#   2004/06/18 01:56:40-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.7
#   into intel.com:/home/lenb/bk/linux-acpi-test-2.6.7
# 
# drivers/acpi/pci_link.c
#   2004/06/18 01:54:24-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/18 01:54:24-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# arch/i386/kernel/mpparse.c
#   2004/06/18 01:54:23-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/18 01:40:30-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.6
#   into intel.com:/home/lenb/src/linux-acpi-test-2.6.7
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/18 01:40:27-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/18 14:25:15+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] XFRM: support (uncompressed) tunnel mode ipcomp6 using xfrm6_tunnel infrastructure.
# 
# net/ipv6/xfrm6_tunnel.c
#   2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +623 -0
# 
# net/ipv6/xfrm6_tunnel.c
#   2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +0 -0
#   BitKeeper file /home2/yoshfuji/BitKeeper/linux-2.6-export-2.6.8/linux-2.6-xfrm6tunnel/net/ipv6/xfrm6_tunnel.c
# 
# net/ipv6/xfrm6_policy.c
#   2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +2 -0
#   [IPV6] XFRM: add missing xfrm6_tunnel.c.
# 
# net/ipv6/ipcomp6.c
#   2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +69 -0
#   [IPV6] XFRM: support (uncompressed) tunnel mode ipcomp6 using xfrm6_tunnel infrastructure.
# 
# net/ipv6/ip6_tunnel.c
#   2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +9 -9
#   [IPV6] XFRM: use xfrm6_tunnel infrastructure to register/unregister protocol handers.
# 
# net/ipv6/Makefile
#   2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +2 -1
#   [IPV6] XFRM: add missing xfrm6_tunnel.c.
# 
# include/net/xfrm.h
#   2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +14 -4
#   [IPV6] XFRM: add missing xfrm6_tunnel.c.
# 
# ChangeSet
#   2004/06/18 13:56:36+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] XFRM: add missing xfrm6_policy_check().
# 
# net/ipv6/ip6_tunnel.c
#   2004/06/18 13:56:27+09:00 yoshfuji@linux-ipv6.org +5 -0
#   [IPV6] XFRM: add missing xfrm6_policy_check().
# 
# ChangeSet
#   2004/06/18 13:54:05+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] make several functions static in ip6_tunnel that should be.
# 
# net/ipv6/ip6_tunnel.c
#   2004/06/18 13:53:56+09:00 yoshfuji@linux-ipv6.org +10 -6
#   [IPV6] make several functions static in ip6_tunnel that should be.
# 
# ChangeSet
#   2004/06/18 00:18:19-04:00 len.brown@intel.com 
#   [ACPI] handle SCI override to nth IOAPIC
#   http://bugzilla.kernel.org/show_bug.cgi?id=2835
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/17 20:18:02-04:00 len.brown@intel.com +1 -0
#   handle SCI override to nth IOAPIC
# 
# arch/i386/kernel/mpparse.c
#   2004/06/17 20:18:02-04:00 len.brown@intel.com +1 -0
#   handle SCI override to nth IOAPIC
# 
# ChangeSet
#   2004/06/17 21:16:48-07:00 rth@twiddle.net 
#   [PATCH] alpha: fix discontigmem+initrd build
#   
#   From: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
#   
#   Compilation fails due to incorrect usage of NODE_DATA().
#   
#   Reported by hpa.
# 
# arch/alpha/mm/numa.c
#   2004/06/14 08:25:24-07:00 rth@twiddle.net +2 -2
#   alpha: fix discontigmem+initrd build
# 
# ChangeSet
#   2004/06/17 21:04:44-07:00 paulus@samba.org 
#   [PATCH] ppc64: Optimize exception/syscall entry/exit
#   
#   This rewrites the PPC64 exception entry/exit routines to make them
#   smaller and faster.
#   
#   In particular we no longer save all of the registers for the common
#   exceptions - system calls, hardware interrupts and decrementer (timer)
#   interrupts - only the volatile registers.  The other registers are saved
#   and restored (if used) by the C functions we call.  This involved
#   changing the registers we use in early exception processing from r20-r23
#   to r9-r12, which ended up changing quite a lot of code in head.S. 
#   Overall this gives us about a 20% reduction in null syscall time. 
#   
#   Some system calls need all the registers (e.g.  fork/clone/vfork and
#   [rt_]sigsuspend).  For these the syscall dispatch code calls a stub that
#   saves the nonvolatile registers before calling the real handler.
#   
#   This also implements the force_successful_syscall_return() thing for
#   ppc64.
#   
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/thread_info.h
#   2004/06/16 22:46:06-07:00 paulus@samba.org +2 -2
#   ppc64: Optimize exception/syscall entry/exit
# 
# include/asm-ppc64/ptrace.h
#   2004/06/16 22:46:06-07:00 paulus@samba.org +12 -0
#   ppc64: Optimize exception/syscall entry/exit
# 
# include/asm-ppc64/processor.h
#   2004/06/16 22:46:06-07:00 paulus@samba.org +1 -2
#   ppc64: Optimize exception/syscall entry/exit
# 
# include/asm-ppc64/ppc_asm.h
#   2004/06/16 22:46:06-07:00 paulus@samba.org +3 -5
#   ppc64: Optimize exception/syscall entry/exit
# 
# include/asm-ppc64/paca.h
#   2004/06/16 22:46:06-07:00 paulus@samba.org +9 -11
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/xmon/xmon.c
#   2004/06/16 22:46:06-07:00 paulus@samba.org +0 -3
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/mm/fault.c
#   2004/06/16 23:23:50-07:00 paulus@samba.org +33 -24
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/traps.c
#   2004/06/16 22:46:06-07:00 paulus@samba.org +15 -1
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/syscalls.c
#   2004/06/16 22:46:06-07:00 paulus@samba.org +14 -0
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/signal32.c
#   2004/06/16 22:46:06-07:00 paulus@samba.org +1 -1
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/signal.c
#   2004/06/16 22:46:06-07:00 paulus@samba.org +2 -2
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/process.c
#   2004/06/16 22:46:06-07:00 paulus@samba.org +5 -1
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/pacaData.c
#   2004/06/16 22:46:06-07:00 paulus@samba.org +0 -2
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/misc.S
#   2004/06/16 22:46:06-07:00 paulus@samba.org +13 -12
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/head.S
#   2004/06/16 22:46:06-07:00 paulus@samba.org +707 -760
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/entry.S
#   2004/06/16 22:48:02-07:00 paulus@samba.org +277 -193
#   ppc64: Optimize exception/syscall entry/exit
# 
# arch/ppc64/kernel/asm-offsets.c
#   2004/06/16 22:46:06-07:00 paulus@samba.org +10 -2
#   ppc64: Optimize exception/syscall entry/exit
# 
# ChangeSet
#   2004/06/17 21:04:32-07:00 paulus@samba.org 
#   [PATCH] ppc64: Implement CONFIG_PREEMPT
#   
#   This implements CONFIG_PREEMPT for ppc64.  Aside from the entry.S
#   changes to check the _TIF_NEED_RESCHED bit when returning from an
#   exception, there are various changes to make the ppc64-specific code
#   preempt-safe, mostly adding preempt_enable/disable or get_cpu/put_cpu
#   calls where needed.  I have been using this on my desktop G5 for the
#   last week without problems.
#   
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/thread_info.h
#   2004/06/09 23:21:41-07:00 paulus@samba.org +5 -2
#   ppc64: Implement CONFIG_PREEMPT
# 
# include/asm-ppc64/system.h
#   2004/06/09 23:21:41-07:00 paulus@samba.org +2 -0
#   ppc64: Implement CONFIG_PREEMPT
# 
# include/asm-ppc64/hardirq.h
#   2004/06/09 23:21:41-07:00 paulus@samba.org +2 -0
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/mm/tlb.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +5 -1
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/mm/init.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +4 -1
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/mm/hugetlbpage.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +4 -1
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/mm/hash_utils.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +7 -3
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/traps.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +2 -4
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/sys_ppc32.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +2 -6
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/signal32.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +5 -7
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/signal.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +3 -5
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/rtas.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +4 -2
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/ptrace32.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +6 -12
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/ptrace.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +4 -8
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/process.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +64 -23
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/entry.S
#   2004/06/09 23:21:41-07:00 paulus@samba.org +50 -9
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/asm-offsets.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +1 -0
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/kernel/align.c
#   2004/06/09 23:21:41-07:00 paulus@samba.org +9 -4
#   ppc64: Implement CONFIG_PREEMPT
# 
# arch/ppc64/Kconfig
#   2004/06/09 23:21:41-07:00 paulus@samba.org +0 -1
#   ppc64: Implement CONFIG_PREEMPT
# 
# ChangeSet
#   2004/06/17 22:54:26-05:00 stevef@smfhome1.smfdom 
#   Fix typo in name of CIFS Kconfig option and add rename stats
# 
# fs/cifs/cifssmb.c
#   2004/06/17 22:54:19-05:00 stevef@smfhome1.smfdom +12 -1
#   add rename stats
# 
# fs/cifs/cifsglob.h
#   2004/06/17 22:54:19-05:00 stevef@smfhome1.smfdom +2 -0
#   add rename stats
# 
# fs/cifs/cifs_debug.c
#   2004/06/17 22:54:19-05:00 stevef@smfhome1.smfdom +7 -1
#   Add rename stats
# 
# fs/Kconfig
#   2004/06/17 22:54:19-05:00 stevef@smfhome1.smfdom +1 -1
#   Fix typo in name of CIFS Kconfig option
# 
# ChangeSet
#   2004/06/17 23:21:03-04:00 len.brown@intel.com 
#   [ACPI] avoid spurious interrupts on VIA
#   http://bugzilla.kernel.org/show_bug.cgi?id=2243
# 
# drivers/acpi/pci_link.c
#   2004/06/11 10:38:46-04:00 len.brown@intel.com +3 -19
#   disable all PCI Interrupt Links to be enabled by _SRS
# 
# ChangeSet
#   2004/06/17 20:05:11-07:00 dsaxena@plexity.net 
#   Merge plexity.net:/home/dsaxena/src/linux-2.6-arm-timer
#   into plexity.net:/home/dsaxena/src/linux-2.6-for-rmk
# 
# arch/arm/mach-integrator/integrator_cp.c
#   2004/06/17 20:05:06-07:00 dsaxena@plexity.net +0 -0
#   Auto merged
# 
# arch/arm/kernel/debug.S
#   2004/06/17 20:05:06-07:00 dsaxena@plexity.net +0 -0
#   Auto merged
# 
# arch/arm/Kconfig
#   2004/06/17 20:05:06-07:00 dsaxena@plexity.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/17 23:00:08-04:00 len.brown@intel.com 
#   [ACPI] fix passive cooling mode indicator (Luming Yu)
#   http://bugzilla.kernel.org/show_bug.cgi?id=1770
# 
# drivers/acpi/thermal.c
#   2004/01/02 00:06:13-05:00 len.brown@intel.com +7 -0
#   fix passive cooling mode indicator (Luming Yu)
# 
# ChangeSet
#   2004/06/17 16:25:47-07:00 tony.luck@intel.com 
#   [PATCH] ia64: switching between CPEI & CPEP
#   
#   A couple of months ago Hidetoshi Seto from Fujitsu proposed
#   a patch to provide similar switching between interrupt mode
#   and polling mode for corrected platform events (CPE) as we
#   have for processor events (CMC) [with the obvious difference
#   that not all platforms support an interrupt for CPE].
#   
#   I dusted it off and made a couple of very minor cleanups (which
#   Seto-san checked out last night on his test setup and confirmed
#   still passes).
#   
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# arch/ia64/kernel/mca.c
#   2004/06/16 13:24:00-07:00 tony.luck@intel.com +71 -16
#   ia64: switching between CPEI & CPEP
# 
# ChangeSet
#   2004/06/17 16:22:26-07:00 pfg@sgi.com 
#   [PATCH] ia64: fix SN2 interrupt rerouting
#   
#   Signed-off-by: Patrick Gefre <pfg@sgi.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# arch/ia64/sn/kernel/irq.c
#   2004/06/17 08:42:20-07:00 pfg@sgi.com +17 -0
#   ia64: fix SN2 interrupt rerouting
# 
# arch/ia64/sn/io/sn2/ml_iograph.c
#   2004/06/17 08:42:20-07:00 pfg@sgi.com +8 -8
#   ia64: fix SN2 interrupt rerouting
# 
# ChangeSet
#   2004/06/17 15:47:19-07:00 davidm@tiger.hpl.hp.com 
#   ia64: Fix build-problem when CONFIG_IA32 is not enabled.
#   
#   Without this fix, you'll get unresolved references to
#   sys_rt_sigaction().
# 
# include/asm-ia64/unistd.h
#   2004/06/17 15:47:11-07:00 davidm@tiger.hpl.hp.com +2 -1
#   (__ARCH_WANT_SYS_RT_SIGACTION): Move outside of
#   	#ifdef CONFIG_IA32_SUPPORT bracket---we need
#   	sys_rt_sigaction() whether we have ia32 emulation or not.
# 
# ChangeSet
#   2004/06/17 15:45:25-07:00 davidm@tiger.hpl.hp.com 
#   ia64: Squish some more hazards & warnings for UP compile.
# 
# include/asm-ia64/system.h
#   2004/06/17 15:45:17-07:00 davidm@tiger.hpl.hp.com +1 -1
#   (local_irq_enable): Precede ia64_ssm() with ia64_stop() to avoid
#   	WAW hazard when local_irq_disable() is followed in the
#   	same instruction-group by local_irq_enable().
# 
# include/asm-ia64/gcc_intrin.h
#   2004/06/17 15:45:17-07:00 davidm@tiger.hpl.hp.com +11 -5
#   (ia64_ptcga): Follow with ia64_dv_serialize_data() to shut up some
#   	compiler/assembler-warnings which showed when compiling for UP.
#   (ia64_ptcl): Likewise.
#   (ia64_intrin_local_irq_restore): Put a stop-bit before the cmp.ne to
#   	work around an apparent GCC v3.4 bug/limitation (it doesn't
#   	seem to heed the clobber of p6/p7 and merrily generates code
#   	that writes to p6/p7 right before the cmp.ne.
# 
# ChangeSet
#   2004/06/17 15:41:52-07:00 dsaxena@plexity.net 
#   [ARM] Remove ADIFCC machine type
#   
#   The code is completely out of date, I am no longer maintaining it, 
#   and nobdy has volunteered to do so; therefore, I am killing it.
#   
#   Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
# 
# arch/arm/mm/Kconfig
#   2004/06/17 15:41:42-07:00 dsaxena@plexity.net +1 -1
#   Remove ADIFCC machine type
# 
# arch/arm/kernel/entry-armv.S
#   2004/06/17 15:41:42-07:00 dsaxena@plexity.net +1 -1
#   Remove ADIFCC machine type
# 
# arch/arm/kernel/debug.S
#   2004/06/17 15:41:42-07:00 dsaxena@plexity.net +0 -26
#   Remove ADIFCC machine type
# 
# arch/arm/boot/compressed/head-xscale.S
#   2004/06/17 15:41:42-07:00 dsaxena@plexity.net +0 -3
#   Remove ADIFCC machine type
# 
# arch/arm/boot/Makefile
#   2004/06/17 15:41:42-07:00 dsaxena@plexity.net +0 -2
#   Remove ADIFCC machine type
# 
# arch/arm/Makefile
#   2004/06/17 15:41:42-07:00 dsaxena@plexity.net +0 -1
#   Remove ADIFCC machine type
# 
# arch/arm/Kconfig
#   2004/06/17 15:41:42-07:00 dsaxena@plexity.net +0 -3
#   Remove ADIFCC machine type
# 
# ChangeSet
#   2004/06/17 15:41:25-07:00 davidm@tiger.hpl.hp.com 
#   ia64: Squish compiler-warning in perfmon.c when compiling for UP.
# 
# arch/ia64/kernel/perfmon.c
#   2004/06/17 15:41:17-07:00 davidm@tiger.hpl.hp.com +26 -25
#   (pfm_force_cleanup): Move nside "#ifdef CONFIG_SMP" bracket to
#   	avoid compiler-warning.
# 
# BitKeeper/deleted/.del-adi_evb_defconfig~5ab95444ffcea5c9
#   2004/06/17 15:27:16-07:00 dsaxena@plexity.net +0 -0
#   Delete: arch/arm/configs/adi_evb_defconfig
# 
# BitKeeper/deleted/.del-vmalloc.h~15c97e3acb543bb0
#   2004/06/17 15:25:00-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/vmalloc.h
# 
# BitKeeper/deleted/.del-uncompress.h~62baa5a4fcf5eb3b
#   2004/06/17 15:25:00-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/uncompress.h
# 
# BitKeeper/deleted/.del-timex.h~a141f6df7754bb0a
#   2004/06/17 15:25:00-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/timex.h
# 
# BitKeeper/deleted/.del-system.h~198f47232b9136f1
#   2004/06/17 15:25:00-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/system.h
# 
# BitKeeper/deleted/.del-serial.h~bc766ee26826eae8
#   2004/06/17 15:24:59-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/serial.h
# 
# BitKeeper/deleted/.del-param.h~80c7330f7482c3c7
#   2004/06/17 15:24:59-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/param.h
# 
# BitKeeper/deleted/.del-memory.h~2d1748648a3d612
#   2004/06/17 15:24:59-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/memory.h
# 
# BitKeeper/deleted/.del-irqs.h~f0180913d4bf323c
#   2004/06/17 15:24:59-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/irqs.h
# 
# BitKeeper/deleted/.del-io.h~e0d8c315f73a9e29
#   2004/06/17 15:24:59-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/io.h
# 
# BitKeeper/deleted/.del-hardware.h~b995a53087c6aa07
#   2004/06/17 15:24:59-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/hardware.h
# 
# BitKeeper/deleted/.del-dma.h~1aab232a2312a68e
#   2004/06/17 15:24:58-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/dma.h
# 
# BitKeeper/deleted/.del-adi_evb.h~cd33495e40db9649
#   2004/06/17 15:24:56-07:00 dsaxena@plexity.net +0 -0
#   Delete: include/asm-arm/arch-adifcc/adi_evb.h
# 
# ChangeSet
#   2004/06/17 15:23:14-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Fix endian bug in g_file_storage
#   
#   This patch fixes a couple of places in g_file_storage where I forgot to
#   use proper byte-swapping.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/file_storage.c
#   2004/06/17 09:15:53-07:00 stern@rowland.harvard.edu +2 -2
#   USB: Fix endian bug in g_file_storage
# 
# ChangeSet
#   2004/06/17 15:22:55-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB Storage: unusual_devs.h update
#   
#   On Thu, 17 Jun 2004, Daniel Nouri wrote:
#   > I get this message when inserting my USB MMC card reader:
#   >
#   > usb 3-1: new full speed USB device using address 4
#   > usb.agent[5388]:      usb-storage: already loaded
#   > usb-storage: This device (04e6,0006,0205 S 01 P 01) has an unneeded Protocol entry in unusual_devs.h
#   > Please send a copy of this message to <linux-usb-devel@lists.sourceforge.net>
#   
#   Thanks for letting us know.  This patch will eliminate that log message.
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# BitKeeper/deleted/.del-mm.c~5479359d6124d62c
#   2004/06/17 15:22:54-07:00 dsaxena@plexity.net +0 -0
#   Delete: arch/arm/mach-adifcc/mm.c
# 
# BitKeeper/deleted/.del-irq.c~df46d54c803ac527
#   2004/06/17 15:22:54-07:00 dsaxena@plexity.net +0 -0
#   Delete: arch/arm/mach-adifcc/irq.c
# 
# BitKeeper/deleted/.del-arch.c~e5363b35d51cf728
#   2004/06/17 15:22:54-07:00 dsaxena@plexity.net +0 -0
#   Delete: arch/arm/mach-adifcc/arch.c
# 
# BitKeeper/deleted/.del-Makefile~bb9d2878ad23132d
#   2004/06/17 15:22:53-07:00 dsaxena@plexity.net +0 -0
#   Delete: arch/arm/mach-adifcc/Makefile
# 
# drivers/usb/storage/unusual_devs.h
#   2004/06/17 09:06:45-07:00 stern@rowland.harvard.edu +1 -1
#   USB Storage: unusual_devs.h update
# 
# ChangeSet
#   2004/06/17 15:22:34-07:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: Lexar Jumpshot CF reader
#   
#   This patch is required to fix up the jumpshot driver, and to supress
#   the 'unneeded entry' message for another device which uses the same
#   VID/PID/rev for multiple different versions of the device.
#   
#   Alan Stern cooked this patch up, originally.
#   
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/unusual_devs.h
#   2004/06/17 08:57:07-07:00 mdharm-usb@one-eyed-alien.net +2 -2
#   USB Storage: Lexar Jumpshot CF reader
# 
# drivers/usb/storage/jumpshot.c
#   2004/06/17 08:51:10-07:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Lexar Jumpshot CF reader
# 
# ChangeSet
#   2004/06/17 15:22:14-07:00 david-b@pacbell.net 
#   [PATCH] USB: add support for Buffalo LUA-U2-KTX
#   
#   Add support for Buffalo's LUA-U2-KTX, which is a AX8817X based usb
#   ethernet adapter.  I just added the USB id and it worked like a dream.
#   
#   From:          Neil Bortnak <neil@bortnak.com>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/usbnet.c
#   2004/06/14 05:52:53-07:00 david-b@pacbell.net +6 -0
#   USB: add support for Buffalo LUA-U2-KTX
# 
# ChangeSet
#   2004/06/17 15:21:44-07:00 david-b@pacbell.net 
#   [PATCH] proper bios handoff in ehci-hcd
#   
#   Stuart Hayes here at Dell has identified this or/and mix-up in the
#   ehci-hcd driver.  Because of this, ehci-hcd is not properly released by
#   BIOSes supporting full 2.0 and port behavior can then become erratic.
#   
#   (Code predates general availability of such BIOS firmware.  This version
#   of the patch also fixes minor linewrap issues.)
#   
#    From:          Gary Lerhaupt <Gary_Lerhaupt@Dell.com>
#    Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#    Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/ehci-hcd.c
#   2004/06/16 01:29:01-07:00 david-b@pacbell.net +4 -3
#   proper bios handoff in ehci-hcd
# 
# ChangeSet
#   2004/06/17 15:21:14-07:00 sean@mess.org 
#   [PATCH] USB: PhidgetServo driver fixes
#   
#   Here is a patch for the phidgetservo driver -- it was using memory after
#   kfree(), and using driver_info is much nicer. :)
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/phidgetservo.c
#   2004/06/16 08:28:42-07:00 sean@mess.org +63 -54
#   USB: PhidgetServo driver fixes
# 
# ChangeSet
#   2004/06/17 15:20:50-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Only process ports with change events pending
#   
#   This patch adds a bit-array to the hub driver's private data structure,
#   used for storing the contents of the hub's interrupt status message.  That
#   message indicates which ports have events pending (and whether the hub
#   itself has events pending).  By only polling the status of the ports
#   listed in the bit-array we can save a fair amount of overhead in hub
#   communication.
#   
#   (The #error test added to hub.h is a little awkward, but it's purely
#   precautionary -- it won't matter until someone decides to support hubs
#   with more than 31 ports!)
#   
#   Also included in the patch, since this seemed the perfect opportunity for
#   it, is Byron's suggestion for handling hub events in the order in which
#   they were received.
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.h
#   2004/06/15 09:10:57-07:00 stern@rowland.harvard.edu +4 -0
#   USB: Only process ports with change events pending
# 
# drivers/usb/core/hub.c
#   2004/06/15 09:11:37-07:00 stern@rowland.harvard.edu +14 -2
#   USB: Only process ports with change events pending
# 
# ChangeSet
#   2004/06/17 14:21:35-07:00 dsaxena@plexity.net 
#   [ARM] Consolidate various ARM timer fns. into single timer_tick() call.
#   
#   Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
# 
# include/asm-arm/mach/time.h
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +2 -6
#   Consolidate various ARM timer functions into a single timer_tick() call.
# 
# arch/arm/mach-versatile/core.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -3
#   Call timer_tick()
# 
# arch/arm/mach-shark/core.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -3
#   Call timer_tick()
# 
# arch/arm/mach-sa1100/time.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -5
#   Call timer_tick()
# 
# arch/arm/mach-s3c2410/time.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -6
#   Call timer_tick()
# 
# arch/arm/mach-rpc/riscpc.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -3
#   Call timer_tick()
# 
# arch/arm/mach-pxa/time.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -5
#   Call timer_tick()
# 
# arch/arm/mach-omap/time.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -3
#   Call timer_tick()
# 
# arch/arm/mach-lh7a40x/time.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -4
#   Call timer_tick()
# 
# arch/arm/mach-ixp4xx/common.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -1
#   Call timer_tick()
# 
# arch/arm/mach-iop3xx/iop321-time.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -1
#   Call timer_tick()
# 
# arch/arm/mach-integrator/time.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +1 -3
#   Call timer_tick()
# 
# arch/arm/mach-footbridge/time.c
#   2004/06/17 14:21:26-07:00 dsaxena@plexity.net +2 -11
#   Call timer_tick()
# 
# arch/arm/mach-epxa10db/time.c
#   2004/06/17 14:21:25-07:00 dsaxena@plexity.net +1 -3
#   Call timer_tick()
# 
# arch/arm/mach-ebsa110/core.c
#   2004/06/17 14:21:25-07:00 dsaxena@plexity.net +1 -3
#   Call timer_tick()
# 
# arch/arm/mach-clps7500/core.c
#   2004/06/17 14:21:25-07:00 dsaxena@plexity.net +2 -3
#   Call timer_tick()
# 
# arch/arm/mach-clps711x/time.c
#   2004/06/17 14:21:25-07:00 dsaxena@plexity.net +1 -3
#   Call timer_tick()
# 
# arch/arm/kernel/time.c
#   2004/06/17 14:21:25-07:00 dsaxena@plexity.net +16 -8
#   Consolidate various ARM timer functions into a single timer_tick() call.
# 
# ChangeSet
#   2004/06/17 13:40:02-07:00 jmorris@redhat.com 
#   [IPV6]: Fix OOPS in fragmentation.
#   
#   Incorrect SKB pointer is passed to output() callback
#   in ip6_fragment().
#   
#   Work done by James Morris and Yoshifuji Hideaki.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: Yoshifuji Hideaki <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv6/ip6_output.c
#   2004/06/17 13:39:47-07:00 jmorris@redhat.com +4 -6
#   [IPV6]: Fix OOPS in fragmentation.
#   
#   Incorrect SKB pointer is passed to output() callback
#   in ip6_fragment().
#   
#   Work done by James Morris and Yoshifuji Hideaki.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: Yoshifuji Hideaki <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/17 16:31:52-04:00 len.brown@intel.com 
#   [ACPI] PCI bus numbering workaround for ServerWorks
#   from David Shaohua Li
#   http://bugzilla.kernel.org/show_bug.cgi?id=1662
# 
# drivers/acpi/pci_root.c
#   2004/06/17 12:31:13-04:00 len.brown@intel.com +48 -1
#   if _BBN is bogus, evaluate _CRS on PCI bus
#   to get the bus number (David Shaohua Li)
# 
# ChangeSet
#   2004/06/17 12:11:42-07:00 davem@nuts.davemloft.net 
#   [NET]: In unregister_netdevice(), do synchronize_net() before final dev_put().
#   
#   This way we make sure that all destination cache updates
#   to remove references to this device are seen by entire
#   system before final destruction of the device.
# 
# ChangeSet
#   2004/06/17 12:09:59-07:00 davem@nuts.davemloft.net 
#   Cset exclude: kuznet@ms2.inr.ac.ru|ChangeSet|20040616204246|05149
# 
# net/core/dst.c
#   2004/06/17 12:09:54-07:00 davem@nuts.davemloft.net +0 -0
#   Exclude
# 
# ChangeSet
#   2004/06/17 11:52:18-07:00 shemminger@osdl.org 
#   [SPARSE]: Fix another net warning.
#   
#   Get rid of warning from assignment in conditional.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/core/net-sysfs.c
#   2004/06/17 11:52:04-07:00 shemminger@osdl.org +1 -1
#   [SPARSE]: Fix another net warning.
#   
#   Get rid of warning from assignment in conditional.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/17 11:40:00-07:00 shemminger@osdl.org 
#   [SPARSE]: Get rid of warning in bridge ethtool ioctl.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/bridge/br_if.c
#   2004/06/17 11:39:35-07:00 shemminger@osdl.org +1 -1
#   [SPARSE]: Get rid of warning in bridge ethtool ioctl.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/17 11:16:48-07:00 shemminger@osdl.org 
#   [SPARSE]: Annotate csum_and_copy_to_user().
# 
# include/asm-sparc64/checksum.h
#   2004/06/17 11:16:34-07:00 shemminger@osdl.org +2 -1
#   [SPARSE]: Annotate csum_and_copy_to_user().
# 
# include/asm-sparc/checksum.h
#   2004/06/17 11:16:34-07:00 shemminger@osdl.org +1 -1
#   [SPARSE]: Annotate csum_and_copy_to_user().
# 
# include/asm-sh/checksum.h
#   2004/06/17 11:16:34-07:00 shemminger@osdl.org +4 -2
#   [SPARSE]: Annotate csum_and_copy_to_user().
# 
# include/asm-parisc/checksum.h
#   2004/06/17 11:16:34-07:00 shemminger@osdl.org +4 -2
#   [SPARSE]: Annotate csum_and_copy_to_user().
# 
# include/asm-mips/checksum.h
#   2004/06/17 11:16:34-07:00 shemminger@osdl.org +2 -1
#   [SPARSE]: Annotate csum_and_copy_to_user().
# 
# include/asm-i386/checksum.h
#   2004/06/17 11:16:34-07:00 shemminger@osdl.org +4 -2
#   [SPARSE]: Annotate csum_and_copy_to_user().
# 
# ChangeSet
#   2004/06/17 11:15:13-07:00 akpm@osdl.org 
#   [BRIDGE]: Fix bridge sysfs improprely initialized kobject.
#   
#   The bridge sysfs interface introduced around 2.6.7-rc1 created a bad
#   entry in /sys because it didn't initialise the name member of the kobject.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/bridge/br_sysfs_br.c
#   2004/06/17 11:14:46-07:00 akpm@osdl.org +1 -3
#   [BRIDGE]: Fix bridge sysfs improprely initialized kobject.
#   
#   The bridge sysfs interface introduced around 2.6.7-rc1 created a bad
#   entry in /sys because it didn't initialise the name member of the kobject.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/17 10:56:25-07:00 shemminger@osdl.org 
#   [SPARSE]: Add annotations to sock_filter.h
#   
#   Since sock_fprog is argument in ioctl, the filter pointer needs
#   to be annotated.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/filter.h
#   2004/06/17 10:56:10-07:00 shemminger@osdl.org +3 -1
#   [SPARSE]: Add annotations to sock_filter.h
#   
#   Since sock_fprog is argument in ioctl, the filter pointer needs
#   to be annotated.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/17 10:51:14-07:00 shemminger@osdl.org 
#   [SPARSE]: Get rid of warning in irtty_ioctl().
#   
#   Don't really need verify_area because result of copy_to_user is checked.
#   Add annotation to get rid of sparse warnings.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Jean Tourrilhes <jt@bougret.hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/irda/irtty-sir.c
#   2004/06/17 10:50:59-07:00 shemminger@osdl.org +1 -9
#   [SPARSE]: Get rid of warning in irtty_ioctl().
#   
#   Don't really need verify_area because result of copy_to_user is checked.
#   Add annotation to get rid of sparse warnings.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Jean Tourrilhes <jt@bougret.hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/17 11:09:05-05:00 stevef@stevef95.austin.ibm.com 
#   fix typo in cifs kernel config option title
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/Kconfig
#   2004/06/17 11:08:47-05:00 stevef@stevef95.austin.ibm.com +1 -1
#   fix typo in cifs kernel config option title
# 
# ChangeSet
#   2004/06/17 02:15:36-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.7-mpparse
#   into intel.com:/home/lenb/bk/linux-acpi-test-2.6.7
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/17 02:15:31-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/17 01:42:44-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.7
#   into intel.com:/home/lenb/bk/linux-acpi-test-2.6.7
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/17 01:42:37-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# arch/ia64/pci/pci.c
#   2004/06/17 01:42:37-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# arch/ia64/kernel/iosapic.c
#   2004/06/17 01:42:36-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/17 01:30:00-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.6
#   into intel.com:/home/lenb/src/linux-acpi-test-2.6.7
# 
# arch/i386/kernel/dmi_scan.c
#   2004/06/17 01:29:57-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/17 01:26:33-04:00 len.brown@intel.com 
#   [ACPI] Fix a lockup which Sid Boyce <sboyce@blueyonder.co.uk>
#   discovered with IOAPIC disabled.
#   
#   The problem was that drivers/serial/8250_acpi.c found COM1 in the ACPI
#   namespace and called acpi_register_gsi() to set up its IRQ.  ACPI tells us
#   that the COM1 IRQ is edge triggered, active high, but acpi_register_gsi()
#   was ignoring the edge_level argument, so it blindly set the COM1 IRQ to be
#   level-triggered.
#   
#   Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org
# 
# arch/i386/kernel/acpi/boot.c
#   2004/06/11 11:22:01-04:00 len.brown@intel.com +6 -4
#   respect edge_level in PIC mode
# 
# ChangeSet
#   2004/06/17 01:23:50-04:00 len.brown@intel.com 
#   [ACPI] delete "__init" from x86_64 version of mp_find_ioapic() 
#   Signed-off-by: Arnd Bergmann <arnd@arndb.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.or
# 
# arch/x86_64/kernel/mpparse.c
#   2004/06/11 11:06:37-04:00 len.brown@intel.com +1 -1
#   From: Arnd Bergmann <arnd@arndb.de>
#   With the 2.6.7-rc3-mm1 acpi changes to arch/x86_64/kernel/mpparse.c,
#   mp_find_ioapic is called from a non-__init function. The fatal code
#   path is reached when loading device drivers for PCI devices.
# 
# ChangeSet
#   2004/06/17 01:19:49-04:00 len.brown@intel.com 
#   [ACPI] mp_find_ioapic() oops from mp_register_gsi() on device resume
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# arch/i386/kernel/mpparse.c
#   2004/05/31 06:03:27-04:00 len.brown@intel.com +1 -1
#   It is called from mp_register_gsi(), which is called on the device resume
#   path.  Kernel oopses.
#   
#   Program received signal SIGEMT, Emulation trap.
#   mp_find_ioapic (gsi=1) at arch/i386/kernel/mpparse.c:862
#   862     {
#   (gdb) bt
#   #0  mp_find_ioapic (gsi=1) at arch/i386/kernel/mpparse.c:862
#   #1  0xc0111de1 in mp_register_gsi (gsi=17, edge_level=1, active_high_low=1)
#       at arch/i386/kernel/mpparse.c:1042
#   #2  0xc010e164 in acpi_register_gsi (gsi=17, edge_level=9, active_high_low=9)
#       at arch/i386/kernel/acpi/boot.c:460
#   #3  0xc01ef27e in acpi_pci_irq_enable (dev=0xc16da800) at drivers/acpi/pci_irq.c:382
# 
# ChangeSet
#   2004/06/17 01:15:58-04:00 len.brown@intel.com 
#   [ACPI] *** Warning: "acpi_register_gsi" [drivers/serial/8250_acpi.ko] undefined!
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# arch/i386/kernel/acpi/boot.c
#   2004/06/17 01:15:53-04:00 len.brown@intel.com +2 -0
#   *** Warning: "acpi_register_gsi" [drivers/serial/8250_acpi.ko] undefined!
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# ChangeSet
#   2004/06/17 00:24:34-04:00 jgarzik@pobox.com 
#   [libata/IDE nvidia] shuffle pci ids
#   
#   * Mark conflicting PCI ids with CONFIG_BLK_DEV_IDE_SATA
#   * Move not-yet-released PCI ids to libata sata_nv driver
# 
# drivers/scsi/sata_nv.c
#   2004/06/17 00:24:28-04:00 jgarzik@pobox.com +11 -3
#   [libata/IDE nvidia] shuffle pci ids
#   
#   * Mark conflicting PCI ids with CONFIG_BLK_DEV_IDE_SATA
#   * Move not-yet-released PCI ids to libata sata_nv driver
# 
# drivers/ide/pci/amd74xx.c
#   2004/06/17 00:24:28-04:00 jgarzik@pobox.com +6 -14
#   [libata/IDE nvidia] shuffle pci ids
#   
#   * Mark conflicting PCI ids with CONFIG_BLK_DEV_IDE_SATA
#   * Move not-yet-released PCI ids to libata sata_nv driver
# 
# ChangeSet
#   2004/06/16 23:10:50-05:00 stevef@smfhome1.smfdom 
#   Fix /proc/fs/cifs/Stats to handle larger return data, and correct Kconfig reference to /proc/fs/cifs/Stats
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/cifsfs.h
#   2004/06/16 23:10:44-05:00 stevef@smfhome1.smfdom +1 -1
#   update cifs version to 1.19
# 
# fs/cifs/cifs_debug.c
#   2004/06/16 23:10:44-05:00 stevef@smfhome1.smfdom +42 -17
#   fix /proc/fs/cifs/Stats to handle larger return data
# 
# fs/cifs/CHANGES
#   2004/06/16 23:10:44-05:00 stevef@smfhome1.smfdom +9 -1
#   Update cifs change log for 1.19
# 
# fs/Kconfig
#   2004/06/16 23:10:44-05:00 stevef@smfhome1.smfdom +11 -2
#   Correct name of /proc/fs/cifs/Stats file.  Add cifs posix extensions configure option.
# 
# ChangeSet
#   2004/06/16 21:05:55-07:00 davidm@tiger.hpl.hp.com 
#   Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5
#   into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5
# 
# arch/ia64/kernel/gate.S
#   2004/06/16 21:05:50-07:00 davidm@tiger.hpl.hp.com +0 -4
#   Auto merged
# 
# arch/ia64/kernel/fsys.S
#   2004/06/16 21:05:50-07:00 davidm@tiger.hpl.hp.com +0 -2
#   Auto merged
# 
# ChangeSet
#   2004/06/16 20:53:53-07:00 davidm@tiger.hpl.hp.com 
#   ia64: Nuke two warnings in mca.c that showed in the simulator configuration.
# 
# arch/ia64/kernel/mca.c
#   2004/06/16 20:53:46-07:00 davidm@tiger.hpl.hp.com +8 -0
#   (ia64_mca_cpe_int_handler): Define only if CONFIG_ACPI is defined.
#   (ia64_mca_cpe_int_caller): Likewise.
# 
# ChangeSet
#   2004/06/16 20:51:30-07:00 davidm@tiger.hpl.hp.com 
#   ia64: Fix ia32 partial-page-list code to compile cleanly in more configs.
#   
# 
# include/asm-ia64/ia32.h
#   2004/06/16 20:51:21-07:00 davidm@tiger.hpl.hp.com +9 -3
#   (IA32_PAGE_SHIFT): Move to here from ia32priv.h.
#   (ia32_copy_partial_page_list): Declare unconditionally.  If
#   	PAGE_SHIFT == IA32_PAGE_SHIFT< define it as a no-op.
#   (ia32_drop_partial_page_list): Likewise.
# 
# arch/ia64/kernel/process.c
#   2004/06/16 20:51:21-07:00 davidm@tiger.hpl.hp.com +2 -6
#   (flush_thread): Remove #ifdef CONFIG_IA32_SUPPORT bracket (no longer needed).
#   	Pass task-pointer to ia32_drop_partial_page_list() instead of
#   	partial-page list (the thread.ppl member may not exist in all
#   	configurations).
#   (exit_thread): Likewise.
# 
# arch/ia64/ia32/sys_ia32.c
#   2004/06/16 20:51:21-07:00 davidm@tiger.hpl.hp.com +8 -5
#   (ia32_drop_partial_page_list): Take task-pointer instead of partial_page_list-
#   	pointer.
#   (sys32_munmap): Declare pstart and pend only when really needed.
#   (sys32_mremap): Likewise.
# 
# arch/ia64/ia32/ia32priv.h
#   2004/06/16 20:51:21-07:00 davidm@tiger.hpl.hp.com +7 -4
#   (_ASM_IA64_IA32_PRIV_H): Rename from _ASM_IA64_IA32_H to avoid name-clash.
#   (IA32_PAGE_SHIFT): Move to include/asm-ia64/ia32.h.
#   (ia32_init_pp_list): Define as 0 for case swhere PAGE_SHIFT==IA32_PAGE_SHIFT.
# 
# ChangeSet
#   2004/06/16 23:44:40-04:00 jgarzik@pobox.com 
#   [libata] put nvidia in Kconfig, in alphabetical order
# 
# drivers/scsi/Kconfig
#   2004/06/16 23:44:34-04:00 jgarzik@pobox.com +8 -8
#   [libata] put nvidia in Kconfig, in alphabetical order
# 
# ChangeSet
#   2004/06/16 23:42:01-04:00 achew@nvidia.com 
#   [libata] Add NVIDIA SATA driver
# 
# drivers/scsi/sata_nv.c
#   2004/06/16 23:41:55-04:00 achew@nvidia.com +1 -1
#   [libata] Add NVIDIA SATA driver
# 
# drivers/scsi/Makefile
#   2004/06/16 23:41:55-04:00 achew@nvidia.com +1 -0
#   [libata] Add NVIDIA SATA driver
# 
# drivers/scsi/Kconfig
#   2004/06/16 23:41:55-04:00 achew@nvidia.com +8 -0
#   [libata] Add NVIDIA SATA driver
# 
# drivers/scsi/sata_nv.c
#   2004/06/16 23:40:44-04:00 jgarzik@pobox.com +345 -0
# 
# drivers/scsi/sata_nv.c
#   2004/06/16 23:40:44-04:00 jgarzik@pobox.com +0 -0
#   BitKeeper file /spare/repo/libata-2.6/drivers/scsi/sata_nv.c
# 
# ChangeSet
#   2004/06/16 23:29:08-04:00 jgarzik@pobox.com 
#   [IDE] Introduce SATA enable/disable config option
#   
#   This config option is introduced to help reduce user confusion,
#   and eliminate conflicts between the IDE driver (which is often
#   built into user kernels) and the new libata SATA driver.
# 
# drivers/ide/pci/siimage.c
#   2004/06/16 23:29:02-04:00 jgarzik@pobox.com +3 -0
#   [IDE] Introduce SATA enable/disable config option
#   
#   This config option is introduced to help reduce user confusion,
#   and eliminate conflicts between the IDE driver (which is often
#   built into user kernels) and the new libata SATA driver.
# 
# drivers/ide/pci/piix.c
#   2004/06/16 23:29:02-04:00 jgarzik@pobox.com +2 -2
#   [IDE] Introduce SATA enable/disable config option
#   
#   This config option is introduced to help reduce user confusion,
#   and eliminate conflicts between the IDE driver (which is often
#   built into user kernels) and the new libata SATA driver.
# 
# drivers/ide/pci/generic.c
#   2004/06/16 23:29:02-04:00 jgarzik@pobox.com +2 -0
#   [IDE] Introduce SATA enable/disable config option
#   
#   This config option is introduced to help reduce user confusion,
#   and eliminate conflicts between the IDE driver (which is often
#   built into user kernels) and the new libata SATA driver.
# 
# drivers/ide/Kconfig
#   2004/06/16 23:29:02-04:00 jgarzik@pobox.com +20 -0
#   [IDE] Introduce SATA enable/disable config option
#   
#   This config option is introduced to help reduce user confusion,
#   and eliminate conflicts between the IDE driver (which is often
#   built into user kernels) and the new libata SATA driver.
# 
# arch/ia64/kernel/head.S
#   2004/06/16 18:09:33-07:00 davidm@tiger.hpl.hp.com +5 -1
#   (_start): Initialize "current" pointer for init-task to be in
#   	region 5, not 7.
# 
# arch/ia64/kernel/entry.S
#   2004/06/16 18:09:33-07:00 davidm@tiger.hpl.hp.com +4 -2
#   (ia64_switch_to): Don't try to map "current"-pointers which are
#   	inside region 5.
# 
# arch/ia64/ia32/ia32_support.c
#   2004/06/16 18:09:33-07:00 davidm@tiger.hpl.hp.com +10 -6
#   ia64: Move "current" pointer for init-task from region 7 to region 5.
#   
#   This patch initializes "current" for the init-task such that it will
#   be an address in region 5 rather than region 7.  Also, it updates the
#   context-switch code such that it won't attempt to install a pinned TLB
#   entry when the current task points inside region 5 (as will happen now
#   with the init-task).
#   
#   This fixes a problem which was triggered by SELinux.  The problem was
#   due to the fact that the init_task is initialized statically (in
#   init_tasks.c) and hence resides in region 5, but the "current" pointer
#   was using the region 7-alias of that data-structure, which causes
#   inconsistencies and failers with the list-maniplulation code.
#   
#   Signed-off-by: Kazuto MIYOSHI <k-miyoshi@cb.jp.nec.com>
#   Signed-off-by: Takayoshi Kochi <t-kochi@bq.jp.nec.com>
#   Signed-off-by: Kaigai Kohei <kaigai@ak.jp.nec.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# ChangeSet
#   2004/06/16 19:57:30-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/via-rhine
#   into pobox.com:/spare/repo/net-drivers-2.6
# 
# drivers/net/via-rhine.c
#   2004/06/16 19:57:26-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/16 19:56:25-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/via-gbit
#   into pobox.com:/spare/repo/net-drivers-2.6
# 
# drivers/net/Kconfig
#   2004/06/16 19:56:21-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/16 19:54:04-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/misc-herbert
#   into pobox.com:/spare/repo/net-drivers-2.6
# 
# drivers/net/yellowfin.c
#   2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/sungem.c
#   2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/starfire.c
#   2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/ns83820.c
#   2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/natsemi.c
#   2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/ibmlana.c
#   2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/forcedeth.c
#   2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/ewrk3.c
#   2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/at1700.c
#   2004/06/16 19:54:00-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/acenic.c
#   2004/06/16 19:54:00-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/3c527.c
#   2004/06/16 19:54:00-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/16 19:51:21-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/ip-copysum
#   into pobox.com:/spare/repo/net-drivers-2.6
# 
# drivers/net/yellowfin.c
#   2004/06/16 19:51:17-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/tulip/winbond-840.c
#   2004/06/16 19:51:17-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/natsemi.c
#   2004/06/16 19:51:17-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/epic100.c
#   2004/06/16 19:51:17-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/16 16:51:07-07:00 jbarnes@engr.sgi.com 
#   [PATCH] ia64: update sn2_defconfig
#   
#   Small patch to update the sn2_defconfig file.  I just did a 'make oldconfig' 
#   with the current sn2_defconfig and removed 8250 support.
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# arch/ia64/configs/sn2_defconfig
#   2004/06/16 09:03:12-07:00 jbarnes@engr.sgi.com +51 -55
#   ia64: update sn2_defconfig
# 
# ChangeSet
#   2004/06/16 16:04:19-07:00 kaos@sgi.com 
#   [PATCH] ia64: Support SN platform specific error features
#   
#   The SN prom supports fine grained error handling features, the OS needs
#   to tell the prom if the OS expects to use these platform specific
#   features.
#   
#   Signed-off-by: Keith Owens <kaos@sgi.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# include/asm-ia64/sn/sn_sal.h
#   2004/06/16 06:14:42-07:00 kaos@sgi.com +34 -0
#   ia64: Support SN platform specific error features
# 
# arch/ia64/sn/kernel/setup.c
#   2004/06/16 06:14:42-07:00 kaos@sgi.com +22 -1
#   ia64: Support SN platform specific error features
# 
# ChangeSet
#   2004/06/16 18:25:29-04:00 alan@redhat.com 
#   [PATCH] add new via-velocity gigabit ethernet driver
#   
#   Contributed by VIA, cleaned up by Alan.
# 
# drivers/net/via-velocity.h
#   2004/06/02 15:49:48-04:00 alan@redhat.com +1885 -0
#   PATCH: via-velocity with new ethtool used
# 
# drivers/net/via-velocity.h
#   2004/06/02 15:49:48-04:00 alan@redhat.com +0 -0
#   BitKeeper file /spare/repo/netdev-2.6/via-gbit/drivers/net/via-velocity.h
# 
# drivers/net/via-velocity.c
#   2004/06/16 17:29:42-04:00 alan@redhat.com +3277 -0
#   PATCH: via-velocity with new ethtool used
# 
# drivers/net/Makefile
#   2004/06/16 16:22:14-04:00 alan@redhat.com +1 -0
#   PATCH: via-velocity with new ethtool used
# 
# drivers/net/Kconfig
#   2004/06/16 16:22:14-04:00 alan@redhat.com +11 -0
#   PATCH: via-velocity with new ethtool used
# 
# drivers/net/via-velocity.c
#   2004/06/16 17:29:42-04:00 alan@redhat.com +0 -0
#   BitKeeper file /spare/repo/netdev-2.6/via-gbit/drivers/net/via-velocity.c
# 
# ChangeSet
#   2004/06/16 15:52:13-05:00 stevef@stevef95.austin.ibm.com 
#   fix throttle to limit number of requests to 50 on wire to server at one time.
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/transport.c
#   2004/06/16 15:52:04-05:00 stevef@stevef95.austin.ibm.com +20 -13
#   fix throttle to limit number of requests to 50 on wire to server at one time.
# 
# ChangeSet
#   2004/06/16 13:48:12-07:00 davem@nuts.davemloft.net 
#   [TCP]: No vegas by default just yet.
# 
# net/ipv4/tcp_input.c
#   2004/06/16 13:47:53-07:00 davem@nuts.davemloft.net +1 -1
#   [TCP]: No vegas by default just yet.
# 
# ChangeSet
#   2004/06/16 11:18:42-07:00 dada1@cosmosbay.com 
#   [NET]: Tidy somaxconn sysctl doc.
# 
# Documentation/networking/ip-sysctl.txt
#   2004/06/16 11:18:23-07:00 dada1@cosmosbay.com +3 -2
#   [NET]: Tidy somaxconn sysctl doc.
# 
# ChangeSet
#   2004/06/16 10:57:05-07:00 dlstevens@us.ibm.com 
#   [IPV4]: Fix interface selection in multicast sockops.
# 
# net/ipv4/ip_sockglue.c
#   2004/06/16 10:56:46-07:00 dlstevens@us.ibm.com +1 -0
#   [IPV4]: Fix interface selection in multicast sockops.
# 
# ChangeSet
#   2004/06/16 10:27:13-07:00 herbert@gondor.apana.org.au 
#   [NET]: Clear dev refs in dst->child.
#   
#   This is a resend of an earlier patch to dst_dev_event.  I've changed
#   it slightly by moving the input/output assignment into dst_ifdown.
#   
#   To recap, this patch drops lingering IPsec references to a device that
#   is being unregistered.  The child processing in the GC is too late
#   since it never runs until the reference on the dst hits zero which
#   could take a long time for things like TCP connections.
#   
#   The reason I've left the input/output assignment outside the loop is
#   because they aren't really necessary for the IPsec dst's, and if
#   it were in the loop then we'll have to do the same child processing
#   in ___dst_free as well.
#   
#   I've tested this with an ESP/IPCOMP tunnel and I can confirm that it
#   does fix the problem.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/core/dst.c
#   2004/06/16 10:26:56-07:00 herbert@gondor.apana.org.au +37 -25
#   [NET]: Clear dev refs in dst->child.
#   
#   This is a resend of an earlier patch to dst_dev_event.  I've changed
#   it slightly by moving the input/output assignment into dst_ifdown.
#   
#   To recap, this patch drops lingering IPsec references to a device that
#   is being unregistered.  The child processing in the GC is too late
#   since it never runs until the reference on the dst hits zero which
#   could take a long time for things like TCP connections.
#   
#   The reason I've left the input/output assignment outside the loop is
#   because they aren't really necessary for the IPsec dst's, and if
#   it were in the loop then we'll have to do the same child processing
#   in ___dst_free as well.
#   
#   I've tested this with an ESP/IPCOMP tunnel and I can confirm that it
#   does fix the problem.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/16 10:23:42-07:00 davem@nuts.davemloft.net 
#   Merge nuts.davemloft.net:/disk1/BK/net-2.6.8
#   into nuts.davemloft.net:/disk1/BK/net-2.6
# 
# net/ipv4/tcp.c
#   2004/06/16 10:23:34-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/16 11:36:45-05:00 jejb@mulgrave.(none) 
#   scsi_debug: num_parts, ptype and (re-)scans
#   
#   From: 	Douglas Gilbert <dougg@torque.net>
#   
#   Changes in version 1.73:
#     - 'num_parts' parameter to specify 0 to 4 partitions
#     - 'ptype' to specify (or change via sysfs) SCSI
#       peripheral device type
#     - support ability to increase the number of targets
#       and/or luns then re-scan a scsi_debug host
#     - remove redundant trailing spaces
#   
#   The new facilties are described at:
#   http://www.torque.net/sg/sdebug26.html
#   A tarball of driver (version 1.73) is also there.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
#   (conflict resolution)
# 
# drivers/scsi/scsi_debug.h
#   2004/06/16 11:36:19-05:00 jejb@mulgrave.(none) +1 -4
#   scsi_debug: num_parts, ptype and (re-)scans
# 
# drivers/scsi/scsi_debug.c
#   2004/06/16 11:36:19-05:00 jejb@mulgrave.(none) +253 -124
#   scsi_debug: num_parts, ptype and (re-)scans
# 
# ChangeSet
#   2004/06/16 09:32:58-05:00 jejb@mulgrave.(none) 
#   SCSI: fix uninitialised variable warning
#   
#   Spotted By: Andrew Morton <akpm@osdl.org>
#   
#   drivers/scsi/scsi_transport_spi.c: In function `spi_dv_retrain':
#   drivers/scsi/scsi_transport_spi.c:393: warning: `period' might be used uninitialized in this function
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_transport_spi.c
#   2004/06/16 09:32:42-05:00 jejb@mulgrave.(none) +1 -1
#   SCSI: fix uninitialised variable warning
# 
# ChangeSet
#   2004/06/15 21:46:23-07:00 jmorris@redhat.com 
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/ss/services.c
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +12 -0
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/ss/policydb.c
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +9 -1
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/include/security.h
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +5 -4
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/include/flask.h
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +9 -0
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/include/class_to_string.h
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +9 -0
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/include/av_permissions.h
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +223 -0
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/include/av_perm_to_string.h
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +12 -0
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/include/av_inherit.h
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +9 -0
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/hooks.c
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +80 -22
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/Makefile
#   2004/06/15 21:46:08-07:00 jmorris@redhat.com +1 -1
#   [SELINUX]: Fine-grained Netlink support - SELinux changes
#   
#   This patch contains SELinux changes which add support for extended Netlink
#   socket classes and the associated permissions nlmsg_read and nlmsg_write.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/15 21:45:30-07:00 jmorris@redhat.com 
#   [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook
#   
#   Modifies the LSM netlink_send() hook so that it takes a struct sock
#   parameter.  SELinux will use this parameter to lookup the class of socket,
#   which was assigned during socket security initialization.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/hooks.c
#   2004/06/15 21:45:15-07:00 jmorris@redhat.com +1 -1
#   [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook
#   
#   Modifies the LSM netlink_send() hook so that it takes a struct sock
#   parameter.  SELinux will use this parameter to lookup the class of socket,
#   which was assigned during socket security initialization.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/dummy.c
#   2004/06/15 21:45:15-07:00 jmorris@redhat.com +1 -1
#   [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook
#   
#   Modifies the LSM netlink_send() hook so that it takes a struct sock
#   parameter.  SELinux will use this parameter to lookup the class of socket,
#   which was assigned during socket security initialization.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/netlink/af_netlink.c
#   2004/06/15 21:45:15-07:00 jmorris@redhat.com +1 -1
#   [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook
#   
#   Modifies the LSM netlink_send() hook so that it takes a struct sock
#   parameter.  SELinux will use this parameter to lookup the class of socket,
#   which was assigned during socket security initialization.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/security.h
#   2004/06/15 21:45:15-07:00 jmorris@redhat.com +11 -8
#   [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook
#   
#   Modifies the LSM netlink_send() hook so that it takes a struct sock
#   parameter.  SELinux will use this parameter to lookup the class of socket,
#   which was assigned during socket security initialization.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/15 21:44:40-07:00 jmorris@redhat.com 
#   [SELINUX]: Fine-grained Netlink support - move security_netlink_send() hook.
#   
#   This patch moves the security_netlink_send() LSM hook after the user copy,
#   so that LSM modules can safely examine skb payload content.  For SELinux,
#   we need to look at the Netlink message type.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/netlink/af_netlink.c
#   2004/06/15 21:44:26-07:00 jmorris@redhat.com +4 -4
#   [SELINUX]: Fine-grained Netlink support - move security_netlink_send() hook.
#   
#   This patch moves the security_netlink_send() LSM hook after the user copy,
#   so that LSM modules can safely examine skb payload content.  For SELinux,
#   we need to look at the Netlink message type.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/15 21:42:03-07:00 jmorris@redhat.com 
#   [SELINUX]: Fine-grained Netlink support - SELinux headers
#   
#   This patch regenerates the SELinux module headers to reflect new class
#   and access vectors definitions.  The size of the diff is misleading;
#   much of it is simply a change in the ordering of the automatically
#   generated definitions. The corresponding generation script has been
#   changed to ensure a stable order in the future.
#   
#   Author: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  James Morris <jmorris@redhat.com>
#   Signed-off-by:  David S. Miller <davem@redhat.com>
# 
# security/selinux/include/flask.h
#   2004/06/15 21:41:48-07:00 jmorris@redhat.com +12 -0
#   [SELINUX]: Fine-grained Netlink support - SELinux headers
#   
#   This patch regenerates the SELinux module headers to reflect new class
#   and access vectors definitions.  The size of the diff is misleading;
#   much of it is simply a change in the ordering of the automatically
#   generated definitions. The corresponding generation script has been
#   changed to ensure a stable order in the future.
#   
#   Author: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  James Morris <jmorris@redhat.com>
#   Signed-off-by:  David S. Miller <davem@redhat.com>
# 
# security/selinux/include/class_to_string.h
#   2004/06/15 21:41:48-07:00 jmorris@redhat.com +12 -0
#   [SELINUX]: Fine-grained Netlink support - SELinux headers
#   
#   This patch regenerates the SELinux module headers to reflect new class
#   and access vectors definitions.  The size of the diff is misleading;
#   much of it is simply a change in the ordering of the automatically
#   generated definitions. The corresponding generation script has been
#   changed to ensure a stable order in the future.
#   
#   Author: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  James Morris <jmorris@redhat.com>
#   Signed-off-by:  David S. Miller <davem@redhat.com>
# 
# security/selinux/include/av_permissions.h
#   2004/06/15 21:41:48-07:00 jmorris@redhat.com +350 -250
#   [SELINUX]: Fine-grained Netlink support - SELinux headers
#   
#   This patch regenerates the SELinux module headers to reflect new class
#   and access vectors definitions.  The size of the diff is misleading;
#   much of it is simply a change in the ordering of the automatically
#   generated definitions. The corresponding generation script has been
#   changed to ensure a stable order in the future.
#   
#   Author: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  James Morris <jmorris@redhat.com>
#   Signed-off-by:  David S. Miller <davem@redhat.com>
# 
# security/selinux/include/av_perm_to_string.h
#   2004/06/15 21:41:48-07:00 jmorris@redhat.com +89 -3
#   [SELINUX]: Fine-grained Netlink support - SELinux headers
#   
#   This patch regenerates the SELinux module headers to reflect new class
#   and access vectors definitions.  The size of the diff is misleading;
#   much of it is simply a change in the ordering of the automatically
#   generated definitions. The corresponding generation script has been
#   changed to ensure a stable order in the future.
#   
#   Author: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by:  James Morris <jmorris@redhat.com>
#   Signed-off-by:  David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/15 21:39:10-07:00 anton@samba.org 
#   [NET]: Allow IP header alignment to be overriden.
#   
#   Author: Anton Blanchard <anton@samba.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/skbuff.h
#   2004/06/15 21:38:55-07:00 anton@samba.org +24 -0
#   [NET]: Allow IP header alignment to be overriden.
#   
#   Author: Anton Blanchard <anton@samba.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/asm-ppc64/system.h
#   2004/06/15 21:38:55-07:00 anton@samba.org +9 -0
#   [NET]: Allow IP header alignment to be overriden.
#   
#   Author: Anton Blanchard <anton@samba.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/s2io.h
#   2004/06/15 21:38:55-07:00 anton@samba.org +0 -1
#   [NET]: Allow IP header alignment to be overriden.
#   
#   Author: Anton Blanchard <anton@samba.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/s2io.c
#   2004/06/15 21:38:55-07:00 anton@samba.org +2 -2
#   [NET]: Allow IP header alignment to be overriden.
#   
#   Author: Anton Blanchard <anton@samba.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/ixgb/ixgb_main.c
#   2004/06/15 21:38:55-07:00 anton@samba.org +2 -3
#   [NET]: Allow IP header alignment to be overriden.
#   
#   Author: Anton Blanchard <anton@samba.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/e1000/e1000_main.c
#   2004/06/15 21:38:55-07:00 anton@samba.org +2 -3
#   [NET]: Allow IP header alignment to be overriden.
#   
#   Author: Anton Blanchard <anton@samba.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/06/15 21:38:55-07:00 anton@samba.org +3 -2
#   [NET]: Allow IP header alignment to be overriden.
#   
#   Author: Anton Blanchard <anton@samba.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/15 21:37:06-07:00 shemminger@osdl.org 
#   [ATM]: Include compiler.h in atm.h
# 
# include/linux/atm.h
#   2004/06/15 21:36:52-07:00 shemminger@osdl.org +1 -0
#   [ATM]: Include compiler.h in atm.h
# 
# ChangeSet
#   2004/06/15 21:35:21-07:00 davem@nuts.davemloft.net 
#   [TCP]: Tweak some default sysctl values.
#   
#   tcp_default_win_scale: 7
#   tcp_vegas_cong_avoid: 1
#   tcp_moderate_rcvbuf: 1
#   tcp_bic: 1
# 
# net/ipv4/tcp_input.c
#   2004/06/15 21:18:53-07:00 davem@nuts.davemloft.net +3 -3
#   [TCP]: Tweak some default sysctl values.
#   
#   tcp_default_win_scale: 7
#   tcp_vegas_cong_avoid: 1
#   tcp_moderate_rcvbuf: 1
#   tcp_bic: 1
# 
# net/ipv4/tcp.c
#   2004/06/15 21:18:53-07:00 davem@nuts.davemloft.net +1 -1
#   [TCP]: Tweak some default sysctl values.
#   
#   tcp_default_win_scale: 7
#   tcp_vegas_cong_avoid: 1
#   tcp_moderate_rcvbuf: 1
#   tcp_bic: 1
# 
# ChangeSet
#   2004/06/15 21:09:47-07:00 yoshfuji@linux-ipv6.org 
#   [IPV6]: UDPv6 checksum.
#   
#   We always need to check UDPv6 checksum because it is mandatory.
#   
#   Author: Yoshifuji Hideaki <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ipv6/udp.c
#   2004/06/15 21:09:31-07:00 yoshfuji@linux-ipv6.org +1 -1
#   [IPV6]: UDPv6 checksum.
#   
#   We always need to check UDPv6 checksum because it is mandatory.
#   
#   Author: Yoshifuji Hideaki <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/15 21:07:24-07:00 jmorris@redhat.com 
#   [SELINUX]: Fix sock_orphan race.
#   
#   The patch below fixes a race between sock_orphan() and
#   selinux_socket_sock_rcv_skb() which can lead to a null pointer deref oops
#   under heavy load.  The sk_callback_lock is used in the patch to 
#   synchronize access to the incoming socket's inode security state.
#   
#   This patch has been under test in the Fedora kernel for over a month 
#   without incident.
#   
#   Author: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# security/selinux/hooks.c
#   2004/06/15 21:07:09-07:00 jmorris@redhat.com +21 -16
#   [SELINUX]: Fix sock_orphan race.
#   
#   The patch below fixes a race between sock_orphan() and
#   selinux_socket_sock_rcv_skb() which can lead to a null pointer deref oops
#   under heavy load.  The sk_callback_lock is used in the patch to 
#   synchronize access to the incoming socket's inode security state.
#   
#   This patch has been under test in the Fedora kernel for over a month 
#   without incident.
#   
#   Author: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/15 20:37:41-07:00 hadi@znyx.com 
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_prio.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +58 -14
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/sch_ingress.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +64 -8
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/police.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +329 -1
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/cls_u32.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +179 -8
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/cls_tcindex.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +2 -2
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/cls_rsvp.h
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +3 -3
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/cls_route.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +3 -3
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/cls_fw.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +174 -3
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/cls_api.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +18 -5
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/Makefile
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +3 -1
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/Kconfig
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +33 -2
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/ethernet/eth.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +3 -0
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/core/skbuff.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +23 -0
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/core/rtnetlink.c
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +4 -2
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/net/pkt_sched.h
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +76 -4
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/net/pkt_cls.h
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +30 -2
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/skbuff.h
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +9 -1
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/rtnetlink.h
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +17 -0
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/pkt_sched.h
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +1 -0
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/pkt_cls.h
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +163 -8
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/netdevice.h
#   2004/06/15 20:37:18-07:00 hadi@znyx.com +2 -0
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/act_api.c
#   2004/06/15 20:37:06-07:00 hadi@znyx.com +978 -0
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/act_api.c
#   2004/06/15 20:37:06-07:00 hadi@znyx.com +0 -0
#   BitKeeper file /disk1/BK/tc-2.6/net/sched/act_api.c
# 
# include/net/pkt_act.h
#   2004/06/15 20:37:05-07:00 hadi@znyx.com +286 -0
#   [NET]: Add tc extensions infrastructure.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/net/pkt_act.h
#   2004/06/15 20:37:05-07:00 hadi@znyx.com +0 -0
#   BitKeeper file /disk1/BK/tc-2.6/include/net/pkt_act.h
# 
# ChangeSet
#   2004/06/16 00:33:13-03:00 acme@toy.kerneljanitors.org 
#   [ECONET] kill some trivial warnings
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/econet/af_econet.c
#   2004/06/16 00:33:01-03:00 acme@toy.kerneljanitors.org +6 -8
#   [ECONET] kill some trivial warnings
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/15 20:24:51-07:00 davem@nuts.davemloft.net 
#   Merge bk://kernel.bkbits.net/acme/net-2.6
#   into nuts.davemloft.net:/disk1/BK/net-2.6
# 
# net/ipv6/tcp_ipv6.c
#   2004/06/15 20:24:38-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/15 20:20:25-07:00 ahu@ds9a.nl 
#   [NET]: Update some sysctl documentation.
#   
#   I ran the following (crappy) script:
#    ...
#   In /proc/sys/ and found a host of undocumented sysctls. This patch documents
#   a number of them, and at least mentions the rest as 'TODO'. Please verify my
#   code-inspired documentation before applying!
#   
#   Signed-off-by: Bert Hubert <ahu@ds9a.nl>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# Documentation/networking/ip-sysctl.txt
#   2004/06/15 20:19:32-07:00 ahu@ds9a.nl +57 -0
#   [NET]: Update some sysctl documentation.
#   
#   I ran the following (crappy) script:
#    ...
#   In /proc/sys/ and found a host of undocumented sysctls. This patch documents
#   a number of them, and at least mentions the rest as 'TODO'. Please verify my
#   code-inspired documentation before applying!
#   
#   Signed-off-by: Bert Hubert <ahu@ds9a.nl>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# Documentation/filesystems/proc.txt
#   2004/06/15 20:19:32-07:00 ahu@ds9a.nl +2 -1
#   [NET]: Update some sysctl documentation.
#   
#   I ran the following (crappy) script:
#    ...
#   In /proc/sys/ and found a host of undocumented sysctls. This patch documents
#   a number of them, and at least mentions the rest as 'TODO'. Please verify my
#   code-inspired documentation before applying!
#   
#   Signed-off-by: Bert Hubert <ahu@ds9a.nl>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/06/15 19:32:48-07:00 dsaxena@omelas.(none) 
#   [ARM] Add include/asm-arm/mach/time.h for shared timer definitions
#   
#   Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
# 
# include/asm-arm/mach/time.h
#   2004/06/15 19:31:40-07:00 dsaxena@omelas.(none) +24 -0
# 
# include/asm-arm/mach/time.h
#   2004/06/15 19:31:40-07:00 dsaxena@omelas.(none) +0 -0
#   BitKeeper file /home/dsaxena/src/linux-2.6-arm-timer/include/asm-arm/mach/time.h
# 
# ChangeSet
#   2004/06/15 19:00:23-07:00 dsaxena@omelas.(none) 
#   [ARM] Delete include/asm-arm/arch-versatile/time.h
#   
#   Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
# 
# BitKeeper/deleted/.del-time.h~c344b24f8045f7dc
#   2004/06/15 18:59:09-07:00 dsaxena@omelas.(none) +0 -0
#   Delete: include/asm-arm/arch-versatile/time.h
# 
# ChangeSet
#   2004/06/15 18:45:01-07:00 dsaxena@omelas.(none) 
#   [ARM] Delete include/asm-arm/arch-ixp4xx/time.h
#   
#   Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
# 
# BitKeeper/deleted/.del-time.h~cc23e4568356fd42
#   2004/06/15 18:44:35-07:00 dsaxena@omelas.(none) +0 -0
#   Delete: include/asm-arm/arch-ixp4xx/time.h
# 
# ChangeSet
#   2004/06/15 18:42:18-07:00 dsaxena@omelas.(none) 
#   [ARM] Delete include/asm-arm/arch-iop3xx/time.h
#   
#   Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
# 
# BitKeeper/deleted/.del-time.h~66507b95d41b2fa3
#   2004/06/15 18:41:53-07:00 dsaxena@omelas.(none) +0 -0
#   Delete: include/asm-arm/arch-iop3xx/time.h
# 
# ChangeSet
#   2004/06/15 18:38:14-07:00 dsaxena@omelas.(none) 
#   [ARM] Delete include/asm-arm/arch-nexuspci/time.h
#   
#   Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
# 
# BitKeeper/deleted/.del-time.h~730e38fa47912a2c
#   2004/06/15 18:37:53-07:00 dsaxena@omelas.(none) +0 -0
#   Delete: include/asm-arm/arch-nexuspci/time.h
# 
# ChangeSet
#   2004/06/15 18:16:01-07:00 dsaxena@omelas.(none) 
#   [ARM] Remove bogus gettimeoffset ptr from machine_desc struct.
#   
#   This was accidently added during the timer code cleanup.
#   
#   Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
# 
# include/asm-arm/mach/arch.h
#   2004/06/15 18:14:13-07:00 dsaxena@omelas.(none) +0 -1
#   Remove bogus gettimeoffset() from machine_desc struct
# 
# ChangeSet
#   2004/06/15 17:57:04-07:00 dsaxena@omelas.(none) 
#   Merge
# 
# arch/arm/mach-omap/board-generic.c
#   2004/06/15 17:57:02-07:00 dsaxena@omelas.(none) +0 -0
#   SCCS merged
# 
# arch/arm/mach-omap/time.c
#   2004/06/15 17:50:10-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# arch/arm/mach-omap/time.c
#   2004/06/15 17:50:10-07:00 dsaxena@omelas.(none) +0 -0
#   Merge rename: include/asm-arm/arch-omap/time.h -> arch/arm/mach-omap/time.c
# 
# arch/arm/mach-omap/board-perseus2.c
#   2004/06/15 17:50:10-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# arch/arm/mach-omap/board-osk.c
#   2004/06/15 17:50:10-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# arch/arm/mach-omap/board-innovator.c
#   2004/06/15 17:50:10-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# arch/arm/Kconfig
#   2004/06/15 17:50:10-07:00 dsaxena@omelas.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/15 17:48:14-07:00 dsaxena@omelas.(none) 
#   [ARM] Timer cleanup
#   
#   Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
# 
# include/asm-arm/mach/arch.h
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +5 -0
#   ARM timer cleanup
# 
# include/asm-arm/arch-ixp4xx/platform.h
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# include/asm-arm/arch-integrator/platform.h
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +4 -0
#   ARM timer cleanup
# 
# arch/arm/mach-versatile/core.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +147 -0
#   ARM timer cleanup
# 
# arch/arm/mach-tbox/core.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +27 -0
#   ARM timer cleanup
# 
# arch/arm/mach-shark/core.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +40 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/yopy.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/xp860.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/trizeps.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +8 -3
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/system3.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/stork.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/simpad.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/sherman.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/shannon.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/pleb.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/pfs168.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/pangolin.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/omnimeter.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/nanoengine.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/lart.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/jornada720.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/itsy.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/huw_webpanel.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/hackkit.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/h3600.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +3 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/graphicsmaster.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/graphicsclient.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/generic.h
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/freebird.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/flexanet.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/empeg.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/cerf.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/brutus.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/badge4.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/assabet.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-sa1100/adsbitsy.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-s3c2410/time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +18 -10
#   ARM timer cleanup
# 
# arch/arm/mach-s3c2410/s3c2410.h
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/mach-s3c2410/mach-vr1000.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +6 -0
#   ARM timer cleanup
# 
# arch/arm/mach-s3c2410/mach-smdk2410.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +6 -0
#   ARM timer cleanup
# 
# arch/arm/mach-s3c2410/mach-h1940.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +6 -0
#   ARM timer cleanup
# 
# arch/arm/mach-s3c2410/mach-bast.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +6 -0
#   ARM timer cleanup
# 
# arch/arm/mach-s3c2410/Makefile
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -1
#   ARM timer cleanup
# 
# arch/arm/mach-rpc/riscpc.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +31 -0
#   ARM timer cleanup
# 
# arch/arm/mach-pxa/time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +27 -4
#   ARM timer cleanup
# 
# arch/arm/mach-pxa/mainstone.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-pxa/lubbock.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-pxa/idp.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-pxa/generic.h
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-pxa/Makefile
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -1
#   ARM timer cleanup
# 
# arch/arm/mach-omap/time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +15 -13
#   ARM timer cleanup
# 
# arch/arm/mach-omap/common.h
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-omap/board-perseus2.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-omap/board-osk.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-omap/board-innovator.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-omap/board-generic.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +7 -0
#   ARM timer cleanup
# 
# arch/arm/mach-omap/Makefile
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -1
#   ARM timer cleanup
# 
# arch/arm/mach-lh7a40x/time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +22 -5
#   ARM timer cleanup
# 
# arch/arm/mach-lh7a40x/arch-lpd7a40x.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/mach-lh7a40x/arch-kev7a400.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/mach-lh7a40x/Makefile
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -1
#   ARM timer cleanup
# 
# arch/arm/mach-ixp4xx/prpmc1100-setup.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-ixp4xx/ixdp425-setup.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +3 -0
#   ARM timer cleanup
# 
# arch/arm/mach-ixp4xx/coyote-setup.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/mach-ixp4xx/common.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +7 -8
#   ARM timer cleanup
# 
# arch/arm/mach-iop3xx/iop321-time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +7 -6
#   ARM timer cleanup
# 
# arch/arm/mach-iop3xx/arch.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/mach-integrator/time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +146 -0
#   ARM timer cleanup
# 
# arch/arm/mach-integrator/integrator_cp.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +6 -0
#   ARM timer cleanup
# 
# arch/arm/mach-integrator/integrator_ap.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +6 -0
#   ARM timer cleanup
# 
# arch/arm/mach-ftvpci/core.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +47 -0
#   ARM timer cleanup
# 
# arch/arm/mach-footbridge/time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +26 -8
#   ARM timer cleanup
# 
# arch/arm/mach-footbridge/arch.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +6 -0
#   ARM timer cleanup
# 
# arch/arm/mach-footbridge/Makefile
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +1 -1
#   ARM timer cleanup
# 
# arch/arm/mach-epxa10db/time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +45 -1
#   ARM timer cleanup
# 
# arch/arm/mach-epxa10db/arch.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +3 -0
#   ARM timer cleanup
# 
# arch/arm/mach-ebsa110/core.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +102 -0
#   ARM timer cleanup
# 
# arch/arm/mach-clps7500/core.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +40 -1
#   ARM timer cleanup
# 
# arch/arm/mach-clps711x/time.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +28 -4
#   ARM timer cleanup
# 
# arch/arm/mach-clps711x/p720t.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/mach-clps711x/fortunet.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/mach-clps711x/edb7211-arch.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/mach-clps711x/clep7312.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/mach-clps711x/ceiva.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/mach-clps711x/cdb89712.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/common/time-acorn.c
#   2004/06/15 17:42:35-07:00 dsaxena@omelas.(none) +3 -2
#   ARM timer cleanup
# 
# arch/arm/mach-clps711x/autcpu12.c
#   2004/06/15 17:42:34-07:00 dsaxena@omelas.(none) +2 -0
#   ARM timer cleanup
# 
# arch/arm/kernel/time.c
#   2004/06/15 17:42:34-07:00 dsaxena@omelas.(none) +12 -15
#   ARM timer cleanup
# 
# arch/arm/kernel/setup.c
#   2004/06/15 17:42:34-07:00 dsaxena@omelas.(none) +3 -0
#   ARM timer cleanup
# 
# arch/arm/kernel/Makefile
#   2004/06/15 17:42:34-07:00 dsaxena@omelas.(none) +1 -2
#   ARM timer cleanup
# 
# arch/arm/common/Makefile
#   2004/06/15 17:42:34-07:00 dsaxena@omelas.(none) +1 -0
#   ARM timer cleanup
# 
# arch/arm/Kconfig
#   2004/06/15 17:42:34-07:00 dsaxena@omelas.(none) +5 -0
#   ARM timer cleanup
# 
# BitKeeper/deleted/.del-time.h~e839fe4bcd9e4cf9
#   2004/06/15 16:48:56-07:00 dsaxena@omelas.(none) +0 -0
#   Delete: include/asm-arm/arch-tbox/time.h
# 
# ChangeSet
#   2004/06/15 16:29:30-07:00 eranian@hpl.hp.com 
#   [PATCH] ia64: fix info in /proc/pal/*/bus_info
#   
#   This patch fixes to minor bugs:
#    - corrected descriptions for bit 52 and 53 of the /proc/pal/CPU*/bus_info
#      entry; they were swapped
#    - corrected a typo for bit 55 of the /proc/pal/CPU*/bus_info entry
#   
#   Signed-off-by: Stephane Eranian <eranian@hpl.hp.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# arch/ia64/kernel/palinfo.c
#   2004/06/15 10:28:07-07:00 eranian@hpl.hp.com +2 -2
#   ia64: fix info in /proc/pal/*/bus_info
# 
# BitKeeper/deleted/.del-time.c~e41898daed8bea09
#   2004/06/15 16:08:17-07:00 dsaxena@omelas.(none) +0 -0
#   Delete: arch/arm/mach-shark/time.c
# 
# arch/arm/mach-shark/time.c
#   2004/06/15 15:58:38-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: arch/arm/mach-shark/time.ch -> arch/arm/mach-shark/time.c
# 
# arch/arm/mach-shark/time.ch
#   2004/06/15 15:46:57-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-shark/time.h -> arch/arm/mach-shark/time.ch
# 
# arch/arm/mach-sa1100/time.c
#   2004/06/15 15:02:29-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-sa1100/time.h -> arch/arm/mach-sa1100/time.c
# 
# arch/arm/mach-s3c2410/time.c
#   2004/06/15 13:52:07-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-s3c2410/time.h -> arch/arm/mach-s3c2410/time.c
# 
# BitKeeper/deleted/.del-time.c~16d0f1fb7b29ea89
#   2004/06/15 13:09:43-07:00 dsaxena@omelas.(none) +0 -23
#   Delete: arch/arm/mach-rpc/time.c
# 
# arch/arm/mach-rpc/time.c
#   2004/06/15 13:02:38-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-rpc/time.h -> arch/arm/mach-rpc/time.c
# 
# arch/arm/mach-pxa/time.c
#   2004/06/15 12:36:09-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-pxa/time.h -> arch/arm/mach-pxa/time.c
# 
# arch/arm/mach-omap/time.c
#   2004/06/15 12:06:48-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-omap/time.h -> arch/arm/mach-omap/time.c
# 
# arch/arm/mach-lh7a40x/time.c
#   2004/06/15 11:01:21-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-lh7a40x/time.h -> arch/arm/mach-lh7a40x/time.c
# 
# ChangeSet
#   2004/06/15 12:48:08-05:00 jejb@mulgrave.(none) 
#   Fix endless loop in SCSI SPI transport class
#   
#   If the driver doesn't update the peroid, we go
#   around forever.  The fix is to keep our old period
#   unless the driver returns a greater one.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_transport_spi.c
#   2004/06/15 12:47:53-05:00 jejb@mulgrave.(none) +3 -1
#   Fix endless loop in SCSI SPI transport class
# 
# ChangeSet
#   2004/06/15 12:32:52-05:00 jejb@mulgrave.(none) 
#   Merge
# 
# drivers/scsi/qlogicpti.c
#   2004/06/15 12:32:34-05:00 jejb@mulgrave.(none) +0 -1
#   SCCS merged
# 
# drivers/scsi/esp.c
#   2004/06/15 12:32:09-05:00 jejb@mulgrave.(none) +0 -1
#   SCCS merged
# 
# include/linux/pci_ids.h
#   2004/06/15 12:28:06-05:00 jejb@mulgrave.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/st.c
#   2004/06/15 12:28:06-05:00 jejb@mulgrave.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/scsi_debug.c
#   2004/06/15 12:28:06-05:00 jejb@mulgrave.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/osst.c
#   2004/06/15 12:28:05-05:00 jejb@mulgrave.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/cpqfcTScontrol.c
#   2004/06/15 12:28:05-05:00 jejb@mulgrave.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/Kconfig
#   2004/06/15 12:28:05-05:00 jejb@mulgrave.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/06/15 12:28:05-05:00 jejb@mulgrave.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/15 12:09:19-05:00 rddunlap@osdl.org 
#   [PATCH] Comment out an unused function in drivers/scsi/wd7000.c
#   
#   Eliminate unused function wd7000_abort() in wd7000 driver.
#   
#     CC [M]  drivers/scsi/wd7000.o
#   drivers/scsi/wd7000.c:1612: warning: `wd7000_abort' defined but not used
#   
#   As the author states in his comment, this is "unfinished business" ;-)
#   
#   
#   From: Mika Kukkonen <mika@osdl.org>
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/wd7000.c
#   2004/06/15 10:49:13-05:00 rddunlap@osdl.org +2 -1
#   Comment out an unused function in drivers/scsi/wd7000.c
# 
# ChangeSet
#   2004/06/15 12:07:20-05:00 bunk@fs.tum.de 
#   [PATCH] modular scsi/mca_53c9x doesn't work
#   
#   On Mon, Jun 14, 2004 at 08:22:15PM +0100, Christoph Hellwig wrote:
#   > On Mon, Jun 14, 2004 at 08:52:56PM +0200, Adrian Bunk wrote:
#   > > The issue described in the mail forwarded below is still present in
#   > > 2.6.7-rc3-mm2 (but not specific to -mm).
#   > >
#   > > I'd suggest the following workaround:
#   >
#   > Please add the exports instead.  It'll affect all the other 53C9X-based
#   > drivers aswell.
#   
#   This sounds like a better solution.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/NCR53C9x.c
#   2004/06/14 17:47:23-05:00 bunk@fs.tum.de +11 -0
#   modular scsi/mca_53c9x doesn't work
# 
# ChangeSet
#   2004/06/15 12:06:00-05:00 akpm@osdl.org 
#   [PATCH] drivers/scsi/megaraid.c: user/kernel pointer bugs
#   
#   From: "Robert T. Johnson" <rtjohnso@eecs.berkeley.edu>
#   
#   Since arg is a user pointer, so are uioc_mimd and uiocp, and hence umc is a
#   user pointer.  Thus reading umc->xferaddr requires dereferencing a user
#   pointer, which isn't safe.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/megaraid.c
#   2004/06/10 08:19:19-05:00 akpm@osdl.org +4 -2
#   drivers/scsi/megaraid.c: user/kernel pointer bugs
# 
# ChangeSet
#   2004/06/15 12:04:04-05:00 g.liakhovetski@gmx.de 
#   [PATCH] tmscsim: 64-bit cleanup
#   
#   > Although, I think, there's still a glitch there (modified if's order).
#   > I'll send a new version, if the approach is approved in principle.
#   
#   Ok, attached is version 3:-) It also fixes a definite (although, perhaps,
#   harmless) bug in scsiiom.c. And removes a redundant assignment in
#   tmscsim.c.
#   
#   Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/tmscsim.c
#   2004/06/14 17:28:50-05:00 g.liakhovetski@gmx.de +40 -34
#   tmscsim: 64-bit cleanup
# 
# ChangeSet
#   2004/06/15 12:01:55-05:00 hch@lst.de 
#   [PATCH] avoid obsolete scsi APIs in eata_pio
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/eata_pio.c
#   2004/06/07 05:22:42-05:00 hch@lst.de +66 -65
#   avoid obsolete scsi APIs in eata_pio
# 
# drivers/scsi/eata_generic.h
#   2004/06/07 05:19:05-05:00 hch@lst.de +1 -1
#   avoid obsolete scsi APIs in eata_pio
# 
# ChangeSet
#   2004/06/15 11:59:06-05:00 hch@lst.de 
#   [PATCH] clean up SCSI_TIMEOUT usage
#   
#    - qlogicfc.c abuses SCSI_TIEMOUT although it's not part of the scsi
#      core, give it it's own ISP_TIMEOUT define
#    - avoid redefining timeouts #ifdef DEBUG, that's a cause for heisenbugs
#      just waiting to happen
#    - now SCSI_TIMEOUT is private to scsi_scan.c, move it there
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_scan.c
#   2004/06/06 06:20:50-05:00 hch@lst.de +5 -0
#   clean up SCSI_TIMEOUT usage
# 
# drivers/scsi/scsi_error.c
#   2004/06/06 06:19:15-05:00 hch@lst.de +4 -9
#   clean up SCSI_TIMEOUT usage
# 
# drivers/scsi/scsi.h
#   2004/06/06 06:17:31-05:00 hch@lst.de +0 -6
#   clean up SCSI_TIMEOUT usage
# 
# drivers/scsi/qlogicfc.c
#   2004/06/06 06:17:21-05:00 hch@lst.de +2 -1
#   clean up SCSI_TIMEOUT usage
# 
# ChangeSet
#   2004/06/15 16:33:27+01:00 rmk@flint.arm.linux.org.uk 
#   [ARM] pxafb doesn't need to include asm/mach-types.h
# 
# drivers/video/pxafb.c
#   2004/06/15 16:31:17+01:00 rmk@flint.arm.linux.org.uk +0 -1
#   pxafb doesn't need to include asm/mach-types.h
# 
# ChangeSet
#   2004/06/15 15:50:19+01:00 elf@com.rmk.(none) 
#   [ARM PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM
#   
#   Patch from Marc Singer
#   
#   [if's replaced by ifdef's.]
#   
#   While the BLOB boot loader doesn't support it, there are two others,
#   UBOOT and Logic's LOLO, that will initialize the SDRAM controller such
#   that the memory appears as a contiguous region.  This layout to be
#   required for WinCE and, thus, is the default for these loaders.  The
#   memory organization had been optimized for discontiguous blocks.  Now,
#   it supports a default mode that is compatible with all of the
#   bootloaders as well as options to optimize for either contiguous or
#   discontiguous models.
#   
#   Withing, there is also a slight change to the way that the DEBUG_LL
#   macros select the UART address.  Now it uses immediate constants
#   exclusively.
#   
# 
# include/asm-arm/arch-lh7a40x/memory.h
#   2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +21 -48
#   [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM
# 
# arch/arm/mach-lh7a40x/Kconfig
#   2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +31 -0
#   [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM
# 
# arch/arm/kernel/debug.S
#   2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +2 -1
#   [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM
# 
# arch/arm/Kconfig
#   2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +2 -2
#   [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM
# 
# Documentation/arm/Sharp-LH/SDRAM
#   2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +51 -0
#   [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM
# 
# Documentation/arm/Sharp-LH/SDRAM
#   2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/Documentation/arm/Sharp-LH/SDRAM
# 
# ChangeSet
#   2004/06/15 15:46:21+01:00 icampbell@com.rmk.(none) 
#   [ARM PATCH] 1926/3:  PXAFB cleanups and fixes
#   
#   Patch from Ian Campbell
#   
#   Sorry, 1926/2 was missing a brace. Fixed here.
#   
#   Previous commentry:
#   I have corrected the grayscale conversion to correctly use the upper
#   byte rather than the lower one. As requested I have also left the
#   actual grayscale conversion where it was this time and just dealt with
#   the palette differences in pxafb_setpalettereg.
#   
#   fb_alloc_cmap is only called when bits_per_pixel is < 16, otherwise
#   any existing cmap is freed.
#   
#   I also fixed up all the spaces and brackets issues (not just the one
#   you raised previously) this introduces some noise in the patch, if
#   you'd like the two patches separately please ask.
# 
# drivers/video/pxafb.c
#   2004/06/15 13:42:45+01:00 icampbell@com.rmk.(none) +50 -43
#   [PATCH] 1926/3:  PXAFB cleanups and fixes
# 
# ChangeSet
#   2004/06/15 14:52:36+01:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Add clock API
#   
#   Since peripheral clocks are be derived in SoC or even platform
#   specific ways, we need a way to keep this information out of the
#   drivers.  AMBA Primecells are defined in terms of functional units
#   where clocks are derived from external sources, and it is up to the
#   SoC designer to determine where to derive those clocks from.
#   
#   Therefore, we provide a very basic API which allows platforms to
#   provide this information in a generic manner to their peripherals.
#   This framework also allows peripherals to shut down unused clock
#   sources when they're not in use.
# 
# include/asm-arm/hardware/clock.h
#   2004/06/15 14:49:41+01:00 rmk@flint.arm.linux.org.uk +121 -0
# 
# include/asm-arm/hardware/clock.h
#   2004/06/15 14:49:41+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/hardware/clock.h
# 
# arch/arm/mach-versatile/clock.h
#   2004/06/15 14:49:33+01:00 rmk@flint.arm.linux.org.uk +25 -0
# 
# arch/arm/mach-versatile/clock.h
#   2004/06/15 14:49:33+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-versatile/clock.h
# 
# arch/arm/mach-versatile/clock.c
#   2004/06/15 14:49:25+01:00 rmk@flint.arm.linux.org.uk +146 -0
# 
# arch/arm/mach-versatile/clock.c
#   2004/06/15 14:49:25+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-versatile/clock.c
# 
# arch/arm/mach-integrator/clock.h
#   2004/06/15 14:49:18+01:00 rmk@flint.arm.linux.org.uk +25 -0
# 
# arch/arm/mach-integrator/clock.h
#   2004/06/15 14:49:18+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-integrator/clock.h
# 
# arch/arm/mach-integrator/clock.c
#   2004/06/15 14:49:09+01:00 rmk@flint.arm.linux.org.uk +138 -0
# 
# include/asm-arm/arch-integrator/impd1.h
#   2004/06/15 14:49:09+01:00 rmk@flint.arm.linux.org.uk +0 -1
#   IM-PD/1 VCO is now controlled via the clock subsystem.
# 
# arch/arm/mach-integrator/clock.c
#   2004/06/15 14:49:09+01:00 rmk@flint.arm.linux.org.uk +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-integrator/clock.c
# 
# drivers/serial/amba-pl011.c
#   2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +58 -23
#   Make PL011 UART use clock layer to obtain clock source information. 
# 
# drivers/input/serio/ambakmi.c
#   2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +33 -5
#   Make keyboard/mouse interface use clock layer to obtain KMI clock
#   source information.
# 
# arch/arm/mach-versatile/Makefile
#   2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +1 -1
#   Add clock.o object.
# 
# arch/arm/mach-integrator/integrator_cp.c
#   2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +62 -0
#   Add Integrator/CP specific clocks.
# 
# arch/arm/mach-integrator/impd1.c
#   2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +28 -13
#   Add clock structures for IM-PD/1 on-board clocks.
# 
# arch/arm/mach-integrator/Makefile
#   2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +1 -1
#   Add clock.o to build objects.
# 
# ChangeSet
#   2004/06/15 00:29:37-04:00 jgarzik@pobox.com 
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# include/linux/libata.h
#   2004/06/15 00:29:32-04:00 jgarzik@pobox.com +2 -2
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# drivers/scsi/sata_vsc.c
#   2004/06/15 00:29:32-04:00 jgarzik@pobox.com +1 -1
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# drivers/scsi/sata_via.c
#   2004/06/15 00:29:32-04:00 jgarzik@pobox.com +1 -1
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# drivers/scsi/sata_sx4.c
#   2004/06/15 00:29:32-04:00 jgarzik@pobox.com +6 -3
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# drivers/scsi/sata_svw.c
#   2004/06/15 00:29:32-04:00 jgarzik@pobox.com +1 -1
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# drivers/scsi/sata_sis.c
#   2004/06/15 00:29:32-04:00 jgarzik@pobox.com +1 -1
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# drivers/scsi/sata_sil.c
#   2004/06/15 00:29:32-04:00 jgarzik@pobox.com +1 -1
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# drivers/scsi/sata_promise.c
#   2004/06/15 00:29:31-04:00 jgarzik@pobox.com +4 -4
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# drivers/scsi/libata-core.c
#   2004/06/15 00:29:31-04:00 jgarzik@pobox.com +29 -21
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# drivers/scsi/ata_piix.c
#   2004/06/15 00:29:31-04:00 jgarzik@pobox.com +2 -2
#   [libata] ->qc_prep hook
#   
#   Rename ->fill_sg hook to ->qc_prep, and call it unconditionally
#   (as opposed to ->fill_sg, which was called only when the
#   flag ATA_QCFLAG_SG was set).
# 
# ChangeSet
#   2004/06/14 23:54:02-04:00 jgarzik@pobox.com 
#   [libata] PCI IDE command-end/irq-acknowledge cleanup
#   
#   Restruct default irq handler (used for many PCI IDE-like SATA
#   controllers) to obtain device status and acknowledge interrupts
#   a bit differently.
#   
#   In an attempt to better attack the "ich5 screaming interrupt" problem,
#   acknowledge and clear the device's INTRQ by reading the Status register
#   _before_ ack'ing the controller's irq status.  This is a deviation
#   from how the Linux IDE driver acknowledges interrupts, but it may
#   be the best method, since the ICH5 appears to continue to assert
#   the interrupt bit in the BMDMA until the device INTRQ line is cleared.
#   
#   Of course, SATA has no INTRQ line per se, so ICH5 essentially has
#   new interrupt behavior not seen before in the PCI IDE world, while
#   pretending that it's compatible with PCI IDE.  Sigh.
#   
#   This change affects all SATA controllers (for which there are libata
#   drivers) except for sata_promise and sata_sx4.
# 
# drivers/scsi/libata-core.c
#   2004/06/14 23:53:57-04:00 jgarzik@pobox.com +57 -83
#   [libata] PCI IDE command-end/irq-acknowledge cleanup
#   
#   Restruct default irq handler (used for many PCI IDE-like SATA
#   controllers) to obtain device status and acknowledge interrupts
#   a bit differently.
#   
#   In an attempt to better attack the "ich5 screaming interrupt" problem,
#   acknowledge and clear the device's INTRQ by reading the Status register
#   _before_ ack'ing the controller's irq status.  This is a deviation
#   from how the Linux IDE driver acknowledges interrupts, but it may
#   be the best method, since the ICH5 appears to continue to assert
#   the interrupt bit in the BMDMA until the device INTRQ line is cleared.
#   
#   Of course, SATA has no INTRQ line per se, so ICH5 essentially has
#   new interrupt behavior not seen before in the PCI IDE world, while
#   pretending that it's compatible with PCI IDE.  Sigh.
#   
#   This change affects all SATA controllers (for which there are libata
#   drivers) except for sata_promise and sata_sx4.
# 
# ChangeSet
#   2004/06/14 22:40:59-04:00 jgarzik@pobox.com 
#   [libata] PCI IDE DMA code shuffling
#   
#   PCI IDE DMA standard (or "bmdma") helper routines ata_bmdma_stop,
#   ata_bmdma_ack_irq, and ata_bmdma_status are added to linux/libata.h,
#   and used in libata-core.
#   
#   There is a minor behavior change, such that, the Alt Status register
#   is read before acknowledging the bmdma interrupt.  This should be ok,
#   and furthermore there will be more significant behavior changes
#   in this area coming soon.
# 
# include/linux/libata.h
#   2004/06/14 22:40:53-04:00 jgarzik@pobox.com +40 -0
#   [libata] PCI IDE DMA code shuffling
#   
#   PCI IDE DMA standard (or "bmdma") helper routines ata_bmdma_stop,
#   ata_bmdma_ack_irq, and ata_bmdma_status are added to linux/libata.h,
#   and used in libata-core.
#   
#   There is a minor behavior change, such that, the Alt Status register
#   is read before acknowledging the bmdma interrupt.  This should be ok,
#   and furthermore there will be more significant behavior changes
#   in this area coming soon.
# 
# drivers/scsi/libata-core.c
#   2004/06/14 22:40:53-04:00 jgarzik@pobox.com +4 -41
#   [libata] PCI IDE DMA code shuffling
#   
#   PCI IDE DMA standard (or "bmdma") helper routines ata_bmdma_stop,
#   ata_bmdma_ack_irq, and ata_bmdma_status are added to linux/libata.h,
#   and used in libata-core.
#   
#   There is a minor behavior change, such that, the Alt Status register
#   is read before acknowledging the bmdma interrupt.  This should be ok,
#   and furthermore there will be more significant behavior changes
#   in this area coming soon.
# 
# drivers/net/acenic.c
#   2004/06/14 18:49:59-04:00 johnpol@2ka.mipt.ru +2 -2
#   Typo in ethtool code in acenic driver
# 
# ChangeSet
#   2004/06/14 18:34:29-04:00 akpm@osdl.org 
#   [PATCH] prism94 build fix
#   
#   init_wds is being instantiated in both isl_ioctl.c and islpci_eth.c, causing
#   linkage errors.
#   
#   drivers/net/wireless/prism54/islpci_mgt.o(.rodata+0x198): In function `islpci_mgmt_rx_fill':
#   /usr/src/25/drivers/net/wireless/prism54/islpci_mgt.c:154: multiple definition of `init_wds'
#   drivers/net/wireless/prism54/islpci_eth.o(.rodata+0x1c8):/usr/src/25/include/linux/skbuff.h:815: first defined here
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/wireless/prism54/islpci_mgt.h
#   2004/06/13 22:29:45-04:00 akpm@osdl.org +1 -1
#   prism94 build fix
# 
# ChangeSet
#   2004/06/14 18:33:35-04:00 a.othieno@bluewin.ch 
#   [PATCH] Kill stale references to Documentation/networking/8139too.txt
#   
#   Documentation/networking/8139too.txt was removed with this ChangeSet:
#   
#     ChangeSet@1.1371.153.2  2004-01-10 15:34:47-05:00  jgarzik@redhat.com
#     [netdrvr] remove Documentation/networking/8139too.txt
#   
#     All sections of the document are woefully outdated.
#   
#   
#   However, `grep' still reveals these references to it:
#   
#   drivers/net/8139too.c:90:		See 8139too.txt for more details.
#   drivers/net/Kconfig:1539:	  <file:Documentation/networking/8139too.txt> as well as the
#   Documentation/networking/00-INDEX:7:8139too.txt
#   
#   Signed-off-by: Arthur Othieno <a.othieno@bluewin.ch>
# 
# drivers/net/Kconfig
#   2004/06/14 14:50:09-04:00 a.othieno@bluewin.ch +1 -3
#   Kill stale references to Documentation/networking/8139too.txt
# 
# drivers/net/8139too.c
#   2004/06/14 14:50:09-04:00 a.othieno@bluewin.ch +0 -2
#   Kill stale references to Documentation/networking/8139too.txt
# 
# Documentation/networking/00-INDEX
#   2004/06/14 14:50:09-04:00 a.othieno@bluewin.ch +0 -2
#   Kill stale references to Documentation/networking/8139too.txt
# 
# ChangeSet
#   2004/06/14 18:32:42-04:00 johnpol@2ka.mipt.ru 
#   [PATCH] Typo in ethtool code in acenic driver
#   
#   In 10mbps detection code.
# 
# ChangeSet
#   2004/06/14 14:38:31-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Remove private khubd semaphore
#   
#   This patch removes the private semaphore used by the hub driver, and uses
#   the regular "serialize" semaphore instead.  This will satisfy the general
#   locking requirements for adding and removing devices attached to the hub.
#   The only tricky aspect is that now the hub event handler must take a
#   reference to the hub device while waiting to acquire the semaphore, in
#   case the hub is disconnected during the wait.
#   
#   The patch also replaces a few occurrences of spin_lock_irqsave() in
#   regions where interrupts are known to be enabled with spin_lock_irq().
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.h
#   2004/06/14 03:33:06-07:00 stern@rowland.harvard.edu +0 -1
#   USB: Remove private khubd semaphore
# 
# drivers/usb/core/hub.c
#   2004/06/14 03:59:02-07:00 stern@rowland.harvard.edu +24 -21
#   USB: Remove private khubd semaphore
# 
# ChangeSet
#   2004/06/14 16:27:27-04:00 jgarzik@pobox.com 
#   [libata] don't probe from workqueue
#   
#   Since we want the probe phase to call other workqueues, this is
#   required to eliminate future deadlocks.
#   
#   Other methods would include starting a single-shot thread just for
#   probing, but overall, using a separate thread for probing is pointless
#   since we are already in process context when we probe.
#   
#   So, we simply call ata_bus_probe directly.
# 
# include/linux/libata.h
#   2004/06/14 16:27:21-04:00 jgarzik@pobox.com +0 -15
#   [libata] don't probe from workqueue
#   
#   Since we want the probe phase to call other workqueues, this is
#   required to eliminate future deadlocks.
#   
#   Other methods would include starting a single-shot thread just for
#   probing, but overall, using a separate thread for probing is pointless
#   since we are already in process context when we probe.
#   
#   So, we simply call ata_bus_probe directly.
# 
# drivers/scsi/libata-core.c
#   2004/06/14 16:27:21-04:00 jgarzik@pobox.com +18 -118
#   [libata] don't probe from workqueue
#   
#   Since we want the probe phase to call other workqueues, this is
#   required to eliminate future deadlocks.
#   
#   Other methods would include starting a single-shot thread just for
#   probing, but overall, using a separate thread for probing is pointless
#   since we are already in process context when we probe.
#   
#   So, we simply call ata_bus_probe directly.
# 
# BitKeeper/deleted/.del-time.h~d87f27565ed1c644
#   2004/06/14 11:55:15-07:00 dsaxena@omelas.(none) +0 -0
#   Delete: include/asm-arm/arch-epxa10db/time.h
# 
# ChangeSet
#   2004/06/14 10:50:59-07:00 mhoffman@lightlink.com 
#   [PATCH] I2C: add alternate VCORE calculations for w83627thf and w83637hf
#   
#   Pick a VRM (for VID interpretation) based on the VRM & OVT config,
#   if available.  Props to Jean Delvare <khali@linux-fr.org> for the
#   idea & code fragment.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/w83627hf.c
#   2004/06/08 19:06:02-07:00 mhoffman@lightlink.com +6 -3
#   I2C: add alternate VCORE calculations for w83627thf and w83637hf
# 
# ChangeSet
#   2004/06/14 10:35:58-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Fix bug in TT initialization introduced by earlier
#   
#   This patch repairs a bug introduced by an earlier patch: The TT
#   initialization code was moved to _after_ the TT's first use.  The patch
#   simply puts the code back the way it used to be.
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/06/13 07:11:31-07:00 stern@rowland.harvard.edu +13 -10
#   USB: Fix bug in TT initialization introduced by earlier
# 
# ChangeSet
#   2004/06/14 10:35:15-07:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: Fix race when removing the SCSI host
#   
#   This patch fixes a race is disconnecting a usb-storage device that occurs
#   with the SCSI layer.  It's primarily reproducable via adding delays into
#   various disconnect and reset processing paths, but has also been
#   encountered in the field.
#   
#   This patch started life as as281b, and was modified by me only to patch
#   properly against current kernels.
#   
#   The main features of the patch are:
#   
#   	Store the host pointer at the start of the control thread
#   	rather than trying to get it from srb->device; after the host
#   	is removed the SCSI device structure may no longer exist.
#   
#   	Keep dev_semaphore locked during the entire time the control
#   	thread or reset handlers are using the us_data structure.
#   
#   	Reorder the items in dissociate_dev() and release_resources()
#   	so that things are released in the opposite order from the way
#   	they were acquired originally.  Don't bother to increment and
#   	decrement the usb_device's reference count; it's unnecessary.
#   
#   	In disconnect(), first set the DISCONNECTING flag so that no
#   	more I/O will take place and no more requests will be accepted.
#   	Next, cut short the current command and wait for it to finish.
#   	Then call scsi_remove_host().  The SCSI core guarantees that
#   	when scsi_remove_host() returns, the host will not be in error
#   	recovery and all outstanding commands will have been cancelled.
#   
#   	Remove some old useless left-over code that was #if'ed out.
#   
#   	Use a wait_queue for the 6-second delay during device resets
#   	so that we can be woken up in the middle if a disconnect occurs.
#   
#   The key point here is that after scsi_remove_host(), everything is idle as
#   far as the SCSI midlayer is concerned.  But if there was a command in
#   progress at the time, the midlayer will abort it without telling us or
#   waiting for it to complete.  Hence we have to wait for the control thread
#   to be idle before we can try to kill it.  This should happen quickly,
#   since all I/O attempted by the thread will fail immediately.
#   
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/usb.h
#   2004/06/13 13:09:07-07:00 mdharm-usb@one-eyed-alien.net +3 -2
#   USB Storage: Fix race when removing the SCSI host
# 
# drivers/usb/storage/usb.c
#   2004/06/13 13:09:07-07:00 mdharm-usb@one-eyed-alien.net +85 -126
#   USB Storage: Fix race when removing the SCSI host
# 
# drivers/usb/storage/transport.c
#   2004/06/13 13:09:07-07:00 mdharm-usb@one-eyed-alien.net +5 -4
#   USB Storage: Fix race when removing the SCSI host
# 
# ChangeSet
#   2004/06/14 10:33:05-07:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: INQUIRY fixup, mode-sense options, Genesys devices
#   
#   This patch does a few things (all in the same section of code).  It started
#   life as patches as226b, as280, and as275.  Later it was merged into as226e
#   and I added significantly to it.
#   
#   
#   First, this patch introduces a new config option to allow people to enable
#   write-protect detection for their USB devices.  With some luck, we've
#   finally got it right and can eventually remove this option in favor of
#   enabling this behavior all the time.
#   
#   Next, we change how we force some flags on -- it turns out that there are
#   some 'generic' entries in the SCSI devinfo which was overriding us when we
#   didn't want it.
#   
#   Finally, we add a safety check to the workaround for GeneSys Logic devices
#   -- if the max_sectors parameter has already been turned down, we won't turn
#   it up.
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/scsiglue.c
#   2004/06/13 08:24:10-07:00 mdharm-usb@one-eyed-alien.net +46 -6
#   USB Storage: INQUIRY fixup, mode-sense options, Genesys devices
# 
# drivers/usb/storage/Kconfig
#   2004/06/13 08:24:10-07:00 mdharm-usb@one-eyed-alien.net +22 -0
#   USB Storage: INQUIRY fixup, mode-sense options, Genesys devices
# 
# arch/arm/mach-footbridge/time.c
#   2004/06/14 10:27:44-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-ebsa285/time.h -> arch/arm/mach-footbridge/time.c
# 
# arch/arm/mach-ebsa110/time.c
#   2004/06/14 10:03:25-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-ebsa110/time.h -> arch/arm/mach-ebsa110/time.c
# 
# ChangeSet
#   2004/06/14 09:45:55-07:00 greg@kroah.com 
#   I2C: sparse cleanups again, based on comments from lkml
#   
#   This is more like the original code.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/it87.c
#   2004/06/14 02:45:18-07:00 greg@kroah.com +1 -4
#   I2C: sparse cleanups again, based on comments from lkml
#   
#   This is more like the original code.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# BitKeeper/deleted/.del-time.c~8f84839a52a43e18
#   2004/06/13 20:40:08-07:00 dsaxena@omelas.(none) +0 -31
#   Delete: arch/arm/mach-clps7500/time.c
# 
# arch/arm/common/time-acorn.c
#   2004/06/13 20:24:17-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: arch/arm/kernel/time-acorn.c -> arch/arm/common/time-acorn.c
# 
# ChangeSet
#   2004/06/12 22:23:05-03:00 acme@toy.kerneljanitors.org 
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/stream.c
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +41 -0
# 
# net/sunrpc/xprt.c
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +2 -2
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/sunrpc/svcsock.c
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv6/tcp_ipv6.c
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_output.c
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +4 -4
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_minisocks.c
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp_ipv4.c
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/ipv4/tcp.c
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +3 -22
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# net/core/stream.c
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +0 -0
#   BitKeeper file /home/acme/bk/net-2.6/net/core/stream.c
# 
# net/core/Makefile
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/tcp.h
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +0 -22
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# include/net/sock.h
#   2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +20 -0
#   [NET] first bits of net/core/stream.c
#   
#   Move tcp sk_wmem_queued related functions to net/core/stream.c, will be
#   used by other SOCK_STREAM protocols, starting with LLC.
#   
#   Also move the tcp_charge_skb to sock.h, for the same reasons.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# 
# ChangeSet
#   2004/06/11 17:22:53-07:00 linux@kodeaffe.de 
#   [PATCH] sysfs: fs/sysfs/inode.c: modify parents ctime and mtime on creation
#   
#   When a node is added to sysfs (e.g. a device plugged in via USB), the
#   filesystem fails to make this change visible in the parent directory's
#   ctime/mtime. This is in contrast to removing a device, because in that
#   case, sysfs makes use of the function simple_unlink from fs/libfs.c which
#   takes care of that. Instead of using simple_link from fs/libfs.c on
#   creation, sysfs implements its own mechanism. This patch hooks into the
#   function sysfs_create and sets the ctime and the mtime of the parent to
#   CURRENT_TIME.
#   
#   Signed-off-by: Sebastian Henschel <linux@kodeaffe.de>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# fs/sysfs/inode.c
#   2004/06/10 14:47:54-07:00 linux@kodeaffe.de +6 -1
#   sysfs: fs/sysfs/inode.c: modify parents ctime and mtime on creation
# 
# ChangeSet
#   2004/06/11 17:22:14-07:00 hannal@us.ibm.com 
#   [PATCH] Driver Model: Add class support to msr.c
#   
#   This patch enables class support in arch/i386/kernel/msr.c. Very simliar
#   to cpuid (with the fixes Zwane/Greg made, thanks).
#   
#   [root@w-hlinder2 root]# tree /sys/class/msr
#   /sys/class/msr
#   | -- msr0
#   |   `-- dev
#   `-- msr1
#       `-- dev
#   
#   2 directories, 2 files
#   
#   Thanks to Randy Dunlap for pointing out the unnecessary tabs. Fixed.
#   
#   Signed-off-by Hanna Linder <hannal@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# arch/i386/kernel/msr.c
#   2004/06/09 16:33:29-07:00 hannal@us.ibm.com +69 -2
#   Driver Model: Add class support to msr.c
# 
# arch/ia64/kernel/unwind.c
#   2004/06/11 17:13:56-07:00 kaos@sgi.com +20 -15
#   ia64: Remove warnings when unwind debug is turned on
# 
# ChangeSet
#   2004/06/11 17:06:39-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb on big endian, ehci needs a byteswap
#   
#   Adds a missing byteswap that would affect interrupt transfers
#   with EHCI on big-endian platforms, like Rick's MIPS-4km uClinux.
#   Needed for external hubs, and then likely for mice, keyboards,
#   and so on.
#   
#    From:          Rick Sewill <rsewill@cableone.net>
#    Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#    Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/ehci-sched.c
#   2004/06/11 06:09:39-07:00 david-b@pacbell.net +1 -1
#   USB: usb on big endian, ehci needs a byteswap
# 
# ChangeSet
#   2004/06/11 17:06:09-07:00 david-b@pacbell.net 
#   [PATCH] USB: retry string fetches on ZLPs not just STALLs
#   
#   This matches the behavior for other descriptor fetches.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/message.c
#   2004/06/11 04:49:33-07:00 david-b@pacbell.net +2 -2
#   USB: retry string fetches on ZLPs not just STALLs
# 
# ChangeSet
#   2004/06/11 17:05:38-07:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet shouldn't oops on cdc error path
#   
#   If the string descriptor fetch works, no problem.  Else
#   make the disconnect() logic -- newly called because of
#   "recent" changes to interface claiming logic -- use its
#   fast cleanup path, since we're still not fully set up yet.
#   
#   Should resolve OSDL bugid 2714; please merge.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/usbnet.c
#   2004/06/10 23:55:54-07:00 david-b@pacbell.net +1 -0
#   USB: usbnet shouldn't oops on cdc error path
# 
# ChangeSet
#   2004/06/11 17:05:08-07:00 david-b@pacbell.net 
#   [PATCH] USB: usbtest just uses module_param()
#   
#   This prevents some warnings during modprobe.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/usbtest.c
#   2004/06/11 00:06:34-07:00 david-b@pacbell.net +8 -8
#   USB: usbtest just uses module_param()
# 
# ChangeSet
#   2004/06/11 16:52:33-07:00 thoffman@arnor.net 
#   [PATCH] USB: ATI Remote driver update
#   
#   Here are some contributed improvements for the ATI remote driver.
#   
#   I submitted the driver and it was accepted several months ago.
#   Since then a few people have sent me patches and suggestions.
#   
#   This patch adds two things:
#   
#   (1) support for the "Lola" X10 remote, sent to me by
#       Seth Cohn <sethcohn (at) yahoo.com>
#   
#   (2) key autorepeat support, sent to me by
#       Vincent Vanackere <vanackere (at) lif.univ-mrs.fr>
#   
#   The key autorepeat support has been tested by me, but the Lola support
#   has not, as I don't have the hardware.
#   
#   Thanks to Seth and Vincent, with my apologies for taking so long to
#   forward their improvements along.
#   
#   
#   Signed-off-by: Torrey Hoffman <thoffman@arnor.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/input/ati_remote.c
#   2004/06/08 17:12:09-07:00 thoffman@arnor.net +42 -12
#   USB: ATI Remote driver update
# 
# drivers/usb/input/Kconfig
#   2004/06/09 15:24:29-07:00 thoffman@arnor.net +8 -6
#   USB: ATI Remote driver update
# 
# ChangeSet
#   2004/06/11 16:51:56-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Mark devices as NOTATTACHED as soon as possible
#   
#   This patch implements something we've been lacking for a long time: a way
#   to mark devices as USB_STATE_NOTATTACHED as soon as we know that they're
#   gone.  The usb_device->state member is no longer protected by the
#   ->serialize semaphore; instead there's a new private spinlock.  Usbcore
#   routines should no longer set ->state directly; instead they should use
#   the new utility routine usb_set_device_state().  There are protections
#   against changing states while devices are being added or removed.
#   
#   	Change assignments to udev->state into calls of
#   	usb_set_device_state().
#   
#   	Add new private device_state_lock to the hub driver, along
#   	with usb_set_device_state() and recursively_mark_NOTATTACHED().
#   
#   	Acquire the new spinlock while adding or removing children[]
#   	pointers.
#   
#   	When disabling a port that has a child device, mark the child
#   	as NOTATTACHED.
#   
#   You mentioned once having tried to do something like this and running into
#   trouble.  Take a good look and let me know if you see any difficulties
#   here.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/usb.h
#   2004/06/09 06:52:00-07:00 stern@rowland.harvard.edu +3 -0
#   USB: Mark devices as NOTATTACHED as soon as possible
# 
# drivers/usb/core/message.c
#   2004/06/09 06:50:10-07:00 stern@rowland.harvard.edu +4 -4
#   USB: Mark devices as NOTATTACHED as soon as possible
# 
# drivers/usb/core/hub.c
#   2004/06/09 07:16:54-07:00 stern@rowland.harvard.edu +85 -12
#   USB: Mark devices as NOTATTACHED as soon as possible
# 
# drivers/usb/core/hcd.c
#   2004/06/09 06:46:56-07:00 stern@rowland.harvard.edu +2 -2
#   USB: Mark devices as NOTATTACHED as soon as possible
# 
# ChangeSet
#   2004/06/11 16:24:02-07:00 davidm@tiger.hpl.hp.com 
#   ia64: Update defconfig
# 
# arch/ia64/defconfig
#   2004/06/11 16:23:55-07:00 davidm@tiger.hpl.hp.com +17 -6
#   Update
# 
# arch/arm/mach-clps7500/time.c
#   2004/06/11 14:14:12-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-cl7500/time.h -> arch/arm/mach-clps7500/time.c
# 
# BitKeeper/deleted/.del-time.c~531bda1d3ed195a5
#   2004/06/11 14:12:46-07:00 dsaxena@omelas.(none) +0 -0
#   Delete: arch/arm/mach-adifcc/time.c
# 
# arch/arm/mach-adifcc/time.c
#   2004/06/11 14:10:55-07:00 dsaxena@omelas.(none) +0 -0
#   Rename: include/asm-arm/arch-adifcc/time.h -> arch/arm/mach-adifcc/time.c
# 
# ChangeSet
#   2004/06/11 11:32:29-07:00 kaos@sgi.com 
#   [PATCH] ia64: Remove warnings when unwind debug is turned on
#   
#   Turning on UNW_DEBUG generates warnings for incorrect number of
#   parameters for formats and several cases of "suggest explicit braces to
#   avoid ambiguous `else'", because UNW_DPRINT contains an if statement.
#   
#   Signed-off-by: Keith Owens <kaos@sgi.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# ChangeSet
#   2004/06/10 20:00:01-04:00 margitsw@t-online.de 
#   [PATCH] prism54: White space and indentation
#   
#   2004-05-29  Margit Schubert-While <margitsw@t-online.de>
#   
#   * White space and indentation patch
# 
# ChangeSet
#   2004/06/10 19:59:53-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Fix typo
#   
#   2004-05-29  Margit Schubert-While <margitsw@t-online.de>
#   
#   * isl_ioctl.c : Fix typo
# 
# ChangeSet
#   2004/06/10 19:59:45-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Fix channel stats, bump version to 1.2
#   
#   2004-05-20      Aurelien Alleaume <slts@free.fr>
#   
#   * islpci_eth.c : use dev_kfree_skb_irq instead of dev_kfree_skb where needed.
#   
#   * isl_ioctl.c : report channel instead of frequency in scan.
#   
#   * islpci_hotplug.c : bump version to 1.2
# 
# ChangeSet
#   2004/06/10 19:59:36-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Reduce module verbosity
#   
#   2004-05-01      Margit Schubert-While <margitsw@t-online.de>
#   
#    * Reduce module verbosity
# 
# ChangeSet
#   2004/06/10 19:59:28-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Align skb patch
#   
#   * islpci_eth.c, islpci_dev.c : Align skb->data unconditonally after
#     allocation. This would appear to improve RX rate
# 
# ChangeSet
#   2004/06/10 19:59:20-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Add likely/unlikely, KO wds completely
#   
#   * islpci_mgt.h : Change init_wds definition
#   
#   * islpci_eth.c : Do some likely/unlikely
# 
# ChangeSet
#   2004/06/10 19:59:11-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Don't allow mib reads while unconfigured
#   
#   004-04-17      Aurelien Alleaume <slts@free.fr>
#   
#           * oid_mgt.c, isl_ioctl.c : Cleanup. Prevented real oid reading
#           before the card is configured with mib values (might be
#           related to
#           bug #53).
# 
# ChangeSet
#   2004/06/10 19:59:03-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Fix bug 77, strengthened oid txn
#   
#   2004-04-09      Aurelien Alleaume <slts@free.fr>
#   
#   * oid_mgt.c, isl_ioctl.c : Cleanups. Bug #77. Minor stuffs.
#   
#   * islpci_mgt.c (islpci_mgt_transaction) : enforce serialization
#     in oid transaction. lindent.sh.
#   
#   * islpci_mgt.c (islpci_mgt_transaction) : Strengthened oid transaction.
# 
# ChangeSet
#   2004/06/10 19:58:55-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Fix bugs 39/73
#   
#   2004-04-07      Margit Schubert-While <margitsw@t-online.de>
#   
#           * Bugs 39 and 73
# 
# ChangeSet
#   2004/06/10 19:58:46-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Fix bugs 74/75
#   
#   2004-03-22      Aurelien Alleaume <slts@free.fr>
#   
#           * oid_mgt.c, isl_ioctl.c : Minor bugfixes : #74 and #75.
# 
# ChangeSet
#   2004/06/10 19:38:59-04:00 bunk@fs.tum.de 
#   [PATCH] add NAPI help texts
#   
#   NAPI seems to be so self-explaining that no help texts are needed. ;-)
#   
#   I combined the two help texts that were at NAPI options, and added them
#   to all NAPI options.
# 
# ChangeSet
#   2004/06/10 19:37:53-04:00 rmk@arm.linux.org.uk 
#   [PATCH] add ARM smc91x driver
# 
# ChangeSet
#   2004/06/10 19:58:38-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Fix endian patch
#   
#   * Split out patch islpci_eth.c :
#   * Fix endian problem (bug 74/75 related)
# 
# ChangeSet
#   2004/06/10 20:52:50-04:00 jgarzik@pobox.com 
#   [netdrvr acenic] remove unneeded ifdefs
# 
# ChangeSet
#   2004/06/10 20:19:03-04:00 shemminger@osdl.org 
#   [PATCH] fix oops from acenic ethtool
#   
#   Fix the following OOPS that happens when doing ifup on FC-2
#   with 2.6.7 in acenic and a security hole due to missing capable(NET_ADMIN),
#   by replacing private ethtool handling with ethtool_ops.
#   
#   (Yes, Jes because of DEV_ETHTOOL_OPS define it will still work
#   on ancient kernels.)
# 
# ChangeSet
#   2004/06/10 19:58:30-04:00 margitsw@t-online.de 
#   [PATCH] prism54: Kernel compatibility
#   
#   2004-03-20      Margit Schubert-While <margitsw@t-online.de>
#   
#   * isl_38xx.[ch], isl_ioctl.c, islpci_dev.[ch], islpci_eth.c
#     islpci_hotplug.c, islpci_mgt.[ch], oid_mgt.c, prismcompat.h:
#     Adopt new prism54 kernel compatibility.
#     Remove remaining kernel version ifdefs.
# 
# ChangeSet
#   2004/06/10 19:37:01-04:00 akpm@osdl.org 
#   [PATCH] fealnx-mac-address-and-other-issues.patch
#   
#   (resend - I need to get this out of my tree my one means or another..)
#   
#   
#   From: "SuD (Alex)" <sud@latinsud.com>
#   
#   I recently was given a surecom 10/100 ethernet card and found that i could
#   not change Mac address for it as other driver/devices allow.  I tried to
#   implement the missing feature and noticed that the device is quite peculiar
#   (or either my system is broken), when trying to fill mac address registers
#   (no matter whether io_ops is set): - If I write a byte (writeb) to an even
#   i/o address it seems like actually a word was written (the next byte is set
#   to 0).  - If I write a byte to an odd i/o address my pc gets bad freezed.
#   
#   That made think of writing 16bit words (writew) for the memory address, as
#   opposed to what most driver examples do.  It works for me (I hope i set the
#   lines at the right place in device_open function after the device is
#   reset).  I hope the code is clean enough and does not mess with byte
#   ordering.  This is the patch (this time against 2.6.5):
#   
#   (akpm: Is this right on big-endian?)
# 
# drivers/net/acenic.c
#   2004/06/10 20:52:44-04:00 jgarzik@pobox.com +0 -6
#   [netdrvr acenic] remove unneeded ifdefs
# 
# drivers/net/acenic.h
#   2004/06/04 17:31:46-04:00 shemminger@osdl.org +0 -1
#   fix oops from acenic ethtool
# 
# drivers/net/acenic.c
#   2004/06/04 17:31:46-04:00 shemminger@osdl.org +127 -121
#   fix oops from acenic ethtool
# 
# drivers/net/wireless/prism54/oid_mgt.h
#   2004/05/28 08:06:38-04:00 margitsw@t-online.de +1 -1
#   prism54: White space and indentation (resend)
# 
# drivers/net/wireless/prism54/oid_mgt.c
#   2004/05/28 09:12:49-04:00 margitsw@t-online.de +7 -7
#   prism54: White space and indentation (resend)
# 
# drivers/net/wireless/prism54/islpci_mgt.c
#   2004/05/28 09:12:49-04:00 margitsw@t-online.de +42 -42
#   prism54: White space and indentation (resend)
# 
# drivers/net/wireless/prism54/islpci_eth.c
#   2004/05/28 09:49:41-04:00 margitsw@t-online.de +8 -8
#   prism54: White space and indentation (resend)
# 
# drivers/net/wireless/prism54/islpci_dev.h
#   2004/05/28 08:25:30-04:00 margitsw@t-online.de +1 -1
#   prism54: White space and indentation (resend)
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/05/28 09:49:41-04:00 margitsw@t-online.de +28 -34
#   prism54: White space and indentation (resend)
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/05/28 09:33:42-04:00 margitsw@t-online.de +1 -1
#   prism54: Fix typo
# 
# drivers/net/wireless/prism54/islpci_hotplug.c
#   2004/05/28 09:49:41-04:00 margitsw@t-online.de +1 -1
#   prism54: Fix channel stats, bump version to 1.2 (resend)
# 
# drivers/net/wireless/prism54/islpci_eth.c
#   2004/05/28 09:49:41-04:00 margitsw@t-online.de +3 -3
#   prism54: Fix channel stats, bump version to 1.2 (resend)
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/05/28 09:49:41-04:00 margitsw@t-online.de +2 -2
#   prism54: Fix channel stats, bump version to 1.2 (resend)
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/06/05 08:11:34-04:00 margitsw@t-online.de +3 -1
#   prism54: Reduce module verbosity (resend)
# 
# drivers/net/wireless/prism54/islpci_eth.c
#   2004/06/05 08:09:41-04:00 margitsw@t-online.de +1 -0
#   prism54: Align skb patch (resend)
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/06/05 08:09:41-04:00 margitsw@t-online.de +1 -0
#   prism54: Align skb patch (resend)
# 
# drivers/net/wireless/prism54/islpci_mgt.h
#   2004/05/28 09:33:42-04:00 margitsw@t-online.de +1 -1
#   prism54: Add likely/unlikely, KO wds completely (resend)
# 
# drivers/net/wireless/prism54/islpci_eth.c
#   2004/05/28 09:33:42-04:00 margitsw@t-online.de +9 -8
#   prism54: Add likely/unlikely, KO wds completely (resend)
# 
# drivers/net/wireless/prism54/oid_mgt.c
#   2004/06/05 08:03:15-04:00 margitsw@t-online.de +40 -21
#   prism54: Don't allow mib reads while unconfigured (resend)
# 
# drivers/net/wireless/prism54/islpci_mgt.c
#   2004/06/05 08:03:15-04:00 margitsw@t-online.de +5 -3
#   prism54: Don't allow mib reads while unconfigured (resend)
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/06/05 08:03:15-04:00 margitsw@t-online.de +3 -1
#   prism54: Don't allow mib reads while unconfigured (resend)
# 
# drivers/net/wireless/prism54/isl_ioctl.h
#   2004/06/05 08:03:15-04:00 margitsw@t-online.de +0 -1
#   prism54: Don't allow mib reads while unconfigured (resend)
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/06/05 08:03:15-04:00 margitsw@t-online.de +5 -31
#   prism54: Don't allow mib reads while unconfigured (resend)
# 
# drivers/net/wireless/prism54/oid_mgt.c
#   2004/05/28 09:08:01-04:00 margitsw@t-online.de +2 -6
#   prism54: Fix bug 77, strengthened oid txn (resend)
# 
# drivers/net/wireless/prism54/islpci_mgt.c
#   2004/05/28 09:08:01-04:00 margitsw@t-online.de +35 -26
#   prism54: Fix bug 77, strengthened oid txn (resend)
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/05/28 09:08:01-04:00 margitsw@t-online.de +13 -76
#   prism54: Fix bug 77, strengthened oid txn (resend)
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/06/05 07:57:11-04:00 margitsw@t-online.de +2 -2
#   prism54: Fix bugs 39/73 (resend)
# 
# drivers/net/wireless/prism54/oid_mgt.c
#   2004/05/28 08:43:01-04:00 margitsw@t-online.de +2 -2
#   prism54: Fix bugs 74/75 (resend)
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/05/28 08:43:01-04:00 margitsw@t-online.de +1 -0
#   prism54: Fix bugs 74/75 (resend)
# 
# drivers/net/wireless/prism54/islpci_eth.c
#   2004/05/28 08:25:30-04:00 margitsw@t-online.de +16 -16
#   prism54: Fix endian patch (resend)
# 
# drivers/net/wireless/prism54/prismcompat.h
#   2004/06/05 07:45:32-04:00 margitsw@t-online.de +46 -0
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/prismcompat.h
#   2004/06/05 07:45:32-04:00 margitsw@t-online.de +0 -0
#   BitKeeper file /spare/repo/netdev-2.6/prism54/drivers/net/wireless/prism54/prismcompat.h
# 
# drivers/net/wireless/prism54/oid_mgt.c
#   2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -0
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/islpci_mgt.h
#   2004/06/05 07:44:14-04:00 margitsw@t-online.de +0 -9
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/islpci_mgt.c
#   2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -15
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/islpci_hotplug.c
#   2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -0
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/islpci_eth.c
#   2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -0
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/islpci_dev.h
#   2004/06/05 07:44:14-04:00 margitsw@t-online.de +0 -20
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/06/05 07:45:32-04:00 margitsw@t-online.de +121 -27
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -1
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/isl_38xx.h
#   2004/06/05 07:45:32-04:00 margitsw@t-online.de +0 -10
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/wireless/prism54/isl_38xx.c
#   2004/06/05 07:45:32-04:00 margitsw@t-online.de +2 -132
#   prism54: Kernel compatibility (resend)
# 
# drivers/net/tulip/Kconfig
#   2004/06/04 11:16:07-04:00 bunk@fs.tum.de +11 -4
#   add NAPI help texts
# 
# drivers/net/Kconfig
#   2004/06/04 11:18:14-04:00 bunk@fs.tum.de +70 -0
#   add NAPI help texts
# 
# drivers/net/arm/smc91x.h
#   2004/05/29 08:04:43-04:00 rmk@arm.linux.org.uk +829 -0
#   Re: smc91x driver
# 
# drivers/net/arm/smc91x.c
#   2004/05/29 07:57:20-04:00 rmk@arm.linux.org.uk +2171 -0
#   Re: smc91x driver
# 
# drivers/net/arm/smc91x.h
#   2004/05/29 08:04:43-04:00 rmk@arm.linux.org.uk +0 -0
#   BitKeeper file /spare/repo/netdev-2.6/misc/drivers/net/arm/smc91x.h
# 
# drivers/net/arm/smc91x.c
#   2004/05/29 07:57:20-04:00 rmk@arm.linux.org.uk +0 -0
#   BitKeeper file /spare/repo/netdev-2.6/misc/drivers/net/arm/smc91x.c
# 
# drivers/net/arm/Makefile
#   2003/07/06 11:12:19-04:00 rmk@arm.linux.org.uk +1 -0
#   Re: smc91x driver
# 
# drivers/net/arm/Kconfig
#   2003/09/28 11:03:12-04:00 rmk@arm.linux.org.uk +17 -0
#   Re: smc91x driver
# 
# drivers/net/fealnx.c
#   2004/04/23 01:29:23-04:00 akpm@osdl.org +5 -0
#   fealnx-mac-address-and-other-issues.patch
# 
# ChangeSet
#   2004/06/10 16:34:14-07:00 kenneth.w.chen@intel.com 
#   [PATCH] ia64: fix race in fsys_bubble_down to avoid fp-register corruption
#   
#   The fast system-call fall-back-path has a race: it reads PSR, modifies
#   some bits, then writes back the new PSR.  Unfortunately, the contents
#   of PSR may change between reading and writing it.  For example, an
#   interrupt could occur which could trigger a context-switch.  The
#   context-switch might in turn flush the floating-point-high (FPH)
#   partition to memory, clear PSR.MFH, and set PSR.DFH.  To prevent this
#   race, the patch below turns off PSR.I before reading PSR.
#   
#   This fixes a floating-point corruption problem that was observed on a
#   system with a libc which has the fast system-call support enabled.
#   
#   The performance impact is minimal (on the order of a handful of cycles).
#   
#   Signed-off-by: Kevin Tian <kevin.tian@intel.com>
#   Signed-off-by: Ken Chen <kenneth.w.chen@intel.com>
#   Signed-off-by: Asit Mallick <asit.k.mallick@intel.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# arch/ia64/kernel/gate.S
#   2004/06/09 05:36:21-07:00 kenneth.w.chen@intel.com +4 -2
#   ia64: fix race in fsys_bubble_down
# 
# arch/ia64/kernel/fsys.S
#   2004/06/09 05:11:54-07:00 kenneth.w.chen@intel.com +2 -1
#   ia64: fix race in fsys_bubble_down
# 
# ChangeSet
#   2004/06/10 13:25:26-07:00 Robert.Picco@hp.com 
#   [PATCH] ia64: mark non-existent NUMA-nodes as offline
#   
#   I found a problem with HP NUMA configuration in 2.6.7-rc3-mm1.  The
#   node_online_map is incorrect because of actions taken by
#   reassign_cpu_only_nodes in arch/ia64/mm/discontig.c.  The mm1 patch
#   which changes the mempolicy for the init_task uses this invalid
#   node_online_map and eventually uses a non-existent node's zonelist
#   when calling __alloc_pages.
#   
#   The patch below takes care of this issue.  It puts the non-existent
#   nodes offline.
#   
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# arch/ia64/mm/discontig.c
#   2004/06/09 15:44:02-07:00 Robert.Picco@hp.com +3 -0
#   ia64: mark non-existent NUMA-nodes as offline
# 
# ChangeSet
#   2004/06/10 12:52:02-07:00 greg@kroah.com 
#   I2C: sparse cleanups for drivers/i2c/*
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/i2c-dev.c
#   2004/06/10 05:51:18-07:00 greg@kroah.com +3 -4
#   I2C: sparse cleanups for drivers/i2c/*
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/it87.c
#   2004/06/10 05:51:18-07:00 greg@kroah.com +4 -1
#   I2C: sparse cleanups for drivers/i2c/*
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/10 12:09:46-07:00 greg@kroah.com 
#   USB: fix up dumb int_user_arg variable name as pointed out by Al Viro.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/auerswald.c
#   2004/06/10 05:08:46-07:00 greg@kroah.com +7 -7
#   USB: fix up dumb int_user_arg variable name as pointed out by Al Viro.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/input/hiddev.c
#   2004/06/10 05:08:46-07:00 greg@kroah.com +4 -5
#   USB: fix up dumb int_user_arg variable name as pointed out by Al Viro.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/audio.c
#   2004/06/10 05:08:46-07:00 greg@kroah.com +32 -32
#   USB: fix up dumb int_user_arg variable name as pointed out by Al Viro.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/10 11:40:08-07:00 greg@kroah.com 
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/whiteheat.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +3 -2
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/kobil_sct.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +5 -4
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/kl5kusb105.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +7 -8
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/io_ti.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +3 -3
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/io_edgeport.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +7 -8
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/ftdi_sio.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +6 -6
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/rtl8150.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +15 -15
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/legousbtower.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +4 -4
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/auerswald.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +8 -6
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/w9968cf.h
#   2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/w9968cf.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +24 -23
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/vicam.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +14 -18
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/usbvideo.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +2 -2
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/stv680.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/se401.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/pwc-if.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +2 -2
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/ov511.h
#   2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/ov511.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/dabusb.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +5 -5
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/input/hiddev.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +26 -24
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/input/hid-core.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +3 -1
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/image/mdc800.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +3 -3
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/audio.c
#   2004/06/10 04:39:09-07:00 greg@kroah.com +36 -30
#   USB: sparse cleanups for the whole driver/usb/* tree.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/10 09:48:09-07:00 rtjohnso@eecs.berkeley.edu 
#   [PATCH] PATCH: 2.6.7-rc3 drivers/usb/core/devio.c: user/kernel pointer bugs
#   
#   Since ctrl is copied in from userspace, ctrl.data cannot safely be
#   dereferenced.  Let me know if you have any questions or if I've made
#   a mistake.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/devio.c
#   2004/06/09 05:49:50-07:00 rtjohnso@eecs.berkeley.edu +2 -2
#   PATCH: 2.6.7-rc3 drivers/usb/core/devio.c: user/kernel pointer bugs
# 
# ChangeSet
#   2004/06/10 09:36:26-07:00 greg@kroah.com 
#   Driver Core: more whitespace fixups
#   
#   This catches the files I had to do by hand as Dmitry's patch differed from my tree.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/base/bus.c
#   2004/06/10 02:35:56-07:00 greg@kroah.com +64 -65
#   Driver Core: more whitespace fixups
#   
#   This catches the files I had to do by hand as Dmitry's patch differed from my tree.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/10 09:34:27-07:00 dtor_core@ameritech.net 
#   [PATCH] Driver Core: Whitespace fixes
#   
#   Whitespace and formatting changes (a,b,c -> a, b, c) in drivers/base
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/base/sys.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +51 -51
#   Driver Core: Whitespace fixes
# 
# drivers/base/power/sysfs.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +9 -9
#   Driver Core: Whitespace fixes
# 
# drivers/base/power/suspend.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +21 -21
#   Driver Core: Whitespace fixes
# 
# drivers/base/power/shutdown.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +9 -9
#   Driver Core: Whitespace fixes
# 
# drivers/base/power/runtime.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +4 -4
#   Driver Core: Whitespace fixes
# 
# drivers/base/power/resume.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +6 -6
#   Driver Core: Whitespace fixes
# 
# drivers/base/power/power.h
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +4 -4
#   Driver Core: Whitespace fixes
# 
# drivers/base/power/main.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +7 -7
#   Driver Core: Whitespace fixes
# 
# drivers/base/platform.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +9 -9
#   Driver Core: Whitespace fixes
# 
# drivers/base/node.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +7 -7
#   Driver Core: Whitespace fixes
# 
# drivers/base/interface.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +9 -9
#   Driver Core: Whitespace fixes
# 
# drivers/base/init.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +2 -2
#   Driver Core: Whitespace fixes
# 
# drivers/base/firmware_class.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +5 -5
#   Driver Core: Whitespace fixes
# 
# drivers/base/firmware.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +3 -3
#   Driver Core: Whitespace fixes
# 
# drivers/base/driver.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +8 -8
#   Driver Core: Whitespace fixes
# 
# drivers/base/core.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +23 -23
#   Driver Core: Whitespace fixes
# 
# drivers/base/class_simple.c
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +6 -6
#   Driver Core: Whitespace fixes
# 
# drivers/base/base.h
#   2004/06/09 23:34:24-07:00 dtor_core@ameritech.net +3 -2
#   Driver Core: Whitespace fixes
# 
# ChangeSet
#   2004/06/10 09:25:58-07:00 dtor_core@ameritech.net 
#   [PATCH] Driver Core: Suppress platform device suffixes
#   
#   Do not add numeric suffix to platform device name if device id is set to
#   -1. This can be used when there can be only one instance of a device
#   (like i8042).
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/base/platform.c
#   2004/06/09 23:33:27-07:00 dtor_core@ameritech.net +4 -1
#   Driver Core: Suppress platform device suffixes
# 
# ChangeSet
#   2004/06/09 11:14:30-07:00 greg@kroah.com 
#   USB: crap, I misapplied a patch with the wrong level
#   
#   This gets rid of usb/host and puts the file in the proper drivers/usb/host
#   directory.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/ohci-lh7a404.c
#   2004/06/09 04:12:00-07:00 greg@kroah.com +0 -0
#   USB: crap, I misapplied a patch with the wrong level
#   
#   This gets rid of usb/host and puts the file in the proper drivers/usb/host
#   directory.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/09 11:10:52-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Update root-hub code for the ohci-lh7a404 driver
#   
#   On Wed, 9 Jun 2004, David Brownell wrote:
#   
#   > Needs an update for ohci-lh7a404.c too ...
#   
#   I didn't even know this driver existed!  Where did usb/host/* come from?
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# usb/host/ohci-lh7a404.c
#   2004/06/09 06:09:47-07:00 stern@rowland.harvard.edu +1 -3
#   USB: Update root-hub code for the ohci-lh7a404 driver
# 
# ChangeSet
#   2004/06/09 11:10:09-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Minor tidying up of hub driver
#   
#   After my last few changesets there were a few small items that needed to
#   be tidied up.
#   
#   	Update kerneldoc to reflect the actual operation of
#   	usb_disconnect() and usb_new_device().  The new locking
#   	requirements are listed too, though they aren't all
#   	implemented yet.
#   
#   	Fulfill the new locking requirement in hcd_panic().
#   
#   	Remove unneeded local variables to conserve stack space in
#   	usb_disconnect(), which calls itself recursively.
#   
#   	In hub_port_connect_change(), store the parent's children[]
#   	pointer as late as possible and don't lock the new device until
#   	then (that's when it becomes globally accessible).  This will
#   	minimize the time that the not-fully-configured device structure
#   	is visible to other parts of the kernel.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/06/09 05:20:00-07:00 stern@rowland.harvard.edu +25 -23
#   USB: Minor tidying up of hub driver
# 
# drivers/usb/core/hcd.c
#   2004/06/09 05:03:06-07:00 stern@rowland.harvard.edu +2 -0
#   USB: Minor tidying up of hub driver
# 
# ChangeSet
#   2004/06/09 11:09:31-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Fix bus-list root-hub race
#   
#   There are a few places where the code enumerates through all the USB
#   devices on all the buses, starting with each bus's root hub and working
#   down.  However a bus does not always have a root hub, and the code does
#   not check that the root_hub pointer is non-NULL.  This patch fixes the
#   problem, using the usb_bus_list_lock semaphore to synchronize access when
#   root hubs are added or removed.
#   
#   In addition it seemed like a good idea to minimize the time that a
#   non-fully-configured root hub is accessible through the bus's pointer.  So
#   this patch delays setting the pointer and holds usb_bus_list_lock while
#   configuring a root hub.
#   
#   It turned out that a bunch of things needed to be changed for all this to
#   work:
#   
#   	Check for NULL root_hub pointer in usb_device_read() and
#   	usb_find_device().
#   
#   	Pass the root-hub device as a separate argument to
#   	hcd_register_root().
#   
#   	Make usb_register_root_hub() acquire the usb_bus_list_lock and
#   	set the bus->root_hub pointer.
#   
#   	For consistency's sake, move the place where the children[]
#   	pointer to a non-root-hub device gets stored as close as possible
#   	to where usb_new_device() is called.
#   
#   	Make usb_disconnect() acquire the usb_bus_list_lock when removing
#   	a root hub.
#   
#   	Change usb_hcd_pci_remove() and the non-PCI host drivers so that
#   	they call usb_disconnect() with a pointer to the bus's root_hub
#   	pointer, not a pointer to a temporary variable.
#   
#   	Change all the host controller drivers not to store the root_hub
#   	pointer in the bus structure but instead to pass it as a new
#   	argument to hcd_register_root().
#   
#   I made some attempt to update the hc_sl811 driver along with the rest, but
#   it's pretty clear that driver won't work in the current framework.  Among
#   other things, it never reads the root hub's device descriptor.  To what
#   extent is the driver really supported?
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/uhci-hcd.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -3
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/host/ohci-sa1111.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +1 -3
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/host/ohci-omap.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +1 -3
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/host/ohci-hcd.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -3
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/host/hc_sl811_rh.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +8 -2
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/host/ehci-hcd.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -3
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/gadget/dummy_hcd.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -3
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/core/usb.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -0
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/core/hub.c
#   2004/06/09 04:45:43-07:00 stern@rowland.harvard.edu +16 -7
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/core/hcd.h
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +3 -3
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/core/hcd.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +10 -3
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/core/hcd-pci.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +1 -3
#   USB: Fix bus-list root-hub race
# 
# drivers/usb/core/devices.c
#   2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -0
#   USB: Fix bus-list root-hub race
# 
# ChangeSet
#   2004/06/09 11:08:58-07:00 oliver@neukum.org 
#   [PATCH] USB: add printer reset ioctl
#   
#     - add soft reset ioctl
#   
#   Signed-off-by: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/usblp.c
#   2004/06/09 10:05:10-07:00 oliver@neukum.org +10 -0
#   USB: add printer reset ioctl
# 
# ChangeSet
#   2004/06/09 10:34:09-07:00 akpm@osdl.org 
#   [PATCH] I2C: w83627hf.c build fix
#   
#   with gcc-2.95:
#   
#   drivers/i2c/chips/w83627hf.c:482: parse error before `static'
#   drivers/i2c/chips/w83627hf.c:502: parse error before `static'
#   drivers/i2c/chips/w83627hf.c: In function `show_regs_fan_1':
#   drivers/i2c/chips/w83627hf.c:541: warning: implicit declaration of function `show_fan'
#   drivers/i2c/chips/w83627hf.c: In function `w83627hf_detect':
#   drivers/i2c/chips/w83627hf.c:1074: `dev_attr_in0_min' undeclared (first use in this function)
#   drivers/i2c/chips/w83627hf.c:1074: (Each undeclared identifier is reported only once
#   drivers/i2c/chips/w83627hf.c:1074: for each function it appears in.)
#   drivers/i2c/chips/w83627hf.c: At top level:
#   drivers/i2c/chips/w83627hf.c:428: warning: `show_regs_in_min0' defined but not used
#   drivers/i2c/chips/w83627hf.c:441: warning: `store_regs_in_min0' defined but not used
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/w83627hf.c
#   2004/06/08 23:10:38-07:00 akpm@osdl.org +3 -3
#   I2C: w83627hf.c build fix
# 
# ChangeSet
#   2004/06/09 10:19:23-07:00 greg@kroah.com 
#   merge i2c-2.6 into driver-2.6 trees due to problems people reported.
# 
# drivers/i2c/chips/w83627hf.c
#   2004/06/09 10:19:12-07:00 greg@kroah.com +0 -1
#   merge i2c-2.6 into driver-2.6 trees due to problems people reported.
# 
# drivers/scsi/scsi_debug.c
#   2004/06/09 10:11:48-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# drivers/i2c/chips/it87.c
#   2004/06/09 10:11:48-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/06/09 10:11:47-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/08 22:45:12-07:00 greg@kroah.com 
#   cpuid: fix hotplug cpu remove bug for class device.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# arch/i386/kernel/cpuid.c
#   2004/06/08 22:44:49-07:00 greg@kroah.com +12 -14
#   cpuid: fix hotplug cpu remove bug for class device.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/base/platform.c
#   2004/06/08 16:46:21-07:00 rmk@arm.linux.org.uk +86 -0
#   Add platform_get_resource()
# 
# ChangeSet
#   2004/06/08 16:28:02-07:00 rmk@arm.linux.org.uk 
#   [PATCH] Add platform_get_resource()
#   
#   This patch adds management of platform device resources to the
#   device model, allowing drivers to lookup resources, IRQs and DMA
#   numbers in the platform device resource array.  We also add a
#   couple of functions which allow platform devices and their resources
#   to be registered.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/device.h
#   2004/05/28 12:29:34-07:00 rmk@arm.linux.org.uk +5 -0
#   Add platform_get_resource()
# 
# ChangeSet
#   2004/06/08 16:26:12-07:00 hannal@us.ibm.com 
#   [PATCH] Add cpu hotplug support to cpuid.c
#   
#   Here is the patch that uses a cpu hotplug callback, to allow dynamic support
#   of cpu id for classes in sysfs.
#   
#   This patch applies on top of the one I sent out earlier that Greg included.
#   I do not have access to hardware that supports cpu hotswapping (virtually or not)
#   so have not been able to test that aspect of the patch. However, the original
#   functionality of listing static cpu's still works.
#   
#   Please consider for testing or inclusion.
#   
#   Signed-off-by: Hanna Linder <hannal@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# arch/i386/kernel/cpuid.c
#   2004/06/08 14:31:22-07:00 hannal@us.ibm.com +48 -11
#   Add cpu hotplug support to cpuid.c
# 
# ChangeSet
#   2004/06/08 16:10:24-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Initialize endpoint autoconfig in g_file_storage
#   
#   This one-line patch corrects a simple problem in the g_file_storage
#   driver.  It neglected to initialize the endpoint-autoconfiguration library
#   before using it.  Please apply.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/file_storage.c
#   2004/06/08 04:03:07-07:00 stern@rowland.harvard.edu +1 -0
#   USB: Initialize endpoint autoconfig in g_file_storage
# 
# ChangeSet
#   2004/06/08 16:09:55-07:00 david-b@pacbell.net 
#   [PATCH] lh7a404 USB host against 2.6.7-rc2
#   
#   Support for the Sharp LH7A404 OHCI, another non-PCI implementation.
#   This uses a platform_device and a workaround for a register read
#   problem.
#   
#   Signed-off-by: Marc Singer <elf@buici.com>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# usb/host/ohci-lh7a404.c
#   2004/06/07 16:24:04-07:00 david-b@pacbell.net +387 -0
#   lh7a404 USB host against 2.6.7-rc2
# 
# drivers/usb/Kconfig
#   2004/06/07 09:24:04-07:00 david-b@pacbell.net +1 -1
#   lh7a404 USB host against 2.6.7-rc2
# 
# usb/host/ohci-lh7a404.c
#   2004/06/07 16:24:04-07:00 david-b@pacbell.net +0 -0
#   BitKeeper file /home/greg/linux/BK/usb-2.6/usb/host/ohci-lh7a404.c
# 
# drivers/usb/host/ohci.h
#   2004/06/07 09:24:04-07:00 david-b@pacbell.net +19 -0
#   lh7a404 USB host against 2.6.7-rc2
# 
# drivers/usb/host/ohci-q.c
#   2004/06/07 09:24:04-07:00 david-b@pacbell.net +3 -3
#   lh7a404 USB host against 2.6.7-rc2
# 
# drivers/usb/host/ohci-hub.c
#   2004/06/07 09:33:47-07:00 david-b@pacbell.net +21 -21
#   lh7a404 USB host against 2.6.7-rc2
# 
# drivers/usb/host/ohci-hcd.c
#   2004/06/07 09:24:04-07:00 david-b@pacbell.net +26 -16
#   lh7a404 USB host against 2.6.7-rc2
# 
# drivers/usb/host/ohci-dbg.c
#   2004/06/07 09:24:04-07:00 david-b@pacbell.net +15 -15
#   lh7a404 USB host against 2.6.7-rc2
# 
# ChangeSet
#   2004/06/08 16:09:24-07:00 david-b@pacbell.net 
#   [PATCH] USB: rndis (3/4) Big Endian support for gadget RNDIS
#   
#   Add byteswapping.  Original version partially worked on PPC with Net2280,
#   this version applies to the latest RNDIS code but hasn't been retested on
#   big-endian.  Ping should be working in at least one one direction.
#   
#   Also added a handful of other things from my BK:  track suspend/resume
#   (to eventually implement wake-on-lan), give a better rndis error
#   message, and add missing declarations for PM-related OIDs (usage is
#   #ifdeffed out by previous patch).
#   
#       From:	   Jon Neal <jon@ballardtech.com>
#       Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#       Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/rndis.c
#   2004/06/07 11:30:16-07:00 david-b@pacbell.net +199 -163
#   USB: rndis (3/4) Big Endian support for gadget RNDIS
# 
# drivers/usb/gadget/ndis.h
#   2004/06/07 11:30:16-07:00 david-b@pacbell.net +30 -0
#   USB: rndis (3/4) Big Endian support for gadget RNDIS
# 
# drivers/usb/gadget/ether.c
#   2004/06/07 11:32:18-07:00 david-b@pacbell.net +28 -2
#   USB: rndis (3/4) Big Endian support for gadget RNDIS
# 
# ChangeSet
#   2004/06/08 16:08:52-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb suspend/resume work better on net2280
#   
#   This makes net2280 behave more correctly with respect to
#   usb suspend and resume processing.
#   
#   So for example gadget zero autoresume testing works.
#   
#   Signed-off-by:	David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/net2280.c
#   2004/06/07 07:31:53-07:00 david-b@pacbell.net +17 -8
#   USB: usb suspend/resume work better on net2280
# 
# ChangeSet
#   2004/06/08 16:08:19-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb root hubs can set power budgets
#   
#   This adds hub_set_power_budget(), mostly so that HCDs for low
#   powered ports (cell phone, PDA, etc) can more easily report their
#   true power budgets.  It's not always 500mA per root hub port; this
#   makes dummy_hcd report the minimum, 8mA.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/dummy_hcd.c
#   2004/06/07 07:31:53-07:00 david-b@pacbell.net +3 -0
#   USB: usb root hubs can set power budgets
# 
# drivers/usb/core/hub.h
#   2004/06/07 07:31:53-07:00 david-b@pacbell.net +11 -0
#   USB: usb root hubs can set power budgets
# 
# ChangeSet
#   2004/06/08 14:36:23-07:00 jmunsin@iki.fi 
#   [PATCH] I2C: drivers/i2c/chips/it87.c cleanup patch
#   
#   Attached is a cleanup patch for the it87 sensor driver, against
#   2.6.7-rc2. Jean Delvare has reviewed it.
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/it87.c
#   2004/06/08 13:33:09-07:00 jmunsin@iki.fi +22 -26
#   I2C: drivers/i2c/chips/it87.c cleanup patch
# 
# ChangeSet
#   2004/06/08 14:31:15-07:00 mhoffman@lightlink.com 
#   [PATCH] I2C: add alternate VCORE calculations for w83627thf and w83637hf
#   
#   This patch adds support for the alternate in0/VCORE calculation which is
#   available for 2 of 4 chips this driver supports.  It also fixes a minor
#   bug in the standard voltage input calculation.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/w83627hf.c
#   2004/06/05 19:02:59-07:00 mhoffman@lightlink.com +91 -3
#   I2C: add alternate VCORE calculations for w83627thf and w83637hf
# 
# ChangeSet
#   2004/06/08 14:12:40-07:00 greg@kroah.com 
#   Merge kroah.com:/home/greg/linux/BK/bleed-2.6
#   into kroah.com:/home/greg/linux/BK/usb-2.6
# 
# include/linux/usb.h
#   2004/06/08 14:12:36-07:00 greg@kroah.com +0 -1
#   Auto merged
# 
# drivers/usb/serial/cyberjack.c
#   2004/06/08 14:12:36-07:00 greg@kroah.com +0 -6
#   Auto merged
# 
# drivers/usb/media/pwc-if.c
#   2004/06/08 14:12:36-07:00 greg@kroah.com +0 -1
#   Auto merged
# 
# drivers/usb/media/Kconfig
#   2004/06/08 14:12:35-07:00 greg@kroah.com +0 -1
#   Auto merged
# 
# drivers/usb/core/devio.c
#   2004/06/08 14:12:35-07:00 greg@kroah.com +0 -1
#   Auto merged
# 
# ChangeSet
#   2004/06/07 21:38:30-07:00 kaos@sgi.com 
#   [PATCH] ia64: Rename SN "modules" variable to "sn_modules".
#   
#   SN code has a "modules" variable that conflicts with a variable of the
#   same name in kernel/module.c.  This conflict breaks lcrash for ia64.
#   Rename "modules" to "sn_modules".
#   
#   Signed-off-by: Keith Owens <kaos@sgi.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# include/asm-ia64/sn/module.h
#   2004/06/07 08:45:42-07:00 kaos@sgi.com +1 -1
#   ia64: Rename modules to sn_modules
# 
# arch/ia64/sn/io/sn2/module.c
#   2004/06/07 08:45:32-07:00 kaos@sgi.com +7 -7
#   ia64: Rename modules to sn_modules
# 
# arch/ia64/sn/io/sn2/klgraph.c
#   2004/06/07 08:49:25-07:00 kaos@sgi.com +2 -2
#   ia64: Rename modules to sn_modules
# 
# arch/ia64/sn/io/machvec/pci_bus_cvlink.c
#   2004/06/07 08:45:20-07:00 kaos@sgi.com +2 -2
#   ia64: Rename modules to sn_modules
# 
# ChangeSet
#   2004/06/07 17:01:22-07:00 david-b@pacbell.net 
#   [PATCH] USB: rndis (4/4) start documenting spec variances
#   
#   This partially reverts one of the changes in an earlier patch,
#   starting to document where Microsoft's spec is lying.  Needed
#   to interop with Windows ME.
#   
#   
#   The Windows ME implementation of RNDIS relies on a message that
#   Microsoft's specification says isn't used.  Restore this (removed
#   in earlier cleanup), and start collecting comments specifically
#   on where MSFT violates its own specifications.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/rndis.c
#   2004/06/07 07:04:50-07:00 david-b@pacbell.net +17 -0
#   USB: rndis (4/4) start documenting spec variances
# 
# ChangeSet
#   2004/06/07 16:58:23-07:00 david-b@pacbell.net 
#   [PATCH] USB: rndis (2/4) fix memory leaks
#   
#   Tao Huang wrote:
#   > I'm writing udc driver for S3C2410. I found RNDIS almost not call my
#   > driver's free_request and free_buffer. So after run my driver about 3
#   > hours the system will out of memory.
#   >
#   > This patch will fix the memory leak.
#   >
#   > There will still have memory leak when driver unload, but I don't known
#   > where is the proper place to fix it.
#   > 1) rndis.c should free resp_queue when it unload
#   > 2) ether.c should free tx_reqs and rx_reqs when it unload (as
#   > eth_reset_config)
#   
#   Thanks ... this is a nice patch to have.
#   
#   
#   From:          Tao Huang <huangt@star-net.cn>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/ether.c
#   2004/06/06 06:34:51-07:00 david-b@pacbell.net +13 -5
#   USB: rndis (2/4) fix memory leaks
# 
# ChangeSet
#   2004/06/07 16:57:06-07:00 david-b@pacbell.net 
#   [PATCH] USB: rndis (1/4) update OID support
#   
#   NDIS devices have a generic attribute get/set API where the attributes
#   are identified by 32 bit "OIDs".  This fixes some problems with the OIDs
#   supported by the original RNDIS patch:
#   
#     - It included OIDs not found in the RNDIS spec.  These have been
#       removed.  As a rule, these weren't exported in the "OIDs I support"
#       list, and only a couple wouldn't fail those accesses, so this mostly
#       changes what debug printk appears.
#   
#     - OIDs used for optional 802.3 statistics were partially supported.
#       They're all in the OID list now, but the support is #ifdeffed out.
#       (Those statistics were mostly just made up, anyway!)
#   
#     - "Required" OIDs for suspend, resume, and wakeup support weren't
#       listed.  Their messages are now defined, but support is #ifdeffed
#       out.  Seems the docs aren't entirely accurate, and Windows can
#       behave reasonably without them.  (This area needs help from someone
#       who knows MS-Windows power management.)
#   
#   There are also a few minor cleanups, more reasonable default volume level
#   for debug messages (never at KERN_INFO, keepalives only if VERBOSE), and
#   dumping of all bytes of some undocumented messages Windows XP has been
#   seen emitting shortly before the host suspended itself.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/rndis.h
#   2004/06/06 06:06:42-07:00 david-b@pacbell.net +37 -4
#   USB: rndis (1/4) update OID support
# 
# drivers/usb/gadget/rndis.c
#   2004/06/06 06:06:42-07:00 david-b@pacbell.net +162 -166
#   USB: rndis (1/4) update OID support
# 
# ChangeSet
#   2004/06/07 16:55:44-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: unusual_devs.h update
#   
#   Given the problems that Dan Scholnik has reported, we should combine the
#   unusual_devs.h entries for the Casio QV cameras into one.  The new
#   NEED_OVERRIDE flag will prevent complaints about unnecessary overrides,
#   and Dan says the same subclass and protocol values should work for all the
#   cameras.  If they don't we'll hear about it soon enough!
#   
#   
#   On Tue, 1 Jun 2004, Dan Scholnik wrote:
#   > On Tue, 2004-06-01 at 14:14, Alan Stern wrote:
#   > > On Tue, 1 Jun 2004, Dan Scholnik wrote:
#   > >
#   > > > Up until the 2.6 kernels, there was one entry for all the QV cameras
#   > > > with both US_SC_8070 and US_PR_CB that I think seemed to work fine for
#   > > > everyone.  As far as I know the only problem was all the folks emailing
#   > > > the log entry stating that the Casio entry wasn't needed.  So, you could
#   > > > revert back to that, or revert back to the 2.6.3ish version (pre-as190)
#   > > > that had the overrides just for product IDs 1001-9009.  I'm not really
#   > > > an expert on Casio's cameras, I'm afraid, just the one model I own which
#   > > > is 4-5 years old now.
#   > > >
#   > > > I'll be happy to prepare a patch any way you choose to go.
#   > >
#   > > How does this work for you?
#   > >
#   > > Alan Stern
#   >
#   > Works fine for me; that's I think exactly how it was from the beginning
#   > until 2.6 and the later 2.4 kernels when all the changes were made.
#   > Just cross your fingers that it doesn't somehow break newer Casios, as
#   > it would seem every camera they ever made falls under that entry.
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/unusual_devs.h
#   2004/06/01 05:46:58-07:00 stern@rowland.harvard.edu +3 -9
#   USB: unusual_devs.h update
# 
# ChangeSet
#   2004/06/07 16:55:17-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Fix resource leakage in the hub driver
#   
#   The hub driver is very careless about returning resources when an error
#   occurs while installing a new device.  This patch attempts to put some
#   order back into the situation.  Details:
#   
#   	Since usb_new_device() allocates neither the device structure
#   	nor the device address, it shouldn't release either one.
#   
#   	Because usb_new_device() no longer releases the device structure,
#   	usb_register_root_hub() doesn't need to take an extra reference
#   	to it.
#   
#   	Since the device address selection and TT setup code is used
#   	only for new devices, not ones being reset, move that code from
#   	hub_port_init() to hub_port_connect_change().  By the same token,
#   	hub_port_init() doesn't have to release the device address or
#   	the device structure.
#   
#   	Just to make things look better, move the failure code in
#   	hub_port_init() to the end of the routine.  And when disabling
#   	endpoint 0, disable both the IN and OUT parts of the endpoint.
#   
#   	In hub_port_connect_change(), make all the failure paths
#   	execute the same code so that resources are always released.
#   	These resources comprise: the pointer from the parent to the
#   	new child device, the HCD state for ep0, the device's address,
#   	and the device structure itself -- in short, everything that's
#   	set up before calling usb_new_device().
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/06/07 10:08:06-07:00 stern@rowland.harvard.edu +45 -50
#   USB: Fix resource leakage in the hub driver
# 
# drivers/usb/core/hcd.c
#   2004/06/07 09:55:49-07:00 stern@rowland.harvard.edu +1 -3
#   USB: Fix resource leakage in the hub driver
# 
# ChangeSet
#   2004/06/07 16:54:49-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Check port reset return code
#   
#   This patch adds checking for the SET-FEATURE request that actually does a
#   port reset.  Without the check, the hub driver just assumes that the port
#   reset command actually was transferred okay.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/06/07 08:20:11-07:00 stern@rowland.harvard.edu +6 -2
#   USB: Check port reset return code
# 
# ChangeSet
#   2004/06/07 16:34:04-07:00 baldrick@free.fr 
#   [PATCH] USB devio.c: deadlock fix
#   
#   proc_resetdevice is called with dev->serialize held.
#   usb_reset_device takes dev->serialize and then calls
#   __usb_reset_device.  To avoid deadlock, proc_resetdevice
#   should call __usb_reset_device directly.
#   
#   Signed-off-by: Duncan Sands <baldrick@free.fr>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/usb.h
#   2004/06/07 01:39:20-07:00 baldrick@free.fr +1 -0
#   USB devio.c: deadlock fix
# 
# drivers/usb/core/devio.c
#   2004/06/07 01:39:20-07:00 baldrick@free.fr +1 -1
#   USB devio.c: deadlock fix
# 
# ChangeSet
#   2004/06/07 14:39:16-07:00 arun.sharma@intel.com 
#   [PATCH] ia64: fix ia32 virtual memory leaks due to partial-page mappings
#   
#   Certain IA-32 applications which do mmap/munmaps which are not
#   PAGE_SIZE aligned could see temporary (recovered at process exit time)
#   memory leaks, because the kernel didn't have enough data to decide if
#   the complete page could be unmapped. This patch adds a new data
#   structure called the "partial page list" which helps the kernel keep
#   track of precisely which 4k pages are in use by the IA-32 application.
#   
#   Armed with this data, the kernel can make better decisions at munmap
#   and mprotect time. No significant performance degradation was observed
#   in the workloads we tested and in some cases, the performance actually
#   improved!  This is possibly due to the reduced length of the vma list.
#   
#   Signed-off-by: Arun Sharma <arun.sharma@intel.com>
#   Signed-off-by: Gordon Jin <gordon.jin@intel.com>
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# include/asm-ia64/processor.h
#   2004/06/04 18:14:13-07:00 arun.sharma@intel.com +4 -1
#   ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings
# 
# include/asm-ia64/ia32.h
#   2004/06/04 18:15:32-07:00 arun.sharma@intel.com +2 -0
#   ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings
# 
# arch/ia64/kernel/process.c
#   2004/06/04 04:59:05-07:00 arun.sharma@intel.com +12 -0
#   ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings
# 
# arch/ia64/ia32/sys_ia32.c
#   2004/06/04 06:31:39-07:00 arun.sharma@intel.com +524 -5
#   ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings
# 
# arch/ia64/ia32/ia32priv.h
#   2004/06/04 03:42:27-07:00 arun.sharma@intel.com +25 -0
#   ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings
# 
# arch/ia64/ia32/ia32_support.c
#   2004/06/04 02:57:01-07:00 arun.sharma@intel.com +8 -0
#   ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings
# 
# arch/ia64/ia32/ia32_entry.S
#   2004/06/04 02:57:01-07:00 arun.sharma@intel.com +1 -1
#   ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings
# 
# arch/ia64/ia32/binfmt_elf32.c
#   2004/06/04 02:57:01-07:00 arun.sharma@intel.com +4 -0
#   ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings
# 
# ChangeSet
#   2004/06/07 13:00:07-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Fix logic in usb_get_descriptor()
#   
#   This patch fixes a simple logic error in usb_get_descriptor().  It also
#   takes the opportunity to make the subroutine a little easier to read.
#   Please apply.
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/message.c
#   2004/06/06 09:43:22-07:00 stern@rowland.harvard.edu +7 -7
#   USB: Fix logic in usb_get_descriptor()
# 
# ChangeSet
#   2004/06/07 12:59:41-07:00 kaie@kuix.de 
#   [PATCH] USB: enable pwc usb camera driver
#   
#   The attached patch enables the pwc driver included with kernel 2.6.7-rc2
#   
#   It also removes the warnings during compilation.
#   However, note that I blindly duplicated the release approach used by
#   other usb camera drivers, replacing the current no-op.
#   
#   The driver works for me with a Logitech QuickCam Notebook Pro and
#   GnomeMeeting.
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/pwc-if.c
#   2004/06/07 02:42:50-07:00 kaie@kuix.de +1 -8
#   USB: enable pwc usb camera driver
# 
# drivers/usb/media/Kconfig
#   2004/06/07 02:27:03-07:00 kaie@kuix.de +1 -1
#   USB: enable pwc usb camera driver
# 
# ChangeSet
#   2004/06/07 12:59:12-07:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: GetMaxLUN tightening
#   
#   This patch started life from Alan Stern as as274, and has been heavily
#   modified.  It narrows the case where a clear_halt() is issued after a
#   failed GetMaxLUN command to only a STALL case.
#   
#   Since the only legimate responses to a GetMaxLUN are STALL or data,
#   anything else is now considered a fatal error and we give up on the device.
#   
#   
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/usb.c
#   2004/06/06 15:22:29-07:00 mdharm-usb@one-eyed-alien.net +8 -2
#   USB Storage: GetMaxLUN tightening
# 
# drivers/usb/storage/transport.c
#   2004/06/06 15:22:29-07:00 mdharm-usb@one-eyed-alien.net +13 -10
#   USB Storage: GetMaxLUN tightening
# 
# ChangeSet
#   2004/06/07 12:58:42-07:00 Siegfried.Hildebrand@FernUni-Hagen.de 
#   [PATCH] Re: Problems with cyberjack usb-serial-module since kernel 2.6.2
#   
#   > Send me a patch to back those changes out to fix your device and I'll
#   > apply it.  If the author is around to realize this, that should wake
#   > them up :)
#   
#   Ok, here you are! :)
#   Attached is a patch for linux-2.6.7-rc2. (though the patch hasn't changed
#   since -rc1)
#   
#   Again a short description:
#   (the patch removes most of the changes done in linux-2.6.2)
#   1. Removed the local buffer of cyberjack_write, because something goes wrong
#   upon a write-request bigger than the buffer. Without this, a write-request
#   stalls with error -3.
#   2. Removed some usb_clear_halt() lines. Without this, the device doesn't even
#   open and returns -7.
#   
#   It works for my cyberjack pinpad USB card reader on
#   - nforce2 chipset
#   - VIA KM266 chipset
#   - AMD Irongate chipset
#   
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/cyberjack.c
#   2004/06/06 09:25:11-07:00 Siegfried.Hildebrand@FernUni-Hagen.de +6 -15
#   Re: Problems with cyberjack usb-serial-module since kernel 2.6.2
# 
# ChangeSet
#   2004/06/07 11:44:48-07:00 alex.williamson@hp.com 
#   [PATCH] ia64: delete McKinley A-stepping code
#   
#   The patch below removes the config option and one bit of code for
#   McKinley A0/A1 CPU workarounds.  These CPUs were never used in
#   production, and IIRC this workaround really only affected X11.
#   
#   Signed-off-by: David Mosberger <davidm@hpl.hp.com>
# 
# include/asm-ia64/pgtable.h
#   2004/06/07 03:07:59-07:00 alex.williamson@hp.com +1 -5
#   ia64: delete McKinley A-stepping code
# 
# arch/ia64/Kconfig
#   2004/06/07 03:03:19-07:00 alex.williamson@hp.com +0 -14
#   ia64: delete McKinley A-stepping code
# 
# ChangeSet
#   2004/06/07 11:27:28-07:00 greg@kroah.com 
#   USB: make usb devices remove their sysfs files when disconnected.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/usb.h
#   2004/06/07 04:26:43-07:00 greg@kroah.com +2 -0
#   USB: make usb devices remove their sysfs files when disconnected.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/sysfs.c
#   2004/06/07 04:26:43-07:00 greg@kroah.com +59 -30
#   USB: make usb devices remove their sysfs files when disconnected.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/message.c
#   2004/06/07 04:26:43-07:00 greg@kroah.com +1 -0
#   USB: make usb devices remove their sysfs files when disconnected.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/06/07 04:26:43-07:00 greg@kroah.com +1 -0
#   USB: make usb devices remove their sysfs files when disconnected.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/07 10:30:35-07:00 greg@kroah.com 
#   Merge kroah.com:/home/greg/linux/BK/bleed-2.6
#   into kroah.com:/home/greg/linux/BK/usb-2.6
# 
# drivers/usb/gadget/ether.c
#   2004/06/07 10:30:30-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/06/04 16:48:04-07:00 greg@kroah.com 
#   Driver core: finally add a MAINTAINERS entry for it.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# MAINTAINERS
#   2004/06/04 09:47:20-07:00 greg@kroah.com +6 -0
#   Driver core: finally add a MAINTAINERS entry for it.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/04 15:54:01-07:00 corbet@lwn.net 
#   [PATCH] Module section offsets in /sys/module
#   
#   So here I am trying to write about how one can apply gdb to a running
#   kernel, and I'd like to tell people how to debug loadable modules.  Only
#   with the 2.6 module loader, there's no way to find out where the various
#   sections in the module image ended up, so you can't do much.  This patch
#   attempts to fix that by adding a "sections" subdirectory to every module's
#   entry in /sys/module; each attribute in that directory associates a
#   beginning address with the section name.  Those attributes can be used by a
#   a simple script to generate an add-symbol-file command for gdb, something
#   like:
#   
#   #!/bin/bash
#   #
#   # gdbline module image
#   #
#   # Outputs an add-symbol-file line suitable for pasting into gdb to examine
#   # a loaded module.
#   #
#   cd /sys/module/$1/sections
#   echo -n add-symbol-file $2 `/bin/cat .text`
#   
#   for section in .[a-z]* *; do
#       if [ $section != ".text" ]; then
#   	echo  " \\"
#   	echo -n "	-s" $section `/bin/cat $section`
#       fi
#   done
#   echo
#   
#   Currently, this feature is absent if CONFIG_KALLSYMS is not set.  I do
#   wonder if CONFIG_DEBUG_INFO might not be a better choice, now that I think
#   about it.  Section names are unmunged, so "ls -a" is needed to see most of
#   them.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# kernel/module.c
#   2004/06/03 14:37:17-07:00 corbet@lwn.net +100 -0
#   Module section offsets in /sys/module
# 
# include/linux/module.h
#   2004/06/03 14:01:29-07:00 corbet@lwn.net +19 -0
#   Module section offsets in /sys/module
# 
# ChangeSet
#   2004/06/04 17:17:42-05:00 stern@rowland.harvard.edu 
#   [PATCH] Make the scsi error handler bus settle delay a per template option
#   
#   On 1 Jun 2004, James Bottomley wrote:
#   > On Tue, 2004-06-01 at 15:29, Alan Stern wrote:
#   > > In addition, the settle-time delays would have to be removed from the
#   > > error handler -- which means adding it to all the low-level drivers.  Is
#   > > that doable?
#   >
#   > Well, for 2.6, I think that a simple flag indicating that the driver
#   > will implement it's own timeout should suffice rather than altering
#   > every LLD...
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_host.h
#   2004/06/04 11:51:31-05:00 stern@rowland.harvard.edu +5 -0
#   Make the scsi error handler bus settle delay a per template option
# 
# drivers/usb/storage/scsiglue.c
#   2004/06/04 11:52:56-05:00 stern@rowland.harvard.edu +3 -0
#   Make the scsi error handler bus settle delay a per template option
# 
# drivers/scsi/scsi_error.c
#   2004/06/04 11:54:06-05:00 stern@rowland.harvard.edu +4 -2
#   Make the scsi error handler bus settle delay a per template option
# 
# ChangeSet
#   2004/06/04 15:15:08-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Genuine changes to hub_port_debounce()
#   
#   This patch includes the algorithmic changes I would like to see in
#   hub_port_debounce().  They are:
#   
#   	Increase the total timeout period from 400 ms to 1500 ms.
#   
#   	Check the port's connect-changed status during the polling
#   	loop.
#   
#   	Return as soon as the connection has been stable for the
#   	required time, even if it has been stably _dis_-connected.
#   	(The current code waits for the full timeout period if there
#   	isn't a connection.)
#   
#   In previous emails I have responded to all the concerns raised by others
#   about these changes, and I can't imagine how they could cause any trouble.
#   
#   	Increasing the total timeout won't affect people with properly
#   	functioning hardware.  Their connections will quickly stabilize
#   	and the routine will return just as before.  People with flaky
#   	hardware that takes a long time to settle down will now be able
#   	to use their devices.
#   
#   	Checking the connect-changed status during the polling loop will
#   	make the test more conservative.  The code will be able to
#   	detect transient disconnections that it would have missed
#   	before, and it won't return until the connection really _is_
#   	stable.  Furthermore, this makes the test compliant with the
#   	USB specification, which requires the stability timer to be
#   	restarted whenever a connection change occurs.
#   
#   	Returning early for disconnections is a simple optimization.
#   	It's more important now that the total timeout length is 1.5
#   	seconds rather than 0.4 seconds.
#   
#   I urge you to apply this patch and for people to try it out.  If there do
#   turn out to be problems... the patch is very small, well-contained, and
#   easy to revert.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/06/04 07:28:00-07:00 stern@rowland.harvard.edu +4 -4
#   USB: Genuine changes to hub_port_debounce()
# 
# ChangeSet
#   2004/06/04 15:14:42-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Superficial improvements to hub_port_debounce()
#   
#   Since my previous suggestions for changes to hub_port_debounce()
#   encountered so much resistance, this patch makes some fairly superficial
#   improvements to the code while leaving the logic of the algorithm almost
#   completely intact.  The only behavioral change is that it actually
#   requests the port status at the start, rather than assuming the status is
#   not CONNECTED.  Changes include:
#   
#   	Vastly improved comments that are now unambiguous and accurately
#   	descriptive of the code.
#   
#   	Local variables changed to more sensible names.  The stability
#   	period is now reported in milliseconds rather than a meaningless
#   	poll count.
#   
#   	The sleep interval is moved from the start of the loop to the
#   	end, so that the first time through we read the port status
#   	immediately.
#   
#   	If the connection has not stabilized after the total timeout
#   	expires, -ETIMEDOUT is returned rather than whatever the
#   	current connect status happens to be.
#   
#   	If the connection does stabilize then the port status is returned
#   	so that hub_port_connect_change() will have an up-to-date value
#   	for the status rather than relying on the pre-debounce value.
#   
#   The changes I wanted to make but other people were worried about are
#   included as comments.  A later (small) patch will uncomment them for
#   testing.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/06/04 07:15:37-07:00 stern@rowland.harvard.edu +34 -30
#   USB: Superficial improvements to hub_port_debounce()
# 
# ChangeSet
#   2004/06/04 15:14:11-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Debounce all connect change events
#   
#   This patch makes the hub driver debounce all connection changes.  Right
#   now the driver only does so if the status happens to be CONNECTED at one
#   particular instant.  However, the whole point of debouncing is that the
#   connection is subject to transient interruptions until it has stabilized;
#   hence deciding whether to debounce based on a single initial test defeats
#   the entire purpose.
#   
#   There are some additional smaller changes that go along with the major
#   one:
#   
#   	Comments added to hub_port_connect_change() detailing the
#   	conditions under which it will be called.
#   
#   	Don't clear the port's connect-changed feature if it wasn't
#   	set.
#   
#   	Skip debouncing if there wasn't a physical connection change
#   	but only a logical port-enable change (or a firmware-download-
#   	induced device morph -- not yet implemented).
#   
#   	Clear all the hub status change indicators in hub_events()
#   	before handling a connect change.  This will reduce syslog
#   	clutter from status change bits that remain set while khubd
#   	is busy taking care of a new device.
#   
#   The patch includes no changes to the debounce routine itself.  Please
#   apply.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/06/04 07:10:33-07:00 stern@rowland.harvard.edu +41 -22
#   USB: Debounce all connect change events
# 
# ChangeSet
#   2004/06/04 15:13:47-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Code cleanup for the UHCI driver
#   
#   This patch makes some simple cleanups in the UHCI driver:
#   
#   	It introduces msecs_to_jiffies() conversions and uses msleep().
#   
#   	It wakes up threads waiting for an endpoint to be disabled
#   	in the oddball case where interrupts aren't working.  (This
#   	should have been in a previous patch but I missed it.)
#   
#   	It disables PCI interrupt generation whenever the controller
#   	is reset and enables it when the controller is started.  This
#   	may possibly solve some people's problems with suspend/resume.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/uhci-hcd.c
#   2004/06/04 08:14:49-07:00 stern@rowland.harvard.edu +28 -17
#   USB: Code cleanup for the UHCI driver
# 
# ChangeSet
#   2004/06/04 15:13:16-07:00 jnardelli@infosciences.com 
#   [PATCH] USB: fix Memory leak in visor.c and ftdi_sio.c
#   
#   Signed-off-by: Joe Nardelli <jnardelli@infosciences.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/visor.c
#   2004/06/04 07:13:10-07:00 jnardelli@infosciences.com +1 -0
#   USB: fix Memory leak in visor.c and ftdi_sio.c
# 
# drivers/usb/serial/ftdi_sio.c
#   2004/06/04 06:53:27-07:00 jnardelli@infosciences.com +1 -0
#   USB: fix Memory leak in visor.c and ftdi_sio.c
# 
# ChangeSet
#   2004/06/04 15:12:44-07:00 spitalnik@penguin.cz 
#   [PATCH] USB: pegasus driver and ATEN device support
#   
#   I have created a patch to add support for ATEN device in pegasus usb driver.
#   I've sent the patch to the maintainer stated in pegasus.h but after several
#   weeks I didn't recieve a response, so I'm sending it to you now. The patch
#   should apply cleanly on 2.6.6, but it doesn't apply cleanly on todays -bk as
#   there was some patch adding some other device. One thing I'm not 100% sure
#   are the flags specified to PEGASUS_DEV, what means HAS_HOME_PNA?
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/pegasus.h
#   2004/04/15 14:37:12-07:00 spitalnik@penguin.cz +3 -0
#   USB: pegasus driver and ATEN device support
# 
# ChangeSet
#   2004/06/04 14:53:48-07:00 Frank.A.Uepping@t-online.de 
#   [PATCH] Driver Core: fix struct device::release issue
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
#   
#   
#   On Saturday 27 March 2004 02:14, Greg KH wrote:
#   > On Sat, Mar 06, 2004 at 12:47:24PM +0100, Frank A. Uepping wrote:
#   > > Hi,
#   > > if device_add fails (e.g. bus_add_device returns an error) then the release
#   > > method will be called for the device. Is this a bug or a feature?
#   >
#   > Are you sure this will happen?  device_initialize() gets a reference
#   > that is still present after device_add() fails, right?  So release()
#   > will not get called.
#   At the label PMError, kobject_unregister is called, which decrements the
#   recount by 2, which will result in calling release at label Done (put_device).
#   
#   kobject_unregister should be superseded by kobject_del.
#   Here is a patch:
# 
# drivers/base/core.c
#   2004/03/27 07:04:27-08:00 Frank.A.Uepping@t-online.de +1 -1
#   Driver Core: fix struct device::release issue
# 
# ChangeSet
#   2004/06/04 14:46:39-07:00 khali@linux-fr.org 
#   [PATCH] I2C: update I2C IDs
#   
#   > > Greg, should I send a patch to you with these?
#   >
#   > Sure, if it's needed.
#   
#   Just noticed that I never sent the promised patch. Here it is. I also
#   added a few other IDs, since we have them in our (2.4) i2c CVS
#   repository. Having them in 2.6 as well will at least prevent collisions.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/i2c-id.h
#   2004/05/31 14:26:48-07:00 khali@linux-fr.org +12 -0
#   I2C: update I2C IDs
# 
# ChangeSet
#   2004/06/04 14:45:53-07:00 vojtech@suse.cz 
#   [PATCH] I2C i2c-piix: Don't treat ServerWorks servers as Laptops
#   
#   I'm sending you this little obvious patch which should enable i2c-piix
#   to work on IBM servers with ServerWorks chipsets. It still will treat
#   any IBM/Intel machine as a laptop and refuse to work, but it's better
#   than before.
#   
#   
#     i2c: Treat only IBM machines with Intel chipsets as IBM laptops.
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/busses/i2c-piix4.c
#   2004/03/19 08:01:34-08:00 vojtech@suse.cz +1 -1
#   I2C i2c-piix: Don't treat ServerWorks servers as Laptops
# 
# ChangeSet
#   2004/06/04 13:24:29-07:00 greg@kroah.com 
#   PCI: convert to using dev_attrs for all PCI devices.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/pci/pci.h
#   2004/06/04 06:23:04-07:00 greg@kroah.com +1 -0
#   PCI: convert to using dev_attrs for all PCI devices.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/pci/pci-sysfs.c
#   2004/06/04 06:23:04-07:00 greg@kroah.com +15 -18
#   PCI: convert to using dev_attrs for all PCI devices.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/pci/pci-driver.c
#   2004/06/04 06:23:04-07:00 greg@kroah.com +1 -0
#   PCI: convert to using dev_attrs for all PCI devices.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/04 11:09:29-07:00 greg@kroah.com 
#   Driver Model: And even more cleanup of silly scsi use of the *ATTR macros...
#     
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/scsi/scsi_transport_spi.c
#   2004/06/04 04:08:48-07:00 greg@kroah.com +2 -2
#   Driver Model: And even more cleanup of silly scsi use of the *ATTR macros...
#     
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/scsi/scsi_sysfs.c
#   2004/06/04 04:08:48-07:00 greg@kroah.com +5 -5
#   Driver Model: And even more cleanup of silly scsi use of the *ATTR macros...
#     
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/04 11:55:11-05:00 jejb@mulgrave.(none) 
#   sg update to 20040516
#   
#   From: Douglas Gilbert <dougg@torque.net>
#   
#   Here are some further refinements to this patch with help
#   from Pat Mansfield:
#        - replace vmalloc() with kmalloc(,GFP_KERNEL)
#        - bump max sg devices from 8192 to 32768
#   
#   Tested to 16k devices (and 8k devices on a box with 512MB
#   ram), Patch is against lk 2.6.6 (or 2.6.6-bk1).
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sg.c
#   2004/06/04 11:54:42-05:00 jejb@mulgrave.(none) +22 -15
#   sg update to 20040516
# 
# ChangeSet
#   2004/06/04 09:13:16-05:00 hch@lst.de 
#   [PATCH] kill dead compat code in advansys
#   
#   I actually wanted to fix up the check_region usage there but got lost
#   in the mess.  Let's start by kicking out the 2.2 compat and using scsi
#   layer constants instead of their own redefinitions first.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/advansys.c
#   2004/06/04 06:19:50-05:00 hch@lst.de +119 -508
#   kill dead compat code in advansys
# 
# ChangeSet
#   2004/06/04 09:09:27-05:00 hch@lst.de 
#   [PATCH] update 53c700 to avoid obsolete headers
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sim710.c
#   2004/06/04 05:53:02-05:00 hch@lst.de +2 -3
#   update 53c700 to avoid obsolete headers
# 
# drivers/scsi/lasi700.c
#   2004/06/04 05:53:02-05:00 hch@lst.de +1 -2
#   update 53c700 to avoid obsolete headers
# 
# drivers/scsi/NCR_D700.c
#   2004/06/04 06:45:28-05:00 hch@lst.de +1 -3
#   update 53c700 to avoid obsolete headers
# 
# drivers/scsi/53c700.h
#   2004/06/04 06:43:36-05:00 hch@lst.de +13 -10
#   update 53c700 to avoid obsolete headers
# 
# drivers/scsi/53c700.c
#   2004/06/04 06:43:46-05:00 hch@lst.de +65 -64
#   update 53c700 to avoid obsolete headers
# 
# ChangeSet
#   2004/06/04 08:59:37-05:00 hch@lst.de 
#   [PATCH] missing forward declarations in scsi_eh.h
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_eh.h
#   2004/06/04 06:45:01-05:00 hch@lst.de +4 -0
#   missing forward declarations in scsi_eh.h
# 
# ChangeSet
#   2004/06/03 21:54:17-05:00 akpm@osdl.org 
#   [PATCH] 3ware 9000 schedule_timeout fix
#   
#   From: "Adam Radford" <aradford@amcc.com>
#   
#   This small patch fixes the broken schedule_timeout() usage in the 3w-9xxx
#   driver, and replaces the calls with msleep().
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/3w-9xxx.c
#   2004/06/03 19:43:06-05:00 akpm@osdl.org +4 -3
#   3ware 9000 schedule_timeout fix
# 
# ChangeSet
#   2004/06/03 21:51:02-05:00 akpm@osdl.org 
#   [PATCH] 3ware 9000 driver update
#   
#   From: "Adam Radford" <aradford@amcc.com>
#   
#   This patch updates the 3w-9xxx driver in 2.6.7-rc2-mm1 to v2.26.02.000 to
#   cleanup several things pointed out by Chris Hellwig / Jeff Garzik.
#   
#   Changes in this release:
#     - Use descriptive defines for phase numbers.
#     - Remove un-needed casts for TW_Command_Full
#     - Rework eh_reset(), eh_abort() spinlocks.
#     - Remove all mdelays, replace w/ schedule_timeout().
#     - Remove MODULE_PARAM cmds_per_lun, add sysfs device attribute 'queue_depth'.
#     - Remove twa_slave_configure().
#     - Remove twa_info().
#     - Remove all bitfields from structures, add bitmask macros.
#     - Remove twa_setup_irq() wrapper, call directly.
#     - Remove un-needed prototypes.
#     - Propogate return value of pci_enable_device(), pci_set_dma_mask(), ioremap().
#     - Use pci_request/free_regions().
#     - Add missing call to pci_disable_device() on probe failure.
#     - Unregister character ioctl interface in twa_remove().
#     - Make some excessively lengthy lines < 80 columns.
#     - Use pci_module_init() instead of pci_register_driver().
#     - Remove bogus TW_IN_INTR check, fix twa_interrupt() spinlock.
#     - Rev driver branch to .02 to denote kernel version.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/3w-9xxx.h
#   2004/06/03 21:44:23-05:00 akpm@osdl.org +31 -53
#   3ware 9000 driver update
# 
# drivers/scsi/3w-9xxx.c
#   2004/06/03 21:44:23-05:00 akpm@osdl.org +167 -159
#   3ware 9000 driver update
# 
# ChangeSet
#   2004/06/03 20:12:20-05:00 arjanv@redhat.com 
#   [PATCH] SCSI: replace deprecated hosts.h file
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/zalon.c
#   2004/05/12 10:46:24-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/wd7000.c
#   2004/05/12 10:46:24-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/wd33c93.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/ultrastor.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/u14-34f.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/tmscsim.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/t128.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sym53c416.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sun3x_esp.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sun3_scsi_vme.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sun3_scsi.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/st.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sr_vendor.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sr_ioctl.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sr.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sim710.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sgiwd93.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sg.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/seagate.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/sd.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/scsicam.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/scsi_pc98.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/scsi_module.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/scsi_ioctl.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/scsi_error.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/scsi_devinfo.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/scsi_debug.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/qlogicpti.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/qlogicisp.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/qlogicfc.c
#   2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/qlogicfas408.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/qlogicfas.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/qla2xxx/qla_os.h
#   2004/05/12 10:46:27-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/qla1280.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/psi240i.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/ppa.h
#   2004/05/12 10:46:24-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/pluto.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/pcmcia/qlogic_stub.c
#   2004/05/12 10:46:25-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/pcmcia/fdomain_stub.c
#   2004/05/12 10:46:25-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/pcmcia/aha152x_stub.c
#   2004/05/12 10:46:25-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/pci2220i.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/pci2000.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/pc980155.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/pas16.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/osst.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/oktagon_esp.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/nsp32.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/ncr53c8xx.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/mvme16x.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/mvme147.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/megaraid.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/mca_53c9x.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/mac_scsi.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/mac_esp.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/lasi700.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/jazz_esp.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/ips.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/ini9100u.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/in2000.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/imm.h
#   2004/05/12 10:46:24-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/ide-scsi.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/ibmmca.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/i60uscsi.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/gvp11.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/g_NCR5380.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/fdomain.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/fd_mcs.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/fcal.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/fastlane.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/esp.c
#   2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/eata_pio.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/eata.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/dtc.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/dmx3191d.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/dec_esp.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/dc395x.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/cyberstormII.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/cyberstorm.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/cpqfcTSworker.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/cpqfcTSinit.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +2 -2
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/cpqfcTScontrol.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/constants.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/bvme6000.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/blz2060.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/blz1230.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/atp870u.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/atari_scsi.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/amiga7xx.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/aic7xxx_old.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/aic7xxx/aiclib.c
#   2004/05/12 10:46:25-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/aic7xxx/aic7xxx_osm.h
#   2004/05/12 10:46:27-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/aic7xxx/aic79xx_osm.h
#   2004/05/12 10:46:27-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/aha1740.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/aha1542.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/advansys.c
#   2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/a3000.c
#   2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/a2091.c
#   2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/NCR_Q720.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/NCR_D700.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/NCR53c406a.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/NCR53C9x.c
#   2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/BusLogic.c
#   2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/53c7xx.c
#   2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/53c700.c
#   2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# drivers/scsi/3w-xxxx.c
#   2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1
#   SCSI: replace deprecated hosts.h file
# 
# ChangeSet
#   2004/06/03 20:07:56-05:00 akpm@osdl.org 
#   [PATCH] scsi_transport_spi.c build fix
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_transport_spi.c
#   2004/06/03 11:23:05-05:00 akpm@osdl.org +1 -1
#   scsi_transport_spi.c build fix
# 
# ChangeSet
#   2004/06/03 20:06:32-05:00 akpm@osdl.org 
#   [PATCH] Lost 2.4 change for BusLogic info
#   
#   From: Alan Cox <alan@redhat.com>
#   
#   I think it might be a good thing if this was fixed to match 2.4
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/Kconfig
#   2004/06/03 01:56:10-05:00 akpm@osdl.org +1 -3
#   Lost 2.4 change for BusLogic info
# 
# ChangeSet
#   2004/06/03 20:05:10-05:00 hch@lst.de 
#   [PATCH] scsi_dev_flags must be __initdata, not __init
#   
#   __init is only for functions
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_devinfo.c
#   2004/05/31 16:05:51-05:00 hch@lst.de +1 -1
#   scsi_dev_flags must be __initdata, not __init
# 
# ChangeSet
#   2004/06/03 20:03:33-05:00 rddunlap@osdl.org 
#   [PATCH] fix check_region usage in eata_pio
#   
#   Based on "eata_generic.h", this SCSI controller has 9 bytes of IO
#   space, not 8, so update request_region(), release_region(), and
#   n_io_port to use 9 instead of 8.
#   
#   diffstat:=
#    drivers/scsi/eata_pio.c |   16 ++++++++--------
#    1 files changed, 8 insertions(+), 8 deletions(-)
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/eata_pio.c
#   2004/06/01 17:29:30-05:00 rddunlap@osdl.org +8 -8
#   fix check_region usage in eata_pio
# 
# ChangeSet
#   2004/06/03 20:01:03-05:00 James.Bottomley@steeleye.com 
#   [PATCH] Advansys: Add basic highmem/DMA support
#   
#   On Wed, 2004-05-19 at 05:38, Herbert Xu wrote:
#   > This is a resend of my patch that adds basic support for highmem
#   > on i386 to the advansys driver.  It has been tested in
#   > http://bugs.debian.org/245238.
#   >
#   > The maintainer email address listed in the MAINTAINERS file bounced
#   > so someone else will need to look at this.
#   
#   I converted your patch to use the DMA-API.  This will be necessary to
#   use the EISA advansys boards---Of course, EISA won't work properly until
#   the entire driver is converted to the driverfs probing API, sigh, but
#   I'll get around to that eventually.
#   
#   OK, and I couldn't resist getting rid of the stupid in_isr locking on
#   the done function.
#   
#   Converted from original patch by Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/advansys.c
#   2004/05/31 12:14:32-05:00 James.Bottomley@steeleye.com +95 -50
#   Add basic highmem/DMA support
# 
# ChangeSet
#   2004/06/03 19:59:37-05:00 hch@lst.de 
#   [PATCH] remove obsolete API usage from dpt_i2o
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/dpti.h
#   2004/05/31 08:34:32-05:00 hch@lst.de +12 -12
#   remove obsolete API usage from dpt_i2o
# 
# drivers/scsi/dpt_i2o.c
#   2004/05/31 08:35:50-05:00 hch@lst.de +28 -25
#   remove obsolete API usage from dpt_i2o
# 
# ChangeSet
#   2004/06/03 19:58:15-05:00 hch@lst.de 
#   [PATCH] fix sym53c416 check_region usage
#   
#   again, the init code could use some bigger rework, but let's stick to
#   the minimal fix until we have some testers.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sym53c416.c
#   2004/05/31 07:18:12-05:00 hch@lst.de +41 -42
#   fix sym53c416 check_region usage
# 
# ChangeSet
#   2004/06/03 19:56:47-05:00 hch@lst.de 
#   [PATCH] fix check_region usage in eata_pio
#   
#   I'd love to rework the init sequence a bit more, but without beeing able
#   to actually test the driver I'd rather stick to the bulletproof fix.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/eata_pio.c
#   2004/05/31 06:30:48-05:00 hch@lst.de +58 -44
#   fix check_region usage in eata_pio
# 
# ChangeSet
#   2004/06/03 19:55:15-05:00 hch@lst.de 
#   [PATCH] handle NO_SENSE in sd
#   
#   Original patch from
#   http://marc.theaimsgroup.com/?l=linux-scsi&m=107428662718579&w=2
#   reworked to according to James' suggestion to handle NO_SENSE the same
#   as RECOVERED_ERROR.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sd.c
#   2004/05/31 05:53:01-05:00 hch@lst.de +4 -4
#   handle NO_SENSE in sd
# 
# ChangeSet
#   2004/06/03 19:53:41-05:00 hch@lst.de 
#   [PATCH] remove sleep_on_timeout usage in megaraid
#   
#   megaraid does sleep_on_timeout on a stack waitq - use msleep instead.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/megaraid.c
#   2004/05/30 08:04:14-05:00 hch@lst.de +3 -6
#   remove sleep_on_timeout usage in megaraid
# 
# ChangeSet
#   2004/06/03 19:52:05-05:00 g.liakhovetski@gmx.de 
#   [PATCH] tmscsim: Store pDCB in device->hostdata
#   
#   On Sun, 23 May 2004, Christoph Hellwig wrote:
#   > The other thing is that most calls to dc390_findDCB could probably be
#   > replaced with stroing the pDCB in scsi_device->hostdata on slave_alloc,
#   > but that could aswell be done in an incremental patch.
#   
#   Done in the attached patch. Tested as usual and a bit harder.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/tmscsim.c
#   2004/05/28 18:17:17-05:00 g.liakhovetski@gmx.de +8 -10
#   tmscsim: Store pDCB in device->hostdata
# 
# ChangeSet
#   2004/06/03 19:50:16-05:00 hch@lst.de 
#   [PATCH] fix dpt_i2o compilation for alpha and sparc
#   
#   This patch has been floating around for ages, got reminded of it again
#   when looking at the debian kernel package.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/dpt_i2o.c
#   2004/05/10 07:21:38-05:00 hch@lst.de +2 -2
#   fix dpt_i2o compilation for alpha and sparc
# 
# ChangeSet
#   2004/06/03 20:43:58-04:00 len.brown@intel.com 
#   [ACPI] acpi=force overrides blacklist pci=noacpi or acpi=noirq (Andi Kleen)
# 
# arch/i386/kernel/dmi_scan.c
#   2004/06/03 20:43:48-04:00 len.brown@intel.com +12 -6
#   acpi=force overrides blacklist pci=noacpi or acpi=noirq (Andi Kleen)
# 
# ChangeSet
#   2004/06/03 19:41:12-05:00 aradford@amcc.com 
#   [PATCH] 2/2 3ware 9000 SATA-RAID driver v2.26.00.009
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/linux/pci_ids.h
#   2004/05/21 17:33:51-05:00 aradford@amcc.com +2 -0
#   3ware 9000 SATA-RAID driver v2.26.00.009
# 
# drivers/scsi/Makefile
#   2004/05/21 17:24:55-05:00 aradford@amcc.com +1 -0
#   3ware 9000 SATA-RAID driver v2.26.00.009
# 
# drivers/scsi/Kconfig
#   2004/05/21 18:29:59-05:00 aradford@amcc.com +12 -1
#   3ware 9000 SATA-RAID driver v2.26.00.009
# 
# drivers/scsi/3w-9xxx.h
#   2004/05/26 15:17:26-05:00 aradford@amcc.com +726 -0
#   3ware 9000 SATA-RAID driver v2.26.00.009
# 
# MAINTAINERS
#   2004/05/21 17:56:25-05:00 aradford@amcc.com +14 -0
#   3ware 9000 SATA-RAID driver v2.26.00.009
# 
# drivers/scsi/3w-9xxx.h
#   2004/05/26 15:17:26-05:00 aradford@amcc.com +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/3w-9xxx.h
# 
# ChangeSet
#   2004/06/03 19:39:01-05:00 aradford@amcc.com 
#   [PATCH] 1/2 3ware 9000 SATA-RAID driver v2.26.00.009
#   
#   Here is an updated version v2.26.00.009 of the 3ware 9000 SATA-RAID driver.
#   
#   Changes in this release:
#      - Convert driver to pci_driver format.
#      - Remove proc interface, add sysfs attributes.
#      - Return SCSI_MLQUEUE_HOST_BUSY when card status is busy.
#   
#   Future versions may include:
#      - PAE fix
#      - 80 column wrap fixes
#      - Remove more prototypes by re-ordering functions.
#      - sysfs queue depth adjustment instead of module_param
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/3w-9xxx.c
#   2004/05/26 15:17:24-05:00 aradford@amcc.com +2144 -0
#   3ware 9000 SATA-RAID driver v2.26.00.009
# 
# drivers/scsi/3w-9xxx.c
#   2004/05/26 15:17:24-05:00 aradford@amcc.com +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/3w-9xxx.c
# 
# ChangeSet
#   2004/06/03 17:37:14-07:00 mochel@digitalimplant.org 
#   [Driver Model] Add default device attributes to struct bus_type.
#   
#   - Add struct bus_type::dev_attrs, which is an array of device 
#     attributes that are added to each device as they are registered.
#   
#    - Also make sure that we don't hang when removing bus attributes
#      if adding one failed.. 
# 
# include/linux/device.h
#   2004/06/03 17:37:08-07:00 mochel@digitalimplant.org +1 -0
#   [Driver Model] Add default device attributes to struct bus_type.
# 
# drivers/base/bus.c
#   2004/06/03 17:37:08-07:00 mochel@digitalimplant.org +35 -1
#   [Driver Model] Add default device attributes to struct bus_type.
# 
# ChangeSet
#   2004/06/03 17:14:32-07:00 greg@kroah.com 
#   USB: remove "devfs" message from kernel log for usb-serial driver
#   
#   No one uses devfs on 2.6 :)
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/bus.c
#   2004/06/03 17:14:00-07:00 greg@kroah.com +2 -2
#   USB: remove "devfs" message from kernel log for usb-serial driver
#   
#   No one uses devfs on 2.6 :)
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/03 17:05:41-07:00 mochel@digitalimplant.org 
#   [Driver Model] Add default attributes for struct bus_type.
#   
#   - Similar to default attributes for struct class, this is an array
#     of attributes, terminated with an attribute with a NULL name, that
#     are added when the bus is registered, and removed when the bus is 
#     unregistered. 
# 
# include/linux/device.h
#   2004/06/03 17:05:35-07:00 mochel@digitalimplant.org +2 -0
#   [Driver Model] Add default attributes for struct bus_type.
# 
# drivers/base/bus.c
#   2004/06/03 17:05:35-07:00 mochel@digitalimplant.org +37 -0
#   [Driver Model] Add default attributes for struct bus_type.
# 
# ChangeSet
#   2004/06/03 16:50:29-07:00 scott@concord.org 
#   [PATCH] USB: kyocera 7135 patch
#   
#   Here is a patch based on 2.6.7-rc2 that makes the Kyocera 7135 work.
#   The Kyocera appears to have the same setup as the Trio.  Its endpoints
#   are laid out like this:
#   
#   > >>>type                  address
#   > >>>usb bulk out:         0x01
#   > >>>usb interrupt in:     0x82
#   > >>>usb bulk out:         0x03
#   > >>>usb bulk in:          0x84
#   The last two are the ones used for the syncing communication.
#   
#   So the patch adds the ids for the kyocera and makes the treo_attach
#   function handle the kyocera too.  I also changed the comment; it appears
#   there was an error in the original comment about the treo:
#   
#   Joe Nardelli wrote:
#   > Actually, the comment isn't quite right for Treos either (oops).  It
#   > should read:
#   >
#   > ...
#   > 1st bulk in endpoint to communicate with the 2nd bulk out endpoint
#   > ...
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/visor.h
#   2004/06/02 07:09:27-07:00 scott@concord.org +3 -0
#   USB: kyocera 7135 patch
# 
# drivers/usb/serial/visor.c
#   2004/06/02 10:03:04-07:00 scott@concord.org +11 -7
#   USB: kyocera 7135 patch
# 
# ChangeSet
#   2004/06/03 16:49:51-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: 2.6-BK usb (printing) broken
#   
#   On Sat, 29 May 2004, Jens Axboe wrote:
#   
#   > > > Both 2.6.7-rc1 and BK current spit out a bunch of:
#   > > >
#   > > > drivers/usb/class/usblp.c: usblp1: nonzero read/write bulk status received: -2
#   > > > drivers/usb/class/usblp.c: usblp1: error -2 reading from printer
#   > > > drivers/usb/class/usblp.c: usblp1: error -115 reading from printer
#   > > > drivers/usb/class/usblp.c: usblp1: error -115 reading from printer
#   > > > ...
#   > > >
#   > > > (about ~80 of that last line) but work for me.
#   
#   > Sorry wasn't quite clear - the above messages are with 2.6.7-rc1 and
#   > current bk with your patch backed out. Current bk with the patch reports
#   > only the timeouts I originally listed.
#   
#   Okay, I feel better.
#   
#   It looks like those errors you see are caused by a bug in the usblp
#   driver.  The patch below ought to help.
# 
# drivers/usb/class/usblp.c
#   2004/05/29 07:25:51-07:00 stern@rowland.harvard.edu +1 -0
#   USB: 2.6-BK usb (printing) broken
# 
# ChangeSet
#   2004/06/03 12:38:31-07:00 hannal@us.ibm.com 
#   [PATCH] Add class support to cpuid.c
#   
#   This patch adds class support to arch/i386/kernel/cpuid.c. This enables udev
#   support. I have tested on a 2-way SMP system and on a 2-way built as UP.
#   Here are the results for the SMP:
#   
#   [hlinder@w-hlinder2 hlinder]$ tree /sys/class/cpuid
#   /sys/class/cpuid
#   |-- cpu0
#   |   `-- dev
#   `-- cpu1
#       `-- dev
#   
#   2 directories, 2 files
#   [hlinder@w-hlinder2 hlinder]$ more /sys/class/cpuid/cpu0/dev
#   203:0
#   [hlinder@w-hlinder2 hlinder]$ more /sys/class/cpuid/cpu1/dev
#   203:1
#   [hlinder@w-hlinder2 hlinder]$
#   
#   And for the UP:
#   
#   [root@w-hlinder2 root]# tree /sys/class/cpuid
#   /sys/class/cpuid
#   `-- cpu0
#       `-- dev
#   
#   1 directory, 1 file
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# arch/i386/kernel/cpuid.c
#   2004/06/02 14:22:27-07:00 hannal@us.ibm.com +36 -2
#   Add class support to cpuid.c
# 
# ChangeSet
#   2004/06/03 12:06:36-07:00 greg@kroah.com 
#   Cset exclude: vojtech@suse.cz|ChangeSet|20040602201956|45549
#   
#   Oops, this broke device removal pretty badly :(
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/transport.c
#   2004/06/03 12:06:28-07:00 greg@kroah.com +0 -0
#   Exclude
# 
# drivers/usb/storage/isd200.c
#   2004/06/03 12:06:28-07:00 greg@kroah.com +0 -0
#   Exclude
# 
# ChangeSet
#   2004/06/03 11:42:20-07:00 greg@kroah.com 
#   Driver Model: Cleanup the i2c driver silly use of the *ATTR macros which just broke
#   
#    
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/w83l785ts.c
#   2004/06/03 11:41:43-07:00 greg@kroah.com +2 -2
#   Driver Model: Cleanup the i2c driver silly use of the *ATTR macros which just broke
#   
#    
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/w83781d.c
#   2004/06/03 11:41:44-07:00 greg@kroah.com +15 -15
#   Driver Model: Cleanup the i2c driver silly use of the *ATTR macros which just broke
#   
#    
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/w83627hf.c
#   2004/06/03 11:41:43-07:00 greg@kroah.com +49 -49
#   Driver Model: Cleanup the i2c driver silly use of the *ATTR macros which just broke
#   
#    
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/via686a.c
#   2004/06/03 11:41:44-07:00 greg@kroah.com +9 -9
#   Driver Model: Cleanup the i2c driver silly use of the *ATTR macros which just broke
#   
#    
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/lm85.c
#   2004/06/03 11:41:43-07:00 greg@kroah.com +13 -13
#   Driver Model: Cleanup the i2c driver silly use of the *ATTR macros which just broke
#   
#    
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/lm78.c
#   2004/06/03 11:41:43-07:00 greg@kroah.com +11 -11
#   Driver Model: Cleanup the i2c driver silly use of the *ATTR macros which just broke
#   
#    
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/it87.c
#   2004/06/03 11:41:44-07:00 greg@kroah.com +11 -11
#   Driver Model: Cleanup the i2c driver silly use of the *ATTR macros which just broke
#   
#    
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/asb100.c
#   2004/06/03 11:41:43-07:00 greg@kroah.com +33 -33
#   Driver Model: Cleanup the i2c driver silly use of the *ATTR macros which just broke
#   
#    
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/03 11:40:44-07:00 greg@kroah.com 
#   Driver Model: More cleanup of silly scsi use of the *ATTR macros...
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/scsi/scsi_debug.c
#   2004/06/03 11:40:14-07:00 greg@kroah.com +8 -8
#   Driver Model: More cleanup of silly scsi use of the *ATTR macros...
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/03 10:41:29-07:00 mochel@digitalimplant.org 
#   [Driver Model] Add default attributes for classes class devices.
#   
#   - add struct class::class_attrs, which is designed to point to an 
#     array of class_attributes that are added when the class is registered
#     and removed when the class is unregistered. 
#     This allows for more consolidated and cleaner definition of and
#     management of attributes.
#   
#   - Add struct class::class_dev_attrs to do something similarly for 
#     class devices. Each class device that is registered with the class
#     gets that set of attributes added for them, and subsequently removed
#     when the device is unregistered.
#   
#   Each array depends on a terminating attribute with a NULL name. Hint:
#   use the new __ATTR_NULL macro to terminate it.
# 
# include/linux/device.h
#   2004/06/03 10:41:22-07:00 mochel@digitalimplant.org +3 -0
#   [Driver Model] Add default attributes for classes class devices.
# 
# ChangeSet
#   2004/06/03 10:27:16-07:00 mochel@digitalimplant.org 
#   [sysfs] Add attr_name() macro
#   
#   - Returns the name of an embedded attribute in a higher-level 
#     attribute.
# 
# ChangeSet
#   2004/06/03 09:48:45-07:00 greg@kroah.com 
#   Add basic sysfs support for raw devices
#   
#   This is needed by people who use udev and want raw devices.
#   SuSE is shipping with this patch.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/char/raw.c
#   2004/06/03 09:48:22-07:00 greg@kroah.com +24 -1
#   Add basic sysfs support for raw devices
#   
#   This is needed by people who use udev and want raw devices.
#   SuSE is shipping with this patch.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/03 08:44:34-07:00 mochel@digitalimplant.org 
#   [Driver Model] Fix up silly scsi usage of DEVICE_ATTR() macros. 
#   
#   - Hey, just because the macro incorrectly included a ';' doesn't mean
#     one shouldn't add one on their own.. (Or at least be consistent.)
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/scsi/scsi_sysfs.c
#   2004/06/03 08:44:27-07:00 mochel@digitalimplant.org +2 -2
#   [Driver Model] Fix up silly scsi usage of DEVICE_ATTR() macros. 
# 
# ChangeSet
#   2004/06/03 00:45:08-04:00 len.brown@intel.com 
#   [ACPI] fix !CONFIG_PCI build (Bjorn Helgaas)
# 
# include/linux/acpi.h
#   2004/06/02 11:02:20-04:00 len.brown@intel.com +2 -2
#   fix !CONFIG_PCI build (Bjorn Helgaas)
# 
# arch/i386/kernel/acpi/boot.c
#   2004/06/02 11:02:20-04:00 len.brown@intel.com +5 -4
#   fix !CONFIG_PCI build (Bjorn Helgaas)
# 
# ChangeSet
#   2004/06/02 21:08:30-04:00 p.lavarre@ieee.org 
#   [PATCH] ata_check_bmdma
#   
#   Move hand-coded BMDMA status check into separate function.
# 
# drivers/scsi/libata-core.c
#   2004/05/27 19:56:57-04:00 p.lavarre@ieee.org +18 -10
#   ata_check_bmdma
# 
# ChangeSet
#   2004/06/02 17:10:52-07:00 mochel@digitalimplant.org 
#   [Driver Model] Consolidate attribute definition macros
#   
#   - Create __ATTR(), __ATTR_RO(), and __ATTR_NULL macros to help define 
#     attributes in a neat, short-hand form. 
#   
#   - Apply these macros to the attribute definition in include/linux/device.h
#   
#   - Note: These can be used to more cleanly define attributes in your own
#     code. e.g: 
#   
#   	static struct device_attribute attrs[] = {
#   		__ATTR_RO(foo),
#   		__ATTR_RO(bar),
#   		__ATTR(baz,0666,baz_show,baz_store),
#   		__ATTR_NULL,
#   	};
#   
#     ...etc. 
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/device.h
#   2004/06/02 17:01:55-07:00 mochel@digitalimplant.org +6 -25
#   [Driver Model] Consolidate object attribute definition.
# 
# ChangeSet
#   2004/06/02 14:07:26-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Move usb_new_device() et al. into hub.c
#   
#   This patch moves usb_new_device(), usb_disconnect(), usb_choose_address(),
#   and usb_release_address() from usb.c to hub.c.  As a side benefit,
#   choose_address() and release_address() can now become static.  The other
#   two can't, because they have to be exported for use by HCD's when
#   registering/unregistering root hubs.
#   
#   Some other features of the patch:
#   
#   	The usb_snddefctrl() and usb_rcvdefctrl() macros have been
#   	removed, since only one of them was used and only in one spot.
#   
#   	The comment about configuration choice needing to interact with
#   	hub power budgeting has been moved in accordance with David's
#   	wish.  usb_new_device() checks to make sure a configuration
#   	could be chosen and logs a warning if no choice was made.
#   
#   	Following Linus's preference, the #ifdef preprocessor stuff has
#   	been removed from around the calls the show_string routine.  It
#   	is now defined as a non-inline routine when debugging is enabled
#   	and as an inline no-op otherwise (the compiler will optimize
#   	away the useless tests).
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/usb.c
#   2004/06/01 09:54:17-07:00 stern@rowland.harvard.edu +0 -229
#   USB: Move usb_new_device() et al. into hub.c
# 
# drivers/usb/core/hub.c
#   2004/06/01 09:54:17-07:00 stern@rowland.harvard.edu +231 -3
#   USB: Move usb_new_device() et al. into hub.c
# 
# drivers/usb/core/hcd.h
#   2004/06/01 09:54:17-07:00 stern@rowland.harvard.edu +0 -7
#   USB: Move usb_new_device() et al. into hub.c
# 
# ChangeSet
#   2004/06/02 14:06:55-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Minor cleanups for hub driver
#   
#   Greg:
#   
#   This patch takes care of some small miscellaneous items in hub.c:
#   
#   	Move the definition of CONFIG to the right place;
#   
#   	Print the proper value for submission status in the error log;
#   
#   	Remove an unused list of all hubs;
#   
#   	Remove some unneeded braces;
#   
#   	Kill an accidentally-resurrected comment.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.h
#   2004/06/01 09:31:11-07:00 stern@rowland.harvard.edu +0 -1
#   USB: Minor cleanups for hub driver
# 
# drivers/usb/core/hub.c
#   2004/06/01 09:39:04-07:00 stern@rowland.harvard.edu +9 -25
#   USB: Minor cleanups for hub driver
# 
# ChangeSet
#   2004/06/02 13:55:44-07:00 oliver@neukum.org 
#   [PATCH] USB: fix race between disconnect and write of acm driver
#   
#   acm uses a workqueue to defer part of a write operation.
#   In case of disconnect this work must be waited for.
#     - fix race between write and disconnect
#   
#   Signed-off-by: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/cdc-acm.c
#   2004/05/31 08:13:14-07:00 oliver@neukum.org +2 -0
#   USB: fix race between disconnect and write of acm driver
# 
# ChangeSet
#   2004/06/02 13:49:28-07:00 oliver@neukum.org 
#   [PATCH] USB: fix racy access to urb->status in cdc acm driver
#   
#   Hi,
#   
#   fix access to urb->status by introduction of an explicit flag
#   for finished data transfer.
#     - fix racy access to urb->status
#   
#   Signed-off-by: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/cdc-acm.h
#   2004/05/31 08:02:12-07:00 oliver@neukum.org +1 -0
#   USB: fix racy access to urb->status in cdc acm driver
# 
# drivers/usb/class/cdc-acm.c
#   2004/05/31 08:02:12-07:00 oliver@neukum.org +10 -6
#   USB: fix racy access to urb->status in cdc acm driver
# 
# ChangeSet
#   2004/06/02 13:36:24-07:00 oliver@neukum.org 
#   [PATCH] USB: error handling of open of acm driver
#   
#   this adds error handling to the open method of the cdc acm driver.
#   The change set is relative to my last patch rewriting probe.
#     - add error handling to open method
#   
#   
#   Signed-off-by: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/cdc-acm.c
#   2004/05/31 06:54:36-07:00 oliver@neukum.org +23 -8
#   USB: error handling of open of acm driver
# 
# ChangeSet
#   2004/06/02 13:31:54-07:00 oliver@neukum.org 
#   [PATCH] USB: proper evaluation of the union descriptor for CDC ACM
#   
#   this changes acm_probe() to using the proper union descriptor.
#   It contains the workaround David suggested. Please apply.
#   
#     - fix probing to use cdc union descriptor
#   
#   Signed-off-by: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/cdc-acm.c
#   2004/05/30 03:56:45-07:00 oliver@neukum.org +100 -174
#   USB: proper evaluation of the union descriptor for CDC ACM
# 
# drivers/usb/class/cdc-acm.h
#   2004/05/30 03:56:45-07:00 oliver@neukum.org +114 -0
#   USB: proper evaluation of the union descriptor for CDC ACM
# 
# drivers/usb/class/cdc-acm.h
#   2004/05/30 03:56:45-07:00 oliver@neukum.org +0 -0
#   BitKeeper file /home/greg/linux/BK/usb-2.6/drivers/usb/class/cdc-acm.h
# 
# ChangeSet
#   2004/06/02 13:25:59-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb retry cleanups
#   
#   This patch stops changing the reported fault mode in cases where retries of
#   GET_DESCRIPTOR fail because the device just doesn't have such a descriptor.
#   Plus, it stops printing messages when retrying.
#   
#   It also reduces the number of retries; the first retry seems to resolve most
#   of these firmware problems.
#   
#   Signed-Off-By:  David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/message.c
#   2004/06/01 08:10:37-07:00 david-b@pacbell.net +1 -4
#   USB: usb retry cleanups
# 
# ChangeSet
#   2004/06/02 13:25:08-07:00 david-b@pacbell.net 
#   [PATCH] USB: pxa/rndis device descriptor
#   
#   This fixes a problem that all pxa2xx_udc g_ether devices
#   would run into.  They'd give the wrong descriptors, like:
#   
#   > --------msg1- usbview ----------
#   > Device Descriptor: bcdUSB:             0x0200
#   > bDeviceClass:         0xFF
#   > bDeviceSubClass:      0x00
#   > bDeviceProtocol:      0x00
#   > bMaxPacketSize0:      0x10 (16)
#   
#   Windows doesn't like RNDIS-supporting devices to point
#   out that they're really vendor-specific.  So this patch
#   makes sure they don't.
#   
#   Signed-off-by: David Brownell <dbrownelL@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/ether.c
#   2004/05/29 04:01:44-07:00 david-b@pacbell.net +10 -11
#   USB: pxa/rndis device descriptor
# 
# ChangeSet
#   2004/06/02 13:19:23-07:00 numlock@freesurf.ch 
#   [PATCH] Add support for ISD-300 controller
#   
#   This patch adds support in unusual_devs.h for the ISD-300 USB controller
#   used in CD-ROM enclosures.
#   
#   With it, since 2.6.0 it allowed me to move gigabytes of data and worked
#   without a hitch.
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/unusual_devs.h
#   2004/05/25 20:32:24-07:00 numlock@freesurf.ch +6 -0
#   Add support for ISD-300 controller
# 
# ChangeSet
#   2004/06/02 13:18:53-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Fix disconnect bug in dummy_hcd
#   
#   Greg:
#   
#   This patch fixes a bug in disconnect handling for the dummy_hcd driver.
#   After a disconnect the driver would still accept URBs for endpoint 0,
#   leading to an oops.  It also improves the ad-hoc technique used by the
#   driver to track its gadget's struct usb_device and fixes the way
#   port-power changes are handled.  Please apply.
#   
#   Alan Stern
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/dummy_hcd.c
#   2004/05/17 10:12:20-07:00 stern@rowland.harvard.edu +11 -4
#   USB: Fix disconnect bug in dummy_hcd
# 
# ChangeSet
#   2004/06/02 13:18:15-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: unusual_devs.h update
#   
#   On Mon, 3 May 2004, zcat wrote:
#   
#   > I am trying to get my camera going as a webcam (concord EyeQ Duo in PC
#   > mode, not HDD mode) with the 2.6.4 kernel using the se401 driver
#   > (compiled in).. It logged the following message, which doesn't mean much
#   > to me so I have no idea if it's useful information or not;
#   >
#   > May  3 21:08:11 mrsnorris kernel: usb 1-1: new full speed USB device
#   > using address 2
#   > May  3 21:08:16 mrsnorris kernel: usb 1-1: control timeout on ep0out
#   > May  3 21:08:16 mrsnorris kernel: usb-storage: This device
#   > (0595,4343,0100 S 00 P 00) has an unneeded Protocol entry in unusual_devs.h
#   > May  3 21:08:16 mrsnorris kernel:    Please send a copy of this message
#   > to <linux-usb-devel@lists.sourceforge.net>
#   
#   This fixes the "unneeded Protocol entry" message.  We never solved the
#   control timeout problem.
#   
#   Alan Stern
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/unusual_devs.h
#   2004/05/03 04:15:35-07:00 stern@rowland.harvard.edu +1 -1
#   USB: unusual_devs.h update
# 
# ChangeSet
#   2004/06/02 15:37:59-04:00 rl@hellgate.ch 
#   [PATCH] Add rhine_power_init(): get power regs into sane state
#   
#   Add rhine_power_init(): get power regs into sane state.
#   Move the respective code out of rhine_init_one. Add code for
#   two additional patterns (Rhine III).
#   
#   Signed-off-by: Roger Luethi <rl@hellgate.ch>
# 
# drivers/net/via-rhine.c
#   2004/06/01 20:00:00-04:00 rl@hellgate.ch +35 -20
#   Add rhine_power_init(): get power regs into sane state
# 
# ChangeSet
#   2004/06/02 15:37:51-04:00 rl@hellgate.ch 
#   [PATCH] Rewrite special-casing
#   
#   Use PCI revision to determine special cases. One bit field replaces a
#   bunch of data structures holding special case information.
#   
#   Replace chip_id, drv_flags in rhine_private with quirks
#   
#   Remove enum rhine_chips, struct rhine_chip_info (and array),
#   enum chip_capability_flags
#   
#   Add enum rhine_revs, enum rhine_quirks (some values in preparation for
#   subsequent changes)
#   
#   wait_for_reset() and enable_mmio() now use quirks instead of chip_id
#   
#   Remove model names from ident strings for now.
#   
#   Signed-off-by: Roger Luethi <rl@hellgate.ch>
# 
# drivers/net/via-rhine.c
#   2004/06/01 20:00:00-04:00 rl@hellgate.ch +76 -58
#   Rewrite special-casing
# 
# ChangeSet
#   2004/06/02 15:37:42-04:00 rl@hellgate.ch 
#   [PATCH] Return codes for rhine_init_one
#   
#   Use return codes in rhine_init_one instead of -ENODEV for all errors.
#   
#   Signed-off-by: Roger Luethi <rl@hellgate.ch>
# 
# drivers/net/via-rhine.c
#   2004/06/01 20:00:00-04:00 rl@hellgate.ch +15 -7
#   Return codes for rhine_init_one
# 
# ChangeSet
#   2004/06/02 15:37:34-04:00 rl@hellgate.ch 
#   [PATCH] Nuke all pci_flags
#   
#   All this code together can be replaced with a single #ifdef USE_MMIO.
#   
#   Signed-off-by: Roger Luethi <rl@hellgate.ch>
# 
# drivers/net/via-rhine.c
#   2004/06/01 20:00:00-04:00 rl@hellgate.ch +11 -20
#   Nuke all pci_flags
# 
# ChangeSet
#   2004/06/02 15:37:26-04:00 rl@hellgate.ch 
#   [PATCH] Nuke default_port, references to if_port, medialock
#   
#   As is, code doesn't do anything useful.
#   
#   Signed-off-by: Roger Luethi <rl@hellgate.ch>
# 
# drivers/net/via-rhine.c
#   2004/06/01 20:00:00-04:00 rl@hellgate.ch +0 -10
#   Nuke default_port, references to if_port, medialock
# 
# ChangeSet
#   2004/06/02 15:37:18-04:00 rl@hellgate.ch 
#   [PATCH] Nuke HasESIPhy and related code
#   
#   This has been dead code forever.
#   
#   Signed-off-by: Roger Luethi <rl@hellgate.ch>
# 
# drivers/net/via-rhine.c
#   2004/06/01 20:00:00-04:00 rl@hellgate.ch +2 -3
#   Nuke HasESIPhy and related code
# 
# ChangeSet
#   2004/06/02 15:37:09-04:00 rl@hellgate.ch 
#   [PATCH] Nuke CanHaveMII and related code
#   
#   All Rhines can have a MII.
#   
#   Signed-off-by: Roger Luethi <rl@hellgate.ch>
# 
# drivers/net/via-rhine.c
#   2004/06/01 20:00:00-04:00 rl@hellgate.ch +26 -40
#   Nuke CanHaveMII and related code
# 
# ChangeSet
#   2004/06/02 15:37:01-04:00 rl@hellgate.ch 
#   [PATCH] Nuke HAS_IP_COPYSUM
#   
#   HAS_IP_COPYSUM has been utterly meaningless for a long time.
#   
#   Signed-off-by: Roger Luethi <rl@hellgate.ch>
# 
# drivers/net/via-rhine.c
#   2004/06/01 20:00:00-04:00 rl@hellgate.ch +0 -5
#   Nuke HAS_IP_COPYSUM
# 
# ChangeSet
#   2004/06/01 12:39:07-05:00 jejb@raven.il.steeleye.com 
#   Merge
# 
# drivers/scsi/sr_ioctl.c
#   2004/06/01 12:38:49-05:00 jejb@raven.il.steeleye.com +0 -0
#   SCCS merged
# 
# drivers/scsi/sg.c
#   2004/06/01 12:36:37-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/scsi_devinfo.c
#   2004/06/01 12:36:37-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/constants.c
#   2004/06/01 12:36:36-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/29 10:47:12-05:00 akpm@osdl.org 
#   [PATCH] remove calls of obsolete scsi APIs in i2o_scsi
#   
#   From: Markus Lidel <Markus.Lidel@shadowconnect.com>
#   
#   Here is a patch from Christoph Hellwig, which removes calls of the obsolete
#   scsi API in i2o_scsi.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/message/i2o/i2o_scsi.c
#   2004/05/28 11:21:05-05:00 akpm@osdl.org +34 -57
#   remove calls of obsolete scsi APIs in i2o_scsi
# 
# ChangeSet
#   2004/05/29 10:44:40-05:00 Markus.Lidel@shadowconnect.com 
#   [PATCH] get I2O working with Adaptec's zero channel
#   
#   this patch now gets the mentioned controllers working with the I2O
#   subsystem. It tested on two different system with ASR-2005S and
#   ASR-2010S and reported as working.
#   
#   It's also tested on i686 and x86_64 with already working I2O controllers
#   without a problem.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/linux/i2o.h
#   2004/05/24 18:53:22-05:00 Markus.Lidel@shadowconnect.com +9 -5
#   get I2O working with Adaptec's zero channel
# 
# drivers/message/i2o/i2o_scsi.c
#   2004/05/24 18:56:46-05:00 Markus.Lidel@shadowconnect.com +3 -3
#   get I2O working with Adaptec's zero channel
# 
# drivers/message/i2o/i2o_core.c
#   2004/05/24 19:07:35-05:00 Markus.Lidel@shadowconnect.com +104 -55
#   get I2O working with Adaptec's zero channel
# 
# drivers/message/i2o/i2o_config.c
#   2004/05/24 16:57:44-05:00 Markus.Lidel@shadowconnect.com +1 -1
#   get I2O working with Adaptec's zero channel
# 
# drivers/message/i2o/i2o_block.c
#   2004/05/24 18:56:06-05:00 Markus.Lidel@shadowconnect.com +4 -4
#   get I2O working with Adaptec's zero channel
# 
# ChangeSet
#   2004/05/29 10:40:12-05:00 brking@us.ibm.com 
#   [PATCH] ipr operational timeout oops
#   
#   This patch fixes an oops that can occur if an adapter times
#   out coming operational.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ipr.h
#   2004/05/26 22:30:13-05:00 brking@us.ibm.com +2 -2
#   ipr operational timeout oops
# 
# drivers/scsi/ipr.c
#   2004/05/26 17:22:36-05:00 brking@us.ibm.com +1 -0
#   ipr operational timeout oops
# 
# ChangeSet
#   2004/05/29 10:37:41-05:00 g.liakhovetski@gmx.de 
#   [PATCH] tmscsim: convert to slave_...
#   
#   On Wed, 26 May 2004, Christoph Hellwig wrote:
#   > Looks like a way to go.  I'm not sure what scan_device is supposed to
#   > do as I already wrote, but from looking at when it's set/cleared I'm
#   > pretty sure it tries to indicate whethere we're currently scanning for
#   > devices.  And useing slave_alloc/slave_configure is a much safer way to
#   > find that out then guessing from the commands sent.
#   
#   Attached is a patch, that moves scan_device to
#   slave_alloc/_configure/_destroy, as you suggested (to be precise, as I
#   understood your suggestion:-))
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/tmscsim.h
#   2004/05/27 17:52:39-05:00 g.liakhovetski@gmx.de +0 -2
#   tmscsim: convert to slave_...
# 
# drivers/scsi/tmscsim.c
#   2004/05/27 17:57:12-05:00 g.liakhovetski@gmx.de +19 -14
#   tmscsim: convert to slave_...
# 
# drivers/scsi/scsiiom.c
#   2004/05/27 17:32:23-05:00 g.liakhovetski@gmx.de +21 -41
#   tmscsim: convert to slave_...
# 
# drivers/scsi/dc390.h
#   2004/05/27 17:57:23-05:00 g.liakhovetski@gmx.de +1 -13
#   tmscsim: convert to slave_...
# 
# ChangeSet
#   2004/05/29 10:33:13-05:00 akpm@osdl.org 
#   [PATCH] unchecked kmalloc in sr_audio_ioctl()
#   
#   From: "Luiz Fernando N. Capitulino" <lcapitulino@prefeitura.sp.gov.br>
#   
#   
#   Signed-off-by:  Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sr_ioctl.c
#   2004/05/26 11:03:15-05:00 akpm@osdl.org +3 -0
#   unchecked kmalloc in sr_audio_ioctl()
# 
# ChangeSet
#   2004/05/29 10:31:04-05:00 g.liakhovetski@gmx.de 
#   [PATCH] tmscsim: remove DeviceCnt
#   
#   On Wed, 26 May 2004, Christoph Hellwig wrote:
#   > On Sun, May 23, 2004 at 11:19:58PM +0200, Guennadi Liakhovetski wrote:
#   > >
#   > > Whereas, DCBCnt is incremented on slave_alloc, decremented on
#   > > slave_destroy and used in a couple more places. So, is it safe to assume
#   > > that DeviceCnt is redundant and remove it in a next patch?... Then it
#   > > might be already safe to move scan_devices as you suggest?
#   >
#   > Looks like a way to go.  I'm not sure what scan_device is supposed to
#   > do as I already wrote, but from looking at when it's set/cleared I'm
#   > pretty sure it tries to indicate whethere we're currently scanning for
#   > devices.  And useing slave_alloc/slave_configure is a much safer way to
#   > find that out then guessing from the commands sent.
#   
#   So, here's the first one - remove DeviceCnt.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/tmscsim.h
#   2004/05/26 15:23:14-05:00 g.liakhovetski@gmx.de +2 -9
#   tmscsim: remove DeviceCnt
# 
# drivers/scsi/tmscsim.c
#   2004/05/26 15:24:01-05:00 g.liakhovetski@gmx.de +1 -2
#   tmscsim: remove DeviceCnt
# 
# drivers/scsi/scsiiom.c
#   2004/05/26 15:23:32-05:00 g.liakhovetski@gmx.de +0 -2
#   tmscsim: remove DeviceCnt
# 
# ChangeSet
#   2004/05/29 10:28:07-05:00 g.liakhovetski@gmx.de 
#   [PATCH] tmscsim: Update version after "new API"
#   
#   The "API-update" patch, just approved by Christoph deserves a new version.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/tmscsim.c
#   2004/05/26 15:16:10-05:00 g.liakhovetski@gmx.de +2 -0
#   tmscsim: Update version after "new API"
# 
# drivers/scsi/dc390.h
#   2004/05/26 15:16:08-05:00 g.liakhovetski@gmx.de +1 -1
#   tmscsim: Update version after "new API"
# 
# ChangeSet
#   2004/05/29 10:24:44-05:00 davej@redhat.com 
#   [PATCH] SCSI: Correct BELKIN card reader whitelist entry.
#   
#   Should be FORCELUN not SPARSELUN ?
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_devinfo.c
#   2004/05/26 08:13:42-05:00 davej@redhat.com +1 -1
#   SCSI: Correct BELKIN card reader whitelist entry.
# 
# ChangeSet
#   2004/05/29 10:22:47-05:00 davej@redhat.com 
#   [PATCH] SCSI: more whitelist updates for usb card readers
#   
#   ATech 9-in-1 card reader.
#   Cbox 3 5 1/2 bay with 6in1 card reader
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_devinfo.c
#   2004/05/26 07:44:43-05:00 davej@redhat.com +3 -0
#   SCSI: more whitelist updates for usb card readers
# 
# ChangeSet
#   2004/05/29 10:20:15-05:00 akpm@osdl.org 
#   [PATCH] Stop megaraid trashing other i960 based devices
#   
#   From: Alan Cox <alan@redhat.com>
#   
#   In 2.4 the megaraid driver was careful to avoid stepping on wrong devices.
#   Specifically the megaraid3 series devices used an intel pci ID (8086:1960)
#   which is the generic i960 identifier not their own.
#   
#   The code to do this in 2.4 worked for almost all cases, but even that code has
#   mysteriously vanished in 2.6 meaning the megaraid driver trashes stuff like
#   promise i2o cards and compaq management cards.
#   
#   The following patch puts back the 2.4 stuff + one additional check so that the
#   driver isn't quite as rude as it was before.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/megaraid.c
#   2004/05/22 20:59:10-05:00 akpm@osdl.org +20 -0
#   Stop megaraid trashing other i960 based devices
# 
# ChangeSet
#   2004/05/29 10:17:42-05:00 lcapitulino@prefeitura.sp.gov.br 
#   [PATCH] qla1280.c warning fix.
#   
#   drivers/scsi/qla1280.c:3124: warning: `qla1280_64bit_start_scsi' defined but not used
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2004/04/13 12:56:24-05:00 lcapitulino@prefeitura.sp.gov.br +2 -2
#   qla1280.c warning fix.
# 
# ChangeSet
#   2004/05/29 10:13:11-05:00 michaelc@cs.wisc.edu 
#   [PATCH] SCSI: remove extra queue unplug calls
#   
#   blk_insert_request will do the right thing and either unplug the queue or
#   call the request_fn, so users of scsi_do_req do not need to call
#   generic_unplug_device themselves. The attached patch just removes that
#   call from scsi_lib.c and the sg driver after they do a scsi_do_req.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sg.c
#   2004/05/24 20:59:40-05:00 michaelc@cs.wisc.edu +0 -1
#   SCSI: remove extra queue unplug calls
# 
# drivers/scsi/scsi_lib.c
#   2004/05/24 20:59:39-05:00 michaelc@cs.wisc.edu +0 -1
#   SCSI: remove extra queue unplug calls
# 
# ChangeSet
#   2004/05/29 10:11:11-05:00 jejb@mulgrave.(none) 
#   MPT Fusion driver 3.01.07 update
#   
#   From: "Moore, Eric Dean" <Emoore@lsil.com>
#   
#   Clean up backword compatibility with 2.4 kernel and older. Patch
#   provided by Christoph Hellwig<hch@lst.de,hch@infradead.org>
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/message/fusion/mptscsih.h
#   2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +0 -71
#   MPT Fusion driver 3.01.07 update
# 
# drivers/message/fusion/mptscsih.c
#   2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +36 -37
#   MPT Fusion driver 3.01.07 update
# 
# drivers/message/fusion/mptlan.c
#   2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +3 -16
#   MPT Fusion driver 3.01.07 update
# 
# drivers/message/fusion/mptctl.c
#   2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +2 -66
#   MPT Fusion driver 3.01.07 update
# 
# drivers/message/fusion/mptbase.h
#   2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +7 -3
#   MPT Fusion driver 3.01.07 update
# 
# drivers/message/fusion/mptbase.c
#   2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +10 -8
#   MPT Fusion driver 3.01.07 update
# 
# drivers/message/fusion/linux_compat.h
#   2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +0 -189
#   MPT Fusion driver 3.01.07 update
# 
# drivers/message/fusion/isense.c
#   2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +0 -8
#   MPT Fusion driver 3.01.07 update
# 
# ChangeSet
#   2004/05/29 10:06:35-05:00 davej@redhat.com 
#   [PATCH] USB / SCSI multi-card reader whitelist updates.
#   
#   For more info see Red Hat bugzilla entries #85851 and #124048
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_devinfo.c
#   2004/05/04 11:44:37-05:00 davej@redhat.com +2 -0
#   USB / SCSI multi-card reader whitelist updates.
# 
# ChangeSet
#   2004/05/29 10:04:10-05:00 brking@us.ibm.com 
#   [PATCH] ipr driver version 2.0.8
#   
#   Bump driver version
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ipr.h
#   2004/05/23 21:48:22-05:00 brking@us.ibm.com +2 -2
#   ipr driver version 2.0.8
# 
# ChangeSet
#   2004/05/29 10:01:45-05:00 brking@us.ibm.com 
#   [PATCH] ipr duplicate ioa reset fix
#   
#   This patch closes a window where if a device had a cancel all
#   outstanding as a result of a check condition and the adapter
#   was reset for some reason, a request sense would still be issued,
#   which would end up timing out and issuing an additional adapter
#   reset. It could also result in a leak of command blocks, depending
#   on when it timed out.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ipr.c
#   2004/05/23 21:43:47-05:00 brking@us.ibm.com +6 -0
#   ipr duplicate ioa reset fix
# 
# ChangeSet
#   2004/05/29 09:59:59-05:00 brking@us.ibm.com 
#   [PATCH] ipr scsi busy io hang
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ipr.c
#   2004/05/23 21:40:15-05:00 brking@us.ibm.com +5 -1
#   ipr scsi busy io hang
# 
# ChangeSet
#   2004/05/29 09:59:10-05:00 jejb@mulgrave.(none) 
#   Convert tmcscsim to new probing interfaces
#   
#   From: 	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
#   
#   Update the driver to use the new pci, scsi and
#   module interfaces.
#   
#   Modified with feedback from hch
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/tmscsim.c
#   2004/05/29 09:58:54-05:00 jejb@mulgrave.(none) +151 -98
#   Convert tmcscsim to new probing interfaces
# 
# drivers/scsi/scsiiom.c
#   2004/05/29 09:58:54-05:00 jejb@mulgrave.(none) +12 -26
#   Convert tmcscsim to new probing interfaces
# 
# drivers/scsi/dc390.h
#   2004/05/29 09:58:54-05:00 jejb@mulgrave.(none) +0 -1
#   Convert tmcscsim to new probing interfaces
# 
# ChangeSet
#   2004/05/29 09:55:10-05:00 jejb@mulgrave.(none) 
#   SCSI: slave_detach -> slave_destory comment fix
#   
#   From: 	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_host.h
#   2004/05/29 09:54:55-05:00 jejb@mulgrave.(none) +2 -2
#   SCSI: slave_detach -> slave_destory comment fix
# 
# ChangeSet
#   2004/05/29 09:48:47-05:00 hch@lst.de 
#   [PATCH] move scsi debugging helpers and give them sane names
#   
#    - give the constants.c prettyprinting helpers proper scsi_ prefixed
#      names (and keep compat versions for 2.6.x)
#    - move them to include/scsi/scsi_dbg.h so now really only legacy stuff
#      is left in drivers/scsi/scsi.h
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_syms.c
#   2004/05/19 12:46:14-05:00 hch@lst.de +6 -6
#   move scsi debugging helpers and give them sane names
# 
# drivers/scsi/scsi.h
#   2004/05/19 12:46:14-05:00 hch@lst.de +42 -15
#   move scsi debugging helpers and give them sane names
# 
# drivers/scsi/constants.c
#   2004/05/19 12:46:14-05:00 hch@lst.de +11 -11
#   move scsi debugging helpers and give them sane names
# 
# include/scsi/scsi_dbg.h
#   2004/05/13 03:45:25-05:00 hch@lst.de +18 -0
#   move scsi debugging helpers and give them sane names
# 
# include/scsi/scsi_dbg.h
#   2004/05/13 03:45:25-05:00 hch@lst.de +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/include/scsi/scsi_dbg.h
# 
# ChangeSet
#   2004/05/27 15:21:03-04:00 herbert@gondor.apana.org.au 
#   [NETDRV #2] Use driver-specific name for resources
#   
#   Here is the next part which uses a driver-specific name instead of
#   dev->name for resource allocations prior to netdev registration.
#   It also changes printks that are in direct response to errors in
#   resource allocations.
# 
# drivers/net/zorro8390.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/yellowfin.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/wd.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/sunhme.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/sungem.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/sun3_82586.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/stnic.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/starfire.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/smc9194.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/smc-ultra32.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/smc-ultra.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/smc-mca.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/r8169.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/oaknet.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ns83820.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ni52.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ne3210.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +6 -4
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ne2k_cbus.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ne2.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ne.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ne-h8300.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/natsemi.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/lp486e.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/lne390.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/jazzsonic.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ibmlana.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/hp.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/hp-plus.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/forcedeth.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/fmv18x.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ewrk3.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/eth16i.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -4
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/eepro.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/e2100.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/defxx.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/cs89x0.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/at1700.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/apne.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/acenic.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/ac3200.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/82596.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/3c527.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/3c523.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/3c507.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/3c503.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# drivers/net/3c501.c
#   2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1
#   2/x: [NETDRV] Use driver-specific name for resources
# 
# ChangeSet
#   2004/05/27 15:20:53-04:00 herbert@gondor.apana.org.au 
#   [NETDRV #1] Ifdef builtin-only probe in ISA/MCA drivers
#   
#   Here is the bit which conditionalises the
#   builtin-only probe functions.
# 
# drivers/net/wd.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/smc-ultra.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/ne2k_cbus.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/ne2.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/ne.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/ne-h8300.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/lne390.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/lance.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/isa-skeleton.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/hp100.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/hp.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/hp-plus.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/ewrk3.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/eth16i.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/es3210.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/eexpress.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/eepro.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/e2100.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/cs89x0.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +1 -1
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/ac3200.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/3c523.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/3c505.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -1
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# drivers/net/3c503.c
#   2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0
#   1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers
# 
# ChangeSet
#   2004/05/27 13:38:57-04:00 rl@hellgate.ch 
#   [PATCH] Nuke HAS_IP_COPYSUM for net drivers
#   
#   Entirely untested, but Obviously Correct(TM). HAS_IP_COPYSUM has been
#   utterly meaningless for a long time.
# 
# drivers/net/yellowfin.c
#   2004/05/25 14:46:47-04:00 rl@hellgate.ch +0 -5
#   Nuke HAS_IP_COPYSUM for net drivers
# 
# drivers/net/tulip/winbond-840.c
#   2004/05/25 14:46:26-04:00 rl@hellgate.ch +0 -6
#   Nuke HAS_IP_COPYSUM for net drivers
# 
# drivers/net/natsemi.c
#   2004/05/25 14:51:58-04:00 rl@hellgate.ch +0 -5
#   Nuke HAS_IP_COPYSUM for net drivers
# 
# drivers/net/epic100.c
#   2004/05/25 14:45:55-04:00 rl@hellgate.ch +0 -5
#   Nuke HAS_IP_COPYSUM for net drivers
# 
# ChangeSet
#   2004/05/25 01:32:47-04:00 len.brown@intel.com 
#   [ACPI] PCI IRQ update (Bjorn Helgaas)
#   http://bugme.osdl.org/show_bug.cgi?id=2574
#   
#   mp_parse_prt() and iosapic_parse_prt() used to allocate all
#   IRQs, whether devices needed them or not.  Some devices
#   failed because the this method enabled unused PCI Interrupt
#   Link Devices, which disrupted active link devices.
#   
#   Now the PRT knowledge is pulled out of the arch
#   code and the IRQ allocation and IO-APIC programming
#   is done by pci_enable_device().
#   This is also a step toward allowing the addition
#   of new root bridges and PRTs at run-time.
#   
#   The architecture supplies
#   
#    unsigned int
#    acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
#   
#   which is called by acpi_pci_irq_enable().  ACPI supplies
#   all the information from the PRT, and the arch sets up
#   the routing and returns the IRQ it allocated.
# 
# include/linux/acpi.h
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +1 -1
#   PCI IRQ update (Bjorn Helgaas)
# 
# include/asm-x86_64/mpspec.h
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +1 -1
#   PCI IRQ update (Bjorn Helgaas)
# 
# include/asm-ia64/iosapic.h
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +0 -1
#   PCI IRQ update (Bjorn Helgaas)
# 
# include/asm-i386/mpspec.h
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +1 -1
#   PCI IRQ update (Bjorn Helgaas)
# 
# include/acpi/acpi_drivers.h
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +1 -1
#   PCI IRQ update (Bjorn Helgaas)
# 
# drivers/serial/8250_hcdp.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +4 -8
#   PCI IRQ update (Bjorn Helgaas)
# 
# drivers/serial/8250_acpi.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +6 -16
#   PCI IRQ update (Bjorn Helgaas)
# 
# drivers/acpi/tables.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +3 -3
#   PCI IRQ update (Bjorn Helgaas)
# 
# drivers/acpi/pci_link.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +2 -2
#   PCI IRQ update (Bjorn Helgaas)
# 
# drivers/acpi/pci_irq.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +36 -83
#   PCI IRQ update (Bjorn Helgaas)
# 
# arch/x86_64/kernel/mpparse.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +39 -76
#   PCI IRQ update (Bjorn Helgaas)
# 
# arch/ia64/pci/pci.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +12 -4
#   PCI IRQ update (Bjorn Helgaas)
# 
# arch/ia64/kernel/iosapic.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +80 -129
#   PCI IRQ update (Bjorn Helgaas)
# 
# arch/ia64/kernel/acpi.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +8 -15
#   PCI IRQ update (Bjorn Helgaas)
# 
# arch/i386/pci/acpi.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +23 -8
#   PCI IRQ update (Bjorn Helgaas)
# 
# arch/i386/kernel/mpparse.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +38 -78
#   PCI IRQ update (Bjorn Helgaas)
# 
# arch/i386/kernel/acpi/boot.c
#   2004/05/25 01:32:34-04:00 len.brown@intel.com +28 -0
#   PCI IRQ update (Bjorn Helgaas)
# 
# ChangeSet
#   2004/05/22 23:32:21-04:00 len.brown@intel.com 
#   Kconfig typo fix from Jochen Voss
# 
# drivers/acpi/Kconfig
#   2004/04/05 06:54:30-04:00 len.brown@intel.com +1 -1
#   Kconfig typo fix from Jochen Voss
# 
diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	2004-06-23 19:04:27 -07:00
+++ b/CREDITS	2004-06-23 19:04:27 -07:00
@@ -2267,8 +2267,8 @@
 N: Eberhard Moenkeberg
 E: emoenke@gwdg.de
 D: CDROM driver "sbpcd" (Matsushita/Panasonic/Soundblaster)
-S: Reinholdstrasse 14
-S: D-37083 Goettingen
+S: Ruhstrathoehe 2 b.
+S: D-37085 Goettingen
 S: Germany
 
 N: Thomas Molina
@@ -2571,6 +2571,14 @@
 D: sonypi, meye drivers, mct_u232 usb serial hacks
 S: Paris, France
 
+N: Matt Porter
+E: mporter@kernel.crashing.org
+D: Motorola PowerPC PReP support
+D: cPCI PowerPC support
+D: Embedded PowerPC 4xx/6xx/7xx/74xx support
+S: Chandler, Arizona 85249
+S: USA
+
 N: Frederic Potter 
 E: fpotter@cirpack.com
 D: Some PCI kernel support
@@ -3109,12 +3117,13 @@
 S: USA
 
 N: Marcelo W. Tosatti
-E: marcelo@conectiva.com.br
-W: http://bazar.conectiva.com.br/~marcelo/
-D: Miscellaneous kernel hacker (mostly VM/MM work)
-S: Conectiva S.A.
-S: R. Tocantins, 89 - Cristo Rei
-S: 80050-430 - Curitiba - Paraná
+E: marcelo.tosatti@cyclades.com
+D: Miscellaneous kernel hacker
+D: v2.4 kernel maintainer
+D: Current pc300/cyclades maintainer
+S: Cyclades Corporation
+S: Av Cristovao Colombo, 462. Floresta.
+S: Porto Alegre
 S: Brazil
 
 N: Stefan Traby
diff -Nru a/Documentation/arm/Sharp-LH/SDRAM b/Documentation/arm/Sharp-LH/SDRAM
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/arm/Sharp-LH/SDRAM	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,51 @@
+README on the SDRAM Controller for the LH7a40X
+==============================================
+
+The standard configuration for the SDRAM controller generates a sparse
+memory array.  The precise layout is determined by the SDRAM chips.  A
+default kernel configuration assembles the discontiguous memory
+regions into separate memory nodes via the NUMA (Non-Uniform Memory
+Architecture) facilities.  In this default configuration, the kernel
+is forgiving about the precise layout.  As long as it is given an
+accurate picture of available memory by the bootloader the kernel will
+execute correctly.
+
+The SDRC supports a mode where some of the chip select lines are
+swapped in order to make SDRAM look like a synchronous ROM.  Setting
+this bit means that the RAM will present as a contiguous array.  Some
+programmers prefer this to the discontiguous layout.  Be aware that
+may be a penalty for this feature where some some configurations of
+memory are significantly reduced; i.e. 64MiB of RAM appears as only 32
+MiB.
+
+There are a couple of configuration options to override the default
+behavior.  When the SROMLL bit is set and memory appears as a
+contiguous array, there is no reason to support NUMA.
+CONFIG_LH7A40X_CONTIGMEM disables NUMA support.  When physical memory
+is discontiguous, the memory tables are organized such that there are
+two banks per nodes with a small gap between them.  This layout wastes
+some kernel memory for page tables representing non-existent memory.
+CONFIG_LH7A40X_ONE_BANK_PER_NODE optimizes the node tables such that
+there are no gaps.  These options control the low level organization
+of the memory management tables in ways that may prevent the kernel
+from booting or may cause the kernel to allocated excessively large
+page tables.  Be warned.  Only change these options if you know what
+you are doing.  The default behavior is a reasonable compromise that
+will suit all users.
+
+--
+
+A typical 32MiB system with the default configuration options will
+find physical memory managed as follows.
+
+   node 0: 0xc0000000 4MiB
+           0xc1000000 4MiB
+   node 1: 0xc4000000 4MiB
+           0xc5000000 4MiB
+   node 2: 0xc8000000 4MiB
+           0xc9000000 4MiB
+   node 3: 0xcc000000 4MiB
+           0xcd000000 4MiB
+
+Setting CONFIG_LH7A40X_ONE_BANK_PER_NODE will put each bank into a
+separate node.
diff -Nru a/Documentation/arm/VFP/release-notes.txt b/Documentation/arm/VFP/release-notes.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/arm/VFP/release-notes.txt	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,55 @@
+Release notes for Linux Kernel VFP support code
+-----------------------------------------------
+
+Date: 	20 May 2004
+Author:	Russell King
+
+This is the first release of the Linux Kernel VFP support code.  It
+provides support for the exceptions bounced from VFP hardware found
+on ARM926EJ-S.
+
+This release has been validated against the SoftFloat-2b library by
+John R. Hauser using the TestFloat-2a test suite.  Details of this
+library and test suite can be found at:
+
+   http://www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html
+
+The operations which have been tested with this package are:
+
+ - fdiv
+ - fsub
+ - fadd
+ - fmul
+ - fcmp
+ - fcmpe
+ - fcvtd
+ - fcvts
+ - fsito
+ - ftosi
+ - fsqrt
+
+All the above pass softfloat tests with the following exceptions:
+
+- fadd/fsub shows some differences in the handling of +0 / -0 results
+  when input operands differ in signs.
+- the handling of underflow exceptions is slightly different.  If a
+  result underflows before rounding, but becomes a normalised number
+  after rounding, we do not signal an underflow exception.
+
+Other operations which have been tested by basic assembly-only tests
+are:
+
+ - fcpy
+ - fabs
+ - fneg
+ - ftoui
+ - ftosiz
+ - ftouiz
+
+The combination operations have not been tested:
+
+ - fmac
+ - fnmac
+ - fmsc
+ - fnmsc
+ - fnmul
diff -Nru a/Documentation/as-iosched.txt b/Documentation/as-iosched.txt
--- a/Documentation/as-iosched.txt	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,165 +0,0 @@
-Anticipatory IO scheduler
--------------------------
-Nick Piggin <piggin@cyberone.com.au>    13 Sep 2003
-
-Attention! Database servers, especially those using "TCQ" disks should
-investigate performance with the 'deadline' IO scheduler. Any system with high
-disk performance requirements should do so, in fact.
-
-If you see unusual performance characteristics of your disk systems, or you
-see big performance regressions versus the deadline scheduler, please email
-me. Database users don't bother unless you're willing to test a lot of patches
-from me ;) its a known issue.
-
-Also, users with hardware RAID controllers, doing striping, may find
-highly variable performance results with using the as-iosched. The
-as-iosched anticipatory implementation is based on the notion that a disk
-device has only one physical seeking head.  A striped RAID controller
-actually has a head for each physical device in the logical RAID device.
-
-However, setting the antic_expire (see tunable parameters below) produces
-very similar behavior to the deadline IO scheduler.
-
-
-Selecting IO schedulers
------------------------
-To choose IO schedulers at boot time, use the argument 'elevator=deadline'.
-'noop' and 'as' (the default) are also available. IO schedulers are assigned
-globally at boot time only presently.
-
-
-Anticipatory IO scheduler Policies
-----------------------------------
-The as-iosched implementation implements several layers of policies
-to determine when an IO request is dispatched to the disk controller.
-Here are the policies outlined, in order of application.
-
-1. one-way Elevator algorithm.
-
-The elevator algorithm is similar to that used in deadline scheduler, with
-the addition that it allows limited backward movement of the elevator
-(i.e. seeks backwards).  A seek backwards can occur when choosing between
-two IO requests where one is behind the elevator's current position, and
-the other is in front of the elevator's position. If the seek distance to
-the request in back of the elevator is less than half the seek distance to
-the request in front of the elevator, then the request in back can be chosen.
-Backward seeks are also limited to a maximum of MAXBACK (1024*1024) sectors.
-This favors forward movement of the elevator, while allowing opportunistic
-"short" backward seeks.
-
-2. FIFO expiration times for reads and for writes.
-
-This is again very similar to the deadline IO scheduler.  The expiration
-times for requests on these lists is tunable using the parameters read_expire
-and write_expire discussed below.  When a read or a write expires in this way,
-the IO scheduler will interrupt its current elevator sweep or read anticipation
-to service the expired request.
-
-3. Read and write request batching
-
-A batch is a collection of read requests or a collection of write
-requests.  The as scheduler alternates dispatching read and write batches
-to the driver.  In the case a read batch, the scheduler submits read
-requests to the driver as long as there are read requests to submit, and
-the read batch time limit has not been exceeded (read_batch_expire).
-The read batch time limit begins counting down only when there are
-competing write requests pending.
-
-In the case of a write batch, the scheduler submits write requests to
-the driver as long as there are write requests available, and the
-write batch time limit has not been exceeded (write_batch_expire).
-However, the length of write batches will be gradually shortened
-when read batches frequently exceed their time limit.
-
-When changing between batch types, the scheduler waits for all requests
-from the previous batch to complete before scheduling requests for the
-next batch.
-
-The read and write fifo expiration times described in policy 2 above
-are checked only when in scheduling IO of a batch for the corresponding
-(read/write) type.  So for example, the read FIFO timeout values are
-tested only during read batches.  Likewise, the write FIFO timeout
-values are tested only during write batches.  For this reason,
-it is generally not recommended for the read batch time
-to be longer than the write expiration time, nor for the write batch
-time to exceed the read expiration time (see tunable parameters below).
-
-When the IO scheduler changes from a read to a write batch,
-it begins the elevator from the request that is on the head of the
-write expiration FIFO.  Likewise, when changing from a write batch to
-a read batch, scheduler begins the elevator from the first entry
-on the read expiration FIFO.
-
-4. Read anticipation.
-
-Read anticipation occurs only when scheduling a read batch.
-This implementation of read anticipation allows only one read request
-to be dispatched to the disk controller at a time.  In
-contrast, many write requests may be dispatched to the disk controller
-at a time during a write batch.  It is this characteristic that can make
-the anticipatory scheduler perform anomalously with controllers supporting
-TCQ, or with hardware striped RAID devices. Setting the antic_expire
-queue paramter (see below) to zero disables this behavior, and the anticipatory
-scheduler behaves essentially like the deadline scheduler.
-
-When read anticipation is enabled (antic_expire is not zero), reads
-are dispatched to the disk controller one at a time.
-At the end of each read request, the IO scheduler examines its next
-candidate read request from its sorted read list.  If that next request
-is from the same process as the request that just completed,
-or if the next request in the queue is "very close" to the
-just completed request, it is dispatched immediately.  Otherwise,
-statistics (average think time, average seek distance) on the process
-that submitted the just completed request are examined.  If it seems
-likely that that process will submit another request soon, and that
-request is likely to be near the just completed request, then the IO
-scheduler will stop dispatching more read requests for up time (antic_expire)
-milliseconds, hoping that process will submit a new request near the one
-that just completed.  If such a request is made, then it is dispatched
-immediately.  If the antic_expire wait time expires, then the IO scheduler
-will dispatch the next read request from the sorted read queue.
-
-To decide whether an anticipatory wait is worthwhile, the scheduler
-maintains statistics for each process that can be used to compute
-mean "think time" (the time between read requests), and mean seek
-distance for that process.  One observation is that these statistics
-are associated with each process, but those statistics are not associated
-with a specific IO device.  So for example, if a process is doing IO
-on several file systems on separate devices, the statistics will be
-a combination of IO behavior from all those devices.
-
-
-Tuning the anticipatory IO scheduler
-------------------------------------
-When using 'as', the anticipatory IO scheduler there are 5 parameters under
-/sys/block/*/iosched/. All are units of milliseconds.
-
-The parameters are:
-* read_expire
-    Controls how long until a read request becomes "expired". It also controls the
-    interval between which expired requests are served, so set to 50, a request
-    might take anywhere < 100ms to be serviced _if_ it is the next on the
-    expired list. Obviously request expiration strategies won't make the disk
-    go faster. The result basically equates to the timeslice a single reader
-    gets in the presence of other IO. 100*((seek time / read_expire) + 1) is
-    very roughly the % streaming read efficiency your disk should get with
-    multiple readers.
-
-* read_batch_expire
-    Controls how much time a batch of reads is given before pending writes are
-    served. A higher value is more efficient. This might be set below read_expire
-    if writes are to be given higher priority than reads, but reads are to be
-    as efficient as possible when there are no writes. Generally though, it
-    should be some multiple of read_expire.
-   
-* write_expire, and
-* write_batch_expire are equivalent to the above, for writes.
-
-* antic_expire
-    Controls the maximum amount of time we can anticipate a good read (one
-    with a short seek distance from the most recently completed request) before
-    giving up. Many other factors may cause anticipation to be stopped early,
-    or some processes will not be "anticipated" at all. Should be a bit higher
-    for big seek time devices though not a linear correspondence - most
-    processes have only a few ms thinktime.
-
diff -Nru a/Documentation/binfmt_misc.txt b/Documentation/binfmt_misc.txt
--- a/Documentation/binfmt_misc.txt	2004-06-23 19:04:29 -07:00
+++ b/Documentation/binfmt_misc.txt	2004-06-23 19:04:29 -07:00
@@ -15,7 +15,7 @@
 	mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc 
 
 To actually register a new binary type, you have to set up a string looking like
-:name:type:offset:magic:mask:interpreter: (where you can choose the ':' upon
+:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':' upon
 your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
 Here is what the fields mean:
  - 'name' is an identifier string. A new /proc file will be created with this
@@ -34,6 +34,28 @@
    The mask is anded with the byte sequence of the file.
  - 'interpreter' is the program that should be invoked with the binary as first
    argument (specify the full path)
+ - 'flags' is an optional field that controls several aspects of the invocation
+   of the interpreter. It is a string of capital letters, each controls a certain
+   aspect. The following flags are supported -
+      'P' - preserve-argv[0].  Legacy behavior of binfmt_misc is to overwrite the
+            original argv[0] with the full path to the binary.  When this flag is
+            included, binfmt_misc will add an argument to the argument vector for
+            this purpose, thus preserving the original argv[0].
+      'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path
+            of the binary to the interpreter as an argument. When this flag is
+            included, binfmt_misc will open the file for reading and pass its
+            descriptor as an argument, instead of the full path, thus allowing
+            the interpreter to execute non-readable binaries. This feature should
+            be used with care - the interpreter has to be trusted not to emit
+            the contents of the non-readable binary.
+      'C' - credentials. Currently, the behavior of binfmt_misc is to calculate
+            the credentials and security token of the new process according to
+            the interpreter. When this flag is included, these attributes are
+            calculated according to the binary. It also implies the 'O' flag.
+            This feature should be used with care as the interpreter
+            will run with root permissions when a setuid binary owned by root
+            is run with binfmt_misc.
+
 
 There are some restrictions:
  - the whole register string may not exceed 255 characters
@@ -83,9 +105,9 @@
 write a wrapper script for it. See Documentation/java.txt for an
 example.
 
-Your interpreter should NOT look in the PATH for the filename; the
-kernel passes it the full filename to use.  Using the PATH can cause
-unexpected behaviour and be a security hazard.
+Your interpreter should NOT look in the PATH for the filename; the kernel
+passes it the full filename (or the file descriptor) to use.  Using $PATH can
+cause unexpected behaviour and can be a security hazard.
 
 
 There is a web page about binfmt_misc at
diff -Nru a/Documentation/block/as-iosched.txt b/Documentation/block/as-iosched.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/block/as-iosched.txt	2004-06-23 19:04:26 -07:00
@@ -0,0 +1,165 @@
+Anticipatory IO scheduler
+-------------------------
+Nick Piggin <piggin@cyberone.com.au>    13 Sep 2003
+
+Attention! Database servers, especially those using "TCQ" disks should
+investigate performance with the 'deadline' IO scheduler. Any system with high
+disk performance requirements should do so, in fact.
+
+If you see unusual performance characteristics of your disk systems, or you
+see big performance regressions versus the deadline scheduler, please email
+me. Database users don't bother unless you're willing to test a lot of patches
+from me ;) its a known issue.
+
+Also, users with hardware RAID controllers, doing striping, may find
+highly variable performance results with using the as-iosched. The
+as-iosched anticipatory implementation is based on the notion that a disk
+device has only one physical seeking head.  A striped RAID controller
+actually has a head for each physical device in the logical RAID device.
+
+However, setting the antic_expire (see tunable parameters below) produces
+very similar behavior to the deadline IO scheduler.
+
+
+Selecting IO schedulers
+-----------------------
+To choose IO schedulers at boot time, use the argument 'elevator=deadline'.
+'noop' and 'as' (the default) are also available. IO schedulers are assigned
+globally at boot time only presently.
+
+
+Anticipatory IO scheduler Policies
+----------------------------------
+The as-iosched implementation implements several layers of policies
+to determine when an IO request is dispatched to the disk controller.
+Here are the policies outlined, in order of application.
+
+1. one-way Elevator algorithm.
+
+The elevator algorithm is similar to that used in deadline scheduler, with
+the addition that it allows limited backward movement of the elevator
+(i.e. seeks backwards).  A seek backwards can occur when choosing between
+two IO requests where one is behind the elevator's current position, and
+the other is in front of the elevator's position. If the seek distance to
+the request in back of the elevator is less than half the seek distance to
+the request in front of the elevator, then the request in back can be chosen.
+Backward seeks are also limited to a maximum of MAXBACK (1024*1024) sectors.
+This favors forward movement of the elevator, while allowing opportunistic
+"short" backward seeks.
+
+2. FIFO expiration times for reads and for writes.
+
+This is again very similar to the deadline IO scheduler.  The expiration
+times for requests on these lists is tunable using the parameters read_expire
+and write_expire discussed below.  When a read or a write expires in this way,
+the IO scheduler will interrupt its current elevator sweep or read anticipation
+to service the expired request.
+
+3. Read and write request batching
+
+A batch is a collection of read requests or a collection of write
+requests.  The as scheduler alternates dispatching read and write batches
+to the driver.  In the case a read batch, the scheduler submits read
+requests to the driver as long as there are read requests to submit, and
+the read batch time limit has not been exceeded (read_batch_expire).
+The read batch time limit begins counting down only when there are
+competing write requests pending.
+
+In the case of a write batch, the scheduler submits write requests to
+the driver as long as there are write requests available, and the
+write batch time limit has not been exceeded (write_batch_expire).
+However, the length of write batches will be gradually shortened
+when read batches frequently exceed their time limit.
+
+When changing between batch types, the scheduler waits for all requests
+from the previous batch to complete before scheduling requests for the
+next batch.
+
+The read and write fifo expiration times described in policy 2 above
+are checked only when in scheduling IO of a batch for the corresponding
+(read/write) type.  So for example, the read FIFO timeout values are
+tested only during read batches.  Likewise, the write FIFO timeout
+values are tested only during write batches.  For this reason,
+it is generally not recommended for the read batch time
+to be longer than the write expiration time, nor for the write batch
+time to exceed the read expiration time (see tunable parameters below).
+
+When the IO scheduler changes from a read to a write batch,
+it begins the elevator from the request that is on the head of the
+write expiration FIFO.  Likewise, when changing from a write batch to
+a read batch, scheduler begins the elevator from the first entry
+on the read expiration FIFO.
+
+4. Read anticipation.
+
+Read anticipation occurs only when scheduling a read batch.
+This implementation of read anticipation allows only one read request
+to be dispatched to the disk controller at a time.  In
+contrast, many write requests may be dispatched to the disk controller
+at a time during a write batch.  It is this characteristic that can make
+the anticipatory scheduler perform anomalously with controllers supporting
+TCQ, or with hardware striped RAID devices. Setting the antic_expire
+queue paramter (see below) to zero disables this behavior, and the anticipatory
+scheduler behaves essentially like the deadline scheduler.
+
+When read anticipation is enabled (antic_expire is not zero), reads
+are dispatched to the disk controller one at a time.
+At the end of each read request, the IO scheduler examines its next
+candidate read request from its sorted read list.  If that next request
+is from the same process as the request that just completed,
+or if the next request in the queue is "very close" to the
+just completed request, it is dispatched immediately.  Otherwise,
+statistics (average think time, average seek distance) on the process
+that submitted the just completed request are examined.  If it seems
+likely that that process will submit another request soon, and that
+request is likely to be near the just completed request, then the IO
+scheduler will stop dispatching more read requests for up time (antic_expire)
+milliseconds, hoping that process will submit a new request near the one
+that just completed.  If such a request is made, then it is dispatched
+immediately.  If the antic_expire wait time expires, then the IO scheduler
+will dispatch the next read request from the sorted read queue.
+
+To decide whether an anticipatory wait is worthwhile, the scheduler
+maintains statistics for each process that can be used to compute
+mean "think time" (the time between read requests), and mean seek
+distance for that process.  One observation is that these statistics
+are associated with each process, but those statistics are not associated
+with a specific IO device.  So for example, if a process is doing IO
+on several file systems on separate devices, the statistics will be
+a combination of IO behavior from all those devices.
+
+
+Tuning the anticipatory IO scheduler
+------------------------------------
+When using 'as', the anticipatory IO scheduler there are 5 parameters under
+/sys/block/*/iosched/. All are units of milliseconds.
+
+The parameters are:
+* read_expire
+    Controls how long until a read request becomes "expired". It also controls the
+    interval between which expired requests are served, so set to 50, a request
+    might take anywhere < 100ms to be serviced _if_ it is the next on the
+    expired list. Obviously request expiration strategies won't make the disk
+    go faster. The result basically equates to the timeslice a single reader
+    gets in the presence of other IO. 100*((seek time / read_expire) + 1) is
+    very roughly the % streaming read efficiency your disk should get with
+    multiple readers.
+
+* read_batch_expire
+    Controls how much time a batch of reads is given before pending writes are
+    served. A higher value is more efficient. This might be set below read_expire
+    if writes are to be given higher priority than reads, but reads are to be
+    as efficient as possible when there are no writes. Generally though, it
+    should be some multiple of read_expire.
+
+* write_expire, and
+* write_batch_expire are equivalent to the above, for writes.
+
+* antic_expire
+    Controls the maximum amount of time we can anticipate a good read (one
+    with a short seek distance from the most recently completed request) before
+    giving up. Many other factors may cause anticipation to be stopped early,
+    or some processes will not be "anticipated" at all. Should be a bit higher
+    for big seek time devices though not a linear correspondence - most
+    processes have only a few ms thinktime.
+
diff -Nru a/Documentation/block/deadline-iosched.txt b/Documentation/block/deadline-iosched.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/block/deadline-iosched.txt	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,78 @@
+Deadline IO scheduler tunables
+==============================
+
+This little file attempts to document how the deadline io scheduler works.
+In particular, it will clarify the meaning of the exposed tunables that may be
+of interest to power users.
+
+Each io queue has a set of io scheduler tunables associated with it. These
+tunables control how the io scheduler works. You can find these entries
+in:
+
+/sys/block/<device>/iosched
+
+assuming that you have sysfs mounted on /sys. If you don't have sysfs mounted,
+you can do so by typing:
+
+# mount none /sys -t sysfs
+
+
+********************************************************************************
+
+
+read_expire	(in ms)
+-----------
+
+The goal of the deadline io scheduler is to attempt to guarentee a start
+service time for a request. As we focus mainly on read latencies, this is
+tunable. When a read request first enters the io scheduler, it is assigned
+a deadline that is the current time + the read_expire value in units of
+miliseconds.
+
+
+write_expire	(in ms)
+-----------
+
+Similar to read_expire mentioned above, but for writes.
+
+
+fifo_batch
+----------
+
+When a read request expires its deadline, we must move some requests from
+the sorted io scheduler list to the block device dispatch queue. fifo_batch
+controls how many requests we move, based on the cost of each request. A
+request is either qualified as a seek or a stream. The io scheduler knows
+the last request that was serviced by the drive (or will be serviced right
+before this one). See seek_cost and stream_unit.
+
+
+write_starved	(number of dispatches)
+-------------
+
+When we have to move requests from the io scheduler queue to the block
+device dispatch queue, we always give a preference to reads. However, we
+don't want to starve writes indefinitely either. So writes_starved controls
+how many times we give preference to reads over writes. When that has been
+done writes_starved number of times, we dispatch some writes based on the
+same criteria as reads.
+
+
+front_merges	(bool)
+------------
+
+Sometimes it happens that a request enters the io scheduler that is contigious
+with a request that is already on the queue. Either it fits in the back of that
+request, or it fits at the front. That is called either a back merge candidate
+or a front merge candidate. Due to the way files are typically laid out,
+back merges are much more common than front merges. For some work loads, you
+may even know that it is a waste of time to spend any time attempting to
+front merge requests. Setting front_merges to 0 disables this functionality.
+Front merges may still occur due to the cached last_merge hint, but since
+that comes at basically 0 cost we leave that on. We simply disable the
+rbtree front sector lookup when the io scheduler merge function is called.
+
+
+Nov 11 2002, Jens Axboe <axboe@suse.de>
+
+
diff -Nru a/Documentation/device-mapper/dm-io.txt b/Documentation/device-mapper/dm-io.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/device-mapper/dm-io.txt	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,75 @@
+dm-io
+=====
+
+Dm-io provides synchronous and asynchronous I/O services. There are three
+types of I/O services available, and each type has a sync and an async
+version.
+
+The user must set up an io_region structure to describe the desired location
+of the I/O. Each io_region indicates a block-device along with the starting
+sector and size of the region.
+
+   struct io_region {
+      struct block_device *bdev;
+      sector_t sector;
+      sector_t count;
+   };
+
+Dm-io can read from one io_region or write to one or more io_regions. Writes
+to multiple regions are specified by an array of io_region structures.
+
+The first I/O service type takes a list of memory pages as the data buffer for
+the I/O, along with an offset into the first page.
+
+   struct page_list {
+      struct page_list *next;
+      struct page *page;
+   };
+
+   int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
+                  struct page_list *pl, unsigned int offset,
+                  unsigned long *error_bits);
+   int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
+                   struct page_list *pl, unsigned int offset,
+                   io_notify_fn fn, void *context);
+
+The second I/O service type takes an array of bio vectors as the data buffer
+for the I/O. This service can be handy if the caller has a pre-assembled bio,
+but wants to direct different portions of the bio to different devices.
+
+   int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where,
+                       int rw, struct bio_vec *bvec,
+                       unsigned long *error_bits);
+   int dm_io_async_bvec(unsigned int num_regions, struct io_region *where,
+                        int rw, struct bio_vec *bvec,
+                        io_notify_fn fn, void *context);
+
+The third I/O service type takes a pointer to a vmalloc'd memory buffer as the
+data buffer for the I/O. This service can be handy if the caller needs to do
+I/O to a large region but doesn't want to allocate a large number of individual
+memory pages.
+
+   int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
+                     void *data, unsigned long *error_bits);
+   int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
+                      void *data, io_notify_fn fn, void *context);
+
+Callers of the asynchronous I/O services must include the name of a completion
+callback routine and a pointer to some context data for the I/O.
+
+   typedef void (*io_notify_fn)(unsigned long error, void *context);
+
+The "error" parameter in this callback, as well as the "*error" parameter in
+all of the synchronous versions, is a bitset (instead of a simple error value).
+In the case of an write-I/O to multiple regions, this bitset allows dm-io to
+indicate success or failure on each individual region.
+
+Before using any of the dm-io services, the user should call dm_io_get()
+and specify the number of pages they expect to perform I/O on concurrently.
+Dm-io will attempt to resize its mempool to make sure enough pages are
+always available in order to avoid unnecessary waiting while performing I/O.
+
+When the user is finished using the dm-io services, they should call
+dm_io_put() and specify the same number of pages that were given on the
+dm_io_get() call.
+
diff -Nru a/Documentation/device-mapper/kcopyd.txt b/Documentation/device-mapper/kcopyd.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/device-mapper/kcopyd.txt	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,47 @@
+kcopyd
+======
+
+Kcopyd provides the ability to copy a range of sectors from one block-device
+to one or more other block-devices, with an asynchronous completion
+notification. It is used by dm-snapshot and dm-mirror.
+
+Users of kcopyd must first create a client and indicate how many memory pages
+to set aside for their copy jobs. This is done with a call to
+kcopyd_client_create().
+
+   int kcopyd_client_create(unsigned int num_pages,
+                            struct kcopyd_client **result);
+
+To start a copy job, the user must set up io_region structures to describe
+the source and destinations of the copy. Each io_region indicates a
+block-device along with the starting sector and size of the region. The source
+of the copy is given as one io_region structure, and the destinations of the
+copy are given as an array of io_region structures.
+
+   struct io_region {
+      struct block_device *bdev;
+      sector_t sector;
+      sector_t count;
+   };
+
+To start the copy, the user calls kcopyd_copy(), passing in the client
+pointer, pointers to the source and destination io_regions, the name of a
+completion callback routine, and a pointer to some context data for the copy.
+
+   int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+                   unsigned int num_dests, struct io_region *dests,
+                   unsigned int flags, kcopyd_notify_fn fn, void *context);
+
+   typedef void (*kcopyd_notify_fn)(int read_err, unsigned int write_err,
+				    void *context);
+
+When the copy completes, kcopyd will call the user's completion routine,
+passing back the user's context pointer. It will also indicate if a read or
+write error occurred during the copy.
+
+When a user is done with all their copy jobs, they should call
+kcopyd_client_destroy() to delete the kcopyd client, which will release the
+associated memory pages.
+
+   void kcopyd_client_destroy(struct kcopyd_client *kc);
+
diff -Nru a/Documentation/device-mapper/linear.txt b/Documentation/device-mapper/linear.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/device-mapper/linear.txt	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,61 @@
+dm-linear
+=========
+
+Device-Mapper's "linear" target maps a linear range of the Device-Mapper
+device onto a linear range of another device.  This is the basic building
+block of logical volume managers.
+
+Parameters: <dev path> <offset>
+    <dev path>: Full pathname to the underlying block-device, or a
+                "major:minor" device-number.
+    <offset>: Starting sector within the device.
+
+
+Example scripts
+===============
+[[
+#!/bin/sh
+# Create an identity mapping for a device
+echo "0 `blockdev --getsize $1` linear $1 0" | dmsetup create identity
+]]
+
+
+[[
+#!/bin/sh
+# Join 2 devices together
+size1=`blockdev --getsize $1`
+size2=`blockdev --getsize $2`
+echo "0 $size1 linear $1 0
+$size1 $size2 linear $2 0" | dmsetup create joined
+]]
+
+
+[[
+#!/usr/bin/perl -w
+# Split a device into 4M chunks and then join them together in reverse order.
+
+my $name = "reverse";
+my $extent_size = 4 * 1024 * 2;
+my $dev = $ARGV[0];
+my $table = "";
+my $count = 0;
+
+if (!defined($dev)) {
+        die("Please specify a device.\n");
+}
+
+my $dev_size = `blockdev --getsize $dev`;
+my $extents = int($dev_size / $extent_size) -
+              (($dev_size % $extent_size) ? 1 : 0);
+
+while ($extents > 0) {
+        my $this_start = $count * $extent_size;
+        $extents--;
+        $count++;
+        my $this_offset = $extents * $extent_size;
+
+        $table .= "$this_start $extent_size linear $dev $this_offset\n";
+}
+
+`echo \"$table\" | dmsetup create $name`;
+]]
diff -Nru a/Documentation/device-mapper/striped.txt b/Documentation/device-mapper/striped.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/device-mapper/striped.txt	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,58 @@
+dm-stripe
+=========
+
+Device-Mapper's "striped" target is used to create a striped (i.e. RAID-0)
+device across one or more underlying devices. Data is written in "chunks",
+with consecutive chunks rotating among the underlying devices. This can
+potentially provide improved I/O throughput by utilizing several physical
+devices in parallel.
+
+Parameters: <num devs> <chunk size> [<dev path> <offset>]+
+    <num devs>: Number of underlying devices.
+    <chunk size>: Size of each chunk of data. Must be a power-of-2 and at
+                  least as large as the system's PAGE_SIZE.
+    <dev path>: Full pathname to the underlying block-device, or a
+                "major:minor" device-number.
+    <offset>: Starting sector within the device.
+
+One or more underlying devices can be specified. The striped device size must
+be a multiple of the chunk size and a multiple of the number of underlying
+devices.
+
+
+Example scripts
+===============
+
+[[
+#!/usr/bin/perl -w
+# Create a striped device across any number of underlying devices. The device
+# will be called "stripe_dev" and have a chunk-size of 128k.
+
+my $chunk_size = 128 * 2;
+my $dev_name = "stripe_dev";
+my $num_devs = @ARGV;
+my @devs = @ARGV;
+my ($min_dev_size, $stripe_dev_size, $i);
+
+if (!$num_devs) {
+        die("Specify at least one device\n");
+}
+
+$min_dev_size = `blockdev --getsize $devs[0]`;
+for ($i = 1; $i < $num_devs; $i++) {
+        my $this_size = `blockdev --getsize $devs[$i]`;
+        $min_dev_size = ($min_dev_size < $this_size) ?
+                        $min_dev_size : $this_size;
+}
+
+$stripe_dev_size = $min_dev_size * $num_devs;
+$stripe_dev_size -= $stripe_dev_size % ($chunk_size * $num_devs);
+
+$table = "0 $stripe_dev_size striped $num_devs $chunk_size";
+for ($i = 0; $i < $num_devs; $i++) {
+        $table .= " $devs[$i] 0";
+}
+
+`echo $table | dmsetup create $dev_name`;
+]]
+
diff -Nru a/Documentation/device-mapper/zero.txt b/Documentation/device-mapper/zero.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/device-mapper/zero.txt	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,37 @@
+dm-zero
+=======
+
+Device-Mapper's "zero" target provides a block-device that always returns
+zero'd data on reads and silently drops writes. This is similar behavior to
+/dev/zero, but as a block-device instead of a character-device.
+
+Dm-zero has no target-specific parameters.
+
+One very interesting use of dm-zero is for creating "sparse" devices in
+conjunction with dm-snapshot. A sparse device reports a device-size larger
+than the amount of actual storage space available for that device. A user can
+write data anywhere within the sparse device and read it back like a normal
+device. Reads to previously unwritten areas will return a zero'd buffer. When
+enough data has been written to fill up the actual storage space, the sparse
+device is deactivated. This can be very useful for testing device and
+filesystem limitations.
+
+To create a sparse device, start by creating a dm-zero device that's the
+desired size of the sparse device. For this example, we'll assume a 10TB
+sparse device.
+
+TEN_TERABYTES=`expr 10 \* 1024 \* 1024 \* 1024 \* 2`   # 10 TB in sectors
+echo "0 $TEN_TERABYTES zero" | dmsetup create zero1
+
+Then create a snapshot of the zero device, using any available block-device as
+the COW device. The size of the COW device will determine the amount of real
+space available to the sparse device. For this example, we'll assume /dev/sdb1
+is an available 10GB partition.
+
+echo "0 $TEN_TERABYTES snapshot /dev/mapper/zero1 /dev/sdb1 p 128" | \
+   dmsetup create sparse1
+
+This will create a 10TB sparse device called /dev/mapper/sparse1 that has
+10GB of actual storage space available. If more than 10GB of data is written
+to this device, it will start returning I/O errors.
+
diff -Nru a/Documentation/devices.txt b/Documentation/devices.txt
--- a/Documentation/devices.txt	2004-06-23 19:04:26 -07:00
+++ b/Documentation/devices.txt	2004-06-23 19:04:26 -07:00
@@ -2377,16 +2377,16 @@
 		  1 = /dev/gpib1	Second GPIB bus
 		    ...
 
-160 block       Carmel 8-port SATA Disks on First Controller
-		  0 = /dev/carmel/0     SATA disk 0 whole disk
-		  1 = /dev/carmel/0p1   SATA disk 0 partition 1
+160 block       Promise SX8 8-port SATA Disks on First Controller
+		  0 = /dev/sx8/0     SATA disk 0 whole disk
+		  1 = /dev/sx8/0p1   SATA disk 0 partition 1
 		    ...
-		 31 = /dev/carmel/0p31  SATA disk 0 partition 31
+		 31 = /dev/sx8/0p31  SATA disk 0 partition 31
 
-		 32 = /dev/carmel/1     SATA disk 1 whole disk
-		 64 = /dev/carmel/2     SATA disk 2 whole disk
+		 32 = /dev/sx8/1     SATA disk 1 whole disk
+		 64 = /dev/sx8/2     SATA disk 2 whole disk
 		    ...
-		224 = /dev/carmel/7     SATA disk 7 whole disk
+		224 = /dev/sx8/7     SATA disk 7 whole disk
 
 		Partitions are handled in the same way as for IDE
 		disks (see major number 3) except that the limit on
@@ -2400,16 +2400,16 @@
 		 17 = /dev/irlpt1	Second IrLPT device
 		    ...
 
-161 block       Carmel 8-port SATA Disks on Second Controller
-		  0 = /dev/carmel/8     SATA disk 8 whole disk
-		  1 = /dev/carmel/8p1   SATA disk 8 partition 1
+161 block       Promise SX8 8-port SATA Disks on Second Controller
+		  0 = /dev/sx8/8     SATA disk 8 whole disk
+		  1 = /dev/sx8/8p1   SATA disk 8 partition 1
 		    ...
-		 31 = /dev/carmel/8p31  SATA disk 8 partition 31
+		 31 = /dev/sx8/8p31  SATA disk 8 partition 31
 
-		 32 = /dev/carmel/9     SATA disk 9 whole disk
-		 64 = /dev/carmel/10    SATA disk 10 whole disk
+		 32 = /dev/sx8/9     SATA disk 9 whole disk
+		 64 = /dev/sx8/10    SATA disk 10 whole disk
 		    ...
-		224 = /dev/carmel/15    SATA disk 15 whole disk
+		224 = /dev/sx8/15    SATA disk 15 whole disk
 
 		Partitions are handled in the same way as for IDE
 		disks (see major number 3) except that the limit on
diff -Nru a/Documentation/fb/sisfb.txt b/Documentation/fb/sisfb.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/fb/sisfb.txt	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,158 @@
+
+What is sisfb?
+==============
+
+sisfb is a framebuffer device driver for SiS (Silicon Integrated Systems)
+graphics chips. Supported are:
+
+- SiS 300 series: SiS 300/305, 540, 630(S), 730(S)
+- SiS 315 series: SiS 315/H/PRO, 55x, (M)65x, 740, (M)661(F/M)X, (M)741(GX)
+- SiS 330 series: SiS 330 ("Xabre"), (M)760
+
+
+Why do I need a framebuffer driver?
+===================================
+
+sisfb is eg. useful if you want a high-resolution text console. Besides that,
+sisfb is required to run DirectFB (which comes with an additional, dedicated
+driver for the 315 series).
+
+On the 300 series, sisfb on kernels older than 2.6.3 furthermore plays an
+important role in connection with DRM/DRI: Sisfb manages the memory heap
+used by DRM/DRI for 3D texture and other data. This memory management is
+required for using DRI/DRM.
+
+Kernels >= around 2.6.3 do not need sisfb any longer for DRI/DRM memory
+management. The SiS DRM driver has been updated and features a memory manager
+of its own (which will be used if sisfb is not compiled). So unless you want
+a graphical console, you don't need sisfb on kernels >=2.6.3.
+
+Sidenote: Since this seems to be a commonly made mistake: sisfb and vesafb
+cannot be active at the same time! Do only select one of them in your kernel
+configuration.
+
+
+How are parameters passed to sisfb?
+===================================
+
+Well, it depends: If compiled statically into the kernel, use lilo's append
+statement to add the parameters to the kernel command line. Please see lilo's
+(or GRUB's) documentation for more information. If sisfb is a kernel module,
+parameters are given with the modprobe (or insmod) command.
+
+Example for sisfb as part of the static kernel: Add the following line to your
+lilo.conf:
+
+     append="video=sisfb:mode:1024x768x16,mem:12288,rate:75"
+
+Example for sisfb as a module: Start sisfb by typing
+
+     modprobe sisfb mode=1024x768x16 rate=75 mem=12288
+
+A common mistake is that folks use a wrong parameter format when using the
+driver compiled into the kernel. Please note: If compiled into the kernel,
+the parameter format is video=sisfb:mode:none or video=sisfb:mode:1024x768x16
+(or whatever mode you want to use, alternatively using any other format
+described above or the vesa keyword instead of mode). If compiled as a module,
+the parameter format reads mode=none or mode=1024x768x16 (or whatever mode you
+want to use). Using a "=" for a ":" (and vice versa) is a huge difference!
+Additionally: If you give more than one argument to the in-kernel sisfb, the
+arguments are separated with ",". For example:
+
+   video=sisfb:mode:1024x768x16,rate:75,mem:12288
+
+
+How do I use it?
+================
+
+Preface statement: This file only covers very little of the driver's
+capabilities and features. Please refer to the author's and maintainer's
+website at http://www.winischhofer.net/linuxsisvga.shtml for more
+information. Additionally, "modinfo sisfb" gives an overview over all
+supported options including some explanation.
+
+The desired display mode can be specified using the keyword "mode" with
+a parameter in one of the follwing formats:
+  - XxYxDepth or
+  - XxY-Depth or
+  - XxY-Depth@Rate or
+  - XxY
+  - or simply use the VESA mode number in hexadecimal or decimal.
+
+For example: 1024x768x16, 1024x768-16@75, 1280x1024-16. If no depth is
+specified, it defaults to 8. If no rate is given, it defaults to 60Hz. Depth 32
+means 24bit color depth (but 32 bit framebuffer depth, which is not relevant
+to the user).
+
+Additionally, sisfb understands the keyword "vesa" followed by a VESA mode
+number in decimal or hexadecimal. For example: vesa=791 or vesa=0x117. Please
+use either "mode" or "vesa" but not both.
+
+Linux 2.4 only: If no mode is given, sisfb defaults to "no mode" (mode=none) if
+compiled as a module; if sisfb is statically compiled into the kernel, it
+defaults to 800x600x8 unless CRT2 type is LCD, in which case the LCD's native
+resolution is used. If you want to switch to a different mode, use the fbset
+shell command.
+
+Linux 2.6 only: If no mode is given, sisfb defaults to 800x600x8 unless CRT2
+type is LCD, in which case it defaults to the LCD's native resolution. If
+you want to switch to another mode, use the stty shell command.
+
+You should compile in both vgacon (to boot if you remove you SiS card from
+your system) and sisfb (for graphics mode). Under Linux 2.6, also "Framebuffer
+console support" (fbcon) is needed for a graphical console.
+
+You should *not* compile-in vesafb. And please do not use the "vga=" keyword
+in lilo's or grub's configuration file; mode selection is done using the
+"mode" or "vesa" keywords as a parameter. See above and below.
+
+
+X11
+===
+
+If using XFree86 or X.org, it is recommended that you don't use the "fbdev"
+driver but the dedicated "sis" X driver. The "sis" X driver and sisfb are
+developed by the same person (Thomas Winischhofer) and cooperate well with
+each other.
+
+
+SVGALib
+=======
+
+SVGALib, if directly accessing the hardware, never restores the screen
+correctly, especially on laptops or if the output devices are LCD or TV.
+Therefore, use the chipset "FBDEV" in SVGALib configuration. This will make
+SVGALib use the framebuffer device for mode switches and restoration.
+
+
+Configuration
+=============
+
+(Some) accepted options:
+
+off      - Disable sisfb. This option is only understood if sisfb is
+           in-kernel, not a module.
+mem:X    - size of memory for the console, rest will be used for DRI/DRM. X
+           is in kilobytes. On 300 series, the default is 4096, 8192 or
+	   16384 (each in kilobyte) depending on how much video ram the card
+           has. On 315/330 series, the default is the maximum available ram
+	   (since DRI/DRM is not supported for these chipsets).
+noaccel  - do not use 2D acceleration engine. (Default: use acceleration)
+noypan   - disable y-panning and scroll by redrawing the entire screen.
+           This is much slower than y-panning. (Default: use y-panning)
+vesa:X   - selects startup videomode. X is number from 0 to 0x1FF and
+           represents the VESA mode number (can be given in decimal or
+	   hexadecimal form, the latter prefixed with "0x").
+mode:X   - selects startup videomode. Please see above for the format of
+           "X".
+
+Boolean options such as "noaccel" or "noypan" are to be given without a
+parameter if sisfb is in-kernel (for example "video=sisfb:noypan). If
+sisfb is a module, these are to be set to 1 (for example "modprobe sisfb
+noypan=1").
+
+--
+Thomas Winischhofer <thomas@winischhofer.net>
+May 27, 2004
+
+
diff -Nru a/Documentation/filesystems/hpfs.txt b/Documentation/filesystems/hpfs.txt
--- a/Documentation/filesystems/hpfs.txt	2004-06-23 19:04:26 -07:00
+++ b/Documentation/filesystems/hpfs.txt	2004-06-23 19:04:26 -07:00
@@ -1,5 +1,5 @@
-Read/Write HPFS 2.05
-1998-2001, Mikulas Patocka
+Read/Write HPFS 2.09
+1998-2004, Mikulas Patocka
 
 email: mikulas@artax.karlin.mff.cuni.cz
 homepage: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
@@ -283,6 +283,14 @@
 2.05 Fixed crash when got mount parameters without =
      Fixed crash when allocation of anode failed due to full disk
      Fixed some crashes when block io or inode allocation failed
+2.06 Fixed some crash on corrupted disk structures
+     Better allocation strategy
+     Reschedule points added so that it doesn't lock CPU long time
+     It should work in read-only mode on Warp Server
+2.07 More fixes for Warp Server. Now it really works
+2.08 Creating new files is not so slow on large disks
+     An attempt to sync deleted file does not generate filesystem error
+2.09 Fixed error on extremly fragmented files
 
 
  vim: set textwidth=80:
diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
--- a/Documentation/filesystems/proc.txt	2004-06-23 19:04:26 -07:00
+++ b/Documentation/filesystems/proc.txt	2004-06-23 19:04:26 -07:00
@@ -201,7 +201,7 @@
  devices     Available devices (block and character)           
  dma         Used DMS channels                                 
  filesystems Supported filesystems                             
- driver	     Various drivers grouped here, currently rtc	(2.4)
+ driver	     Various drivers grouped here, currently rtc (2.4) and hpet (2.6)
  execdomains Execdomains, related to security			(2.4)
  fb	     Frame Buffer devices				(2.4)
  fs	     File system parameters, currently nfs/exports	(2.4)
@@ -1640,7 +1640,8 @@
 
 Writing to this file results in a flush of the routing cache.
 
-gc_elastic, gc_interval, gc_min_interval, gc_tresh, gc_timeout
+gc_elasticity, gc_interval, gc_min_interval, gc_tresh, gc_timeout,
+gc_thresh, gc_thresh1, gc_thresh2, gc_thresh3
 --------------------------------------------------------------
 
 Values to  control  the  frequency  and  behavior  of  the  garbage collection
diff -Nru a/Documentation/hpet.txt b/Documentation/hpet.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/hpet.txt	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,298 @@
+		High Precision Event Timer Driver for Linux
+
+The High Precision Event Timer (HPET) hardware is the future replacement for the 8254 and Real
+Time Clock (RTC) periodic timer functionality.  Each HPET can have up two 32 timers.  It is possible
+to configure the first two timers as legacy replacements for 8254 and RTC periodic.  A specification
+done by INTEL and Microsoft can be found at http://www.intel.com/labs/platcomp/hpet/hpetspec.htm.
+
+The driver supports detection of HPET driver allocation and initialization of the HPET before the
+driver module_init routine is called.  This enables platform code which uses timer 0 or 1 as the
+main timer to intercept HPET initialization.  An example of this initialization can be found in
+arch/i386/kernel/time_hpet.c.
+
+The driver provides two APIs which are very similar to the API found in the rtc.c driver.
+There is a user space API and a kernel space API.  An example user space program is provided
+below.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <memory.h>
+#include <malloc.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <linux/hpet.h>
+
+
+extern void hpet_open_close(int, const char **);
+extern void hpet_info(int, const char **);
+extern void hpet_poll(int, const char **);
+extern void hpet_fasync(int, const char **);
+extern void hpet_read(int, const char **);
+
+#include <sys/poll.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+struct hpet_command {
+	char		*command;
+	void		(*func)(int argc, const char ** argv);
+} hpet_command[] = {
+	{
+		"open-close",
+		hpet_open_close
+	},
+	{
+		"info",
+		hpet_info
+	},
+	{
+		"poll",
+		hpet_poll
+	},
+	{
+		"fasync",
+		hpet_fasync
+	},
+};
+
+int
+main(int argc, const char ** argv)
+{
+	int	i;
+
+	argc--;
+	argv++;
+
+	if (!argc) {
+		fprintf(stderr, "-hpet: requires command\n");
+		return -1;
+	}
+
+
+	for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
+		if (!strcmp(argv[0], hpet_command[i].command)) {
+			argc--;
+			argv++;
+			fprintf(stderr, "-hpet: executing %s\n",
+				hpet_command[i].command);
+			hpet_command[i].func(argc, argv);
+			return 0;
+		}
+
+	fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
+
+	return -1;
+}
+
+void
+hpet_open_close(int argc, const char **argv)
+{
+	int	fd;
+
+	if (argc != 1) {
+		fprintf(stderr, "hpet_open_close: device-name\n");
+		return;
+	}
+
+	fd = open(argv[0], O_RDWR);
+	if (fd < 0)
+		fprintf(stderr, "hpet_open_close: open failed\n");
+	else
+		close(fd);
+
+	return;
+}
+
+void
+hpet_info(int argc, const char **argv)
+{
+}
+
+void
+hpet_poll(int argc, const char **argv)
+{
+	unsigned long		freq;
+	int			iterations, i, fd;
+	struct pollfd		pfd;
+	struct hpet_info	info;
+	struct timeval		stv, etv;
+	struct timezone		tz;
+	long			usec;
+
+	if (argc != 3) {
+		fprintf(stderr, "hpet_poll: device-name freq iterations\n");
+		return;
+	}
+
+	freq = atoi(argv[1]);
+	iterations = atoi(argv[2]);
+
+	fd = open(argv[0], O_RDWR);
+
+	if (fd < 0) {
+		fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
+		return;
+	}
+
+	if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
+		fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
+		goto out;
+	}
+
+	if (ioctl(fd, HPET_INFO, &info) < 0) {
+		fprintf(stderr, "hpet_poll: failed to get info\n");
+		goto out;
+	}
+
+	fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
+
+	if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
+		fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
+		goto out;
+	}
+
+	if (ioctl(fd, HPET_IE_ON, 0) < 0) {
+		fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
+		goto out;
+	}
+
+	pfd.fd = fd;
+	pfd.events = POLLIN;
+
+	for (i = 0; i < iterations; i++) {
+		pfd.revents = 0;
+		gettimeofday(&stv, &tz);
+		if (poll(&pfd, 1, -1) < 0)
+			fprintf(stderr, "hpet_poll: poll failed\n");
+		else {
+			long 	data;
+
+			gettimeofday(&etv, &tz);
+			usec = stv.tv_sec * 1000000 + stv.tv_usec;
+			usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
+
+			fprintf(stderr,
+				"hpet_poll: expired time = 0x%lx\n", usec);
+
+			fprintf(stderr, "hpet_poll: revents = 0x%x\n",
+				pfd.revents);
+
+			if (read(fd, &data, sizeof(data)) != sizeof(data)) {
+				fprintf(stderr, "hpet_poll: read failed\n");
+			}
+			else
+				fprintf(stderr, "hpet_poll: data 0x%lx\n",
+					data);
+		}
+	}
+
+out:
+	close(fd);
+	return;
+}
+
+static int hpet_sigio_count;
+
+static void
+hpet_sigio(int val)
+{
+	fprintf(stderr, "hpet_sigio: called\n");
+	hpet_sigio_count++;
+}
+
+void
+hpet_fasync(int argc, const char **argv)
+{
+	unsigned long		freq;
+	int			iterations, i, fd, value;
+	sig_t			oldsig;
+	struct hpet_info	info;
+
+	hpet_sigio_count = 0;
+	fd = -1;
+
+	if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
+		fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
+		return;
+	}
+
+	if (argc != 3) {
+		fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
+		goto out;
+	}
+
+	fd = open(argv[0], O_RDWR);
+
+	if (fd < 0) {
+		fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
+		return;
+	}
+
+
+	if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
+		((value = fcntl(fd, F_GETFL)) == 1) ||
+		(fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
+		fprintf(stderr, "hpet_fasync: fcntl failed\n");
+		goto out;
+	}
+
+	freq = atoi(argv[1]);
+	iterations = atoi(argv[2]);
+
+	if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
+		fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
+		goto out;
+	}
+
+	if (ioctl(fd, HPET_INFO, &info) < 0) {
+		fprintf(stderr, "hpet_fasync: failed to get info\n");
+		goto out;
+	}
+
+	fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
+
+	if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
+		fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
+		goto out;
+	}
+
+	if (ioctl(fd, HPET_IE_ON, 0) < 0) {
+		fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
+		goto out;
+	}
+
+	for (i = 0; i < iterations; i++) {
+		(void) pause();
+		fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
+	}
+
+out:
+	signal(SIGIO, oldsig);
+
+	if (fd >= 0)
+		close(fd);
+
+	return;
+}
+
+The kernel API has three interfaces exported from the driver:
+
+	hpet_register(struct hpet_task *tp, int periodic)
+	hpet_unregister(struct hpet_task *tp)
+	hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
+
+The kernel module using this interface fills in the ht_func and ht_data members of the
+hpet_task structure before calling hpet_register.  hpet_control simply vectors to the hpet_ioctl
+routine and has the same commands and respective arguments as the user API.  hpet_unregister
+is used to terminate usage of the HPET timer reserved by hpet_register.
+
+
diff -Nru a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
--- a/Documentation/ioctl-number.txt	2004-06-23 19:04:28 -07:00
+++ b/Documentation/ioctl-number.txt	2004-06-23 19:04:28 -07:00
@@ -189,3 +189,5 @@
 					<mailto:michael.klein@puffin.lb.shuttle.de>
 0xDD	00-3F	ZFCP device driver	see drivers/s390/scsi/
 					<mailto:aherrman@de.ibm.com>
+0xF3	00-3F	video/sisfb.h		sisfb (in development)
+					<mailto:thomas@winischhofer.net>
diff -Nru a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
--- a/Documentation/networking/00-INDEX	2004-06-23 19:04:28 -07:00
+++ b/Documentation/networking/00-INDEX	2004-06-23 19:04:28 -07:00
@@ -4,8 +4,6 @@
 	- information on the 3Com EtherLink Plus (3c505) driver.
 6pack.txt
 	- info on the 6pack protocol, an alternative to KISS for AX.25
-8139too.txt
-	- info on the 8139too driver for RTL-8139 based network cards.
 Configurable
 	- info on some of the configurable network parameters
 DLINK.txt
diff -Nru a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
--- a/Documentation/networking/ip-sysctl.txt	2004-06-23 19:04:26 -07:00
+++ b/Documentation/networking/ip-sysctl.txt	2004-06-23 19:04:26 -07:00
@@ -17,6 +17,16 @@
 	Disable Path MTU Discovery.
 	default FALSE
 
+min_pmtu - INTEGER
+	default 562 - minimum discovered Path MTU
+
+mtu_expires - INTEGER
+	Time, in seconds, that cached PMTU information is kept.
+
+min_adv_mss - INTEGER
+	The advertised MSS depends on the first hop route MTU, but will
+	never be lower than this setting.
+
 IP Fragmentation:
 
 ipfrag_high_thresh - INTEGER
@@ -345,6 +355,20 @@
 	conections.
 	Default: 7
 
+
+tcp_frto - BOOLEAN
+	Enables F-RTO, an enhanced recovery algorithm for TCP retransmission
+	timeouts.  It is particularly beneficial in wireless environments
+	where packet loss is typically due to random radio interference
+	rather than intermediate router congestion.
+
+somaxconn - INTEGER
+	Limit of socket listen() backlog, known in userspace as SOMAXCONN.
+	Defaults to 128.  See also tcp_max_syn_backlog for additional tuning
+	for TCP sockets.
+
+IP Variables:
+
 ip_local_port_range - 2 INTEGERS
 	Defines the local port range that is used by TCP and UDP to
 	choose the local port. The first number is the first, the 
@@ -586,6 +610,19 @@
 	The max value from conf/{all,interface}/arp_ignore is used
 	when ARP request is received on the {interface}
 
+app_solicit - INTEGER
+	The maximum number of probes to send to the user space ARP daemon
+	via netlink before dropping back to multicast probes (see
+	mcast_solicit).  Defaults to 0.
+
+disable_policy - BOOLEAN
+	Disable IPSEC policy (SPD) for this interface
+
+disable_xfrm - BOOLEAN
+	Disable IPSEC encryption on this interface, whatever the policy
+
+
+
 tag - INTEGER
 	Allows you to write a number, which can be used as required.
 	Default value is 0.
@@ -678,9 +715,11 @@
 			    disabled if local forwarding is enabled.
 
 autoconf - BOOLEAN
-	Configure link-local addresses using L2 hardware addresses.
+	Autoconfigure addresses using Prefix Information in Router 
+	Advertisements.
 
-	Default: TRUE
+	Functional default: enabled if accept_ra is enabled.
+			    disabled if accept_ra is disabled.
 
 dad_transmits - INTEGER
 	The amount of Duplicate Address Detection probes to send.
@@ -803,5 +842,26 @@
 	0 : disable this.
 	Default: 1
 
+
+UNDOCUMENTED:
+
+dev_weight FIXME
+discovery_slots FIXME
+discovery_timeout FIXME
+fast_poll_increase FIXME
+ip6_queue_maxlen FIXME
+lap_keepalive_time FIXME
+lo_cong FIXME
+max_baud_rate FIXME
+max_dgram_qlen FIXME
+max_noreply_time FIXME
+max_tx_data_size FIXME
+max_tx_window FIXME
+min_tx_turn_time FIXME
+mod_cong FIXME
+no_cong FIXME
+no_cong_thresh FIXME
+slot_timeout FIXME
+warn_noreply_time FIXME
 
 $Id: ip-sysctl.txt,v 1.20 2001/12/13 09:00:18 davem Exp $
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2004-06-23 19:04:27 -07:00
+++ b/MAINTAINERS	2004-06-23 19:04:27 -07:00
@@ -90,6 +90,20 @@
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
+3W-XXXX ATA-RAID CONTROLLER DRIVER
+P:	Adam Radford
+M:	linuxraid@amcc.com
+L:	linux-scsi@vger.kernel.org
+W:	http://www.amcc.com
+S:	Supported
+
+3W-9XXX SATA-RAID CONTROLLER DRIVER
+P:	Adam Radford
+M:	linuxraid@amcc.com
+L:	linux-scsi@vger.kernel.org
+W:	http://www.amcc.com
+S:	Supported
+
 53C700 AND 53C700-66 SCSI DRIVER
 P:	James E.J. Bottomley
 M:	James.Bottomley@HansenPartnership.com
@@ -689,6 +703,12 @@
 L:	blinux-list@redhat.com
 S:	Maintained
 
+DRIVER CORE, KOBJECTS, AND SYSFS
+P:	Greg Kroah-Hartman
+M:	greg@kroah.com
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+
 DRM DRIVERS
 L:	dri-devel@lists.sourceforge.net
 S:	Supported
@@ -1249,6 +1269,13 @@
 M:	benh@kernel.crashing.org
 W:	http://www.linuxppc.org/
 L:	linuxppc-dev@lists.linuxppc.org
+S:	Maintained
+
+LINUX FOR POWERPC EMBEDDED PPC4XX
+P:	Matt Porter
+M:	mporter@kernel.crashing.org
+W:	http://www.penguinppc.org/
+L:	linuxppc-embedded@lists.linuxppc.org
 S:	Maintained
 
 LLC (802.2)
diff -Nru a/Makefile b/Makefile
--- a/Makefile	2004-06-23 19:04:27 -07:00
+++ b/Makefile	2004-06-23 19:04:27 -07:00
@@ -290,8 +290,6 @@
 OBJCOPY		= $(CROSS_COMPILE)objcopy
 OBJDUMP		= $(CROSS_COMPILE)objdump
 AWK		= awk
-RPM 		:= $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \
-		    	else echo rpm; fi)
 GENKSYMS	= scripts/genksyms/genksyms
 DEPMOD		= /sbin/depmod
 KALLSYMS	= scripts/kallsyms
@@ -409,13 +407,6 @@
 
 scripts_basic: include/linux/autoconf.h
 
-
-# That's our default target when none is given on the command line
-# Note that 'modules' will be added as a prerequisite as well, 
-# in the CONFIG_MODULES part below
-
-all:	vmlinux
-
 # Objects we will link into vmlinux / subdirs we need to visit
 init-y		:= init/
 drivers-y	:= drivers/ sound/
@@ -449,6 +440,19 @@
 
 include $(srctree)/arch/$(ARCH)/Makefile
 
+# Default kernel image to build when no specific target is given.
+# KBUILD_IMAGE may be overruled on the commandline or
+# set in the environment
+# Also any assingments in arch/$(ARCH)/Makefiel take precedence over
+# this default value
+export KBUILD_IMAGE ?= vmlinux
+
+# The all: target is the default when no target is given on the
+# command line.
+# This allow a user to issue only 'make' to build a kernel including modules
+# Defaults vmlinux but it is usually overriden in the arch makefile
+all: vmlinux
+
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 CFLAGS		+= -Os
 else
@@ -795,7 +799,7 @@
 
 # Directories & files removed with 'make clean'
 CLEAN_DIRS  += $(MODVERDIR)
-CLEAN_FILES +=	vmlinux System.map kernel.spec \
+CLEAN_FILES +=	vmlinux System.map \
                 .tmp_kallsyms* .tmp_version .tmp_vmlinux*
 
 # Directories & files removed with 'make mrproper'
@@ -848,37 +852,19 @@
 		-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
 		-type f -print | xargs rm -f
 
-# RPM target
-# ---------------------------------------------------------------------------
-
-.PHONY: rpm
 
-# Remove hyphens since they have special meaning in RPM filenames
-KERNELPATH=kernel-$(subst -,,$(KERNELRELEASE))
+# Packaging of the kernel to various formats
+# ---------------------------------------------------------------------------
+# rpm target kept for backward compatibility
+package-dir	:= $(srctree)/scripts/package
 
-#	If you do a make spec before packing the tarball you can rpm -ta it
+.PHONY: %-pkg rpm
 
-spec:
-	$(CONFIG_SHELL) $(srctree)/scripts/mkspec > $(objtree)/kernel.spec
-
-#	a) Build a tar ball
-#	b) generate an rpm from it
-#	c) and pack the result
-#	- Use /. to avoid tar packing just the symlink
-
-rpm:	clean spec
-	set -e; \
-	cd .. ; \
-	ln -sf $(srctree) $(KERNELPATH) ; \
-	tar -cvz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. ; \
-	rm $(KERNELPATH)
-
-	set -e; \
-	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version;\
-	mv -f $(objtree)/.tmp_version $(objtree)/.version;
+%pkg: FORCE
+	$(Q)$(MAKE) -f $(package-dir)/Makefile $@
+rpm: FORCE
+	$(Q)$(MAKE) -f $(package-dir)/Makefile $@
 
-	$(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz
-	rm ../$(KERNELPATH).tar.gz
 
 # Brief documentation of the typical targets used
 # ---------------------------------------------------------------------------
@@ -905,6 +891,8 @@
 	@echo  '  tags/TAGS	  - Generate tags file for editors'
 	@echo  '  cscope	  - Generate cscope index'
 	@echo  '  checkstack      - Generate a list of stack hogs'
+	@echo  'Kernel packaging:'
+	@$(MAKE) -f $(package-dir)/Makefile help
 	@echo  ''
 	@echo  'Documentation targets:'
 	@$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
diff -Nru a/arch/alpha/kernel/init_task.c b/arch/alpha/kernel/init_task.c
--- a/arch/alpha/kernel/init_task.c	2004-06-23 19:04:26 -07:00
+++ b/arch/alpha/kernel/init_task.c	2004-06-23 19:04:26 -07:00
@@ -4,6 +4,7 @@
 #include <linux/init.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
+#include <linux/mqueue.h>
 #include <asm/uaccess.h>
 
 
diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
--- a/arch/alpha/mm/numa.c	2004-06-23 19:04:25 -07:00
+++ b/arch/alpha/mm/numa.c	2004-06-23 19:04:25 -07:00
@@ -279,8 +279,8 @@
 				       initrd_end,
 				       phys_to_virt(PFN_PHYS(max_low_pfn)));
 		} else {
-			nid = NODE_DATA(kvaddr_to_nid(initrd_start));
-			reserve_bootmem_node(nid,
+			nid = kvaddr_to_nid(initrd_start);
+			reserve_bootmem_node(NODE_DATA(nid),
 					     virt_to_phys((void *)initrd_start),
 					     INITRD_SIZE);
 		}
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/Kconfig	2004-06-23 19:04:27 -07:00
@@ -72,9 +72,6 @@
 	prompt "ARM system type"
 	default ARCH_RPC
 
-config ARCH_ADIFCC
-	bool "ADIFCC-based"
-
 config ARCH_CLPS7500
 	bool "Cirrus-CL-PS7500FE"
 
@@ -191,6 +188,11 @@
 	depends on ARCH_RPC
 	default y
 
+config TIMER_ACORN
+	bool
+	depends on ARCH_ACORN || ARCH_CLPS7500
+	default y
+
 #####################################################################
 # Footbridge support
 config FOOTBRIDGE
@@ -246,10 +248,10 @@
 # Select various configuration options depending on the machine type
 config DISCONTIGMEM
 	bool
-	depends on ARCH_EDB7211 || ARCH_SA1100 || ARCH_LH7A40X
+	depends on ARCH_EDB7211 || ARCH_SA1100 || (ARCH_LH7A40X && !LH7A40X_SROMLL)
 	default y
 	help
-	  Say Y to upport efficient handling of discontiguous physical memory,
+	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)
 	  or have huge holes in the physical address space for other reasons.
 	  See <file:Documentation/vm/numa> for more.
@@ -257,7 +259,7 @@
 # Now handle the bus types
 config PCI
 	bool "PCI support" if ARCH_INTEGRATOR_AP
-	default y if ARCH_FTVPCI || ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX
+	default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -270,11 +272,6 @@
 	  doesn't.
 
 # Select the host bridge type
-config PCI_HOST_PLX90X0
-	bool
-	depends on PCI && ARCH_FTVPCI
-	default y
-
 config PCI_HOST_VIA82C505
 	bool
 	depends on PCI && ARCH_SHARK
@@ -421,6 +418,17 @@
 	  If you do not feel you need a faster FP emulation you should better
 	  choose NWFPE.
 
+config VFP
+	bool "VFP-format floating point maths"
+	help
+	  Say Y to include VFP support code in the kernel. This is needed
+	  if your hardware includes a VFP unit.
+
+	  Please see <file:Documentation/arm/VFP/release-notes.txt> for
+	  release notes and additional status information.
+
+	  Say N if your target does not have VFP hardware.
+
 source "fs/Kconfig.binfmt"
 
 source "drivers/base/Kconfig"
@@ -539,7 +547,7 @@
 
 config LEDS
 	bool "Timer and CPU usage LEDs"
-	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
+	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
 	help
 	  If you say Y here, the LEDs on your machine will be used
 	  to provide useful information about your current system status.
@@ -553,7 +561,7 @@
 
 config LEDS_TIMER
 	bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB)
-	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
+	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
 	default y if ARCH_EBSA110
 	help
 	  If you say Y here, one of the system LEDs (the green one on the
@@ -609,7 +617,7 @@
 
 source "net/Kconfig"
 
-if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_FTVPCI || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
+if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
 source "drivers/ide/Kconfig"
 endif
 
diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile
--- a/arch/arm/Makefile	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/Makefile	2004-06-23 19:04:26 -07:00
@@ -74,9 +74,6 @@
 textaddr-$(CONFIG_ARCH_CO285)	   := 0x60008000
  machine-$(CONFIG_ARCH_CO285)	   := footbridge
   incdir-$(CONFIG_ARCH_CO285)	   := ebsa285
- machine-$(CONFIG_ARCH_FTVPCI)	   := ftvpci
-  incdir-$(CONFIG_ARCH_FTVPCI)	   := nexuspci
- machine-$(CONFIG_ARCH_TBOX)	   := tbox
  machine-$(CONFIG_ARCH_SHARK)	   := shark
  machine-$(CONFIG_ARCH_SA1100)	   := sa1100
 ifeq ($(CONFIG_ARCH_SA1100),y)
@@ -91,7 +88,6 @@
  machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
 textaddr-$(CONFIG_ARCH_FORTUNET)   := 0xc0008000
  machine-$(CONFIG_ARCH_IOP3XX)	   := iop3xx
- machine-$(CONFIG_ARCH_ADIFCC)	   := adifcc
  machine-$(CONFIG_ARCH_IXP4XX)	   := ixp4xx
  machine-$(CONFIG_ARCH_OMAP)	   := omap
  machine-$(CONFIG_ARCH_S3C2410)	   := s3c2410
@@ -119,6 +115,7 @@
 endif
 core-$(CONFIG_FPE_NWFPE)	+= arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)	+= $(FASTFPE_OBJ)
+core-$(CONFIG_VFP)		+= arch/arm/vfp/
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
 drivers-$(CONFIG_ARCH_CLPS7500)	+= drivers/acorn/char/
diff -Nru a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
--- a/arch/arm/boot/Makefile	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/boot/Makefile	2004-06-23 19:04:25 -07:00
@@ -49,8 +49,6 @@
    zreladdr-$(CONFIG_ARCH_PXA)		:= 0xa0008000
    zreladdr-$(CONFIG_ARCH_IOP3XX)	:= 0xa0008000
 params_phys-$(CONFIG_ARCH_IOP3XX)	:= 0xa0000100
-   zreladdr-$(CONFIG_ARCH_ADIFCC)	:= 0xc0008000
-params_phys-$(CONFIG_ARCH_ADIFCC)	:= 0xc0000100
    zreladdr-$(CONFIG_ARCH_IXP4XX)	:= 0x00008000
 params-phys-$(CONFIG_ARCH_IXP4XX)	:= 0x00000100
    zreladdr-$(CONFIG_ARCH_OMAP)		:= 0x10008000
diff -Nru a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
--- a/arch/arm/boot/compressed/head-xscale.S	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/boot/compressed/head-xscale.S	2004-06-23 19:04:26 -07:00
@@ -66,7 +66,4 @@
 		mov	r7, #MACH_TYPE_IQ80310
 #endif
 
-#ifdef CONFIG_ARCH_ADI_EVB
-		mov	r7, #MACH_TYPE_ADI_EVB
-#endif
 
diff -Nru a/arch/arm/common/Makefile b/arch/arm/common/Makefile
--- a/arch/arm/common/Makefile	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/common/Makefile	2004-06-23 19:04:26 -07:00
@@ -6,6 +6,6 @@
 obj-$(CONFIG_ARM_AMBA)		+= amba.o
 obj-$(CONFIG_ICST525)		+= icst525.o
 obj-$(CONFIG_SA1111)		+= sa1111.o
-obj-$(CONFIG_PCI_HOST_PLX90X0)	+= plx90x0.o
 obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
 obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
+obj-$(CONFIG_TIMER_ACORN)	+= time-acorn.o
diff -Nru a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
--- a/arch/arm/common/dmabounce.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/common/dmabounce.c	2004-06-23 19:04:25 -07:00
@@ -234,7 +234,7 @@
 		}
 	}
 
-	dma_addr = virt_to_bus(ptr);
+	dma_addr = virt_to_dma(dev, ptr);
 
 	if (device_info && dma_needs_bounce(dev, dma_addr, size)) {
 		struct safe_buffer *buf;
@@ -248,7 +248,7 @@
 
 		dev_dbg(dev,
 			"%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
-			__func__, buf->ptr, (void *) virt_to_bus(buf->ptr),
+			__func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr),
 			buf->safe, (void *) buf->safe_dma_addr);
 
 		if ((dir == DMA_TO_DEVICE) ||
@@ -290,7 +290,7 @@
 
 		dev_dbg(dev,
 			"%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
-			__func__, buf->ptr, (void *) virt_to_bus(buf->ptr),
+			__func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr),
 			buf->safe, (void *) buf->safe_dma_addr);
 
 
@@ -342,7 +342,7 @@
 
 		dev_dbg(dev,
 			"%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
-			__func__, buf->ptr, (void *) virt_to_bus(buf->ptr),
+			__func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr),
 			buf->safe, (void *) buf->safe_dma_addr);
 
 		DO_STATS ( device_info->bounce_count++ );
@@ -367,7 +367,7 @@
 		}
 		consistent_sync(buf->safe, size, dir);
 	} else {
-		consistent_sync(bus_to_virt(dma_addr), size, dir);
+		consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
 	}
 }
 
diff -Nru a/arch/arm/common/plx90x0.c b/arch/arm/common/plx90x0.c
--- a/arch/arm/common/plx90x0.c	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,178 +0,0 @@
-/* 
- * Driver for PLX Technology PCI9000-series host bridge.
- *
- * Copyright (C) 1997, 1998, 1999, 2000 FutureTV Labs 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/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/ptrace.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-
-/*
- * Since the following functions are all very similar, the common parts
- * are pulled out into these macros.
- */
-
-#define PLX_CLEAR_CONFIG						\
-	__raw_writel(0, PLX_BASE + 0xac);				\
-	local_irq_restore(flags); }
-
-#define PLX_SET_CONFIG							\
-	{ unsigned long flags;						\
-	local_irq_save(flags);						\
-	__raw_writel((1<<31 | (bus->number << 16)			\
-		| (devfn << 8) | (where & ~3)				\
-		| ((bus->number == 0)?0:1)), PLX_BASE + 0xac);		\
-
-#define PLX_CONFIG_WRITE(size)						\
-	PLX_SET_CONFIG							\
-	__raw_write##size(value, PCIO_BASE + (where & 3));		\
-	if (__raw_readw(PLX_BASE + 0x6) & 0x2000)			\
-		__raw_writew(0x2000, PLX_BASE + 0x6);			\
-	PLX_CLEAR_CONFIG						\
-	return PCIBIOS_SUCCESSFUL;
-
-#define PLX_CONFIG_READ(size)						\
-	PLX_SET_CONFIG							\
-	*value = __raw_read##size(PCIO_BASE + (where & 3));		\
-	if (__raw_readw(PLX_BASE + 0x6) & 0x2000) {			\
-		__raw_writew(0x2000, PLX_BASE + 0x6);			\
-		*value = 0xffffffffUL;					\
-	}								\
-	PLX_CLEAR_CONFIG						\
-	return PCIBIOS_SUCCESSFUL;
-
-/* Configuration space access routines */
-
-static int 
-plx90x0_read_config (struct pci_bus *bus, unsigned int devfn, int where,
-		     int where, int size, u32 *value)
-{
-	switch (size) {
-	case 1:
-		PLX_CONFIG_READ(b)
-		break;
-	case 2:
-		PLX_CONFIG_READ(w)
-		break;
-	case 4:
-		PLX_CONFIG_READ(l)
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int 
-plx90x0_write_config (struct pci_bus *bus, unsigned int devfn, int where,
-		      int where, int size, u32 value)
-{
-	switch (size) {
-	case 1:
-		PLX_CONFIG_WRITE(b)
-		break;
-	case 2:
-		PLX_CONFIG_WRITE(w)
-		break;
-	case 4:
-		PLX_CONFIG_WRITE(l)
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops plx90x0_ops = 
-{
-	.read	= plx90x0_read_config,
-	.write	= plx90x0_write_config,
-};
-
-static void 
-plx_syserr_handler(int irq, void *handle, struct pt_regs *regs)
-{
-	printk("PLX90x0: machine check %04x (pc=%08lx)\n", 
-	       readw(PLX_BASE + 6), regs->ARM_pc);
-	__raw_writew(0xf000, PLX_BASE + 6);
-}
-
-/*
- * Initialise the PCI system.
- */
-
-void __init
-plx90x0_init(struct arm_sysdata *sysdata)
-{
-	static const unsigned long int base = PLX_BASE;
-	char *what;
-	unsigned long bar = (unsigned long)virt_to_bus((void *)PAGE_OFFSET);
-
-	/* Have a sniff around and see which PLX device is present. */
-	unsigned long id = __raw_readl(base + 0xf0);
-	
-#if 0
-	/* This check was a good idea, but can fail.  The PLX9060 puts no
-	   default value in these registers unless NB# is asserted (which it
-	   isn't on these cards).  */
-	if ((id & 0xffff) != PCI_VENDOR_ID_PLX)
-		return;		/* Nothing found */
-#endif
-
-	/* Found one - now work out what it is. */
-	switch (id >> 16) {
-	case 0:		/* PCI_DEVICE_ID_PLX_9060 */
-		what = "PCI9060";
-		break;
-	case PCI_DEVICE_ID_PLX_9060ES:
-		what = "PCI9060ES";
-		break;
-	case PCI_DEVICE_ID_PLX_9060SD:
-		what = "PCI9060SD";		/* uhuhh.. */
-		break;
-	case PCI_DEVICE_ID_PLX_9080:
-		what = "PCI9080";
-		break;
-	default:
-		printk("PCI: Unknown PLX device %04lx found -- ignored.\n",
-		       id >> 16);
-		return;
-	}
-	
-	printk("PCI: PLX Technology %s host bridge found.\n", what);
-	
-	/* Now set it up for both master and slave accesses. */
-	__raw_writel(0xffff0147,	base + 0x4);
-	__raw_writeb(32,		base + 0xd);
-	__raw_writel(0x8 | bar,		base + 0x18);
-	__raw_writel(0xf8000008,	base + 0x80);
-	__raw_writel(0x40000001,	base + 0x84);
-	__raw_writel(0,			base + 0x88);
-	__raw_writel(0,			base + 0x8c);
-	__raw_writel(0x11,		base + 0x94);
-	__raw_writel(0xC3 + (4 << 28)
-		+ (8 << 11) + (1 << 10)
-		     + (1 << 24),	base + 0x98);
-	__raw_writel(0xC0000000,	base + 0x9c);
-	__raw_writel(PLX_MEM_START,	base + 0xa0);
-	__raw_writel(PLX_IO_START,	base + 0xa4);
-	__raw_writel(0x3,		base + 0xa8);
-	__raw_writel(0,			base + 0xac);
-	__raw_writel(0x10001,		base + 0xe8);
-	__raw_writel(0x8000767e,	base + 0xec);
-	
-	request_irq(IRQ_SYSERR, plx_syserr_handler, 0, 
-		    "system error", NULL);
-
-	pci_scan_bus(0, &plx90x0_ops, sysdata);
-}
diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
--- a/arch/arm/common/sa1111.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/common/sa1111.c	2004-06-23 19:04:28 -07:00
@@ -610,7 +610,7 @@
  *	%-EBUSY		physical address already marked in-use.
  *	%0		successful.
  */
-static int __init
+static int
 __sa1111_probe(struct device *me, struct resource *mem, int irq)
 {
 	struct sa1111 *sachip;
diff -Nru a/arch/arm/common/time-acorn.c b/arch/arm/common/time-acorn.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/common/time-acorn.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,67 @@
+/*
+ *  linux/arch/arm/common/time-acorn.c
+ *
+ *  Copyright (c) 1996-2000 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
+ * published by the Free Software Foundation.
+ *
+ *  Changelog:
+ *   24-Sep-1996	RMK	Created
+ *   10-Oct-1996	RMK	Brought up to date with arch-sa110eval
+ *   04-Dec-1997	RMK	Updated for new arch/arm/time.c
+ *   13=Jun-2004	DS	Moved to arch/arm/common b/c shared w/CLPS7500
+ */
+#include <linux/timex.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/hardware/ioc.h>
+
+#include <asm/mach/time.h>
+
+static unsigned long ioctime_gettimeoffset(void)
+{
+	unsigned int count1, count2, status;
+	long offset;
+
+	ioc_writeb (0, IOC_T0LATCH);
+	barrier ();
+	count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
+	barrier ();
+	status = ioc_readb(IOC_IRQREQA);
+	barrier ();
+	ioc_writeb (0, IOC_T0LATCH);
+	barrier ();
+	count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
+
+	offset = count2;
+	if (count2 < count1) {
+		/*
+		 * We have not had an interrupt between reading count1
+		 * and count2.
+		 */
+		if (status & (1 << 5))
+			offset -= LATCH;
+	} else if (count2 > count1) {
+		/*
+		 * We have just had another interrupt between reading
+		 * count1 and count2.
+		 */
+		offset -= LATCH;
+	}
+
+	offset = (LATCH - offset) * (tick_nsec / 1000);
+	return (offset + LATCH/2) / LATCH;
+}
+
+void __init ioctime_init(void)
+{
+	ioc_writeb(LATCH & 255, IOC_T0LTCHL);
+	ioc_writeb(LATCH >> 8, IOC_T0LTCHH);
+	ioc_writeb(0, IOC_T0GO);
+
+	gettimeoffset = ioctime_gettimeoffset;
+}
diff -Nru a/arch/arm/configs/adi_evb_defconfig b/arch/arm/configs/adi_evb_defconfig
--- a/arch/arm/configs/adi_evb_defconfig	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,678 +0,0 @@
-#
-# Automatically generated by make menuconfig: don't edit
-#
-CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
-
-#
-# System Type
-#
-CONFIG_ARCH_ADIFCC=y
-# CONFIG_ARCH_ARCA5K is not set
-# 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_IOP310 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_SHARK is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-
-#
-# Footbridge Implementations
-#
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
-# CONFIG_ARCH_EBSA285_ADDIN is not set
-# CONFIG_ARCH_EBSA285_HOST is not set
-# CONFIG_ARCH_NETWINDER is not set
-
-#
-# SA11x0 Implementations
-#
-# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_CERF is not set
-# CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
-# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
-# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
-# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_SHERMAN is not set
-# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_USB is not set
-# CONFIG_SA1100_USB_NETLINK is not set
-# CONFIG_SA1100_USB_CHAR is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-# CONFIG_ARCH_CDB89712 is not set
-# CONFIG_ARCH_CLEP7312 is not set
-# CONFIG_ARCH_EDB7211 is not set
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-CONFIG_ARCH_ADI_EVB=y
-CONFIG_XSCALE_PMU_TIMER=y
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-# CONFIG_CPU_32v3 is not set
-# CONFIG_CPU_32v4 is not set
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
-# CONFIG_CPU_SA1100 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_XSCALE=y
-CONFIG_ARM_THUMB=y
-# CONFIG_XSCALE_TOOLS is not set
-CONFIG_XSCALE_WRITE_ALLOC=y
-CONFIG_XSCALE_PMU=y
-CONFIG_ARM_THUMB=y
-# CONFIG_DISCONTIGMEM is not set
-
-#
-# General setup
-#
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_FASTFPE is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/mtdblock1 mem=32M initrd=0xc0800000,3M"
-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_REDBOOT_PARTS is not set
-# CONFIG_MTD_BOOTLDR_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_NORA is not set
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_CDB89712 is not set
-# CONFIG_MTD_SA1100 is not set
-# CONFIG_MTD_DC21285 is not set
-# CONFIG_MTD_IQ80310 is not set
-CONFIG_MTD_ADI_EVB=y
-# CONFIG_MTD_PCI is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_DOC1000 is not set
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_PNPBIOS is not set
-
-#
-# 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_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-# 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
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK=y
-CONFIG_RTNETLINK=y
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
-# CONFIG_SUNLANCE is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNLANCE 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_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input core support
-#
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X is not set
-# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
-# CONFIG_SERIAL_UART00 is not set
-# CONFIG_SERIAL_UART00_CONSOLE is not set
-# CONFIG_SERIAL_SA1100 is not set
-# CONFIG_SERIAL_SA1100_CONSOLE is not set
-# CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_HUB6 is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# L3 serial bus support
-#
-# CONFIG_L3 is not set
-# CONFIG_L3_ALGOBIT is not set
-# CONFIG_L3_BIT_SA1100_GPIO is not set
-# CONFIG_L3_SA1111 is not set
-# CONFIG_BIT_SA1100_GPIO is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_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
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# File systems
-#
-# CONFIG_QUOTA is not set
-# 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_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_BFS_FS is not set
-# CONFIG_CMS_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=y
-CONFIG_JFFS2_FS_DEBUG=0
-# 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_FREEVXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG 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=y
-# 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
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_NFS_FS is not set
-# CONFIG_NFS_V3 is not set
-# CONFIG_ROOT_NFS is not set
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-# CONFIG_SUNRPC is not set
-# CONFIG_LOCKD is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE 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_SMB_NLS is not set
-# CONFIG_NLS is not set
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-# CONFIG_MCP_SA1100 is not set
-# CONFIG_MCP_UCB1200 is not set
-# CONFIG_MCP_UCB1200_AUDIO is not set
-# CONFIG_MCP_UCB1200_TS is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-# CONFIG_USB_OHCI is not set
-# CONFIG_USB_OHCI_SA1111 is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_USS720 is not set
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_SERIAL_GENERIC is not set
-# 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_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-# CONFIG_USB_SERIAL_VISOR is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_PL2303 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_RIO500 is not set
-# CONFIG_USB_ID75 is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_SLAB=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_NO_PGT_CACHE is not set
-CONFIG_DEBUG_LL=y
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
--- a/arch/arm/kernel/Makefile	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/kernel/Makefile	2004-06-23 19:04:28 -07:00
@@ -11,8 +11,7 @@
 		   time.o traps.o
 
 obj-$(CONFIG_APM)		+= apm.o
-obj-$(CONFIG_ARCH_ACORN)	+= ecard.o time-acorn.o
-obj-$(CONFIG_ARCH_CLPS7500)	+= time-acorn.o
+obj-$(CONFIG_ARCH_ACORN)	+= ecard.o 
 obj-$(CONFIG_FOOTBRIDGE)	+= isa.o
 obj-$(CONFIG_FIQ)		+= fiq.o
 obj-$(CONFIG_MODULES)		+= armksyms.o module.o
diff -Nru a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
--- a/arch/arm/kernel/debug.S	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/kernel/debug.S	2004-06-23 19:04:26 -07:00
@@ -439,32 +439,6 @@
 #endif
 		.endm
 
-#elif defined(CONFIG_ARCH_ADI_EVB)
-
-		.macro	addruart,rx
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		mov	\rx, #0x00400000	@ physical base address
-		orrne	\rx, \rx, #0xff000000	@ virtual base
-		.endm
-
-		.macro	senduart,rd,rx
-		strb	\rd, [\rx]
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldrb	\rd, [\rx, #0x5]
-		and	\rd, \rd, #0x60
-		teq	\rd, #0x60
-		bne	1002b
-		.endm
-
-		.macro	waituart,rd,rx
-1001:		ldrb	\rd, [\rx, #0x6]
-		tst	\rd, #0x10
-		beq	1001b
-		.endm
-
 #elif defined(CONFIG_ARCH_IXP4XX)
 
                 .macro  addruart,rx
@@ -591,7 +565,8 @@
 		.macro  addruart,rx
 		mrc     p15, 0, \rx, c1, c0
 		tst     \rx, #1                 @ MMU enabled?
-		ldr     \rx, =0x80000700        @ physical base address
+		mov     \rx, #0x00000700        @ offset from base
+		orreq   \rx, \rx, #0x80000000   @ physical base
 		orrne   \rx, \rx, #0xf8000000   @ virtual base
 		.endm
 
diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
--- a/arch/arm/kernel/entry-armv.S	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/kernel/entry-armv.S	2004-06-23 19:04:26 -07:00
@@ -19,6 +19,7 @@
 #include <asm/thread_info.h>
 #include <asm/glue.h>
 #include <asm/ptrace.h>
+#include <asm/vfpmacros.h>
 
 #include "entry-header.S"
 
@@ -561,7 +562,7 @@
 		.macro	irq_prio_table
 		.endm
 
-#elif defined(CONFIG_ARCH_IOP310) || defined(CONFIG_ARCH_ADIFCC)
+#elif defined(CONFIG_ARCH_IOP310)
 
 		.macro	disable_fiq
 		.endm
@@ -1198,8 +1199,13 @@
 		mov	pc, lr				@ CP#7
 		mov	pc, lr				@ CP#8
 		mov	pc, lr				@ CP#9
+#ifdef CONFIG_VFP
+		b	do_vfp				@ CP#10 (VFP)
+		b	do_vfp				@ CP#11 (VFP)
+#else
 		mov	pc, lr				@ CP#10 (VFP)
 		mov	pc, lr				@ CP#11 (VFP)
+#endif
 		mov	pc, lr				@ CP#12
 		mov	pc, lr				@ CP#13
 		mov	pc, lr				@ CP#14 (Debug)
@@ -1260,6 +1266,13 @@
 		ldr	r3, [r2, #TI_CPU_DOMAIN]!
 		stmia	ip, {r4 - sl, fp, sp, lr}	@ Store most regs on stack
 		mcr	p15, 0, r3, c3, c0, 0		@ Set domain register
+#ifdef CONFIG_VFP
+		@ Always disable VFP so we can lazily save/restore the old
+		@ state. This occurs in the context of the previous thread.
+		VFPFMRX	r4, FPEXC
+		bic	r4, r4, #FPEXC_ENABLE
+		VFPFMXR	FPEXC, r4
+#endif
 		ldmib	r2, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
 
 		__INIT
diff -Nru a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
--- a/arch/arm/kernel/init_task.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/kernel/init_task.c	2004-06-23 19:04:28 -07:00
@@ -7,6 +7,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/init_task.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
--- a/arch/arm/kernel/process.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/kernel/process.c	2004-06-23 19:04:28 -07:00
@@ -314,10 +314,16 @@
 	memset(thread->used_cp, 0, sizeof(thread->used_cp));
 	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
 	fp_init(&thread->fpstate);
+#if defined(CONFIG_VFP)
+	vfp_flush_thread(&thread->vfpstate);
+#endif
 }
 
 void release_thread(struct task_struct *dead_task)
 {
+#if defined(CONFIG_VFP)
+	vfp_release_thread(&dead_task->thread_info->vfpstate);
+#endif
 }
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
diff -Nru a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
--- a/arch/arm/kernel/setup.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/kernel/setup.c	2004-06-23 19:04:27 -07:00
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
+#include <linux/interrupt.h>
 
 #include <asm/elf.h>
 #include <asm/hardware.h>
@@ -34,6 +35,7 @@
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
+#include <asm/mach/time.h>
 
 #ifndef MEM_SIZE
 #define MEM_SIZE	(16*1024*1024)
@@ -727,6 +729,7 @@
 	 * Set up various architecture-specific pointers
 	 */
 	init_arch_irq = mdesc->init_irq;
+	init_arch_time = mdesc->init_time;
 	init_machine = mdesc->init_machine;
 
 #ifdef CONFIG_VT
diff -Nru a/arch/arm/kernel/time-acorn.c b/arch/arm/kernel/time-acorn.c
--- a/arch/arm/kernel/time-acorn.c	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,66 +0,0 @@
-/*
- *  linux/arch/arm/kernel/time-acorn.c
- *
- *  Copyright (c) 1996-2000 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
- * published by the Free Software Foundation.
- *
- *  Changelog:
- *   24-Sep-1996	RMK	Created
- *   10-Oct-1996	RMK	Brought up to date with arch-sa110eval
- *   04-Dec-1997	RMK	Updated for new arch/arm/time.c
- */
-#include <linux/timex.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/hardware/ioc.h>
-
-extern unsigned long (*gettimeoffset)(void);
-
-static unsigned long ioctime_gettimeoffset(void)
-{
-	unsigned int count1, count2, status;
-	long offset;
-
-	ioc_writeb (0, IOC_T0LATCH);
-	barrier ();
-	count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
-	barrier ();
-	status = ioc_readb(IOC_IRQREQA);
-	barrier ();
-	ioc_writeb (0, IOC_T0LATCH);
-	barrier ();
-	count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
-
-	offset = count2;
-	if (count2 < count1) {
-		/*
-		 * We have not had an interrupt between reading count1
-		 * and count2.
-		 */
-		if (status & (1 << 5))
-			offset -= LATCH;
-	} else if (count2 > count1) {
-		/*
-		 * We have just had another interrupt between reading
-		 * count1 and count2.
-		 */
-		offset -= LATCH;
-	}
-
-	offset = (LATCH - offset) * (tick_nsec / 1000);
-	return (offset + LATCH/2) / LATCH;
-}
-
-void __init ioctime_init(void)
-{
-	ioc_writeb(LATCH & 255, IOC_T0LTCHL);
-	ioc_writeb(LATCH >> 8, IOC_T0LTCHH);
-	ioc_writeb(0, IOC_T0GO);
-
-	gettimeoffset = ioctime_gettimeoffset;
-}
diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
--- a/arch/arm/kernel/time.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/kernel/time.c	2004-06-23 19:04:27 -07:00
@@ -27,12 +27,15 @@
 #include <linux/errno.h>
 #include <linux/profile.h>
 #include <linux/sysdev.h>
+#include <linux/timer.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
 
+#include <asm/mach/time.h>
+
 u64 jiffies_64 = INITIAL_JIFFIES;
 
 EXPORT_SYMBOL(jiffies_64);
@@ -49,15 +52,11 @@
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY	(1000000/HZ)
 
-static int dummy_set_rtc(void)
-{
-	return 0;
-}
 
 /*
  * hook for setting the RTC's idea of the current time.
  */
-int (*set_rtc)(void) = dummy_set_rtc;
+int (*set_rtc)(void);
 
 static unsigned long dummy_gettimeoffset(void)
 {
@@ -238,7 +237,7 @@
 #endif
 
 #ifdef CONFIG_LEDS_TIMER
-static void do_leds(void)
+static inline void do_leds(void)
 {
 	static unsigned int count = 50;
 
@@ -248,7 +247,7 @@
 	}
 }
 #else
-#define do_leds()
+#define	do_leds()
 #endif
 
 void do_gettimeofday(struct timeval *tv)
@@ -316,12 +315,18 @@
 
 EXPORT_SYMBOL(do_settimeofday);
 
-static struct irqaction timer_irq = {
-	.name	= "timer",
-	.flags	= SA_INTERRUPT,
-};
+void timer_tick(struct pt_regs *regs)
+{
+	do_profile(regs);
+	do_leds();
+	do_set_rtc();
+	do_timer(regs);
+}
+
+void (*init_arch_time)(void);
+
+void __init time_init(void)
+{
+	init_arch_time();
+}
 
-/*
- * Include architecture specific code
- */
-#include <asm/arch/time.h>
diff -Nru a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
--- a/arch/arm/kernel/traps.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/kernel/traps.c	2004-06-23 19:04:26 -07:00
@@ -426,7 +426,7 @@
 
 	/*
 	 * Flush a region from virtual address 'r0' to virtual address 'r1'
-	 * _inclusive_.  There is no alignment requirement on either address;
+	 * _exclusive_.  There is no alignment requirement on either address;
 	 * user space does not need to know the hardware cache layout.
 	 *
 	 * r2 contains flags.  It should ALWAYS be passed as ZERO until it
diff -Nru a/arch/arm/mach-adifcc/Makefile b/arch/arm/mach-adifcc/Makefile
--- a/arch/arm/mach-adifcc/Makefile	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,11 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y			:= arch.o irq.o mm.o
-obj-m			:=
-obj-n			:=
-obj-			:=
-
diff -Nru a/arch/arm/mach-adifcc/arch.c b/arch/arm/mach-adifcc/arch.c
--- a/arch/arm/mach-adifcc/arch.c	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,32 +0,0 @@
-/*
- *  linux/arch/arm/mach-adifcc/arch.c
- *
- *  Copyright (C) 2001 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-extern void adifcc_map_io(void);
-extern void adifcc_init_irq(void);
-
-#ifdef CONFIG_ARCH_ADI_EVB
-MACHINE_START(ADI_EVB, "ADI 80200FCC Evaluation Board")
-	MAINTAINER("MontaVista Software Inc.")
-	BOOT_MEM(0xc0000000, 0x00400000, 0xff400000)
-	MAPIO(adifcc_map_io)
-	INITIRQ(adifcc_init_irq)
-MACHINE_END
-#endif
-
diff -Nru a/arch/arm/mach-adifcc/irq.c b/arch/arm/mach-adifcc/irq.c
--- a/arch/arm/mach-adifcc/irq.c	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,61 +0,0 @@
-/*
- * linux/arch/arm/mach-xscale/irq.c
- *
- * Author:  Deepak Saxena
- * Copyright:   (C) 2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Based on IOP80310 code.  Currently there's nothing more than the
- * 80200 on chip interrupts. That'll change once the hardware adds
- * support for PCI though.
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-
-static void xs80200_irq_mask (unsigned int irq)
-{
-	long INTCTL;
-	asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (INTCTL));
-	switch (irq) {
-	    case IRQ_XS80200_BCU:     INTCTL &= ~(1<<3); break;
-	    case IRQ_XS80200_PMU:     INTCTL &= ~(1<<2); break;
-	    case IRQ_XS80200_EXTIRQ:  INTCTL &= ~(1<<1); break;
-	    case IRQ_XS80200_EXTFIQ:  INTCTL &= ~(1<<0); break;
-	}
-	asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (INTCTL));
-}
-
-static void xs80200_irq_unmask (unsigned int irq)
-{
-	long INTCTL;
-	asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (INTCTL));
-	switch (irq) {
-	    case IRQ_XS80200_BCU:	INTCTL |= (1<<3); break;
-	    case IRQ_XS80200_PMU:	INTCTL |= (1<<2); break;
-	    case IRQ_XS80200_EXTIRQ:	INTCTL |= (1<<1); break;
-	    case IRQ_XS80200_EXTFIQ:	INTCTL |= (1<<0); break;
-	}
-	asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (INTCTL));
-}
-
-void __init adifcc_init_irq(void)
-{
-	int i;
-
-	for (i = 0; i < NR_XS80200_IRQS; i++) {
-		irq_desc[i].valid	= 1;
-		irq_desc[i].probe_ok	= 0;
-		irq_desc[i].mask_ack	= xs80200_irq_mask;
-		irq_desc[i].mask	= xs80200_irq_mask;
-		irq_desc[i].unmask	= xs80200_irq_unmask;
-	}
-}
-
-
diff -Nru a/arch/arm/mach-adifcc/mm.c b/arch/arm/mach-adifcc/mm.c
--- a/arch/arm/mach-adifcc/mm.c	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,23 +0,0 @@
-/*
- *  linux/arch/arm/mach-xscale/mm.c
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-
-static struct map_desc adifcc_io_desc[] __initdata = {
- /* on-board devices */
- { 0xff400000,   0x00400000,   0x00300000,   MT_DEVICE }
-};
-
-void __init adifcc_map_io(void)
-{
-	iotable_init(adifcc_io_desc, ARRAY_SIZE(adifcc_io_desc));
-}
diff -Nru a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
--- a/arch/arm/mach-clps711x/autcpu12.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-clps711x/autcpu12.c	2004-06-23 19:04:26 -07:00
@@ -37,6 +37,7 @@
 
 extern void clps711x_map_io(void);
 extern void clps711x_init_irq(void);
+extern void clps711x_init_time(void);
 
 /*
  * The on-chip registers are given a size of 1MB so that a section can
@@ -65,5 +66,6 @@
 	BOOT_PARAMS(0xc0020000)
 	MAPIO(autcpu12_map_io)
 	INITIRQ(clps711x_init_irq)
+	INITTIME(clp711x_init_time)
 MACHINE_END
 
diff -Nru a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
--- a/arch/arm/mach-clps711x/cdb89712.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-clps711x/cdb89712.c	2004-06-23 19:04:25 -07:00
@@ -34,6 +34,7 @@
 
 extern void clps711x_init_irq(void);
 extern void clps711x_map_io(void);
+extern void clps711x-init_time(void);
 
 /*
  * Map the CS89712 Ethernet port.  That should be moved to the
@@ -55,6 +56,7 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(cdb89712_map_io)
 	INITIRQ(clps711x_init_irq)
+	INITTIME(clps711x_init_time)
 MACHINE_END
 
 static int cdb89712_hw_init(void)
diff -Nru a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c
--- a/arch/arm/mach-clps711x/ceiva.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-clps711x/ceiva.c	2004-06-23 19:04:25 -07:00
@@ -35,6 +35,7 @@
 #include <asm/mach/map.h>
 
 extern void clps711x_init_irq(void);
+extern void clps711x_init_time(void);
 
 static struct map_desc ceiva_io_desc[] __initdata = {
  /* virtual, physical, length, type */
@@ -58,4 +59,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(ceiva_map_io)
 	INITIRQ(clps711x_init_irq)
+	INITTIME(clps711x_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c
--- a/arch/arm/mach-clps711x/clep7312.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-clps711x/clep7312.c	2004-06-23 19:04:27 -07:00
@@ -25,6 +25,7 @@
 
 extern void clps711x_init_irq(void);
 extern void clps711x_map_io(void); 
+extern void clps711x_init_time(void);
 
 static void __init
 fixup_clep7312(struct machine_desc *desc, struct tag *tags,
@@ -44,5 +45,6 @@
 	FIXUP(fixup_clep7312)
 	MAPIO(clps711x_map_io)
 	INITIRQ(clps711x_init_irq)
+	INITTIME(clps711x_init_time)
 MACHINE_END
 
diff -Nru a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c
--- a/arch/arm/mach-clps711x/edb7211-arch.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-clps711x/edb7211-arch.c	2004-06-23 19:04:28 -07:00
@@ -27,6 +27,7 @@
 
 extern void clps711x_init_irq(void);
 extern void edb7211_map_io(void);
+extern void clps711x_init_time(void);
 
 static void __init
 fixup_edb7211(struct machine_desc *desc, struct tag *tags,
@@ -56,4 +57,5 @@
 	FIXUP(fixup_edb7211)
 	MAPIO(edb7211_map_io)
 	INITIRQ(clps711x_init_irq)
+	INITTIME(clps711x_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c
--- a/arch/arm/mach-clps711x/fortunet.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-clps711x/fortunet.c	2004-06-23 19:04:27 -07:00
@@ -33,6 +33,7 @@
 
 extern void clps711x_map_io(void);
 extern void clps711x_init_irq(void);
+extern void clps711x_init_time(void);
 
 struct meminfo memmap = {
 	.nr_banks	= 1,
@@ -82,4 +83,5 @@
 	FIXUP(fortunet_fixup)
 	MAPIO(clps711x_map_io)
 	INITIRQ(clps711x_init_irq)
+	INITTIME(clps711x_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
--- a/arch/arm/mach-clps711x/p720t.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-clps711x/p720t.c	2004-06-23 19:04:27 -07:00
@@ -36,6 +36,7 @@
 
 extern void clps711x_init_irq(void);
 extern void clps711x_map_io(void);
+extern void clps711x_init_time(void);
 
 /*
  * Map the P720T system PLD.  It occupies two address spaces:
@@ -86,6 +87,7 @@
 	FIXUP(fixup_p720t)
 	MAPIO(p720t_map_io)
 	INITIRQ(clps711x_init_irq)
+	INITTIME(clps711x_init_time)
 MACHINE_END
 
 static int p720t_hw_init(void)
diff -Nru a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c
--- a/arch/arm/mach-clps711x/time.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-clps711x/time.c	2004-06-23 19:04:25 -07:00
@@ -18,12 +18,17 @@
  */
 #include <linux/timex.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
 
 #include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/leds.h>
 #include <asm/io.h>
 #include <asm/hardware/clps7111.h>
 
-extern unsigned long (*gettimeoffset)(void);
+#include <asm/mach/time.h>
+
 
 /*
  * gettimeoffset() returns time since last timer tick, in usecs.
@@ -38,18 +43,35 @@
 	return (hwticks * (tick_nsec / 1000)) / LATCH;
 }
 
-void __init clps711x_setup_timer(void)
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	timer_tick(regs);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction clps711x_timer_irq = {
+	.name		= "CLPS711x Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= p720t_timer_interrupt
+};
+
+void __init clps711x_init_time(void)
 {
 	struct timespec tv;
 	unsigned int syscon;
 
-	gettimeoffset = clps711x_gettimeoffset;
-
 	syscon = clps_readl(SYSCON1);
 	syscon |= SYSCON1_TC2S | SYSCON1_TC2M;
 	clps_writel(syscon, SYSCON1);
 
 	clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */
+
+	setup_irq(IRQ_TC2OI, &clps711x_timer_irq);
+	gettimeoffset = clps711x_gettimeoffset;
 
 	tv.tv_nsec = 0;
 	tv.tv_sec = clps_readl(RTCDR);
diff -Nru a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
--- a/arch/arm/mach-clps7500/core.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-clps7500/core.c	2004-06-23 19:04:27 -07:00
@@ -10,12 +10,13 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
-#include <linux/timer.h>
+#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
+#include <asm/mach/time.h>
 
 #include <asm/hardware.h>
 #include <asm/hardware/iomd.h>
@@ -265,10 +266,47 @@
 	iotable_init(cl7500_io_desc, ARRAY_SIZE(cl7500_io_desc));
 }
 
+extern void ioctime_init(void);
+
+static irqreturn_t
+clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	timer_tick(regs);
+
+	/* Why not using do_leds interface?? */
+	{
+		/* Twinkle the lights. */
+		static int count, state = 0xff00;
+		if (count-- == 0) {
+			state ^= 0x100;
+			count = 25;
+			*((volatile unsigned int *)LED_ADDRESS) = state;
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static struct irqaction clps7500_timer_irq = {
+	.name		= "CLPS7500 Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= clps7500_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt.
+ */
+void __init clps7500_init_time(void)
+{
+	ioctime_init();
+
+	setup_irq(IRQ_TIMER, &clps7500_timer_irq);
+}
+
 MACHINE_START(CLPS7500, "CL-PS7500")
 	MAINTAINER("Philip Blundell")
 	BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
 	MAPIO(clps7500_map_io)
 	INITIRQ(clps7500_init_irq)
+	INITTIME(clps7500_init_time)
 MACHINE_END
 
diff -Nru a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
--- a/arch/arm/mach-ebsa110/core.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-ebsa110/core.c	2004-06-23 19:04:26 -07:00
@@ -26,6 +26,8 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 
+#include <asm/mach/time.h>
+
 #define IRQ_MASK		0xfe000000	/* read */
 #define IRQ_MSET		0xfe000000	/* write */
 #define IRQ_STAT		0xff000000	/* read */
@@ -89,6 +91,103 @@
 	iotable_init(ebsa110_io_desc, ARRAY_SIZE(ebsa110_io_desc));
 }
 
+
+#define PIT_CTRL		(PIT_BASE + 0x0d)
+#define PIT_T2			(PIT_BASE + 0x09)
+#define PIT_T1			(PIT_BASE + 0x05)
+#define PIT_T0			(PIT_BASE + 0x01)
+
+/*
+ * This is the rate at which your MCLK signal toggles (in Hz)
+ * This was measured on a 10 digit frequency counter sampling
+ * over 1 second.
+ */
+#define MCLK	47894000
+
+/*
+ * This is the rate at which the PIT timers get clocked
+ */
+#define CLKBY7	(MCLK / 7)
+
+/*
+ * This is the counter value.  We tick at 200Hz on this platform.
+ */
+#define COUNT	((CLKBY7 + (HZ / 2)) / HZ)
+
+/*
+ * Get the time offset from the system PIT.  Note that if we have missed an
+ * interrupt, then the PIT counter will roll over (ie, be negative).
+ * This actually works out to be convenient.
+ */
+static unsigned long ebsa110_gettimeoffset(void)
+{
+	unsigned long offset, count;
+
+	__raw_writeb(0x40, PIT_CTRL);
+	count = __raw_readb(PIT_T1);
+	count |= __raw_readb(PIT_T1) << 8;
+
+	/*
+	 * If count > COUNT, make the number negative.
+	 */
+	if (count > COUNT)
+		count |= 0xffff0000;
+
+	offset = COUNT;
+	offset -= count;
+
+	/*
+	 * `offset' is in units of timer counts.  Convert
+	 * offset to units of microseconds.
+	 */
+	offset = offset * (1000000 / HZ) / COUNT;
+
+	return offset;
+}
+
+static irqreturn_t
+ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u32 count;
+
+	/* latch and read timer 1 */
+	__raw_writeb(0x40, PIT_CTRL);
+	count = __raw_readb(PIT_T1);
+	count |= __raw_readb(PIT_T1) << 8;
+
+	count += COUNT;
+
+	__raw_writeb(count & 0xff, PIT_T1);
+	__raw_writeb(count >> 8, PIT_T1);
+
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction ebsa110_timer_irq = {
+	.name		= "EBSA110 Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= ebsa110_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt.
+ */
+void __init ebsa110_time_init(void)
+{
+	/*
+	 * Timer 1, mode 2, LSB/MSB
+	 */
+	__raw_writeb(0x70, PIT_CTRL);
+	__raw_writeb(COUNT & 0xff, PIT_T1);
+	__raw_writeb(COUNT >> 8, PIT_T1);
+
+	gettimeoffset = ebsa110_gettimeoffset;
+
+	setup_irq(IRQ_EBSA110_TIMER0, &ebsa110_timer_irq);
+}
+
 MACHINE_START(EBSA110, "EBSA110")
 	MAINTAINER("Russell King")
 	BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000)
@@ -98,4 +197,5 @@
 	SOFT_REBOOT
 	MAPIO(ebsa110_map_io)
 	INITIRQ(ebsa110_init_irq)
+	INITTIME(ebsa110_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-ebsa110/time.c b/arch/arm/mach-ebsa110/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ebsa110/time.c	2004-06-23 19:04:26 -07:00
@@ -0,0 +1,118 @@
+/*
+ *  linux/include/asm-arm/arch-ebsa110/time.h
+ *
+ *  Copyright (C) 1996,1997,1998 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
+ * published by the Free Software Foundation.
+ *
+ * No real time clock on the evalulation board!
+ *
+ * Changelog:
+ *  10-Oct-1996	RMK	Created
+ *  04-Dec-1997	RMK	Updated for new arch/arm/kernel/time.c
+ *  07-Aug-1998	RMK	Updated for arch/arm/kernel/leds.c
+ *  28-Dec-1998	APH	Made leds code optional
+ */
+
+#include <asm/leds.h>
+#include <asm/io.h>
+
+extern unsigned long (*gettimeoffset)(void);
+
+#define PIT_CTRL		(PIT_BASE + 0x0d)
+#define PIT_T2			(PIT_BASE + 0x09)
+#define PIT_T1			(PIT_BASE + 0x05)
+#define PIT_T0			(PIT_BASE + 0x01)
+
+/*
+ * This is the rate at which your MCLK signal toggles (in Hz)
+ * This was measured on a 10 digit frequency counter sampling
+ * over 1 second.
+ */
+#define MCLK	47894000
+
+/*
+ * This is the rate at which the PIT timers get clocked
+ */
+#define CLKBY7	(MCLK / 7)
+
+/*
+ * This is the counter value.  We tick at 200Hz on this platform.
+ */
+#define COUNT	((CLKBY7 + (HZ / 2)) / HZ)
+
+/*
+ * Get the time offset from the system PIT.  Note that if we have missed an
+ * interrupt, then the PIT counter will roll over (ie, be negative).
+ * This actually works out to be convenient.
+ */
+static unsigned long ebsa110_gettimeoffset(void)
+{
+	unsigned long offset, count;
+
+	__raw_writeb(0x40, PIT_CTRL);
+	count = __raw_readb(PIT_T1);
+	count |= __raw_readb(PIT_T1) << 8;
+
+	/*
+	 * If count > COUNT, make the number negative.
+	 */
+	if (count > COUNT)
+		count |= 0xffff0000;
+
+	offset = COUNT;
+	offset -= count;
+
+	/*
+	 * `offset' is in units of timer counts.  Convert
+	 * offset to units of microseconds.
+	 */
+	offset = offset * (1000000 / HZ) / COUNT;
+
+	return offset;
+}
+
+static irqreturn_t
+timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u32 count;
+
+	/* latch and read timer 1 */
+	__raw_writeb(0x40, PIT_CTRL);
+	count = __raw_readb(PIT_T1);
+	count |= __raw_readb(PIT_T1) << 8;
+
+	count += COUNT;
+
+	__raw_writeb(count & 0xff, PIT_T1);
+	__raw_writeb(count >> 8, PIT_T1);
+
+	do_leds();
+	do_timer(regs);
+	do_profile(regs);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Set up timer interrupt.
+ */
+void __init time_init(void)
+{
+	/*
+	 * Timer 1, mode 2, LSB/MSB
+	 */
+	__raw_writeb(0x70, PIT_CTRL);
+	__raw_writeb(COUNT & 0xff, PIT_T1);
+	__raw_writeb(COUNT >> 8, PIT_T1);
+
+	gettimeoffset = ebsa110_gettimeoffset;
+
+	timer_irq.handler = timer_interrupt;
+
+	setup_irq(IRQ_EBSA110_TIMER0, &timer_irq);
+}
+
+
diff -Nru a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c
--- a/arch/arm/mach-epxa10db/arch.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-epxa10db/arch.c	2004-06-23 19:04:27 -07:00
@@ -29,10 +29,13 @@
 
 extern void epxa10db_map_io(void);
 extern void epxa10db_init_irq(void);
+extern void epxa10db_init_time(void);
 
 MACHINE_START(CAMELOT, "Altera Epxa10db")
 	MAINTAINER("Altera Corporation")
 	BOOT_MEM(0x00000000, 0x7fffc000, 0xffffc000)
 	MAPIO(epxa10db_map_io)
 	INITIRQ(epxa10db_init_irq)
+	INITTIME(epxa10db_init_time)
 MACHINE_END
+
diff -Nru a/arch/arm/mach-epxa10db/time.c b/arch/arm/mach-epxa10db/time.c
--- a/arch/arm/mach-epxa10db/time.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-epxa10db/time.c	2004-06-23 19:04:25 -07:00
@@ -10,11 +10,17 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
 
 #include <asm/hardware.h>
+#include <asm/system.h>
+#include <asm/leds.h>
 
+#include <asm/mach/time.h>
 
-extern int (*set_rtc)(void);
+#define TIMER00_TYPE (volatile unsigned int*)
+#include <asm/arch/timer00.h>
 
 static int epxa10db_set_rtc(void)
 {
@@ -29,3 +35,39 @@
 }
 
 __initcall(epxa10db_rtc_init);
+
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+epxa10db_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+	// ...clear the interrupt
+	*TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))|=TIMER0_CR_CI_MSK;
+
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction epxa10db_timer_irq = {
+	.name		= "Excalibur Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= epxa10db_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init epxa10db_init_time(void)
+{
+	/* Start the timer */
+	*TIMER0_LIMIT(IO_ADDRESS(EXC_TIMER00_BASE))=(unsigned int)(EXC_AHB2_CLK_FREQUENCY/200);
+	*TIMER0_PRESCALE(IO_ADDRESS(EXC_TIMER00_BASE))=1;
+	*TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))=TIMER0_CR_IE_MSK | TIMER0_CR_S_MSK;
+
+	setup_irq(IRQ_TIMER0, &epxa10db_timer_irq);
+}
+
diff -Nru a/arch/arm/mach-footbridge/Makefile b/arch/arm/mach-footbridge/Makefile
--- a/arch/arm/mach-footbridge/Makefile	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-footbridge/Makefile	2004-06-23 19:04:27 -07:00
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y			:= arch.o dc21285.o dma.o irq.o isa-irq.o mm.o
+obj-y			:= arch.o dc21285.o dma.o irq.o isa-irq.o mm.o time.o
 obj-m			:=
 obj-n			:=
 obj-			:=
diff -Nru a/arch/arm/mach-footbridge/arch.c b/arch/arm/mach-footbridge/arch.c
--- a/arch/arm/mach-footbridge/arch.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-footbridge/arch.c	2004-06-23 19:04:26 -07:00
@@ -22,6 +22,7 @@
 
 extern void footbridge_map_io(void);
 extern void footbridge_init_irq(void);
+extern void footbridge_init_time(void);
 
 unsigned int mem_fclk_21285 = 50000000;
 
@@ -43,6 +44,7 @@
 	VIDEO(0x000a0000, 0x000bffff)
 	MAPIO(footbridge_map_io)
 	INITIRQ(footbridge_init_irq)
+	INITTIME(footbridge_init_time)
 MACHINE_END
 #endif
 
@@ -78,6 +80,7 @@
 	FIXUP(fixup_netwinder)
 	MAPIO(footbridge_map_io)
 	INITIRQ(footbridge_init_irq)
+	INITTIME(footbridge_init_time)
 MACHINE_END
 #endif
 
@@ -103,6 +106,7 @@
 	FIXUP(fixup_cats)
 	MAPIO(footbridge_map_io)
 	INITIRQ(footbridge_init_irq)
+	INITTIME(footbridge_init_time)
 MACHINE_END
 #endif
 
@@ -129,6 +133,7 @@
 	FIXUP(fixup_coebsa285)
 	MAPIO(footbridge_map_io)
 	INITIRQ(footbridge_init_irq)
+	INITTIME(footbridge_init_time)
 MACHINE_END
 #endif
 
@@ -139,5 +144,6 @@
 	BOOT_PARAMS(0x00000100)
 	MAPIO(footbridge_map_io)
 	INITIRQ(footbridge_init_irq)
+	INITTIME(footbridge_init_time)
 MACHINE_END
 #endif
diff -Nru a/arch/arm/mach-footbridge/time.c b/arch/arm/mach-footbridge/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-footbridge/time.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,296 @@
+/*
+ *  linux/include/asm-arm/arch-ebsa285/time.h
+ *
+ *  Copyright (C) 1998 Russell King.
+ *  Copyright (C) 1998 Phil Blundell
+ *
+ * CATS has a real-time clock, though the evaluation board doesn't.
+ *
+ * Changelog:
+ *  21-Mar-1998	RMK	Created
+ *  27-Aug-1998	PJB	CATS support
+ *  28-Dec-1998	APH	Made leds optional
+ *  20-Jan-1999	RMK	Started merge of EBSA285, CATS and NetWinder
+ *  16-Mar-1999	RMK	More support for EBSA285-like machines with RTCs in
+ */
+
+#define RTC_PORT(x)		(rtc_base+(x))
+#define RTC_ALWAYS_BCD		0
+
+#include <linux/timex.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/hardware/dec21285.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include <asm/hardware/clps7111.h>
+
+#include <asm/mach/time.h>
+
+static int rtc_base;
+
+#define mSEC_10_from_14 ((14318180 + 100) / 200)
+
+static unsigned long isa_gettimeoffset(void)
+{
+	int count;
+
+	static int count_p = (mSEC_10_from_14/6);    /* for the first call after boot */
+	static unsigned long jiffies_p = 0;
+
+	/*
+	 * cache volatile jiffies temporarily; we have IRQs turned off. 
+	 */
+	unsigned long jiffies_t;
+
+	/* timer count may underflow right here */
+	outb_p(0x00, 0x43);	/* latch the count ASAP */
+
+	count = inb_p(0x40);	/* read the latched count */
+
+	/*
+	 * We do this guaranteed double memory access instead of a _p 
+	 * postfix in the previous port access. Wheee, hackady hack
+	 */
+ 	jiffies_t = jiffies;
+
+	count |= inb_p(0x40) << 8;
+
+	/* Detect timer underflows.  If we haven't had a timer tick since 
+	   the last time we were called, and time is apparently going
+	   backwards, the counter must have wrapped during this routine. */
+	if ((jiffies_t == jiffies_p) && (count > count_p))
+		count -= (mSEC_10_from_14/6);
+	else
+		jiffies_p = jiffies_t;
+
+	count_p = count;
+
+	count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
+	count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
+
+	return count;
+}
+
+static irqreturn_t
+isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static unsigned long __init get_isa_cmos_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int i;
+
+	// check to see if the RTC makes sense.....
+	if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
+		return mktime(1970, 1, 1, 0, 0, 0);
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+
+	for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec  = CMOS_READ(RTC_SECONDS);
+		min  = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day  = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon  = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		BCD_TO_BIN(sec);
+		BCD_TO_BIN(min);
+		BCD_TO_BIN(hour);
+		BCD_TO_BIN(day);
+		BCD_TO_BIN(mon);
+		BCD_TO_BIN(year);
+	}
+	if ((year += 1900) < 1970)
+		year += 100;
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+static int
+set_isa_cmos_time(void)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+	unsigned long nowtime = xtime.tv_sec;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else
+		retval = -1;
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
+
+static unsigned long timer1_latch;
+
+static unsigned long timer1_gettimeoffset (void)
+{
+	unsigned long value = timer1_latch - *CSR_TIMER1_VALUE;
+
+	return ((tick_nsec / 1000) * value) / timer1_latch;
+}
+
+static irqreturn_t
+timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	*CSR_TIMER1_CLR = 0;
+
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction footbridge_timer_irq = {
+	.flags	= SA_INTERRUPT
+};
+
+/*
+ * Set up timer interrupt.
+ */
+void __init footbridge_init_time(void)
+{
+	if (machine_is_co285() ||
+	    machine_is_personal_server())
+		/*
+		 * Add-in 21285s shouldn't access the RTC
+		 */
+		rtc_base = 0;
+	else
+		rtc_base = 0x70;
+
+	if (rtc_base) {
+		int reg_d, reg_b;
+
+		/*
+		 * Probe for the RTC.
+		 */
+		reg_d = CMOS_READ(RTC_REG_D);
+
+		/*
+		 * make sure the divider is set
+		 */
+		CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
+
+		/*
+		 * Set control reg B
+		 *   (24 hour mode, update enabled)
+		 */
+		reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
+		reg_b |= 2;
+		CMOS_WRITE(reg_b, RTC_REG_B);
+
+		if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
+		    CMOS_READ(RTC_REG_B) == reg_b) {
+			struct timespec tv;
+
+			/*
+			 * We have a RTC.  Check the battery
+			 */
+			if ((reg_d & 0x80) == 0)
+				printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
+
+			tv.tv_nsec = 0;
+			tv.tv_sec = get_isa_cmos_time();
+			do_settimeofday(&tv);
+			set_rtc = set_isa_cmos_time;
+		} else
+			rtc_base = 0;
+	}
+
+	if (machine_is_ebsa285() ||
+	    machine_is_co285() ||
+	    machine_is_personal_server()) {
+		gettimeoffset = timer1_gettimeoffset;
+
+		timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
+
+		*CSR_TIMER1_CLR  = 0;
+		*CSR_TIMER1_LOAD = timer1_latch;
+		*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+
+		footbridge_timer_irq.name = "Timer1 Timer Tick";
+		footbrdige_timer_irq.handler = timer1_interrupt;
+		
+		setup_irq(IRQ_TIMER1, &footbridge_timer_irq);
+
+	} else {
+		/* enable PIT timer */
+		/* set for periodic (4) and LSB/MSB write (0x30) */
+		outb(0x34, 0x43);
+		outb((mSEC_10_from_14/6) & 0xFF, 0x40);
+		outb((mSEC_10_from_14/6) >> 8, 0x40);
+
+		gettimeoffset = isa_gettimeoffset;
+
+		footbridge_timer_irq.name = "ISA Timer Tick";
+		footbrdige_timer_irq.handler = isa_timer_interrupt;
+		
+		setup_irq(IRQ_ISA, &footbridge_timer_irq);
+	}
+}
diff -Nru a/arch/arm/mach-ftvpci/Makefile b/arch/arm/mach-ftvpci/Makefile
--- a/arch/arm/mach-ftvpci/Makefile	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,13 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y			:= core.o
-obj-m			:=
-obj-n			:=
-obj-			:=
-
-obj-$(CONFIG_PCI)	+= pci.o
-obj-$(CONFIG_LEDS)	+= leds.o
diff -Nru a/arch/arm/mach-ftvpci/core.c b/arch/arm/mach-ftvpci/core.c
--- a/arch/arm/mach-ftvpci/core.c	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,96 +0,0 @@
-/*
- *  linux/arch/arm/mach-ftvpci/core.c
- *
- *  Architecture specific fixups.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/mm.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-extern unsigned long soft_irq_mask;
-
-static const unsigned char irq_cmd[] =
-{
-	INTCONT_IRQ_DUART,
-	INTCONT_IRQ_PLX,
-	INTCONT_IRQ_D,
-	INTCONT_IRQ_C,
-	INTCONT_IRQ_B,
-	INTCONT_IRQ_A,
-	INTCONT_IRQ_SYSERR
-};
-
-static void ftvpci_mask_irq(unsigned int irq)
-{
-	__raw_writel(irq_cmd[irq], INTCONT_BASE);
-	soft_irq_mask &= ~(1<<irq);
-}
-
-static void ftvpci_unmask_irq(unsigned int irq)
-{
-	soft_irq_mask |= (1<<irq);
-	__raw_writel(irq_cmd[irq] | 1, INTCONT_BASE);
-}
- 
-static void __init ftvpci_init_irq(void)
-{
-	unsigned int i;
-
-	/* Mask all FIQs */
-	__raw_writel(INTCONT_FIQ_PLX, INTCONT_BASE);
-	__raw_writel(INTCONT_FIQ_D, INTCONT_BASE);
-	__raw_writel(INTCONT_FIQ_C, INTCONT_BASE);
-	__raw_writel(INTCONT_FIQ_B, INTCONT_BASE);
-	__raw_writel(INTCONT_FIQ_A, INTCONT_BASE);
-	__raw_writel(INTCONT_FIQ_SYSERR, INTCONT_BASE);
-
-	/* Disable all interrupts initially. */
-	for (i = 0; i < NR_IRQS; i++) {
-		if (i >= FIRST_IRQ && i <= LAST_IRQ) {
-			irq_desc[i].valid	= 1;
-			irq_desc[i].probe_ok	= 1;
-			irq_desc[i].mask_ack	= ftvpci_mask_irq;
-			irq_desc[i].mask	= ftvpci_mask_irq;
-			irq_desc[i].unmask	= ftvpci_unmask_irq;
-			ftvpci_mask_irq(i);
-		} else {
-			irq_desc[i].valid	= 0;
-			irq_desc[i].probe_ok	= 0;
-		}	
-	}		
-}
-
-static struct map_desc ftvpci_io_desc[] __initdata = {
- 	{ INTCONT_BASE,	INTCONT_START,	0x00001000, MT_DEVICE },
- 	{ PLX_BASE,	PLX_START,	0x00001000, MT_DEVICE },
- 	{ PCIO_BASE,	PLX_IO_START,	0x00100000, MT_DEVICE },
- 	{ DUART_BASE,	DUART_START,	0x00001000, MT_DEVICE },
-	{ STATUS_BASE,	STATUS_START,	0x00001000, MT_DEVICE }
-};
-
-static void __init ftvpci_map_io(void)
-{
-	iotable_init(ftvpci_io_desc, ARRAY_SIZE(ftvpci_io_desc));
-}
-
-MACHINE_START(NEXUSPCI, "FTV/PCI")
-	MAINTAINER("Philip Blundell")
-	BOOT_MEM(0x40000000, 0x10000000, 0xe0000000)
-	MAPIO(ftvpci_map_io)
-	INITIRQ(ftvpci_init_irq)
-MACHINE_END
diff -Nru a/arch/arm/mach-ftvpci/leds.c b/arch/arm/mach-ftvpci/leds.c
--- a/arch/arm/mach-ftvpci/leds.c	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,36 +0,0 @@
-/*
- *  linux/arch/arm/kernel/leds-ftvpci.c
- *
- *  Copyright (C) 1999 FutureTV Labs Ltd
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/leds.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-static void ftvpci_leds_event(led_event_t ledevt)
-{
-	static int led_state = 0;
-
-	switch(ledevt) {
-	case led_timer:
-		led_state ^= 1;
-		raw_writeb(0x1a | led_state, INTCONT_BASE);
-		break;
-
-	default:
-		break;
-	}
-}
-
-static int __init ftvpci_leds_init(void)
-{
-	leds_event = ftvpci_leds_event;
-	return 0;
-}
-
-arch_initcall(ftvpci_leds_init);
diff -Nru a/arch/arm/mach-ftvpci/pci.c b/arch/arm/mach-ftvpci/pci.c
--- a/arch/arm/mach-ftvpci/pci.c	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,60 +0,0 @@
-/*
- *  linux/arch/arm/kernel/ftv-pci.c
- *
- *  PCI bios-type initialisation for PCI machines
- *
- *  Bits taken from various places.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * Owing to a PCB cockup, issue A backplanes are wired thus:
- *
- * Slot 1    2    3    4    5   Bridge   S1    S2    S3    S4
- * IRQ  D    C    B    A    A            C     B     A     D
- *      A    D    C    B    B            D     C     B     A
- *      B    A    D    C    C            A     D     C     B
- *      C    B    A    D    D            B     A     D     C
- *
- * ID A31  A30  A29  A28  A27   A26      DEV4  DEV5  DEV6  DEV7
- *
- * Actually, this isn't too bad, because with the processor card
- * in slot 5 on the primary bus, the IRQs rotate on both sides
- * as you'd expect.
- */
-
-static int irqmap_ftv[] __initdata = { IRQ_PCI_D, IRQ_PCI_C, IRQ_PCI_B, IRQ_PCI_A };
-
-static int __init ftv_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	if (slot > 0x10)
-		slot--;
-	return irqmap_ftv[(slot - pin) & 3];
-}
-
-static u8 __init ftv_swizzle(struct pci_dev *dev, u8 *pin)
-{
-	return PCI_SLOT(dev->devfn);
-}
-
-/* ftv host-specific stuff */
-static struct hw_pci ftv_pci __initdata = {
-	.init		= plx90x0_init,
-	.swizzle	= ftv_swizzle,
-	.map_irq	= ftv_map_irq,
-};
-
-static int __init ftv_pci_init(void)
-{
-	if (machine_is_ftvpci())
-		pci_common_init(&ftv_pci);
-	return 0;
-}
-
-subsys_initcall(ftv_pci_init);
diff -Nru a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
--- a/arch/arm/mach-integrator/Makefile	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-integrator/Makefile	2004-06-23 19:04:28 -07:00
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y					:= core.o lm.o time.o
+obj-y					:= clock.o core.o lm.o time.o
 obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+= integrator_ap.o
 obj-$(CONFIG_ARCH_INTEGRATOR_CP)	+= integrator_cp.o
 
diff -Nru a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-integrator/clock.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,138 @@
+/*
+ *  linux/arch/arm/mach-integrator/clock.c
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <asm/semaphore.h>
+#include <asm/hardware/clock.h>
+#include <asm/hardware/icst525.h>
+
+#include "clock.h"
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+	down(&clocks_sem);
+	list_for_each_entry(p, &clocks, node) {
+		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+	up(&clocks_sem);
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+	module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_use(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_use);
+
+void clk_unuse(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_unuse);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret = -EIO;
+	if (clk->setvco) {
+		struct icst525_vco vco;
+
+		vco = icst525_khz_to_vco(clk->params, rate);
+		clk->rate = icst525_khz(clk->params, vco);
+
+		printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
+			clk->name, vco.s, vco.r, vco.v);
+
+		clk->setvco(clk, vco);
+		ret = 0;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+/*
+ * These are fixed clocks.
+ */
+static struct clk kmi_clk = {
+	.name	= "KMIREFCLK",
+	.rate	= 24000000,
+};
+
+static struct clk uart_clk = {
+	.name	= "UARTCLK",
+	.rate	= 14745600,
+};
+
+int clk_register(struct clk *clk)
+{
+	down(&clocks_sem);
+	list_add(&clk->node, &clocks);
+	up(&clocks_sem);
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+	down(&clocks_sem);
+	list_del(&clk->node);
+	up(&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static int __init clk_init(void)
+{
+	clk_register(&kmi_clk);
+	clk_register(&uart_clk);
+	return 0;
+}
+arch_initcall(clk_init);
diff -Nru a/arch/arm/mach-integrator/clock.h b/arch/arm/mach-integrator/clock.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-integrator/clock.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,25 @@
+/*
+ *  linux/arch/arm/mach-integrator/clock.h
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * 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.
+ */
+struct module;
+struct icst525_params;
+
+struct clk {
+	struct list_head	node;
+	unsigned long		rate;
+	struct module		*owner;
+	const char		*name;
+	const struct icst525_params *params;
+	void			*data;
+	void			(*setvco)(struct clk *, struct icst525_vco vco);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
diff -Nru a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
--- a/arch/arm/mach-integrator/impd1.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-integrator/impd1.c	2004-06-23 19:04:26 -07:00
@@ -25,13 +25,16 @@
 #include <asm/arch/impd1.h>
 #include <asm/sizes.h>
 
+#include "clock.h"
+
 static int module_id;
 
 module_param_named(lmid, module_id, int, 0444);
 MODULE_PARM_DESC(lmid, "logic module stack position");
 
 struct impd1_module {
-	void	*base;
+	void		*base;
+	struct clk	vcos[2];
 };
 
 static const struct icst525_params impd1_vco_params = {
@@ -43,25 +46,20 @@
 	.rd_max		= 120,
 };
 
-void impd1_set_vco(struct device *dev, int vconr, unsigned long period)
+static void impd1_setvco(struct clk *clk, struct icst525_vco vco)
 {
-	struct impd1_module *impd1 = dev_get_drvdata(dev);
-	struct icst525_vco vco;
+	struct impd1_module *impd1 = clk->data;
+	int vconr = clk - impd1->vcos;
 	u32 val;
 
-	vco = icst525_ps_to_vco(&impd1_vco_params, period);
-
-	pr_debug("Guessed VCO reg params: S=%d R=%d V=%d\n",
-		vco.s, vco.r, vco.v);
-
 	val = vco.v | (vco.r << 9) | (vco.s << 16);
 
 	writel(0xa05f, impd1->base + IMPD1_LOCK);
 	switch (vconr) {
-	case 1:
+	case 0:
 		writel(val, impd1->base + IMPD1_OSC1);
 		break;
-	case 2:
+	case 1:
 		writel(val, impd1->base + IMPD1_OSC2);
 		break;
 	}
@@ -77,8 +75,6 @@
 #endif
 }
 
-EXPORT_SYMBOL(impd1_set_vco);
-
 void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
 {
 	struct impd1_module *impd1 = dev_get_drvdata(dev);
@@ -140,6 +136,11 @@
 	}
 };
 
+static const char *impd1_vconames[2] = {
+	"CLCDCLK",
+	"AUXVCO2",
+};
+
 static int impd1_probe(struct lm_device *dev)
 {
 	struct impd1_module *impd1;
@@ -168,6 +169,16 @@
 
 	printk("IM-PD1 found at 0x%08lx\n", dev->resource.start);
 
+	for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) {
+		impd1->vcos[i].owner = THIS_MODULE,
+		impd1->vcos[i].name = impd1_vconames[i],
+		impd1->vcos[i].params = &impd1_vco_params,
+		impd1->vcos[i].data = impd1,
+		impd1->vcos[i].setvco = impd1_setvco;
+
+		clk_register(&impd1->vcos[i]);
+	}
+
 	for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
 		struct impd1_device *idev = impd1_devs + i;
 		struct amba_device *d;
@@ -216,12 +227,16 @@
 {
 	struct impd1_module *impd1 = lm_get_drvdata(dev);
 	struct list_head *l, *n;
+	int i;
 
 	list_for_each_safe(l, n, &dev->dev.children) {
 		struct device *d = list_to_dev(l);
 
 		device_unregister(d);
 	}
+
+	for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++)
+		clk_unregister(&impd1->vcos[i]);
 
 	lm_set_drvdata(dev, NULL);
 
diff -Nru a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
--- a/arch/arm/mach-integrator/integrator_ap.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-integrator/integrator_ap.c	2004-06-23 19:04:28 -07:00
@@ -281,11 +281,17 @@
 	}
 }
 
+static void ap_time_init(void)
+{
+	integrator_time_init(1000000 * TICKS_PER_uSEC / HZ, 0);
+}
+
 MACHINE_START(INTEGRATOR, "ARM-Integrator")
 	MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
 	BOOT_MEM(0x00000000, 0x16000000, 0xf1600000)
 	BOOT_PARAMS(0x00000100)
 	MAPIO(ap_map_io)
 	INITIRQ(ap_init_irq)
+	INITTIME(ap_time_init)
 	INIT_MACHINE(ap_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
--- a/arch/arm/mach-integrator/integrator_cp.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-integrator/integrator_cp.c	2004-06-23 19:04:28 -07:00
@@ -23,6 +23,7 @@
 #include <asm/mach-types.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba_kmi.h>
+#include <asm/hardware/icst525.h>
 
 #include <asm/arch/lm.h>
 
@@ -32,12 +33,16 @@
 #include <asm/mach/mmc.h>
 #include <asm/mach/map.h>
 
+#include "clock.h"
+
 #define INTCP_PA_MMC_BASE		0x1c000000
 #define INTCP_PA_AACI_BASE		0x1d000000
 
 #define INTCP_PA_FLASH_BASE		0x24000000
 #define INTCP_FLASH_SIZE		SZ_32M
 
+#define INTCP_PA_CLCD_BASE		0xc0000000
+
 #define INTCP_VA_CIC_BASE		0xf1000040
 #define INTCP_VA_PIC_BASE		0xf1400000
 #define INTCP_VA_SIC_BASE		0xfca00000
@@ -210,6 +215,44 @@
 }
 
 /*
+ * Clock handling
+ */
+#define CM_LOCK (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
+#define CM_AUXOSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+0x1c)
+
+static const struct icst525_params cp_auxvco_params = {
+	.ref		= 24000,
+	.vco_max	= 320000,
+	.vd_min 	= 8,
+	.vd_max 	= 263,
+	.rd_min 	= 3,
+	.rd_max 	= 65,
+};
+
+static void cp_auxvco_set(struct clk *clk, struct icst525_vco vco)
+{
+	u32 val;
+
+	val = readl(CM_AUXOSC) & ~0x7ffff;
+	val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+	writel(0xa05f, CM_LOCK);
+	writel(val, CM_AUXOSC);
+	writel(0, CM_LOCK);
+}
+
+static struct clk cp_clcd_clk = {
+	.name	= "CLCDCLK",
+	.params	= &cp_auxvco_params,
+	.setvco = cp_auxvco_set,
+};
+
+static struct clk cp_mmci_clk = {
+	.name	= "MCLK",
+	.rate	= 14745600,
+};
+
+/*
  * Flash handling.
  */
 static int intcp_flash_init(void)
@@ -308,7 +351,7 @@
 }
 
 static struct mmc_platform_data mmc_data = {
-	.mclk		= 33000000,
+	.mclk		= 14745600,
 	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
 	.status		= mmc_status,
 };
@@ -340,15 +383,34 @@
 	.periphid	= 0,
 };
 
+static struct amba_device clcd_device = {
+	.dev		= {
+		.bus_id	= "mb:c0",
+		.coherent_dma_mask = ~0,
+	},
+	.res		= {
+		.start	= INTCP_PA_CLCD_BASE,
+		.end	= INTCP_PA_CLCD_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	.dma_mask	= ~0,
+	.irq		= { IRQ_CP_CLCDCINT, NO_IRQ },
+	.periphid	= 0,
+};
+
 static struct amba_device *amba_devs[] __initdata = {
 	&mmc_device,
 	&aaci_device,
+	&clcd_device,
 };
 
 static void __init intcp_init(void)
 {
 	int i;
 
+	clk_register(&cp_clcd_clk);
+	clk_register(&cp_mmci_clk);
+
 	platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
@@ -357,11 +419,17 @@
 	}
 }
 
+static void __init intcp_init_time(void)
+{
+	integrator_time_init(1000000 / HZ, TIMER_CTRL_IE);
+}
+
 MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
 	MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
 	BOOT_MEM(0x00000000, 0x16000000, 0xf1600000)
 	BOOT_PARAMS(0x00000100)
 	MAPIO(intcp_map_io)
 	INITIRQ(intcp_init_irq)
+	INITTIME(intcp_init_time)
 	INIT_MACHINE(intcp_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
--- a/arch/arm/mach-integrator/time.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-integrator/time.c	2004-06-23 19:04:26 -07:00
@@ -10,9 +10,16 @@
 #include <linux/kernel.h>
 #include <linux/time.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
+#include <asm/system.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/time.h>
 
 #define RTC_DR		(IO_ADDRESS(INTEGRATOR_RTC_BASE) + 0)
 #define RTC_MR		(IO_ADDRESS(INTEGRATOR_RTC_BASE) + 4)
@@ -44,3 +51,140 @@
 }
 
 __initcall(integrator_rtc_init);
+
+
+/*
+ * Where is the timer (VA)?
+ */
+#define TIMER0_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000000)
+#define TIMER1_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000100)
+#define TIMER2_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000200)
+#define VA_IC_BASE     IO_ADDRESS(INTEGRATOR_IC_BASE) 
+
+/*
+ * How long is the timer interval?
+ */
+#define TIMER_INTERVAL	(TICKS_PER_uSEC * mSEC_10)
+#if TIMER_INTERVAL >= 0x100000
+#define TICKS2USECS(x)	(256 * (x) / TICKS_PER_uSEC)
+#elif TIMER_INTERVAL >= 0x10000
+#define TICKS2USECS(x)	(16 * (x) / TICKS_PER_uSEC)
+#else
+#define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
+#endif
+
+#define TIMER_CTRL_IE	(1 << 5)			/* Interrupt Enable */
+
+/*
+ * What does it look like?
+ */
+typedef struct TimerStruct {
+	unsigned long TimerLoad;
+	unsigned long TimerValue;
+	unsigned long TimerControl;
+	unsigned long TimerClear;
+} TimerStruct_t;
+
+extern unsigned long (*gettimeoffset)(void);
+
+static unsigned long timer_reload;
+
+/*
+ * Returns number of ms since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long integrator_gettimeoffset(void)
+{
+	volatile TimerStruct_t *timer1 = (TimerStruct_t *)TIMER1_VA_BASE;
+	unsigned long ticks1, ticks2, status;
+
+	/*
+	 * Get the current number of ticks.  Note that there is a race
+	 * condition between us reading the timer and checking for
+	 * an interrupt.  We get around this by ensuring that the
+	 * counter has not reloaded between our two reads.
+	 */
+	ticks2 = timer1->TimerValue & 0xffff;
+	do {
+		ticks1 = ticks2;
+		status = __raw_readl(VA_IC_BASE + IRQ_RAW_STATUS);
+		ticks2 = timer1->TimerValue & 0xffff;
+	} while (ticks2 > ticks1);
+
+	/*
+	 * Number of ticks since last interrupt.
+	 */
+	ticks1 = timer_reload - ticks2;
+
+	/*
+	 * Interrupt pending?  If so, we've reloaded once already.
+	 */
+	if (status & (1 << IRQ_TIMERINT1))
+		ticks1 += timer_reload;
+
+	/*
+	 * Convert the ticks to usecs
+	 */
+	return TICKS2USECS(ticks1);
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
+
+	// ...clear the interrupt
+	timer1->TimerClear = 1;
+
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction integrator_timer_irq = {
+	.name		= "Integrator Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= integrator_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init integrator_time_init(unsigned long reload, unsigned int ctrl)
+{
+	volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
+	volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
+	volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
+	unsigned int timer_ctrl = 0x80 | 0x40;	/* periodic */
+
+	timer_reload = reload;
+	timer_ctrl |= ctrl;
+
+	if (timer_reload > 0x100000) {
+		timer_reload >>= 8;
+		timer_ctrl |= 0x08; /* /256 */
+	} else if (timer_reload > 0x010000) {
+		timer_reload >>= 4;
+		timer_ctrl |= 0x04; /* /16 */
+	}
+
+	/*
+	 * Initialise to a known state (all timers off)
+	 */
+	timer0->TimerControl = 0;
+	timer1->TimerControl = 0;
+	timer2->TimerControl = 0;
+
+	timer1->TimerLoad    = timer_reload;
+	timer1->TimerValue   = timer_reload;
+	timer1->TimerControl = timer_ctrl;
+
+	/* 
+	 * Make irqs happen for the system timer
+	 */
+	setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
+	gettimeoffset = integrator_gettimeoffset;
+}
diff -Nru a/arch/arm/mach-iop3xx/arch.c b/arch/arm/mach-iop3xx/arch.c
--- a/arch/arm/mach-iop3xx/arch.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-iop3xx/arch.c	2004-06-23 19:04:27 -07:00
@@ -29,6 +29,7 @@
 #ifdef CONFIG_ARCH_IQ80321
 extern void iq80321_map_io(void);
 extern void iop321_init_irq(void);
+extern void iop321_init_time(void);
 #endif
 
 #ifdef CONFIG_ARCH_IQ80310
@@ -67,6 +68,7 @@
 	FIXUP(fixup_iop321)
 	MAPIO(iq80321_map_io)
 	INITIRQ(iop321_init_irq)
+	INITTIME(iop321_init_time)
 MACHINE_END
 
 #else
diff -Nru a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c
--- a/arch/arm/mach-iop3xx/iop321-time.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-iop3xx/iop321-time.c	2004-06-23 19:04:28 -07:00
@@ -23,7 +23,9 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
+
 #include <asm/mach/irq.h>
+#include <asm/mach/time.h>
 
 static unsigned long iop321_gettimeoffset(void)
 {
@@ -61,27 +63,26 @@
 
 	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
 
-	do_timer(regs);
+	timer_tick(regs);
 
 	return IRQ_HANDLED;
 }
 
-extern unsigned long (*gettimeoffset)(void);
-
-static struct irqaction timer_irq = {
-	.name		= "timer",
+static struct irqaction iop321_timer_irq = {
+	.name		= "IOP321 Timer Tick",
 	.handler	= iop321_timer_interrupt,
+	.flags		= SA_INTERRUPT
 };
 
 extern int setup_arm_irq(int, struct irqaction*);
 
-void __init time_init(void)
+void __init iop321_init_time(void)
 {
 	u32 timer_ctl;
 	u32 latch = LATCH;
 
 	gettimeoffset = iop321_gettimeoffset;
-	setup_irq(IRQ_IOP321_TIMER0, &timer_irq);
+	setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq);
 
 	timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD |
 			IOP321_TMR_RATIO_1_1;
diff -Nru a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
--- a/arch/arm/mach-ixp4xx/common.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-ixp4xx/common.c	2004-06-23 19:04:27 -07:00
@@ -36,6 +36,7 @@
 
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
+#include <asm/mach/time.h>
 
 
 /*************************************************************************
@@ -227,24 +228,22 @@
 	 * Catch up with the real idea of time
 	 */
 	do {	
-		do_timer(regs);
+		timer_tick(regs);
 		last_jiffy_time += LATCH;
 	} while((*IXP4XX_OSTS - last_jiffy_time) > LATCH);
 
 	return IRQ_HANDLED;
 }
 
-extern unsigned long (*gettimeoffset)(void);
-
-static struct irqaction timer_irq = {
-	.name	= "IXP4xx Timer Tick",
-	.flags	= SA_INTERRUPT
+static struct irqaction ixp4xx_timer_irq = {
+	.name		= "IXP4xx Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= ixp4xx_timer_interrupt
 };
 
-void __init time_init(void)
+void __init ixp4xx_init_time(void)
 {
 	gettimeoffset = ixp4xx_gettimeoffset;
-	timer_irq.handler = ixp4xx_timer_interrupt;
 
 	/* Clear Pending Interrupt by writing '1' to it */
 	*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
@@ -257,7 +256,7 @@
 	last_jiffy_time = 0;
 
 	/* Connect the interrupt handler and enable the interrupt */
-	setup_irq(IRQ_IXP4XX_TIMER1, &timer_irq);
+	setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
 }
 
 
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	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c	2004-06-23 19:04:26 -07:00
@@ -84,6 +84,7 @@
                 IXP4XX_PERIPHERAL_BASE_VIRT)
         MAPIO(coyote_map_io)
         INITIRQ(ixp4xx_init_irq)
+	INITTIME(ixp4xx_init_time)
         BOOT_PARAMS(0x0100)
 	INIT_MACHINE(coyote_init)
 MACHINE_END
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	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c	2004-06-23 19:04:27 -07:00
@@ -113,6 +113,7 @@
 		IXP4XX_PERIPHERAL_BASE_VIRT)
 	MAPIO(ixdp425_map_io)
 	INITIRQ(ixp4xx_init_irq)
+	INITTIME(ixp4xx_init_time)
 	BOOT_PARAMS(0x0100)
 	INIT_MACHINE(ixdp425_init)
 MACHINE_END
@@ -123,6 +124,7 @@
 		IXP4XX_PERIPHERAL_BASE_VIRT)
 	MAPIO(ixdp425_map_io)
 	INITIRQ(ixp4xx_init_irq)
+	INITTIME(ixp4xx_init_time)
 	BOOT_PARAMS(0x0100)
 	INIT_MACHINE(ixdp425_init)
 MACHINE_END
@@ -140,6 +142,7 @@
 		IXP4XX_PERIPHERAL_BASE_VIRT)
 	MAPIO(ixdp425_map_io)
 	INITIRQ(ixp4xx_init_irq)
+	INITTIME(ixp4xx_init_time)
 	BOOT_PARAMS(0x0100)
 	INIT_MACHINE(ixdp425_init)
 MACHINE_END
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	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-ixp4xx/prpmc1100-setup.c	2004-06-23 19:04:25 -07:00
@@ -84,6 +84,7 @@
                 IXP4XX_PERIPHERAL_BASE_VIRT)
         MAPIO(prpmc1100_map_io)
         INITIRQ(ixp4xx_init_irq)
+	INITTIME(ixp4xx_init_time)
         BOOT_PARAMS(0x0100)
 	INIT_MACHINE(prpmc1100_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig
--- a/arch/arm/mach-lh7a40x/Kconfig	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-lh7a40x/Kconfig	2004-06-23 19:04:27 -07:00
@@ -34,6 +34,37 @@
 config ARCH_LH7A404
 	bool
 
+config LH7A40X_CONTIGMEM
+	bool "Disable NUMA Support"
+	depends on ARCH_LH7A40X
+	help
+	  Say Y here if your bootloader sets the SROMLL bit(s) in
+	  the SDRAM controller, organizing memory as a contiguous
+	  array.  This option will disable CONFIG_DISCONTIGMEM and
+          force the kernel to manage all memory in one node.
+
+	  Setting this option incorrectly may prevent the kernel from
+	  booting.  It is OK to leave it N.
+
+	  For more information, consult
+	    <file:Documentation/arm/Sharp-LH/SDRAM>.
+
+config LH7A40X_ONE_BANK_PER_NODE
+	bool "Optimize NUMA Node Tables for Size"
+	depends on ARCH_LH7A40X && !LH7A40X_CONTIGMEM
+	help
+	  Say Y here to produce compact memory node tables.  By
+	  default pairs of adjacent physical RAM banks are managed
+	  together in a single node, incurring some wasted overhead
+	  in the node tables, however also maintaining compatibility
+	  with systems where physical memory is truly contiguous.
+
+	  Setting this option incorrectly may prevent the kernel from
+	  booting.  It is OK to leave it N.
+
+	  For more information, consult
+	    <file:Documentation/arm/Sharp-LH/SDRAM>.
+
 endmenu
 
 endif
diff -Nru a/arch/arm/mach-lh7a40x/Makefile b/arch/arm/mach-lh7a40x/Makefile
--- a/arch/arm/mach-lh7a40x/Makefile	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-lh7a40x/Makefile	2004-06-23 19:04:27 -07:00
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y			:= fiq.o
+obj-y			:= fiq.o time.o
 # generic.o
 obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o
 obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o ide-lpd7a40x.o irq-lh7a400.o
diff -Nru a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c	2004-06-23 19:04:25 -07:00
@@ -25,6 +25,7 @@
 
       /* This function calls the board specific IRQ initialization function. */
 extern void lh7a400_init_irq (void);
+extern void lh7a40x_init_time (void);
 
 static struct map_desc kev7a400_io_desc[] __initdata = {
 	{ IO_VIRT,    IO_PHYS,    IO_SIZE,    MT_DEVICE },
@@ -108,4 +109,5 @@
 	BOOT_PARAMS (0xc0000100)
 	MAPIO (kev7a400_map_io)
 	INITIRQ (lh7a400_init_irq)
+	INITTIME (lh7a40x_init_time)
 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	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c	2004-06-23 19:04:25 -07:00
@@ -280,6 +280,7 @@
 #ifdef CONFIG_MACH_LPD7A404
 
 extern void lh7a404_init_irq (void);
+extern void lh7a40x_init_time (void);
 
 MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
 	MAINTAINER ("Marc Singer")
@@ -287,6 +288,7 @@
 	BOOT_PARAMS (0xc0000100)
 	MAPIO (lpd7a400_map_io)
 	INITIRQ (lh7a404_init_irq)
+	INITTIME (lh7a40x_init_time)
 	INIT_MACHINE (lpd7a40x_init)
 MACHINE_END
 
diff -Nru a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-lh7a40x/time.c	2004-06-23 19:04:27 -07:00
@@ -0,0 +1,67 @@
+/* 
+ *  arch/arm/mach-lh7a40x/time.c
+ *
+ *  Copyright (C) 2004 Logic Product Development
+ *
+ *  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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/leds.h>
+
+#include <asm/mach/time.h>
+
+#if HZ < 100
+# define TIMER_CONTROL	TIMER_CONTROL1
+# define TIMER_LOAD	TIMER_LOAD1
+# define TIMER_CONSTANT	(508469/HZ)
+# define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
+# define TIMER_EOI	TIMER_EOI1
+# define TIMER_IRQ	IRQ_T1UI
+#else
+# define TIMER_CONTROL	TIMER_CONTROL3
+# define TIMER_LOAD	TIMER_LOAD3
+# define TIMER_CONSTANT	(3686400/HZ)
+# define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC)
+# define TIMER_EOI	TIMER_EOI3
+# define TIMER_IRQ	IRQ_T3UI
+#endif
+
+static irqreturn_t
+lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	TIMER_EOI = 0;
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction lh7a40x_timer_irq = {
+	.name		= "LHA740x Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= lh7a40x_timer_interrupt
+};
+
+void __init lh7a40x_init_time(void)
+{
+				/* Stop/disable all timers */
+	TIMER_CONTROL1 = 0;
+	TIMER_CONTROL2 = 0;
+	TIMER_CONTROL3 = 0;
+
+	setup_irq (TIMER_IRQ, &lh7a40x_timer_irq);
+
+	TIMER_LOAD = TIMER_CONSTANT;
+	TIMER_CONTROL = TIMER_MODE;
+}
+
diff -Nru a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
--- a/arch/arm/mach-omap/Makefile	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-omap/Makefile	2004-06-23 19:04:25 -07:00
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := common.o irq.o dma.o clocks.o mux.o bus.o gpio.o
+obj-y := common.o irq.o dma.o clocks.o mux.o bus.o gpio.o time.o
 obj-m :=
 obj-n :=
 obj-  :=
diff -Nru a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c
--- a/arch/arm/mach-omap/board-generic.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-omap/board-generic.c	2004-06-23 19:04:27 -07:00
@@ -65,6 +65,11 @@
 	omap_map_io();
 }
 
+static void __init omap_generic_init_time(void)
+{
+	omap_init_time();
+}
+
 MACHINE_START(OMAP_GENERIC, "Generic OMAP-1510/1610/1710")
 	MAINTAINER("Tony Lindgren <tony@atomide.com>")
 	BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
@@ -72,4 +77,6 @@
 	MAPIO(omap_generic_map_io)
 	INITIRQ(omap_generic_init_irq)
 	INIT_MACHINE(omap_generic_init)
+	INITTIME(omap_generic_init_time)
 MACHINE_END
+
diff -Nru a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c
--- a/arch/arm/mach-omap/board-innovator.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-omap/board-innovator.c	2004-06-23 19:04:25 -07:00
@@ -156,5 +156,6 @@
 	BOOT_PARAMS(0x10000100)
 	MAPIO(innovator_map_io)
 	INITIRQ(innovator_init_irq)
+	INITTIME(omap_init_time)
 	INIT_MACHINE(innovator_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c
--- a/arch/arm/mach-omap/board-osk.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-omap/board-osk.c	2004-06-23 19:04:28 -07:00
@@ -94,5 +94,6 @@
 	BOOT_PARAMS(0x10000100)
 	MAPIO(osk_map_io)
 	INITIRQ(osk_init_irq)
+	INITTIME(omap_init_time)
 	INIT_MACHINE(osk_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c
--- a/arch/arm/mach-omap/board-perseus2.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-omap/board-perseus2.c	2004-06-23 19:04:28 -07:00
@@ -111,5 +111,6 @@
 	BOOT_PARAMS(0x10000100)
 	MAPIO(omap_perseus2_map_io)
 	INITIRQ(omap_perseus2_init_irq)
+	INITTIME(omap_init_time)
 	INIT_MACHINE(omap_perseus2_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h
--- a/arch/arm/mach-omap/common.h	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-omap/common.h	2004-06-23 19:04:27 -07:00
@@ -28,6 +28,7 @@
 #define __ARCH_ARM_MACH_OMAP_COMMON_H
 
 extern void omap_map_io(void);
+extern void omap_init_time(void);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
 
diff -Nru a/arch/arm/mach-omap/time.c b/arch/arm/mach-omap/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/time.c	2004-06-23 19:04:27 -07:00
@@ -0,0 +1,212 @@
+/*
+ * arch/arm/mach-omap/time.c
+ *
+ * OMAP Timer Tick 
+ *
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/arch/clocks.h>
+
+#ifndef __instrument
+#define __instrument
+#define __noinstrument __attribute__ ((no_instrument_function))
+#endif
+
+typedef struct {
+	u32 cntl;     /* CNTL_TIMER, R/W */
+	u32 load_tim; /* LOAD_TIM,   W */
+	u32 read_tim; /* READ_TIM,   R */
+} mputimer_regs_t;
+
+#define mputimer_base(n) \
+    ((volatile mputimer_regs_t*)IO_ADDRESS(OMAP_MPUTIMER_BASE + \
+				 (n)*OMAP_MPUTIMER_OFFSET))
+
+static inline unsigned long timer32k_read(int reg) {
+	unsigned long val;
+	val = omap_readw(reg + OMAP_32kHz_TIMER_BASE);
+	return val;
+}
+static inline void timer32k_write(int reg,int val) {
+	omap_writew(val, reg + OMAP_32kHz_TIMER_BASE);
+}
+
+/*
+ * How long is the timer interval? 100 HZ, right...
+ * IRQ rate = (TVR + 1) / 32768 seconds
+ * TVR = 32768 * IRQ_RATE -1
+ * IRQ_RATE =  1/100
+ * TVR = 326
+ */
+#define TIMER32k_PERIOD 326
+//#define TIMER32k_PERIOD 0x7ff
+
+static inline void start_timer32k(void) {
+	timer32k_write(TIMER32k_CR,
+		       TIMER32k_TSS | TIMER32k_TRB |
+		       TIMER32k_INT | TIMER32k_ARL);
+}
+
+#ifdef CONFIG_MACH_OMAP_PERSEUS2
+/*
+ * After programming PTV with 0 and setting the MPUTIM_CLOCK_ENABLE
+ * (external clock enable)  bit, the timer count rate is 6.5 MHz (13
+ * MHZ input/2). !! The divider by 2 is undocumented !!
+ */
+#define MPUTICKS_PER_SEC (13000000/2)
+#else
+/*
+ * After programming PTV with 0, the timer count rate is 6 MHz.
+ * WARNING! this must be an even number, or machinecycles_to_usecs
+ * below will break.
+ */
+#define MPUTICKS_PER_SEC  (12000000/2)
+#endif
+
+static int mputimer_started[3] = {0,0,0};
+
+static inline void __noinstrument start_mputimer(int n,
+						 unsigned long load_val)
+{
+	volatile mputimer_regs_t* timer = mputimer_base(n);
+
+	mputimer_started[n] = 0;
+	timer->cntl = MPUTIM_CLOCK_ENABLE;
+	udelay(1);
+
+	timer->load_tim = load_val;
+        udelay(1);
+	timer->cntl = (MPUTIM_CLOCK_ENABLE | MPUTIM_AR | MPUTIM_ST);
+	mputimer_started[n] = 1;
+}
+
+static inline unsigned long __noinstrument
+read_mputimer(int n)
+{
+	volatile mputimer_regs_t* timer = mputimer_base(n);
+	return (mputimer_started[n] ? timer->read_tim : 0);
+}
+
+void __noinstrument start_mputimer1(unsigned long load_val)
+{
+	start_mputimer(0, load_val);
+}
+void __noinstrument start_mputimer2(unsigned long load_val)
+{
+	start_mputimer(1, load_val);
+}
+void __noinstrument start_mputimer3(unsigned long load_val)
+{
+	start_mputimer(2, load_val);
+}
+
+unsigned long __noinstrument read_mputimer1(void)
+{
+	return read_mputimer(0);
+}
+unsigned long __noinstrument read_mputimer2(void)
+{
+	return read_mputimer(1);
+}
+unsigned long __noinstrument read_mputimer3(void)
+{
+	return read_mputimer(2);
+}
+
+unsigned long __noinstrument do_getmachinecycles(void)
+{
+	return 0 - read_mputimer(0);
+}
+
+unsigned long __noinstrument machinecycles_to_usecs(unsigned long mputicks)
+{
+	/* Round up to nearest usec */
+	return ((mputicks * 1000) / (MPUTICKS_PER_SEC / 2 / 1000) + 1) >> 1;
+}
+
+/*
+ * This marks the time of the last system timer interrupt
+ * that was *processed by the ISR* (timer 2).
+ */
+static unsigned long systimer_mark;
+
+static unsigned long omap_gettimeoffset(void)
+{
+	/* Return elapsed usecs since last system timer ISR */
+	return machinecycles_to_usecs(do_getmachinecycles() - systimer_mark);
+}
+
+static irqreturn_t
+omap_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long now, ilatency;
+
+	/*
+	 * Mark the time at which the timer interrupt ocurred using
+	 * timer1. We need to remove interrupt latency, which we can
+	 * retrieve from the current system timer2 counter. Both the
+	 * offset timer1 and the system timer2 are counting at 6MHz,
+	 * so we're ok.
+	 */
+	now = 0 - read_mputimer1();
+	ilatency = MPUTICKS_PER_SEC / 100 - read_mputimer2();
+	systimer_mark = now - ilatency;
+
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction omap_timer_irq = {
+	.name		= "OMAP Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= omap_timer_interrupt
+};
+
+void __init omap_init_time(void)
+{
+	/* Since we don't call request_irq, we must init the structure */
+	gettimeoffset = omap_gettimeoffset;
+
+#ifdef OMAP1510_USE_32KHZ_TIMER
+	timer32k_write(TIMER32k_CR, 0x0);
+	timer32k_write(TIMER32k_TVR,TIMER32k_PERIOD);
+	setup_irq(INT_OS_32kHz_TIMER, &omap_timer_irq);
+	start_timer32k();
+#else
+	setup_irq(INT_TIMER2, &omap_timer_irq);
+	start_mputimer2(MPUTICKS_PER_SEC / 100 - 1);
+#endif
+}
+
diff -Nru a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
--- a/arch/arm/mach-pxa/Makefile	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-pxa/Makefile	2004-06-23 19:04:27 -07:00
@@ -3,7 +3,7 @@
 #
 
 # Common support (must be linked before board specific support)
-obj-y += generic.o irq.o dma.o
+obj-y += generic.o irq.o dma.o time.o
 obj-$(CONFIG_PXA25x) += pxa25x.o
 obj-$(CONFIG_PXA27x) += pxa27x.o
 
diff -Nru a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
--- a/arch/arm/mach-pxa/generic.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-pxa/generic.c	2004-06-23 19:04:26 -07:00
@@ -59,6 +59,24 @@
 EXPORT_SYMBOL(pxa_gpio_mode);
 
 /*
+ * Routine to safely enable or disable a clock in the CKEN
+ */
+void pxa_set_cken(int clock, int enable)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+
+	if (enable)
+		CKEN |= clock;
+	else
+		CKEN &= ~clock;
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(pxa_set_cken);
+
+/*
  * Intel PXA2xx internal register mapping.
  *
  * Note 1: not all PXA2xx variants implement all those addresses.
@@ -180,10 +198,26 @@
 	.resource	= pxafb_resources,
 };
 
+static struct platform_device ffuart_device = {
+	.name		= "pxa2xx-uart",
+	.id		= 0,
+};
+static struct platform_device btuart_device = {
+	.name		= "pxa2xx-uart",
+	.id		= 1,
+};
+static struct platform_device stuart_device = {
+	.name		= "pxa2xx-uart",
+	.id		= 2,
+};
+
 static struct platform_device *devices[] __initdata = {
 	&pxamci_device,
 	&udc_device,
 	&pxafb_device,
+	&ffuart_device,
+	&btuart_device,
+	&stuart_device,
 };
 
 static int __init pxa_init(void)
diff -Nru a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
--- a/arch/arm/mach-pxa/generic.h	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-pxa/generic.h	2004-06-23 19:04:28 -07:00
@@ -11,6 +11,7 @@
 
 extern void __init pxa_map_io(void);
 extern void __init pxa_init_irq(void);
+extern void __init pxa_init_time(void);
 
 #define SET_BANK(__nr,__start,__size) \
 	mi->bank[__nr].start = (__start), \
diff -Nru a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
--- a/arch/arm/mach-pxa/idp.c	2004-06-23 19:04:24 -07:00
+++ b/arch/arm/mach-pxa/idp.c	2004-06-23 19:04:24 -07:00
@@ -118,5 +118,6 @@
 	BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
 	MAPIO(idp_map_io)
 	INITIRQ(idp_init_irq)
+	INITTIME(pxa_init_time)
 	INIT_MACHINE(idp_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
--- a/arch/arm/mach-pxa/lubbock.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-pxa/lubbock.c	2004-06-23 19:04:26 -07:00
@@ -220,5 +220,6 @@
 	BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
 	MAPIO(lubbock_map_io)
 	INITIRQ(lubbock_init_irq)
+	INITTIME(pxa_init_time)
 	INIT_MACHINE(lubbock_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
--- a/arch/arm/mach-pxa/mainstone.c	2004-06-23 19:04:29 -07:00
+++ b/arch/arm/mach-pxa/mainstone.c	2004-06-23 19:04:29 -07:00
@@ -137,5 +137,6 @@
 	BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
 	MAPIO(mainstone_map_io)
 	INITIRQ(mainstone_init_irq)
+	INITTIME(pxa_init_time)
 	INIT_MACHINE(mainstone_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-pxa/time.c	2004-06-23 19:04:26 -07:00
@@ -0,0 +1,124 @@
+/*
+ * arch/arm/mach-pxa/time.c
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+
+static inline unsigned long pxa_get_rtc_time(void)
+{
+	return RCNR;
+}
+
+static int pxa_set_rtc(void)
+{
+	unsigned long current_time = xtime.tv_sec;
+
+	if (RTSR & RTSR_ALE) {
+		/* make sure not to forward the clock over an alarm */
+		unsigned long alarm = RTAR;
+		if (current_time >= alarm && alarm >= RCNR)
+			return -ERESTARTSYS;
+	}
+	RCNR = current_time;
+	return 0;
+}
+
+/* IRQs are disabled before entering here from do_gettimeofday() */
+static unsigned long pxa_gettimeoffset (void)
+{
+	long ticks_to_match, elapsed, usec;
+
+	/* Get ticks before next timer match */
+	ticks_to_match = OSMR0 - OSCR;
+
+	/* We need elapsed ticks since last match */
+	elapsed = LATCH - ticks_to_match;
+
+	/* don't get fooled by the workaround in pxa_timer_interrupt() */
+	if (elapsed <= 0)
+		return 0;
+
+	/* Now convert them to usec */
+	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
+
+	return usec;
+}
+
+static irqreturn_t
+pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int next_match;
+
+	/* Loop until we get ahead of the free running timer.
+	 * This ensures an exact clock tick count and time accuracy.
+	 * IRQs are disabled inside the loop to ensure coherence between
+	 * lost_ticks (updated in do_timer()) and the match reg value, so we
+	 * can use do_gettimeofday() from interrupt handlers.
+	 *
+	 * HACK ALERT: it seems that the PXA timer regs aren't updated right
+	 * away in all cases when a write occurs.  We therefore compare with
+	 * 8 instead of 0 in the while() condition below to avoid missing a
+	 * match if OSCR has already reached the next OSMR value.
+	 * Experience has shown that up to 6 ticks are needed to work around
+	 * this problem, but let's use 8 to be conservative.  Note that this
+	 * affect things only when the timer IRQ has been delayed by nearly
+	 * exactly one tick period which should be a pretty rare event.
+	 */
+	do {
+		timer_tick(regs);
+		OSSR = OSSR_M0;  /* Clear match on timer 0 */
+		next_match = (OSMR0 += LATCH);
+	} while( (signed long)(next_match - OSCR) <= 8 );
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction pxa_timer_irq = {
+	.name		= "PXA Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= pxa_timer_interrupt
+};
+
+void __init pxa_init_time(void)
+{
+	struct timespec tv;
+
+	gettimeoffset = pxa_gettimeoffset;
+	set_rtc = pxa_set_rtc;
+
+	tv.tv_nsec = 0;
+	tv.tv_sec = pxa_get_rtc_time();
+	do_settimeofday(&tv);
+
+	OSMR0 = 0;		/* set initial match at 0 */
+	OSSR = 0xf;		/* clear status on all timers */
+	setup_irq(IRQ_OST0, &pxa_timer_irq);
+	OIER |= OIER_E0;	/* enable match on timer 0 to cause interrupts */
+	OSCR = 0;		/* initialize free-running timer, force first match */
+}
+
diff -Nru a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
--- a/arch/arm/mach-rpc/riscpc.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-rpc/riscpc.c	2004-06-23 19:04:27 -07:00
@@ -14,6 +14,8 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
 
 #include <asm/elf.h>
 #include <asm/io.h>
@@ -25,6 +27,7 @@
 
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
+#include <asm/mach/time.h>
 
 extern void rpc_init_irq(void);
 
@@ -82,6 +85,31 @@
 	elf_hwcap &= ~HWCAP_HALF;
 }
 
+static irqreturn_t
+rpc_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction rpc_timer_irq = {
+	.name		= "RiscPC Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= rpc_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt.
+ */
+void __init rpc_init_time(void)
+{
+	extern void ioctime_init(void);
+	ioctime_init();
+
+	setup_irq(IRQ_TIMER, &rpc_timer_irq);
+}
+
 MACHINE_START(RISCPC, "Acorn-RiscPC")
 	MAINTAINER("Russell King")
 	BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
@@ -90,4 +118,5 @@
 	DISABLE_PARPORT(1)
 	MAPIO(rpc_map_io)
 	INITIRQ(rpc_init_irq)
+	INITTIME(rpc_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
--- a/arch/arm/mach-s3c2410/Makefile	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-s3c2410/Makefile	2004-06-23 19:04:25 -07:00
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y			:= s3c2410.o irq.o
+obj-y			:= s3c2410.o irq.o time.o
 obj-m			:=
 obj-n			:=
 obj-			:=
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	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-s3c2410/mach-bast.c	2004-06-23 19:04:27 -07:00
@@ -185,10 +185,16 @@
 
 }
 
+void __init bast_init_time(void)
+{
+	s3c2410_init_time();
+}
+
 MACHINE_START(BAST, "Simtec-BAST")
      MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
      BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      MAPIO(bast_map_io)
      INITIRQ(bast_init_irq)
+     INITTIME(bast_init_time)
 MACHINE_END
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	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-s3c2410/mach-h1940.c	2004-06-23 19:04:28 -07:00
@@ -91,10 +91,16 @@
 
 }
 
+void __init ipaq_init_time(void)
+{
+	s3c2410_init_time();
+}
+
 MACHINE_START(H1940, "IPAQ-H1940")
      MAINTAINER("Ben Dooks <ben@fluff.org>")
      BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      MAPIO(ipaq_map_io)
      INITIRQ(ipaq_init_irq)
+     INITTIME(ipaq_init_time)
 MACHINE_END
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	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c	2004-06-23 19:04:27 -07:00
@@ -99,6 +99,11 @@
 	s3c2410_init_irq();
 }
 
+void __init smdk2410_init_time(void)
+{
+	s3c2401_init_time();
+}
+
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
 				    * to SMDK2410 */
      MAINTAINER("Jonas Dietsche")
@@ -106,4 +111,5 @@
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      MAPIO(smdk2410_map_io)
      INITIRQ(smdk2410_init_irq)
+     INITTIME(smdk2410_init_time)
 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	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c	2004-06-23 19:04:28 -07:00
@@ -155,10 +155,16 @@
 
 }
 
+void __init vr1000_init_time(void)
+{
+	s3c2401_init_time();
+}
+
 MACHINE_START(VR1000, "Simtec-VR1000")
      MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
      BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      MAPIO(vr1000_map_io)
      INITIRQ(vr1000_init_irq)
+     INITTIME(vr1000_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
--- a/arch/arm/mach-s3c2410/s3c2410.h	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-s3c2410/s3c2410.h	2004-06-23 19:04:26 -07:00
@@ -4,3 +4,5 @@
 
 extern void s3c2410_init_irq(void);
 
+extern s3c2410_init_time(void);
+
diff -Nru a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/time.c	2004-06-23 19:04:26 -07:00
@@ -0,0 +1,176 @@
+/* linux/include/asm-arm/arch-s3c2410/time.h
+ *
+ *  Copyright (C) 2003 Simtec Electronics <linux@simtec.co.uk>
+ *    Ben Dooks, <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/system.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/arch/map.h>
+#include <asm/arch/regs-timer.h>
+#include <asm/mach/time.h>
+
+static unsigned long timer_startval;
+static unsigned long timer_ticks_usec;
+
+#ifdef CONFIG_S3C2410_RTC
+extern void s3c2410_rtc_check();
+#endif
+
+/* with an 12MHz clock, we get 12 ticks per-usec
+ */
+
+
+/***
+ * Returns microsecond  since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ * IRQs are disabled before entering here from do_gettimeofday()
+ */
+static unsigned long s3c2410_gettimeoffset (void)
+{
+	unsigned long tdone;
+	unsigned long usec;
+
+	/* work out how many ticks have gone since last timer interrupt */
+
+	tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4));
+
+	/* currently, tcnt is in 12MHz units, but this may change
+	 * for non-bast machines...
+	 */
+
+	usec = tdone / timer_ticks_usec;
+
+	return usec;
+}
+
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+s3c2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction s3c2410_timer_irq = {
+	.name		= "S32410 Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= s3c2410_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ *
+ * Currently we only use timer4, as it is the only timer which has no
+ * other function that can be exploited externally
+ */
+void __init s3c2410_init_time (void)
+{
+	unsigned long tcon;
+	unsigned long tcnt;
+	unsigned long tcfg1;
+	unsigned long tcfg0;
+
+	gettimeoffset = s3c2410_gettimeoffset;
+
+	tcnt = 0xffff;  /* default value for tcnt */
+
+	/* read the current timer configuration bits */
+
+	tcon = __raw_readl(S3C2410_TCON);
+	tcfg1 = __raw_readl(S3C2410_TCFG1);
+	tcfg0 = __raw_readl(S3C2410_TCFG0);
+
+	/* configure the system for whichever machine is in use */
+
+	if (machine_is_bast() || machine_is_vr1000()) {
+		timer_ticks_usec = 12;	      /* timer is at 12MHz */
+		tcnt = (timer_ticks_usec * (1000*1000)) / HZ;
+	}
+
+	/* for the h1940, we use the pclk from the core to generate
+	 * the timer values. since 67.5MHz is not a value we can directly
+	 * generate the timer value from, we need to pre-scale and
+	 * divied before using it.
+	 *
+	 * overall divsior to get 200Hz is 337500
+	 *   we can fit tcnt if we pre-scale by 6, producing a tick rate
+	 *   of 11.25MHz, and a tcnt of 56250.
+	 */
+
+	if (machine_is_h1940() || machine_is_smdk2410() ) {
+		timer_ticks_usec = s3c2410_pclk / (1000*1000);
+		timer_ticks_usec /= 6;
+
+		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
+		tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
+
+		tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+		tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
+
+		tcnt = (s3c2410_pclk / 6) / HZ;
+	}
+
+
+	printk("setup_timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx\n",
+	       tcon, tcnt, tcfg0, tcfg1);
+
+	/* check to see if timer is within 16bit range... */
+	if (tcnt > 0xffff) {
+		panic("setup_timer: HZ is too small, cannot configure timer!");
+		return;
+	}
+
+	__raw_writel(tcfg1, S3C2410_TCFG1);
+	__raw_writel(tcfg0, S3C2410_TCFG0);
+
+	timer_startval = tcnt;
+	__raw_writel(tcnt, S3C2410_TCNTB(4));
+
+	/* ensure timer is stopped... */
+
+	tcon &= ~(7<<20);
+	tcon |= S3C2410_TCON_T4RELOAD;
+	tcon |= S3C2410_TCON_T4MANUALUPD;
+
+	__raw_writel(tcon, S3C2410_TCON);
+	__raw_writel(tcnt, S3C2410_TCNTB(4));
+	__raw_writel(tcnt, S3C2410_TCMPB(4));
+
+	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
+
+	/* start the timer running */
+	tcon |= S3C2410_TCON_T4START;
+	tcon &= ~S3C2410_TCON_T4MANUALUPD;
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+
+
diff -Nru a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c
--- a/arch/arm/mach-sa1100/adsbitsy.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-sa1100/adsbitsy.c	2004-06-23 19:04:25 -07:00
@@ -147,4 +147,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(adsbitsy_map_io)
 	INITIRQ(adsbitsy_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
--- a/arch/arm/mach-sa1100/assabet.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-sa1100/assabet.c	2004-06-23 19:04:25 -07:00
@@ -324,5 +324,6 @@
 	FIXUP(fixup_assabet)
 	MAPIO(assabet_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 	INIT_MACHINE(assabet_init)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
--- a/arch/arm/mach-sa1100/badge4.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-sa1100/badge4.c	2004-06-23 19:04:25 -07:00
@@ -245,4 +245,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(badge4_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/brutus.c b/arch/arm/mach-sa1100/brutus.c
--- a/arch/arm/mach-sa1100/brutus.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-sa1100/brutus.c	2004-06-23 19:04:28 -07:00
@@ -37,4 +37,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(brutus_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
--- a/arch/arm/mach-sa1100/cerf.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-sa1100/cerf.c	2004-06-23 19:04:26 -07:00
@@ -92,4 +92,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(cerf_map_io)
 	INITIRQ(cerf_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/empeg.c b/arch/arm/mach-sa1100/empeg.c
--- a/arch/arm/mach-sa1100/empeg.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-sa1100/empeg.c	2004-06-23 19:04:27 -07:00
@@ -35,4 +35,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(empeg_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/flexanet.c b/arch/arm/mach-sa1100/flexanet.c
--- a/arch/arm/mach-sa1100/flexanet.c	2004-06-23 19:04:29 -07:00
+++ b/arch/arm/mach-sa1100/flexanet.c	2004-06-23 19:04:29 -07:00
@@ -183,5 +183,6 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(flexanet_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
 
diff -Nru a/arch/arm/mach-sa1100/freebird.c b/arch/arm/mach-sa1100/freebird.c
--- a/arch/arm/mach-sa1100/freebird.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-sa1100/freebird.c	2004-06-23 19:04:25 -07:00
@@ -77,4 +77,5 @@
 #endif
 	MAPIO(freebird_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
--- a/arch/arm/mach-sa1100/generic.h	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-sa1100/generic.h	2004-06-23 19:04:27 -07:00
@@ -6,6 +6,7 @@
 
 extern void __init sa1100_map_io(void);
 extern void __init sa1100_init_irq(void);
+extern void __init sa1100_init_time(void);
 
 #define SET_BANK(__nr,__start,__size) \
 	mi->bank[__nr].start = (__start), \
diff -Nru a/arch/arm/mach-sa1100/graphicsclient.c b/arch/arm/mach-sa1100/graphicsclient.c
--- a/arch/arm/mach-sa1100/graphicsclient.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-sa1100/graphicsclient.c	2004-06-23 19:04:28 -07:00
@@ -198,4 +198,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(graphicsclient_map_io)
 	INITIRQ(graphicsclient_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c
--- a/arch/arm/mach-sa1100/graphicsmaster.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-sa1100/graphicsmaster.c	2004-06-23 19:04:26 -07:00
@@ -287,4 +287,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(graphicsmaster_map_io)
 	INITIRQ(graphicsmaster_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
--- a/arch/arm/mach-sa1100/h3600.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-sa1100/h3600.c	2004-06-23 19:04:26 -07:00
@@ -286,6 +286,7 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(h3100_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
 
 #endif /* CONFIG_SA1100_H3100 */
@@ -400,6 +401,7 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(h3600_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
 
 #endif /* CONFIG_SA1100_H3600 */
@@ -783,6 +785,7 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(h3800_map_io)
 	INITIRQ(h3800_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
 
 #endif /* CONFIG_SA1100_H3800 */
diff -Nru a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
--- a/arch/arm/mach-sa1100/hackkit.c	2004-06-23 19:04:29 -07:00
+++ b/arch/arm/mach-sa1100/hackkit.c	2004-06-23 19:04:29 -07:00
@@ -174,4 +174,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(hackkit_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/huw_webpanel.c b/arch/arm/mach-sa1100/huw_webpanel.c
--- a/arch/arm/mach-sa1100/huw_webpanel.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-sa1100/huw_webpanel.c	2004-06-23 19:04:28 -07:00
@@ -81,4 +81,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(huw_webpanel_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/itsy.c b/arch/arm/mach-sa1100/itsy.c
--- a/arch/arm/mach-sa1100/itsy.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-sa1100/itsy.c	2004-06-23 19:04:28 -07:00
@@ -37,4 +37,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(itsy_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
--- a/arch/arm/mach-sa1100/jornada720.c	2004-06-23 19:04:29 -07:00
+++ b/arch/arm/mach-sa1100/jornada720.c	2004-06-23 19:04:29 -07:00
@@ -101,4 +101,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(jornada720_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
--- a/arch/arm/mach-sa1100/lart.c	2004-06-23 19:04:29 -07:00
+++ b/arch/arm/mach-sa1100/lart.c	2004-06-23 19:04:29 -07:00
@@ -43,4 +43,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(lart_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
--- a/arch/arm/mach-sa1100/nanoengine.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-sa1100/nanoengine.c	2004-06-23 19:04:25 -07:00
@@ -49,4 +49,5 @@
 	FIXUP(fixup_nanoengine)
 	MAPIO(nanoengine_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/omnimeter.c b/arch/arm/mach-sa1100/omnimeter.c
--- a/arch/arm/mach-sa1100/omnimeter.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-sa1100/omnimeter.c	2004-06-23 19:04:25 -07:00
@@ -59,4 +59,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(omnimeter_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/pangolin.c b/arch/arm/mach-sa1100/pangolin.c
--- a/arch/arm/mach-sa1100/pangolin.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-sa1100/pangolin.c	2004-06-23 19:04:28 -07:00
@@ -40,4 +40,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(pangolin_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c
--- a/arch/arm/mach-sa1100/pfs168.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-sa1100/pfs168.c	2004-06-23 19:04:25 -07:00
@@ -112,4 +112,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(pfs168_map_io)
 	INITIRQ(pfs168_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
--- a/arch/arm/mach-sa1100/pleb.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-sa1100/pleb.c	2004-06-23 19:04:26 -07:00
@@ -31,4 +31,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(pleb_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
--- a/arch/arm/mach-sa1100/shannon.c	2004-06-23 19:04:29 -07:00
+++ b/arch/arm/mach-sa1100/shannon.c	2004-06-23 19:04:29 -07:00
@@ -41,4 +41,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(shannon_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/sherman.c b/arch/arm/mach-sa1100/sherman.c
--- a/arch/arm/mach-sa1100/sherman.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-sa1100/sherman.c	2004-06-23 19:04:27 -07:00
@@ -27,4 +27,5 @@
         BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
         MAPIO(sherman_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
--- a/arch/arm/mach-sa1100/simpad.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-sa1100/simpad.c	2004-06-23 19:04:25 -07:00
@@ -231,4 +231,5 @@
         BOOT_PARAMS(0xc0000100)
 	MAPIO(simpad_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/stork.c b/arch/arm/mach-sa1100/stork.c
--- a/arch/arm/mach-sa1100/stork.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-sa1100/stork.c	2004-06-23 19:04:27 -07:00
@@ -331,6 +331,7 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(stork_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
 
 
diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
--- a/arch/arm/mach-sa1100/system3.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-sa1100/system3.c	2004-06-23 19:04:28 -07:00
@@ -470,4 +470,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(system3_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-sa1100/time.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,112 @@
+/*
+ * linux/include/asm-arm/arch-sa1100/time.h
+ *
+ * Copyright (C) 1998 Deborah Wallach.
+ * Twiddles  (C) 1999 	Hugo Fiennes <hugo@empeg.com>
+ * 
+ * 2000/03/29 (C) Nicolas Pitre <nico@cam.org>
+ *	Rewritten: big cleanup, much simpler, better HZ accuracy.
+ *
+ */
+
+
+#define RTC_DEF_DIVIDER		(32768 - 1)
+#define RTC_DEF_TRIM            0
+
+static unsigned long __init sa1100_get_rtc_time(void)
+{
+	/*
+	 * According to the manual we should be able to let RTTR be zero
+	 * and then a default diviser for a 32.768KHz clock is used.
+	 * Apparently this doesn't work, at least for my SA1110 rev 5.
+	 * If the clock divider is uninitialized then reset it to the
+	 * default value to get the 1Hz clock.
+	 */
+	if (RTTR == 0) {
+		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+		printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n");
+		/* The current RTC value probably doesn't make sense either */
+		RCNR = 0;
+		return 0;
+	}
+	return RCNR;
+}
+
+static int sa1100_set_rtc(void)
+{
+	unsigned long current_time = xtime.tv_sec;
+
+	if (RTSR & RTSR_ALE) {
+		/* make sure not to forward the clock over an alarm */
+		unsigned long alarm = RTAR;
+		if (current_time >= alarm && alarm >= RCNR)
+			return -ERESTARTSYS;
+	}
+	RCNR = current_time;
+	return 0;
+}
+
+/* IRQs are disabled before entering here from do_gettimeofday() */
+static unsigned long sa1100_gettimeoffset (void)
+{
+	unsigned long ticks_to_match, elapsed, usec;
+
+	/* Get ticks before next timer match */
+	ticks_to_match = OSMR0 - OSCR;
+
+	/* We need elapsed ticks since last match */
+	elapsed = LATCH - ticks_to_match;
+
+	/* Now convert them to usec */
+	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
+
+	return usec;
+}
+
+/*
+ * We will be entered with IRQs enabled.
+ *
+ * Loop until we get ahead of the free running timer.
+ * This ensures an exact clock tick count and time accuracy.
+ * IRQs are disabled inside the loop to ensure coherence between
+ * lost_ticks (updated in do_timer()) and the match reg value, so we
+ * can use do_gettimeofday() from interrupt handlers.
+ */
+static irqreturn_t
+sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned int next_match;
+
+	do {
+		timer_tick(regs);
+		OSSR = OSSR_M0;  /* Clear match on timer 0 */
+		next_match = (OSMR0 += LATCH);
+	} while ((signed long)(next_match - OSCR) <= 0);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction sa1100_timer_irq = {
+	.name		= "SA11xx Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= sa1100_timer_interrupt
+};
+
+void __init sa1100_init_time(void)
+{
+	struct timespec tv;
+
+	gettimeoffset = sa1100_gettimeoffset;
+	set_rtc = sa1100_set_rtc;
+
+	tv.tv_nsec = 0;
+	tv.tv_sec = sa1100_get_rtc_time();
+	do_settimeofday(&tv);
+
+	OSMR0 = 0;		/* set initial match at 0 */
+	OSSR = 0xf;		/* clear status on all timers */
+	setup_irq(IRQ_OST0, &sa1100_timer_irq);
+	OIER |= OIER_E0;	/* enable match on timer 0 to cause interrupts */
+	OSCR = 0;		/* initialize free-running timer, force first match */
+}
+
diff -Nru a/arch/arm/mach-sa1100/trizeps.c b/arch/arm/mach-sa1100/trizeps.c
--- a/arch/arm/mach-sa1100/trizeps.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mach-sa1100/trizeps.c	2004-06-23 19:04:28 -07:00
@@ -228,4 +228,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(trizeps_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/xp860.c b/arch/arm/mach-sa1100/xp860.c
--- a/arch/arm/mach-sa1100/xp860.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-sa1100/xp860.c	2004-06-23 19:04:27 -07:00
@@ -89,4 +89,5 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	MAPIO(xp860_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/yopy.c b/arch/arm/mach-sa1100/yopy.c
--- a/arch/arm/mach-sa1100/yopy.c	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-sa1100/yopy.c	2004-06-23 19:04:25 -07:00
@@ -91,4 +91,5 @@
 	BOOT_PARAMS(0xc0000100)
 	MAPIO(yopy_map_io)
 	INITIRQ(sa1100_init_irq)
+	INITTIME(sa1100_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
--- a/arch/arm/mach-shark/core.c	2004-06-23 19:04:27 -07:00
+++ b/arch/arm/mach-shark/core.c	2004-06-23 19:04:27 -07:00
@@ -5,13 +5,18 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/param.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
+#include <asm/mach/time.h>
 
 extern void shark_init_irq(void);
 
@@ -24,10 +29,43 @@
 	iotable_init(shark_io_desc, ARRAY_SIZE(shark_io_desc));
 }
 
+#define IRQ_TIMER 0
+#define HZ_TIME ((1193180 + HZ/2) / HZ)
+
+static irqreturn_t
+shark_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction shark_timer_irq = {
+	.name		= "Shark Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= shark_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init shark_init_time(void)
+{
+        unsigned long flags;
+
+	outb(0x34, 0x43);               /* binary, mode 0, LSB/MSB, Ch 0 */
+	outb(HZ_TIME & 0xff, 0x40);     /* LSB of count */
+	outb(HZ_TIME >> 8, 0x40);
+
+	setup_irq(IRQ_TIMER, &shark_timer_irq);
+}
+
+
 MACHINE_START(SHARK, "Shark")
 	MAINTAINER("Alexander Schulz")
 	BOOT_MEM(0x08000000, 0x40000000, 0xe0000000)
 	BOOT_PARAMS(0x08003000)
 	MAPIO(shark_map_io)
 	INITIRQ(shark_init_irq)
+	INITTIME(shark_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-tbox/Makefile b/arch/arm/mach-tbox/Makefile
--- a/arch/arm/mach-tbox/Makefile	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,11 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y			:= core.o
-obj-m			:=
-obj-n			:=
-obj-			:=
-
diff -Nru a/arch/arm/mach-tbox/core.c b/arch/arm/mach-tbox/core.c
--- a/arch/arm/mach-tbox/core.c	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,73 +0,0 @@
-/*
- *  linux/arch/arm/mm/mm-tbox.c
- *
- *  Copyright (C) 1998, 1999, 2000 Phil Blundell
- *  Copyright (C) 1998-1999 Russell King
- *
- *  Extra MM routines for the Tbox architecture
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/elf.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-extern unsigned long soft_irq_mask;
-
-static void tbox_mask_irq(unsigned int irq)
-{
-	__raw_writel(0, INTCONT + (irq << 2));
-	soft_irq_mask &= ~(1<<irq);
-}
-
-static void tbox_unmask_irq(unsigned int irq)
-{
-	soft_irq_mask |= (1<<irq);
-	__raw_writel(1, INTCONT + (irq << 2));
-}
- 
-static void tbox_init_irq(void)
-{
-	unsigned int i;
-
-	/* Disable all interrupts initially. */
-	for (i = 0; i < NR_IRQS; i++) {
-		if (i <= 10 || (i >= 12 && i <= 13)) {
-			irq_desc[i].valid	= 1;
-			irq_desc[i].probe_ok	= 0;
-			irq_desc[i].mask_ack	= tbox_mask_irq;
-			irq_desc[i].mask	= tbox_mask_irq;
-			irq_desc[i].unmask	= tbox_unmask_irq;
-			tbox_mask_irq(i);
-		} else {
-			irq_desc[i].valid	= 0;
-			irq_desc[i].probe_ok	= 0;
-		}
-	}
-}
-
-static struct map_desc tbox_io_desc[] __initdata = {
-	/* See hardware.h for details */
-	{ IO_BASE,	IO_START,	0x00100000, MT_DEVICE }
-};
-
-static void __init tbox_map_io(void)
-{
-	iotable_init(tbox_io_desc, ARRAY_SIZE(tbox_io_desc));
-}
-
-MACHINE_START(TBOX, "unknown-TBOX")
-	MAINTAINER("Philip Blundell")
-	BOOT_MEM(0x80000000, 0x00400000, 0xe0000000)
-	MAPIO(tbox_map_io)
-	INITIRQ(tbox_init_irq)
-MACHINE_END
-
diff -Nru a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile
--- a/arch/arm/mach-versatile/Makefile	2004-06-23 19:04:25 -07:00
+++ b/arch/arm/mach-versatile/Makefile	2004-06-23 19:04:25 -07:00
@@ -2,4 +2,4 @@
 # Makefile for the linux kernel.
 #
 
-obj-y					:= core.o
+obj-y					:= core.o clock.o
diff -Nru a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-versatile/clock.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,146 @@
+/*
+ *  linux/arch/arm/mach-versatile/clock.c
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <asm/semaphore.h>
+#include <asm/hardware/clock.h>
+#include <asm/hardware/icst525.h>
+
+#include "clock.h"
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+	down(&clocks_sem);
+	list_for_each_entry(p, &clocks, node) {
+		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+	up(&clocks_sem);
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+	module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_use(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_use);
+
+void clk_unuse(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_unuse);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret = -EIO;
+#if 0 // Not yet
+	if (clk->setvco) {
+		struct icst525_vco vco;
+
+		vco = icst525_khz_to_vco(clk->params, rate);
+		clk->rate = icst525_khz(clk->params, vco);
+
+		printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
+			clk->name, vco.s, vco.r, vco.v);
+
+		clk->setvco(clk, vco);
+		ret = 0;
+	}
+#endif
+	return 0;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+/*
+ * These are fixed clocks.
+ */
+static struct clk kmi_clk = {
+	.name	= "KMIREFCLK",
+	.rate	= 24000000,
+};
+
+static struct clk uart_clk = {
+	.name	= "UARTCLK",
+	.rate	= 24000000,
+};
+
+static struct clk mmci_clk = {
+	.name	= "MCLK",
+	.rate	= 33000000,
+};
+
+int clk_register(struct clk *clk)
+{
+	down(&clocks_sem);
+	list_add(&clk->node, &clocks);
+	up(&clocks_sem);
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+	down(&clocks_sem);
+	list_del(&clk->node);
+	up(&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static int __init clk_init(void)
+{
+	clk_register(&kmi_clk);
+	clk_register(&uart_clk);
+	clk_register(&mmci_clk);
+	return 0;
+}
+arch_initcall(clk_init);
diff -Nru a/arch/arm/mach-versatile/clock.h b/arch/arm/mach-versatile/clock.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-versatile/clock.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,25 @@
+/*
+ *  linux/arch/arm/mach-versatile/clock.h
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * 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.
+ */
+struct module;
+struct icst525_params;
+
+struct clk {
+	struct list_head	node;
+	unsigned long		rate;
+	struct module		*owner;
+	const char		*name;
+	const struct icst525_params *params;
+	void			*data;
+	void			(*setvco)(struct clk *, struct icst525_vco vco);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
diff -Nru a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
--- a/arch/arm/mach-versatile/core.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mach-versatile/core.c	2004-06-23 19:04:26 -07:00
@@ -22,7 +22,9 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/sysdev.h>
+#include <linux/interrupt.h>
 
+#include <asm/system.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -33,6 +35,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/irq.h>
+#include <asm/mach/time.h>
 #include <asm/mach/map.h>
 #ifdef CONFIG_MMC
 #include <asm/mach/mmc.h>
@@ -511,11 +514,153 @@
 	leds_event = versatile_leds_event;
 }
 
+/*
+ * Where is the timer (VA)?
+ */
+#define TIMER0_VA_BASE		 IO_ADDRESS(VERSATILE_TIMER0_1_BASE)
+#define TIMER1_VA_BASE		(IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20)
+#define TIMER2_VA_BASE		 IO_ADDRESS(VERSATILE_TIMER2_3_BASE)
+#define TIMER3_VA_BASE		(IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20)
+#define VA_IC_BASE		 IO_ADDRESS(VERSATILE_VIC_BASE) 
+
+/*
+ * How long is the timer interval?
+ */
+#define TIMER_INTERVAL	(TICKS_PER_uSEC * mSEC_10)
+#if TIMER_INTERVAL >= 0x100000
+#define TIMER_RELOAD	(TIMER_INTERVAL >> 8)		/* Divide by 256 */
+#define TIMER_CTRL	0x88				/* Enable, Clock / 256 */
+#define TICKS2USECS(x)	(256 * (x) / TICKS_PER_uSEC)
+#elif TIMER_INTERVAL >= 0x10000
+#define TIMER_RELOAD	(TIMER_INTERVAL >> 4)		/* Divide by 16 */
+#define TIMER_CTRL	0x84				/* Enable, Clock / 16 */
+#define TICKS2USECS(x)	(16 * (x) / TICKS_PER_uSEC)
+#else
+#define TIMER_RELOAD	(TIMER_INTERVAL)
+#define TIMER_CTRL	0x80				/* Enable */
+#define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
+#endif
+
+#define TIMER_CTRL_IE	(1 << 5)	/* Interrupt Enable */
+
+/*
+ * What does it look like?
+ */
+typedef struct TimerStruct {
+	unsigned long TimerLoad;
+	unsigned long TimerValue;
+	unsigned long TimerControl;
+	unsigned long TimerClear;
+} TimerStruct_t;
+
+extern unsigned long (*gettimeoffset)(void);
+
+/*
+ * Returns number of ms since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long versatile_gettimeoffset(void)
+{
+	volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE;
+	unsigned long ticks1, ticks2, status;
+
+	/*
+	 * Get the current number of ticks.  Note that there is a race
+	 * condition between us reading the timer and checking for
+	 * an interrupt.  We get around this by ensuring that the
+	 * counter has not reloaded between our two reads.
+	 */
+	ticks2 = timer0->TimerValue & 0xffff;
+	do {
+		ticks1 = ticks2;
+		status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS);
+		ticks2 = timer0->TimerValue & 0xffff;
+	} while (ticks2 > ticks1);
+
+	/*
+	 * Number of ticks since last interrupt.
+	 */
+	ticks1 = TIMER_RELOAD - ticks2;
+
+	/*
+	 * Interrupt pending?  If so, we've reloaded once already.
+	 *
+	 * FIXME: Need to check this is effectively timer 0 that expires
+	 */
+	if (status & IRQMASK_TIMERINT0_1)
+		ticks1 += TIMER_RELOAD;
+
+	/*
+	 * Convert the ticks to usecs
+	 */
+	return TICKS2USECS(ticks1);
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
+
+	// ...clear the interrupt
+	timer0->TimerClear = 1;
+
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction versatile_timer_irq = {
+	.name		= "Versatile Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= versatile_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init versatile_init_time(void)
+{
+	volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
+	volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
+	volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
+	volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE;
+
+	/* 
+	 * set clock frequency: 
+	 *	VERSATILE_REFCLK is 32KHz
+	 *	VERSATILE_TIMCLK is 1MHz
+	 */
+	*(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= 
+	  ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
+	   (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel));
+
+	/*
+	 * Initialise to a known state (all timers off)
+	 */
+	timer0->TimerControl = 0;
+	timer1->TimerControl = 0;
+	timer2->TimerControl = 0;
+	timer3->TimerControl = 0;
+
+	timer0->TimerLoad    = TIMER_RELOAD;
+	timer0->TimerValue   = TIMER_RELOAD;
+	timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE;  /* periodic + IE */
+
+	/* 
+	 * Make irqs happen for the system timer
+	 */
+	setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq);
+	gettimeoffset = versatile_gettimeoffset;
+}
+
 MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
 	MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
 	BOOT_MEM(0x00000000, 0x101f1000, 0xf11f1000)
 	BOOT_PARAMS(0x00000100)
 	MAPIO(versatile_map_io)
 	INITIRQ(versatile_init_irq)
+	INITTIME(versatile_init_time)
 	INIT_MACHINE(versatile_init)
 MACHINE_END
diff -Nru a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
--- a/arch/arm/mm/Kconfig	2004-06-23 19:04:26 -07:00
+++ b/arch/arm/mm/Kconfig	2004-06-23 19:04:26 -07:00
@@ -220,7 +220,7 @@
 # XScale
 config CPU_XSCALE
 	bool
-	depends on ARCH_IOP3XX || ARCH_ADIFCC || ARCH_PXA || ARCH_IXP4XX
+	depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX
 	default y
 	select CPU_32v5
 	select CPU_ABRT_EV5T
diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
--- a/arch/arm/mm/consistent.c	2004-06-23 19:04:28 -07:00
+++ b/arch/arm/mm/consistent.c	2004-06-23 19:04:28 -07:00
@@ -194,7 +194,7 @@
 		/*
 		 * Set the "dma handle"
 		 */
-		*handle = page_to_bus(page);
+		*handle = page_to_dma(dev, page);
 
 		do {
 			BUG_ON(!pte_none(*pte));
diff -Nru a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/vfp/Makefile	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,12 @@
+#
+# linux/arch/arm/vfp/Makefile
+#
+# Copyright (C) 2001 ARM Limited
+#
+
+# EXTRA_CFLAGS := -DDEBUG
+# EXTRA_AFLAGS := -DDEBUG
+
+obj-y			+= vfp.o
+
+vfp-$(CONFIG_VFP)	+= entry.o vfpmodule.o vfphw.o vfpsingle.o vfpdouble.o
diff -Nru a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/vfp/entry.S	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,45 @@
+/*
+ *  linux/arch/arm/vfp/entry.S
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * 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.
+ *
+ * Basic entry code, called from the kernel's undefined instruction trap.
+ *  r0  = faulted instruction
+ *  r5  = faulted PC+4
+ *  r9  = successful return
+ *  r10 = thread_info structure
+ *  lr  = failure return
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/thread_info.h>
+#include <asm/vfpmacros.h>
+
+	.globl	do_vfp
+do_vfp:
+ 	ldr	r4, .LCvfp
+	add	r10, r10, #TI_VFPSTATE	@ r10 = workspace
+	ldr	pc, [r4]		@ call VFP entry point
+
+.LCvfp:
+	.word	vfp_vector
+
+@ This code is called if the VFP does not exist. It needs to flag the
+@ failure to the VFP initialisation code.
+
+	__INIT
+	.globl	vfp_testing_entry
+vfp_testing_entry:
+	ldr	r0, VFP_arch_address
+	str	r5, [r0]		@ known non-zero value
+	mov	pc, r9			@ we have handled the fault
+
+VFP_arch_address:
+	.word	VFP_arch
+
+	__FINIT
diff -Nru a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/vfp/vfp.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,333 @@
+/*
+ *  linux/arch/arm/vfp/vfp.h
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * 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.
+ */
+
+static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
+{
+	if (shift) {
+		if (shift < 32)
+			val = val >> shift | ((val << (32 - shift)) != 0);
+		else
+			val = val != 0;
+	}
+	return val;
+}
+
+static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
+{
+	if (shift) {
+		if (shift < 64)
+			val = val >> shift | ((val << (64 - shift)) != 0);
+		else
+			val = val != 0;
+	}
+	return val;
+}
+
+static inline u32 vfp_hi64to32jamming(u64 val)
+{
+	u32 v;
+
+	asm(
+	"cmp	%Q1, #1		@ vfp_hi64to32jamming\n\t"
+	"movcc	%0, %R1\n\t"
+	"orrcs	%0, %R1, #1"
+	: "=r" (v) : "r" (val) : "cc");
+
+	return v;
+}
+
+static inline void add128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml)
+{
+	asm(	"adds	%Q0, %Q2, %Q4\n\t"
+		"adcs	%R0, %R2, %R4\n\t"
+		"adcs	%Q1, %Q3, %Q5\n\t"
+		"adc	%R1, %R3, %R5"
+	    : "=r" (nl), "=r" (nh)
+	    : "0" (nl), "1" (nh), "r" (ml), "r" (mh)
+	    : "cc");
+	*resh = nh;
+	*resl = nl;
+}
+
+static inline void sub128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml)
+{
+	asm(	"subs	%Q0, %Q2, %Q4\n\t"
+		"sbcs	%R0, %R2, %R4\n\t"
+		"sbcs	%Q1, %Q3, %Q5\n\t"
+		"sbc	%R1, %R3, %R5\n\t"
+	    : "=r" (nl), "=r" (nh)
+	    : "0" (nl), "1" (nh), "r" (ml), "r" (mh)
+	    : "cc");
+	*resh = nh;
+	*resl = nl;
+}
+
+static inline void mul64to128(u64 *resh, u64 *resl, u64 n, u64 m)
+{
+	u32 nh, nl, mh, ml;
+	u64 rh, rma, rmb, rl;
+
+	nl = n;
+	ml = m;
+	rl = (u64)nl * ml;
+
+	nh = n >> 32;
+	rma = (u64)nh * ml;
+
+	mh = m >> 32;
+	rmb = (u64)nl * mh;
+	rma += rmb;
+
+	rh = (u64)nh * mh;
+	rh += ((u64)(rma < rmb) << 32) + (rma >> 32);
+
+	rma <<= 32;
+	rl += rma;
+	rh += (rl < rma);
+
+	*resl = rl;
+	*resh = rh;
+}
+
+static inline void shift64left(u64 *resh, u64 *resl, u64 n)
+{
+	*resh = n >> 63;
+	*resl = n << 1;
+}
+
+static inline u64 vfp_hi64multiply64(u64 n, u64 m)
+{
+	u64 rh, rl;
+	mul64to128(&rh, &rl, n, m);
+	return rh | (rl != 0);
+}
+
+static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
+{
+	u64 mh, ml, remh, reml, termh, terml, z;
+
+	if (nh >= m)
+		return ~0ULL;
+	mh = m >> 32;
+	z = (mh << 32 <= nh) ? 0xffffffff00000000ULL : (nh / mh) << 32;
+	mul64to128(&termh, &terml, m, z);
+	sub128(&remh, &reml, nh, nl, termh, terml);
+	ml = m << 32;
+	while ((s64)remh < 0) {
+		z -= 0x100000000ULL;
+		add128(&remh, &reml, remh, reml, mh, ml);
+	}
+	remh = (remh << 32) | (reml >> 32);
+	z |= (mh << 32 <= remh) ? 0xffffffff : remh / mh;
+	return z;
+}
+
+/*
+ * Operations on unpacked elements
+ */
+#define vfp_sign_negate(sign)	(sign ^ 0x8000)
+
+/*
+ * Single-precision
+ */
+struct vfp_single {
+	s16	exponent;
+	u16	sign;
+	u32	significand;
+};
+
+extern s32 vfp_get_float(unsigned int reg);
+extern void vfp_put_float(unsigned int reg, s32 val);
+
+/*
+ * VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
+ * VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent
+ * VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand
+ *  which are not propagated to the float upon packing.
+ */
+#define VFP_SINGLE_MANTISSA_BITS	(23)
+#define VFP_SINGLE_EXPONENT_BITS	(8)
+#define VFP_SINGLE_LOW_BITS		(32 - VFP_SINGLE_MANTISSA_BITS - 2)
+#define VFP_SINGLE_LOW_BITS_MASK	((1 << VFP_SINGLE_LOW_BITS) - 1)
+
+/*
+ * The bit in an unpacked float which indicates that it is a quiet NaN
+ */
+#define VFP_SINGLE_SIGNIFICAND_QNAN	(1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS))
+
+/*
+ * Operations on packed single-precision numbers
+ */
+#define vfp_single_packed_sign(v)	((v) & 0x80000000)
+#define vfp_single_packed_negate(v)	((v) ^ 0x80000000)
+#define vfp_single_packed_abs(v)	((v) & ~0x80000000)
+#define vfp_single_packed_exponent(v)	(((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
+#define vfp_single_packed_mantissa(v)	((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1))
+
+/*
+ * Unpack a single-precision float.  Note that this returns the magnitude
+ * of the single-precision float mantissa with the 1. if necessary,
+ * aligned to bit 30.
+ */
+static inline void vfp_single_unpack(struct vfp_single *s, s32 val)
+{
+	u32 significand;
+
+	s->sign = vfp_single_packed_sign(val) >> 16,
+	s->exponent = vfp_single_packed_exponent(val);
+
+	significand = (u32) val;
+	significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
+	if (s->exponent && s->exponent != 255)
+		significand |= 0x40000000;
+	s->significand = significand;
+}
+
+/*
+ * Re-pack a single-precision float.  This assumes that the float is
+ * already normalised such that the MSB is bit 30, _not_ bit 31.
+ */
+static inline s32 vfp_single_pack(struct vfp_single *s)
+{
+	u32 val;
+	val = (s->sign << 16) +
+	      (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
+	      (s->significand >> VFP_SINGLE_LOW_BITS);
+	return (s32)val;
+}
+
+#define VFP_NUMBER		(1<<0)
+#define VFP_ZERO		(1<<1)
+#define VFP_DENORMAL		(1<<2)
+#define VFP_INFINITY		(1<<3)
+#define VFP_NAN			(1<<4)
+#define VFP_NAN_SIGNAL		(1<<5)
+
+#define VFP_QNAN		(VFP_NAN)
+#define VFP_SNAN		(VFP_NAN|VFP_NAN_SIGNAL)
+
+static inline int vfp_single_type(struct vfp_single *s)
+{
+	int type = VFP_NUMBER;
+	if (s->exponent == 255) {
+		if (s->significand == 0)
+			type = VFP_INFINITY;
+		else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN)
+			type = VFP_QNAN;
+		else
+			type = VFP_SNAN;
+	} else if (s->exponent == 0) {
+		if (s->significand == 0)
+			type |= VFP_ZERO;
+		else
+			type |= VFP_DENORMAL;
+	}
+	return type;
+}
+
+#ifndef DEBUG
+#define vfp_single_normaliseround(sd,vsd,fpscr,except,func) __vfp_single_normaliseround(sd,vsd,fpscr,except)
+u32 __vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions);
+#else
+u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func);
+#endif
+
+/*
+ * Double-precision
+ */
+struct vfp_double {
+	s16	exponent;
+	u16	sign;
+	u64	significand;
+};
+
+extern u64 vfp_get_double(unsigned int reg);
+extern void vfp_put_double(unsigned int reg, u64 val);
+
+#define VFP_DOUBLE_MANTISSA_BITS	(52)
+#define VFP_DOUBLE_EXPONENT_BITS	(11)
+#define VFP_DOUBLE_LOW_BITS		(64 - VFP_DOUBLE_MANTISSA_BITS - 2)
+#define VFP_DOUBLE_LOW_BITS_MASK	((1 << VFP_DOUBLE_LOW_BITS) - 1)
+
+/*
+ * The bit in an unpacked double which indicates that it is a quiet NaN
+ */
+#define VFP_DOUBLE_SIGNIFICAND_QNAN	(1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS))
+
+/*
+ * Operations on packed single-precision numbers
+ */
+#define vfp_double_packed_sign(v)	((v) & (1ULL << 63))
+#define vfp_double_packed_negate(v)	((v) ^ (1ULL << 63))
+#define vfp_double_packed_abs(v)	((v) & ~(1ULL << 63))
+#define vfp_double_packed_exponent(v)	(((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
+#define vfp_double_packed_mantissa(v)	((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
+
+/*
+ * Unpack a double-precision float.  Note that this returns the magnitude
+ * of the double-precision float mantissa with the 1. if necessary,
+ * aligned to bit 62.
+ */
+static inline void vfp_double_unpack(struct vfp_double *s, s64 val)
+{
+	u64 significand;
+
+	s->sign = vfp_double_packed_sign(val) >> 48;
+	s->exponent = vfp_double_packed_exponent(val);
+
+	significand = (u64) val;
+	significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
+	if (s->exponent && s->exponent != 2047)
+		significand |= (1ULL << 62);
+	s->significand = significand;
+}
+
+/*
+ * Re-pack a double-precision float.  This assumes that the float is
+ * already normalised such that the MSB is bit 30, _not_ bit 31.
+ */
+static inline s64 vfp_double_pack(struct vfp_double *s)
+{
+	u64 val;
+	val = ((u64)s->sign << 48) +
+	      ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
+	      (s->significand >> VFP_DOUBLE_LOW_BITS);
+	return (s64)val;
+}
+
+static inline int vfp_double_type(struct vfp_double *s)
+{
+	int type = VFP_NUMBER;
+	if (s->exponent == 2047) {
+		if (s->significand == 0)
+			type = VFP_INFINITY;
+		else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
+			type = VFP_QNAN;
+		else
+			type = VFP_SNAN;
+	} else if (s->exponent == 0) {
+		if (s->significand == 0)
+			type |= VFP_ZERO;
+		else
+			type |= VFP_DENORMAL;
+	}
+	return type;
+}
+
+u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func);
+
+/*
+ * System registers
+ */
+extern u32 vfp_get_sys(unsigned int reg);
+extern void vfp_put_sys(unsigned int reg, u32 val);
+
+u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
diff -Nru a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/vfp/vfpdouble.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,1186 @@
+/*
+ *  linux/arch/arm/vfp/vfpdouble.c
+ *
+ * This code is derived in part from John R. Housers softfloat library, which
+ * carries the following notice:
+ *
+ * ===========================================================================
+ * This C source file is part of the SoftFloat IEC/IEEE Floating-point
+ * Arithmetic Package, Release 2.
+ *
+ * Written by John R. Hauser.  This work was made possible in part by the
+ * International Computer Science Institute, located at Suite 600, 1947 Center
+ * Street, Berkeley, California 94704.  Funding was partially provided by the
+ * National Science Foundation under grant MIP-9311980.  The original version
+ * of this code was written as part of a project to build a fixed-point vector
+ * processor in collaboration with the University of California at Berkeley,
+ * overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
+ * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+ * arithmetic/softfloat.html'.
+ *
+ * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
+ * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+ * TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
+ * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+ * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+ *
+ * Derivative works are acceptable, even for commercial purposes, so long as
+ * (1) they include prominent notice that the work is derivative, and (2) they
+ * include prominent notice akin to these three paragraphs for those parts of
+ * this code that are retained.
+ * ===========================================================================
+ */
+#include <linux/kernel.h>
+#include <asm/bitops.h>
+#include <asm/ptrace.h>
+#include <asm/vfp.h>
+
+#include "vfpinstr.h"
+#include "vfp.h"
+
+static struct vfp_double vfp_double_default_qnan = {
+	.exponent	= 2047,
+	.sign		= 0,
+	.significand	= VFP_DOUBLE_SIGNIFICAND_QNAN,
+};
+
+static void vfp_double_dump(const char *str, struct vfp_double *d)
+{
+	pr_debug("VFP: %s: sign=%d exponent=%d significand=%016llx\n",
+		 str, d->sign != 0, d->exponent, d->significand);
+}
+
+static void vfp_double_normalise_denormal(struct vfp_double *vd)
+{
+	int bits = 31 - fls(vd->significand >> 32);
+	if (bits == 31)
+		bits = 62 - fls(vd->significand);
+
+	vfp_double_dump("normalise_denormal: in", vd);
+
+	if (bits) {
+		vd->exponent -= bits - 1;
+		vd->significand <<= bits;
+	}
+
+	vfp_double_dump("normalise_denormal: out", vd);
+}
+
+u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func)
+{
+	u64 significand, incr;
+	int exponent, shift, underflow;
+	u32 rmode;
+
+	vfp_double_dump("pack: in", vd);
+
+	/*
+	 * Infinities and NaNs are a special case.
+	 */
+	if (vd->exponent == 2047 && (vd->significand == 0 || exceptions))
+		goto pack;
+
+	/*
+	 * Special-case zero.
+	 */
+	if (vd->significand == 0) {
+		vd->exponent = 0;
+		goto pack;
+	}
+
+	exponent = vd->exponent;
+	significand = vd->significand;
+
+	shift = 32 - fls(significand >> 32);
+	if (shift == 32)
+		shift = 64 - fls(significand);
+	if (shift) {
+		exponent -= shift;
+		significand <<= shift;
+	}
+
+#ifdef DEBUG
+	vd->exponent = exponent;
+	vd->significand = significand;
+	vfp_double_dump("pack: normalised", vd);
+#endif
+
+	/*
+	 * Tiny number?
+	 */
+	underflow = exponent < 0;
+	if (underflow) {
+		significand = vfp_shiftright64jamming(significand, -exponent);
+		exponent = 0;
+#ifdef DEBUG
+		vd->exponent = exponent;
+		vd->significand = significand;
+		vfp_double_dump("pack: tiny number", vd);
+#endif
+		if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1)))
+			underflow = 0;
+	}
+
+	/*
+	 * Select rounding increment.
+	 */
+	incr = 0;
+	rmode = fpscr & FPSCR_RMODE_MASK;
+
+	if (rmode == FPSCR_ROUND_NEAREST) {
+		incr = 1ULL << VFP_DOUBLE_LOW_BITS;
+		if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0)
+			incr -= 1;
+	} else if (rmode == FPSCR_ROUND_TOZERO) {
+		incr = 0;
+	} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
+		incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
+
+	pr_debug("VFP: rounding increment = 0x%08llx\n", incr);
+
+	/*
+	 * Is our rounding going to overflow?
+	 */
+	if ((significand + incr) < significand) {
+		exponent += 1;
+		significand = (significand >> 1) | (significand & 1);
+		incr >>= 1;
+#ifdef DEBUG
+		vd->exponent = exponent;
+		vd->significand = significand;
+		vfp_double_dump("pack: overflow", vd);
+#endif
+	}
+
+	/*
+	 * If any of the low bits (which will be shifted out of the
+	 * number) are non-zero, the result is inexact.
+	 */
+	if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1))
+		exceptions |= FPSCR_IXC;
+
+	/*
+	 * Do our rounding.
+	 */
+	significand += incr;
+
+	/*
+	 * Infinity?
+	 */
+	if (exponent >= 2046) {
+		exceptions |= FPSCR_OFC | FPSCR_IXC;
+		if (incr == 0) {
+			vd->exponent = 2045;
+			vd->significand = 0x7fffffffffffffffULL;
+		} else {
+			vd->exponent = 2047;		/* infinity */
+			vd->significand = 0;
+		}
+	} else {
+		if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0)
+			exponent = 0;
+		if (exponent || significand > 0x8000000000000000ULL)
+			underflow = 0;
+		if (underflow)
+			exceptions |= FPSCR_UFC;
+		vd->exponent = exponent;
+		vd->significand = significand >> 1;
+	}
+
+ pack:
+	vfp_double_dump("pack: final", vd);
+	{
+		s64 d = vfp_double_pack(vd);
+		pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func,
+			 dd, d, exceptions);
+		vfp_put_double(dd, d);
+	}
+	return exceptions;
+}
+
+/*
+ * Propagate the NaN, setting exceptions if it is signalling.
+ * 'n' is always a NaN.  'm' may be a number, NaN or infinity.
+ */
+static u32
+vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
+		  struct vfp_double *vdm, u32 fpscr)
+{
+	struct vfp_double *nan;
+	int tn, tm = 0;
+
+	tn = vfp_double_type(vdn);
+
+	if (vdm)
+		tm = vfp_double_type(vdm);
+
+	if (fpscr & FPSCR_DEFAULT_NAN)
+		/*
+		 * Default NaN mode - always returns a quiet NaN
+		 */
+		nan = &vfp_double_default_qnan;
+	else {
+		/*
+		 * Contemporary mode - select the first signalling
+		 * NAN, or if neither are signalling, the first
+		 * quiet NAN.
+		 */
+		if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
+			nan = vdn;
+		else
+			nan = vdm;
+		/*
+		 * Make the NaN quiet.
+		 */
+		nan->significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
+	}
+
+	*vdd = *nan;
+
+	/*
+	 * If one was a signalling NAN, raise invalid operation.
+	 */
+	return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : 0x100;
+}
+
+/*
+ * Extended operations
+ */
+static u32 vfp_double_fabs(int dd, int unused, int dm, u32 fpscr)
+{
+	vfp_put_double(dd, vfp_double_packed_abs(vfp_get_double(dm)));
+	return 0;
+}
+
+static u32 vfp_double_fcpy(int dd, int unused, int dm, u32 fpscr)
+{
+	vfp_put_double(dd, vfp_get_double(dm));
+	return 0;
+}
+
+static u32 vfp_double_fneg(int dd, int unused, int dm, u32 fpscr)
+{
+	vfp_put_double(dd, vfp_double_packed_negate(vfp_get_double(dm)));
+	return 0;
+}
+
+static u32 vfp_double_fsqrt(int dd, int unused, int dm, u32 fpscr)
+{
+	struct vfp_double vdm, vdd;
+	int ret, tm;
+
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+	tm = vfp_double_type(&vdm);
+	if (tm & (VFP_NAN|VFP_INFINITY)) {
+		struct vfp_double *vdp = &vdd;
+
+		if (tm & VFP_NAN)
+			ret = vfp_propagate_nan(vdp, &vdm, NULL, fpscr);
+		else if (vdm.sign == 0) {
+ sqrt_copy:
+			vdp = &vdm;
+			ret = 0;
+		} else {
+ sqrt_invalid:
+			vdp = &vfp_double_default_qnan;
+			ret = FPSCR_IOC;
+		}
+		vfp_put_double(dd, vfp_double_pack(vdp));
+		return ret;
+	}
+
+	/*
+	 * sqrt(+/- 0) == +/- 0
+	 */
+	if (tm & VFP_ZERO)
+		goto sqrt_copy;
+
+	/*
+	 * Normalise a denormalised number
+	 */
+	if (tm & VFP_DENORMAL)
+		vfp_double_normalise_denormal(&vdm);
+
+	/*
+	 * sqrt(<0) = invalid
+	 */
+	if (vdm.sign)
+		goto sqrt_invalid;
+
+	vfp_double_dump("sqrt", &vdm);
+
+	/*
+	 * Estimate the square root.
+	 */
+	vdd.sign = 0;
+	vdd.exponent = ((vdm.exponent - 1023) >> 1) + 1023;
+	vdd.significand = (u64)vfp_estimate_sqrt_significand(vdm.exponent, vdm.significand >> 32) << 31;
+
+	vfp_double_dump("sqrt estimate1", &vdd);
+
+	vdm.significand >>= 1 + (vdm.exponent & 1);
+	vdd.significand += 2 + vfp_estimate_div128to64(vdm.significand, 0, vdd.significand);
+
+	vfp_double_dump("sqrt estimate2", &vdd);
+
+	/*
+	 * And now adjust.
+	 */
+	if ((vdd.significand & VFP_DOUBLE_LOW_BITS_MASK) <= 5) {
+		if (vdd.significand < 2) {
+			vdd.significand = ~0ULL;
+		} else {
+			u64 termh, terml, remh, reml;
+			vdm.significand <<= 2;
+			mul64to128(&termh, &terml, vdd.significand, vdd.significand);
+			sub128(&remh, &reml, vdm.significand, 0, termh, terml);
+			while ((s64)remh < 0) {
+				vdd.significand -= 1;
+				shift64left(&termh, &terml, vdd.significand);
+				terml |= 1;
+				add128(&remh, &reml, remh, reml, termh, terml);
+			}
+			vdd.significand |= (remh | reml) != 0;
+		}
+	}
+	vdd.significand = vfp_shiftright64jamming(vdd.significand, 1);
+
+	return vfp_double_normaliseround(dd, &vdd, fpscr, 0, "fsqrt");
+}
+
+/*
+ * Equal	:= ZC
+ * Less than	:= N
+ * Greater than	:= C
+ * Unordered	:= CV
+ */
+static u32 vfp_compare(int dd, int signal_on_qnan, int dm, u32 fpscr)
+{
+	s64 d, m;
+	u32 ret = 0;
+
+	m = vfp_get_double(dm);
+	if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) {
+		ret |= FPSCR_C | FPSCR_V;
+		if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
+			/*
+			 * Signalling NaN, or signalling on quiet NaN
+			 */
+			ret |= FPSCR_IOC;
+	}
+
+	d = vfp_get_double(dd);
+	if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) {
+		ret |= FPSCR_C | FPSCR_V;
+		if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
+			/*
+			 * Signalling NaN, or signalling on quiet NaN
+			 */
+			ret |= FPSCR_IOC;
+	}
+
+	if (ret == 0) {
+		if (d == m || vfp_double_packed_abs(d | m) == 0) {
+			/*
+			 * equal
+			 */
+			ret |= FPSCR_Z | FPSCR_C;
+		} else if (vfp_double_packed_sign(d ^ m)) {
+			/*
+			 * different signs
+			 */
+			if (vfp_double_packed_sign(d))
+				/*
+				 * d is negative, so d < m
+				 */
+				ret |= FPSCR_N;
+			else
+				/*
+				 * d is positive, so d > m
+				 */
+				ret |= FPSCR_C;
+		} else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) {
+			/*
+			 * d < m
+			 */
+			ret |= FPSCR_N;
+		} else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) {
+			/*
+			 * d > m
+			 */
+			ret |= FPSCR_C;
+		}
+	}
+
+	return ret;
+}
+
+static u32 vfp_double_fcmp(int dd, int unused, int dm, u32 fpscr)
+{
+	return vfp_compare(dd, 0, dm, fpscr);
+}
+
+static u32 vfp_double_fcmpe(int dd, int unused, int dm, u32 fpscr)
+{
+	return vfp_compare(dd, 1, dm, fpscr);
+}
+
+static u32 vfp_double_fcmpz(int dd, int unused, int dm, u32 fpscr)
+{
+	return vfp_compare(dd, 0, -1, fpscr);
+}
+
+static u32 vfp_double_fcmpez(int dd, int unused, int dm, u32 fpscr)
+{
+	return vfp_compare(dd, 1, -1, fpscr);
+}
+
+static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr)
+{
+	struct vfp_double vdm;
+	struct vfp_single vsd;
+	int tm;
+	u32 exceptions = 0;
+
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+
+	tm = vfp_double_type(&vdm);
+
+	/*
+	 * If we have a signalling NaN, signal invalid operation.
+	 */
+	if (tm == VFP_SNAN)
+		exceptions = FPSCR_IOC;
+
+	if (tm & VFP_DENORMAL)
+		vfp_double_normalise_denormal(&vdm);
+
+	vsd.sign = vdm.sign;
+	vsd.significand = vfp_hi64to32jamming(vdm.significand);
+
+	/*
+	 * If we have an infinity or a NaN, the exponent must be 255
+	 */
+	if (tm & (VFP_INFINITY|VFP_NAN)) {
+		vsd.exponent = 255;
+		if (tm & VFP_NAN)
+			vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
+		goto pack_nan;
+	} else if (tm & VFP_ZERO)
+		vsd.exponent = 0;
+	else
+		vsd.exponent = vdm.exponent - (1023 - 127);
+
+	return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fcvts");
+
+ pack_nan:
+	vfp_put_float(sd, vfp_single_pack(&vsd));
+	return exceptions;
+}
+
+static u32 vfp_double_fuito(int dd, int unused, int dm, u32 fpscr)
+{
+	struct vfp_double vdm;
+	u32 m = vfp_get_float(dm);
+
+	vdm.sign = 0;
+	vdm.exponent = 1023 + 63 - 1;
+	vdm.significand = (u64)m;
+
+	return vfp_double_normaliseround(dd, &vdm, fpscr, 0, "fuito");
+}
+
+static u32 vfp_double_fsito(int dd, int unused, int dm, u32 fpscr)
+{
+	struct vfp_double vdm;
+	u32 m = vfp_get_float(dm);
+
+	vdm.sign = (m & 0x80000000) >> 16;
+	vdm.exponent = 1023 + 63 - 1;
+	vdm.significand = vdm.sign ? -m : m;
+
+	return vfp_double_normaliseround(dd, &vdm, fpscr, 0, "fsito");
+}
+
+static u32 vfp_double_ftoui(int sd, int unused, int dm, u32 fpscr)
+{
+	struct vfp_double vdm;
+	u32 d, exceptions = 0;
+	int rmode = fpscr & FPSCR_RMODE_MASK;
+	int tm;
+
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+
+	/*
+	 * Do we have a denormalised number?
+	 */
+	tm = vfp_double_type(&vdm);
+	if (tm & VFP_DENORMAL)
+		exceptions |= FPSCR_IDC;
+
+	if (tm & VFP_NAN)
+		vdm.sign = 0;
+
+	if (vdm.exponent >= 1023 + 32) {
+		d = vdm.sign ? 0 : 0xffffffff;
+		exceptions = FPSCR_IOC;
+	} else if (vdm.exponent >= 1023 - 1) {
+		int shift = 1023 + 63 - vdm.exponent;
+		u64 rem, incr = 0;
+
+		/*
+		 * 2^0 <= m < 2^32-2^8
+		 */
+		d = (vdm.significand << 1) >> shift;
+		rem = vdm.significand << (65 - shift);
+
+		if (rmode == FPSCR_ROUND_NEAREST) {
+			incr = 0x8000000000000000ULL;
+			if ((d & 1) == 0)
+				incr -= 1;
+		} else if (rmode == FPSCR_ROUND_TOZERO) {
+			incr = 0;
+		} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
+			incr = ~0ULL;
+		}
+
+		if ((rem + incr) < rem) {
+			if (d < 0xffffffff)
+				d += 1;
+			else
+				exceptions |= FPSCR_IOC;
+		}
+
+		if (d && vdm.sign) {
+			d = 0;
+			exceptions |= FPSCR_IOC;
+		} else if (rem)
+			exceptions |= FPSCR_IXC;
+	} else {
+		d = 0;
+		if (vdm.exponent | vdm.significand) {
+			exceptions |= FPSCR_IXC;
+			if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
+				d = 1;
+			else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) {
+				d = 0;
+				exceptions |= FPSCR_IOC;
+			}
+		}
+	}
+
+	pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
+
+	vfp_put_float(sd, d);
+
+	return exceptions;
+}
+
+static u32 vfp_double_ftouiz(int sd, int unused, int dm, u32 fpscr)
+{
+	return vfp_double_ftoui(sd, unused, dm, FPSCR_ROUND_TOZERO);
+}
+
+static u32 vfp_double_ftosi(int sd, int unused, int dm, u32 fpscr)
+{
+	struct vfp_double vdm;
+	u32 d, exceptions = 0;
+	int rmode = fpscr & FPSCR_RMODE_MASK;
+
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+	vfp_double_dump("VDM", &vdm);
+
+	/*
+	 * Do we have denormalised number?
+	 */
+	if (vfp_double_type(&vdm) & VFP_DENORMAL)
+		exceptions |= FPSCR_IDC;
+
+	if (vdm.exponent >= 1023 + 32) {
+		d = 0x7fffffff;
+		if (vdm.sign)
+			d = ~d;
+		exceptions |= FPSCR_IOC;
+	} else if (vdm.exponent >= 1023 - 1) {
+		int shift = 1023 + 63 - vdm.exponent;	/* 58 */
+		u64 rem, incr = 0;
+
+		d = (vdm.significand << 1) >> shift;
+		rem = vdm.significand << (65 - shift);
+
+		if (rmode == FPSCR_ROUND_NEAREST) {
+			incr = 0x8000000000000000ULL;
+			if ((d & 1) == 0)
+				incr -= 1;
+		} else if (rmode == FPSCR_ROUND_TOZERO) {
+			incr = 0;
+		} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
+			incr = ~0ULL;
+		}
+
+		if ((rem + incr) < rem && d < 0xffffffff)
+			d += 1;
+		if (d > 0x7fffffff + (vdm.sign != 0)) {
+			d = 0x7fffffff + (vdm.sign != 0);
+			exceptions |= FPSCR_IOC;
+		} else if (rem)
+			exceptions |= FPSCR_IXC;
+
+		if (vdm.sign)
+			d = -d;
+	} else {
+		d = 0;
+		if (vdm.exponent | vdm.significand) {
+			exceptions |= FPSCR_IXC;
+			if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
+				d = 1;
+			else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign)
+				d = -1;
+		}
+	}
+
+	pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
+
+	vfp_put_float(sd, (s32)d);
+
+	return exceptions;
+}
+
+static u32 vfp_double_ftosiz(int dd, int unused, int dm, u32 fpscr)
+{
+	return vfp_double_ftosi(dd, unused, dm, FPSCR_ROUND_TOZERO);
+}
+
+
+static u32 (* const fop_extfns[32])(int dd, int unused, int dm, u32 fpscr) = {
+	[FEXT_TO_IDX(FEXT_FCPY)]	= vfp_double_fcpy,
+	[FEXT_TO_IDX(FEXT_FABS)]	= vfp_double_fabs,
+	[FEXT_TO_IDX(FEXT_FNEG)]	= vfp_double_fneg,
+	[FEXT_TO_IDX(FEXT_FSQRT)]	= vfp_double_fsqrt,
+	[FEXT_TO_IDX(FEXT_FCMP)]	= vfp_double_fcmp,
+	[FEXT_TO_IDX(FEXT_FCMPE)]	= vfp_double_fcmpe,
+	[FEXT_TO_IDX(FEXT_FCMPZ)]	= vfp_double_fcmpz,
+	[FEXT_TO_IDX(FEXT_FCMPEZ)]	= vfp_double_fcmpez,
+	[FEXT_TO_IDX(FEXT_FCVT)]	= vfp_double_fcvts,
+	[FEXT_TO_IDX(FEXT_FUITO)]	= vfp_double_fuito,
+	[FEXT_TO_IDX(FEXT_FSITO)]	= vfp_double_fsito,
+	[FEXT_TO_IDX(FEXT_FTOUI)]	= vfp_double_ftoui,
+	[FEXT_TO_IDX(FEXT_FTOUIZ)]	= vfp_double_ftouiz,
+	[FEXT_TO_IDX(FEXT_FTOSI)]	= vfp_double_ftosi,
+	[FEXT_TO_IDX(FEXT_FTOSIZ)]	= vfp_double_ftosiz,
+};
+
+
+
+
+static u32
+vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn,
+			  struct vfp_double *vdm, u32 fpscr)
+{
+	struct vfp_double *vdp;
+	u32 exceptions = 0;
+	int tn, tm;
+
+	tn = vfp_double_type(vdn);
+	tm = vfp_double_type(vdm);
+
+	if (tn & tm & VFP_INFINITY) {
+		/*
+		 * Two infinities.  Are they different signs?
+		 */
+		if (vdn->sign ^ vdm->sign) {
+			/*
+			 * different signs -> invalid
+			 */
+			exceptions = FPSCR_IOC;
+			vdp = &vfp_double_default_qnan;
+		} else {
+			/*
+			 * same signs -> valid
+			 */
+			vdp = vdn;
+		}
+	} else if (tn & VFP_INFINITY && tm & VFP_NUMBER) {
+		/*
+		 * One infinity and one number -> infinity
+		 */
+		vdp = vdn;
+	} else {
+		/*
+		 * 'n' is a NaN of some type
+		 */
+		return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
+	}
+	*vdd = *vdp;
+	return exceptions;
+}
+
+static u32
+vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,
+	       struct vfp_double *vdm, u32 fpscr)
+{
+	u32 exp_diff;
+	u64 m_sig;
+
+	if (vdn->significand & (1ULL << 63) ||
+	    vdm->significand & (1ULL << 63)) {
+		pr_info("VFP: bad FP values in %s\n", __func__);
+		vfp_double_dump("VDN", vdn);
+		vfp_double_dump("VDM", vdm);
+	}
+
+	/*
+	 * Ensure that 'n' is the largest magnitude number.  Note that
+	 * if 'n' and 'm' have equal exponents, we do not swap them.
+	 * This ensures that NaN propagation works correctly.
+	 */
+	if (vdn->exponent < vdm->exponent) {
+		struct vfp_double *t = vdn;
+		vdn = vdm;
+		vdm = t;
+	}
+
+	/*
+	 * Is 'n' an infinity or a NaN?  Note that 'm' may be a number,
+	 * infinity or a NaN here.
+	 */
+	if (vdn->exponent == 2047)
+		return vfp_double_fadd_nonnumber(vdd, vdn, vdm, fpscr);
+
+	/*
+	 * We have two proper numbers, where 'vdn' is the larger magnitude.
+	 *
+	 * Copy 'n' to 'd' before doing the arithmetic.
+	 */
+	*vdd = *vdn;
+
+	/*
+	 * Align 'm' with the result.
+	 */
+	exp_diff = vdn->exponent - vdm->exponent;
+	m_sig = vfp_shiftright64jamming(vdm->significand, exp_diff);
+
+	/*
+	 * If the signs are different, we are really subtracting.
+	 */
+	if (vdn->sign ^ vdm->sign) {
+		m_sig = vdn->significand - m_sig;
+		if ((s64)m_sig < 0) {
+			vdd->sign = vfp_sign_negate(vdd->sign);
+			m_sig = -m_sig;
+		}
+	} else {
+		m_sig += vdn->significand;
+	}
+	vdd->significand = m_sig;
+
+	return 0;
+}
+
+static u32
+vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn,
+		    struct vfp_double *vdm, u32 fpscr)
+{
+	vfp_double_dump("VDN", vdn);
+	vfp_double_dump("VDM", vdm);
+
+	/*
+	 * Ensure that 'n' is the largest magnitude number.  Note that
+	 * if 'n' and 'm' have equal exponents, we do not swap them.
+	 * This ensures that NaN propagation works correctly.
+	 */
+	if (vdn->exponent < vdm->exponent) {
+		struct vfp_double *t = vdn;
+		vdn = vdm;
+		vdm = t;
+		pr_debug("VFP: swapping M <-> N\n");
+	}
+
+	vdd->sign = vdn->sign ^ vdm->sign;
+
+	/*
+	 * If 'n' is an infinity or NaN, handle it.  'm' may be anything.
+	 */
+	if (vdn->exponent == 2047) {
+		if (vdn->significand || (vdm->exponent == 2047 && vdm->significand))
+			return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
+		if ((vdm->exponent | vdm->significand) == 0) {
+			*vdd = vfp_double_default_qnan;
+			return FPSCR_IOC;
+		}
+		vdd->exponent = vdn->exponent;
+		vdd->significand = 0;
+		return 0;
+	}
+
+	/*
+	 * If 'm' is zero, the result is always zero.  In this case,
+	 * 'n' may be zero or a number, but it doesn't matter which.
+	 */
+	if ((vdm->exponent | vdm->significand) == 0) {
+		vdd->exponent = 0;
+		vdd->significand = 0;
+		return 0;
+	}
+
+	/*
+	 * We add 2 to the destination exponent for the same reason
+	 * as the addition case - though this time we have +1 from
+	 * each input operand.
+	 */
+	vdd->exponent = vdn->exponent + vdm->exponent - 1023 + 2;
+	vdd->significand = vfp_hi64multiply64(vdn->significand, vdm->significand);
+
+	vfp_double_dump("VDD", vdd);
+	return 0;
+}
+
+#define NEG_MULTIPLY	(1 << 0)
+#define NEG_SUBTRACT	(1 << 1)
+
+static u32
+vfp_double_multiply_accumulate(int dd, int dn, int dm, u32 fpscr, u32 negate, char *func)
+{
+	struct vfp_double vdd, vdp, vdn, vdm;
+	u32 exceptions;
+
+	vfp_double_unpack(&vdn, vfp_get_double(dn));
+	if (vdn.exponent == 0 && vdn.significand)
+		vfp_double_normalise_denormal(&vdn);
+
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+	if (vdm.exponent == 0 && vdm.significand)
+		vfp_double_normalise_denormal(&vdm);
+
+	exceptions = vfp_double_multiply(&vdp, &vdn, &vdm, fpscr);
+	if (negate & NEG_MULTIPLY)
+		vdp.sign = vfp_sign_negate(vdp.sign);
+
+	vfp_double_unpack(&vdn, vfp_get_double(dd));
+	if (negate & NEG_SUBTRACT)
+		vdn.sign = vfp_sign_negate(vdn.sign);
+
+	exceptions |= vfp_double_add(&vdd, &vdn, &vdp, fpscr);
+
+	return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, func);
+}
+
+/*
+ * Standard operations
+ */
+
+/*
+ * sd = sd + (sn * sm)
+ */
+static u32 vfp_double_fmac(int dd, int dn, int dm, u32 fpscr)
+{
+	return vfp_double_multiply_accumulate(dd, dn, dm, fpscr, 0, "fmac");
+}
+
+/*
+ * sd = sd - (sn * sm)
+ */
+static u32 vfp_double_fnmac(int dd, int dn, int dm, u32 fpscr)
+{
+	return vfp_double_multiply_accumulate(dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac");
+}
+
+/*
+ * sd = -sd + (sn * sm)
+ */
+static u32 vfp_double_fmsc(int dd, int dn, int dm, u32 fpscr)
+{
+	return vfp_double_multiply_accumulate(dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc");
+}
+
+/*
+ * sd = -sd - (sn * sm)
+ */
+static u32 vfp_double_fnmsc(int dd, int dn, int dm, u32 fpscr)
+{
+	return vfp_double_multiply_accumulate(dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
+}
+
+/*
+ * sd = sn * sm
+ */
+static u32 vfp_double_fmul(int dd, int dn, int dm, u32 fpscr)
+{
+	struct vfp_double vdd, vdn, vdm;
+	u32 exceptions;
+
+	vfp_double_unpack(&vdn, vfp_get_double(dn));
+	if (vdn.exponent == 0 && vdn.significand)
+		vfp_double_normalise_denormal(&vdn);
+
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+	if (vdm.exponent == 0 && vdm.significand)
+		vfp_double_normalise_denormal(&vdm);
+
+	exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
+	return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fmul");
+}
+
+/*
+ * sd = -(sn * sm)
+ */
+static u32 vfp_double_fnmul(int dd, int dn, int dm, u32 fpscr)
+{
+	struct vfp_double vdd, vdn, vdm;
+	u32 exceptions;
+
+	vfp_double_unpack(&vdn, vfp_get_double(dn));
+	if (vdn.exponent == 0 && vdn.significand)
+		vfp_double_normalise_denormal(&vdn);
+
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+	if (vdm.exponent == 0 && vdm.significand)
+		vfp_double_normalise_denormal(&vdm);
+
+	exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
+	vdd.sign = vfp_sign_negate(vdd.sign);
+
+	return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fnmul");
+}
+
+/*
+ * sd = sn + sm
+ */
+static u32 vfp_double_fadd(int dd, int dn, int dm, u32 fpscr)
+{
+	struct vfp_double vdd, vdn, vdm;
+	u32 exceptions;
+
+	vfp_double_unpack(&vdn, vfp_get_double(dn));
+	if (vdn.exponent == 0 && vdn.significand)
+		vfp_double_normalise_denormal(&vdn);
+
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+	if (vdm.exponent == 0 && vdm.significand)
+		vfp_double_normalise_denormal(&vdm);
+
+	exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
+
+	return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fadd");
+}
+
+/*
+ * sd = sn - sm
+ */
+static u32 vfp_double_fsub(int dd, int dn, int dm, u32 fpscr)
+{
+	struct vfp_double vdd, vdn, vdm;
+	u32 exceptions;
+
+	vfp_double_unpack(&vdn, vfp_get_double(dn));
+	if (vdn.exponent == 0 && vdn.significand)
+		vfp_double_normalise_denormal(&vdn);
+
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+	if (vdm.exponent == 0 && vdm.significand)
+		vfp_double_normalise_denormal(&vdm);
+
+	/*
+	 * Subtraction is like addition, but with a negated operand.
+	 */
+	vdm.sign = vfp_sign_negate(vdm.sign);
+
+	exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
+
+	return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fsub");
+}
+
+/*
+ * sd = sn / sm
+ */
+static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr)
+{
+	struct vfp_double vdd, vdn, vdm;
+	u32 exceptions = 0;
+	int tm, tn;
+
+	vfp_double_unpack(&vdn, vfp_get_double(dn));
+	vfp_double_unpack(&vdm, vfp_get_double(dm));
+
+	vdd.sign = vdn.sign ^ vdm.sign;
+
+	tn = vfp_double_type(&vdn);
+	tm = vfp_double_type(&vdm);
+
+	/*
+	 * Is n a NAN?
+	 */
+	if (tn & VFP_NAN)
+		goto vdn_nan;
+
+	/*
+	 * Is m a NAN?
+	 */
+	if (tm & VFP_NAN)
+		goto vdm_nan;
+
+	/*
+	 * If n and m are infinity, the result is invalid
+	 * If n and m are zero, the result is invalid
+	 */
+	if (tm & tn & (VFP_INFINITY|VFP_ZERO))
+		goto invalid;
+
+	/*
+	 * If n is infinity, the result is infinity
+	 */
+	if (tn & VFP_INFINITY)
+		goto infinity;
+
+	/*
+	 * If m is zero, raise div0 exceptions
+	 */
+	if (tm & VFP_ZERO)
+		goto divzero;
+
+	/*
+	 * If m is infinity, or n is zero, the result is zero
+	 */
+	if (tm & VFP_INFINITY || tn & VFP_ZERO)
+		goto zero;
+
+	if (tn & VFP_DENORMAL)
+		vfp_double_normalise_denormal(&vdn);
+	if (tm & VFP_DENORMAL)
+		vfp_double_normalise_denormal(&vdm);
+
+	/*
+	 * Ok, we have two numbers, we can perform division.
+	 */
+	vdd.exponent = vdn.exponent - vdm.exponent + 1023 - 1;
+	vdm.significand <<= 1;
+	if (vdm.significand <= (2 * vdn.significand)) {
+		vdn.significand >>= 1;
+		vdd.exponent++;
+	}
+	vdd.significand = vfp_estimate_div128to64(vdn.significand, 0, vdm.significand);
+	if ((vdd.significand & 0x1ff) <= 2) {
+		u64 termh, terml, remh, reml;
+		mul64to128(&termh, &terml, vdm.significand, vdd.significand);
+		sub128(&remh, &reml, vdn.significand, 0, termh, terml);
+		while ((s64)remh < 0) {
+			vdd.significand -= 1;
+			add128(&remh, &reml, remh, reml, 0, vdm.significand);
+		}
+		vdd.significand |= (reml != 0);
+	}
+	return vfp_double_normaliseround(dd, &vdd, fpscr, 0, "fdiv");
+
+ vdn_nan:
+	exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr);
+ pack:
+	vfp_put_double(dd, vfp_double_pack(&vdd));
+	return exceptions;
+
+ vdm_nan:
+	exceptions = vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr);
+	goto pack;
+
+ zero:
+	vdd.exponent = 0;
+	vdd.significand = 0;
+	goto pack;
+
+ divzero:
+	exceptions = FPSCR_DZC;
+ infinity:
+	vdd.exponent = 2047;
+	vdd.significand = 0;
+	goto pack;
+
+ invalid:
+	vfp_put_double(dd, vfp_double_pack(&vfp_double_default_qnan));
+	return FPSCR_IOC;
+}
+
+static u32 (* const fop_fns[16])(int dd, int dn, int dm, u32 fpscr) = {
+	[FOP_TO_IDX(FOP_FMAC)]	= vfp_double_fmac,
+	[FOP_TO_IDX(FOP_FNMAC)]	= vfp_double_fnmac,
+	[FOP_TO_IDX(FOP_FMSC)]	= vfp_double_fmsc,
+	[FOP_TO_IDX(FOP_FNMSC)]	= vfp_double_fnmsc,
+	[FOP_TO_IDX(FOP_FMUL)]	= vfp_double_fmul,
+	[FOP_TO_IDX(FOP_FNMUL)]	= vfp_double_fnmul,
+	[FOP_TO_IDX(FOP_FADD)]	= vfp_double_fadd,
+	[FOP_TO_IDX(FOP_FSUB)]	= vfp_double_fsub,
+	[FOP_TO_IDX(FOP_FDIV)]	= vfp_double_fdiv,
+};
+
+#define FREG_BANK(x)	((x) & 0x0c)
+#define FREG_IDX(x)	((x) & 3)
+
+u32 vfp_double_cpdo(u32 inst, u32 fpscr)
+{
+	u32 op = inst & FOP_MASK;
+	u32 exceptions = 0;
+	unsigned int dd = vfp_get_sd(inst);
+	unsigned int dn = vfp_get_sn(inst);
+	unsigned int dm = vfp_get_sm(inst);
+	unsigned int vecitr, veclen, vecstride;
+	u32 (*fop)(int, int, s32, u32);
+
+	veclen = fpscr & FPSCR_LENGTH_MASK;
+	vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2;
+
+	/*
+	 * If destination bank is zero, vector length is always '1'.
+	 * ARM DDI0100F C5.1.3, C5.3.2.
+	 */
+	if (FREG_BANK(dd) == 0)
+		veclen = 0;
+
+	pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
+		 (veclen >> FPSCR_LENGTH_BIT) + 1);
+
+	fop = (op == FOP_EXT) ? fop_extfns[dn] : fop_fns[FOP_TO_IDX(op)];
+	if (!fop)
+		goto invalid;
+
+	for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
+		u32 except;
+
+		if (op == FOP_EXT)
+			pr_debug("VFP: itr%d (d%u.%u) = op[%u] (d%u.%u)\n",
+				 vecitr >> FPSCR_LENGTH_BIT,
+				 dd >> 1, dd & 1, dn,
+				 dm >> 1, dm & 1);
+		else
+			pr_debug("VFP: itr%d (d%u.%u) = (d%u.%u) op[%u] (d%u.%u)\n",
+				 vecitr >> FPSCR_LENGTH_BIT,
+				 dd >> 1, dd & 1,
+				 dn >> 1, dn & 1,
+				 FOP_TO_IDX(op),
+				 dm >> 1, dm & 1);
+
+		except = fop(dd, dn, dm, fpscr);
+		pr_debug("VFP: itr%d: exceptions=%08x\n",
+			 vecitr >> FPSCR_LENGTH_BIT, except);
+
+		exceptions |= except;
+
+		/*
+		 * This ensures that comparisons only operate on scalars;
+		 * comparisons always return with one FPSCR status bit set.
+		 */
+		if (except & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
+			break;
+
+		/*
+		 * CHECK: It appears to be undefined whether we stop when
+		 * we encounter an exception.  We continue.
+		 */
+
+		dd = FREG_BANK(dd) + ((FREG_IDX(dd) + vecstride) & 6);
+		dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6);
+		if (FREG_BANK(dm) != 0)
+			dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 6);
+	}
+	return exceptions;
+
+ invalid:
+	return ~0;
+}
diff -Nru a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/vfp/vfphw.S	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,210 @@
+/*
+ *  linux/arch/arm/vfp/vfphw.S
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * 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 code is called from the kernel's undefined instruction trap.
+ * r9 holds the return address for successful handling.
+ * lr holds the return address for unrecognised instructions.
+ * r10 points at the start of the private FP workspace in the thread structure
+ * sp points to a struct pt_regs (as defined in include/asm/proc/ptrace.h)
+ */
+#include <asm/thread_info.h>
+#include <asm/vfpmacros.h>
+#include "../kernel/entry-header.S"
+
+	.macro	DBGSTR, str
+#ifdef DEBUG
+	stmfd	sp!, {r0-r3, ip, lr}
+	add	r0, pc, #4
+	bl	printk
+	b	1f
+	.asciz  "<7>VFP: \str\n"
+	.balign 4
+1:	ldmfd	sp!, {r0-r3, ip, lr}
+#endif
+	.endm
+
+	.macro  DBGSTR1, str, arg
+#ifdef DEBUG
+	stmfd	sp!, {r0-r3, ip, lr}
+	mov	r1, \arg
+	add	r0, pc, #4
+	bl	printk
+	b	1f
+	.asciz  "<7>VFP: \str\n"
+	.balign 4
+1:	ldmfd	sp!, {r0-r3, ip, lr}
+#endif
+	.endm
+
+	.macro  DBGSTR3, str, arg1, arg2, arg3
+#ifdef DEBUG
+	stmfd	sp!, {r0-r3, ip, lr}
+	mov	r3, \arg3
+	mov	r2, \arg2
+	mov	r1, \arg1
+	add	r0, pc, #4
+	bl	printk
+	b	1f
+	.asciz  "<7>VFP: \str\n"
+	.balign 4
+1:	ldmfd	sp!, {r0-r3, ip, lr}
+#endif
+	.endm
+
+
+@ VFP hardware support entry point.
+@
+@  r0  = faulted instruction
+@  r5  = faulted PC+4
+@  r9  = successful return
+@  r10 = vfp_state union
+@  lr  = failure return
+
+	.globl	vfp_support_entry
+vfp_support_entry:
+	DBGSTR3	"instr %08x pc %08x state %p", r0, r5, r10
+
+	VFPFMRX	r1, FPEXC		@ Is the VFP enabled?
+	DBGSTR1	"fpexc %08x", r1
+	tst	r1, #FPEXC_ENABLE
+	bne	look_for_VFP_exceptions	@ VFP is already enabled
+
+	DBGSTR1 "enable %x", r10
+	ldr	r3, last_VFP_context_address
+	orr	r1, r1, #FPEXC_ENABLE	@ user FPEXC has the enable bit set
+	ldr	r4, [r3]		@ last_VFP_context pointer
+	bic	r2, r1, #FPEXC_EXCEPTION @ make sure exceptions are disabled
+	cmp	r4, r10
+	beq	check_for_exception	@ we are returning to the same
+					@ process, so the registers are
+					@ still there.  In this case, we do
+					@ not want to drop a pending exception.
+
+	VFPFMXR	FPEXC, r2		@ enable VFP, disable any pending
+					@ exceptions, so we can get at the
+					@ rest of it
+
+	@ Save out the current registers to the old thread state
+
+	DBGSTR1	"save old state %p", r4
+	cmp	r4, #0
+	beq	no_old_VFP_process
+	VFPFMRX	r2, FPSCR		@ current status
+	VFPFMRX	r6, FPINST		@ FPINST (always there, rev0 onwards)
+	tst	r1, #FPEXC_FPV2		@ is there an FPINST2 to read?
+	VFPFMRX	r8, FPINST2, NE		@ FPINST2 if needed - avoids reading
+					@ nonexistant reg on rev0
+	VFPFSTMIA r4 			@ save the working registers
+	add	r4, r4, #8*16+4
+	stmia	r4, {r1, r2, r6, r8}	@ save FPEXC, FPSCR, FPINST, FPINST2
+					@ and point r4 at the word at the
+					@ start of the register dump
+
+no_old_VFP_process:
+	DBGSTR1	"load state %p", r10
+	str	r10, [r3]		@ update the last_VFP_context pointer
+					@ Load the saved state back into the VFP
+	add	r4, r10, #8*16+4
+	ldmia	r4, {r1, r2, r6, r8}	@ load FPEXC, FPSCR, FPINST, FPINST2
+	VFPFLDMIA r10	 		@ reload the working registers while
+					@ FPEXC is in a safe state
+	tst	r1, #FPEXC_FPV2		@ is there an FPINST2 to write?
+	VFPFMXR	FPINST2, r8, NE		@ FPINST2 if needed - avoids writing
+					@ nonexistant reg on rev0
+	VFPFMXR	FPINST, r6
+	VFPFMXR	FPSCR, r2		@ restore status
+
+check_for_exception:
+	tst	r1, #FPEXC_EXCEPTION
+	bne	process_exception	@ might as well handle the pending
+					@ exception before retrying branch
+					@ out before setting an FPEXC that
+					@ stops us reading stuff
+	VFPFMXR	FPEXC, r1		@ restore FPEXC last
+	sub	r5, r5, #4
+	str	r5, [sp, #S_PC]		@ retry the instruction
+	mov	pc, r9			@ we think we have handled things
+
+
+look_for_VFP_exceptions:
+	tst	r1, #FPEXC_EXCEPTION
+	bne	process_exception
+	VFPFMRX	r2, FPSCR
+	tst	r2, #FPSCR_IXE		@ IXE doesn't set FPEXC_EXCEPTION !
+	bne	process_exception
+
+	@ Fall into hand on to next handler - appropriate coproc instr
+	@ not recognised by VFP
+
+	DBGSTR	"not VFP"
+	mov	pc, lr
+
+process_exception:
+	DBGSTR	"bounce"
+	sub	r5, r5, #4
+	str	r5, [sp, #S_PC]		@ retry the instruction on exit from
+					@ the imprecise exception handling in
+					@ the support code
+	mov	r2, sp			@ nothing stacked - regdump is at TOS
+	mov	lr, r9			@ setup for a return to the user code.
+
+	@ Now call the C code to package up the bounce to the support code
+	@   r0 holds the trigger instruction
+	@   r1 holds the FPEXC value
+	@   r2 pointer to register dump
+	b	VFP9_bounce		@ we have handled this - the support
+					@ code will raise an exception if
+					@ required. If not, the user code will
+					@ retry the faulted instruction
+
+last_VFP_context_address:
+	.word	last_VFP_context
+
+	.globl	vfp_get_float
+vfp_get_float:
+	add	pc, pc, r0, lsl #3
+	mov	r0, r0
+	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+	mrc	p10, 0, r0, c\dr, c0, 0	@ fmrs	r0, s0
+	mov	pc, lr
+	mrc	p10, 0, r0, c\dr, c0, 4	@ fmrs	r0, s1
+	mov	pc, lr
+	.endr
+
+	.globl	vfp_put_float
+vfp_put_float:
+	add	pc, pc, r0, lsl #3
+	mov	r0, r0
+	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+	mcr	p10, 0, r1, c\dr, c0, 0	@ fmsr	r0, s0
+	mov	pc, lr
+	mcr	p10, 0, r1, c\dr, c0, 4	@ fmsr	r0, s1
+	mov	pc, lr
+	.endr
+
+	.globl	vfp_get_double
+vfp_get_double:
+	mov	r0, r0, lsr #1
+	add	pc, pc, r0, lsl #3
+	mov	r0, r0
+	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+	mrrc	p10, 1, r0, r1, c\dr	@ fmrrd	r0, r1, d\dr
+	mov	pc, lr
+	.endr
+
+	.globl	vfp_put_double
+vfp_put_double:
+	mov	r0, r0, lsr #1
+	add	pc, pc, r0, lsl #3
+	mov	r0, r0
+	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+	mcrr	p10, 1, r1, r2, c\dr	@ fmrrd	r1, r2, d\dr
+	mov	pc, lr
+	.endr
diff -Nru a/arch/arm/vfp/vfpinstr.h b/arch/arm/vfp/vfpinstr.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/vfp/vfpinstr.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,88 @@
+/*
+ *  linux/arch/arm/vfp/vfpinstr.h
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * 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.
+ *
+ * VFP instruction masks.
+ */
+#define INST_CPRTDO(inst)	(((inst) & 0x0f000000) == 0x0e000000)
+#define INST_CPRT(inst)		((inst) & (1 << 4))
+#define INST_CPRT_L(inst)	((inst) & (1 << 20))
+#define INST_CPRT_Rd(inst)	(((inst) & (15 << 12)) >> 12)
+#define INST_CPRT_OP(inst)	(((inst) >> 21) & 7)
+#define INST_CPNUM(inst)	((inst) & 0xf00)
+#define CPNUM(cp)		((cp) << 8)
+
+#define FOP_MASK	(0x00b00040)
+#define FOP_FMAC	(0x00000000)
+#define FOP_FNMAC	(0x00000040)
+#define FOP_FMSC	(0x00100000)
+#define FOP_FNMSC	(0x00100040)
+#define FOP_FMUL	(0x00200000)
+#define FOP_FNMUL	(0x00200040)
+#define FOP_FADD	(0x00300000)
+#define FOP_FSUB	(0x00300040)
+#define FOP_FDIV	(0x00800000)
+#define FOP_EXT		(0x00b00040)
+
+#define FOP_TO_IDX(inst)	((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4)
+
+#define FEXT_MASK	(0x000f0080)
+#define FEXT_FCPY	(0x00000000)
+#define FEXT_FABS	(0x00000080)
+#define FEXT_FNEG	(0x00010000)
+#define FEXT_FSQRT	(0x00010080)
+#define FEXT_FCMP	(0x00040000)
+#define FEXT_FCMPE	(0x00040080)
+#define FEXT_FCMPZ	(0x00050000)
+#define FEXT_FCMPEZ	(0x00050080)
+#define FEXT_FCVT	(0x00070080)
+#define FEXT_FUITO	(0x00080000)
+#define FEXT_FSITO	(0x00080080)
+#define FEXT_FTOUI	(0x000c0000)
+#define FEXT_FTOUIZ	(0x000c0080)
+#define FEXT_FTOSI	(0x000d0000)
+#define FEXT_FTOSIZ	(0x000d0080)
+
+#define FEXT_TO_IDX(inst)	((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
+
+#define vfp_get_sd(inst)	((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22)
+#define vfp_get_dd(inst)	((inst & 0x0000f000) >> 12)
+#define vfp_get_sm(inst)	((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
+#define vfp_get_dm(inst)	((inst & 0x0000000f))
+#define vfp_get_sn(inst)	((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
+#define vfp_get_dn(inst)	((inst & 0x000f0000) >> 16)
+
+#define vfp_single(inst)	(((inst) & 0x0000f00) == 0xa00)
+
+#define FPSCR_N	(1 << 31)
+#define FPSCR_Z	(1 << 30)
+#define FPSCR_C (1 << 29)
+#define FPSCR_V	(1 << 28)
+
+/*
+ * Since we aren't building with -mfpu=vfp, we need to code
+ * these instructions using their MRC/MCR equivalents.
+ */
+#define vfpreg(_vfp_) #_vfp_
+
+#define fmrx(_vfp_) ({			\
+	u32 __v;			\
+	asm("mrc%? p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmrx	%0, " #_vfp_	\
+	    : "=r" (__v));		\
+	__v;				\
+ })
+
+#define fmxr(_vfp_,_var_)		\
+	asm("mcr%? p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr	" #_vfp_ ", %0"	\
+	   : : "r" (_var_))
+
+u32 vfp_single_cpdo(u32 inst, u32 fpscr);
+u32 vfp_single_cprt(u32 inst, u32 fpscr, struct pt_regs *regs);
+
+u32 vfp_double_cpdo(u32 inst, u32 fpscr);
diff -Nru a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/vfp/vfpmodule.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,288 @@
+/*
+ *  linux/arch/arm/vfp/vfpmodule.c
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * 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/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/vfp.h>
+
+#include "vfpinstr.h"
+#include "vfp.h"
+
+/*
+ * Our undef handlers (in entry.S)
+ */
+void vfp_testing_entry(void);
+void vfp_support_entry(void);
+
+void (*vfp_vector)(void) = vfp_testing_entry;
+union vfp_state *last_VFP_context;
+
+/*
+ * Dual-use variable.
+ * Used in startup: set to non-zero if VFP checks fail
+ * After startup, holds VFP architecture
+ */
+unsigned int VFP_arch;
+
+/*
+ * Per-thread VFP initialisation.
+ */
+void vfp_flush_thread(union vfp_state *vfp)
+{
+	memset(vfp, 0, sizeof(union vfp_state));
+
+	vfp->hard.fpexc = FPEXC_ENABLE;
+	vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
+
+	/*
+	 * Disable VFP to ensure we initialise it first.
+	 */
+	fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+
+	/*
+	 * Ensure we don't try to overwrite our newly initialised
+	 * state information on the first fault.
+	 */
+	if (last_VFP_context == vfp)
+		last_VFP_context = NULL;
+}
+
+/*
+ * Per-thread VFP cleanup.
+ */
+void vfp_release_thread(union vfp_state *vfp)
+{
+	if (last_VFP_context == vfp)
+		last_VFP_context = NULL;
+}
+
+/*
+ * Raise a SIGFPE for the current process.
+ * sicode describes the signal being raised.
+ */
+void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
+{
+	siginfo_t info;
+
+	memset(&info, 0, sizeof(info));
+
+	info.si_signo = SIGFPE;
+	info.si_code = sicode;
+	info.si_addr = (void *)(instruction_pointer(regs) - 4);
+
+	/*
+	 * This is the same as NWFPE, because it's not clear what
+	 * this is used for
+	 */
+	current->thread.error_code = 0;
+	current->thread.trap_no = 6;
+
+	force_sig_info(SIGFPE, &info, current);
+}
+
+static void vfp_panic(char *reason)
+{
+	int i;
+
+	printk(KERN_ERR "VFP: Error: %s\n", reason);
+	printk(KERN_ERR "VFP: EXC 0x%08x SCR 0x%08x INST 0x%08x\n",
+		fmrx(FPEXC), fmrx(FPSCR), fmrx(FPINST));
+	for (i = 0; i < 32; i += 2)
+		printk(KERN_ERR "VFP: s%2u: 0x%08x s%2u: 0x%08x\n",
+		       i, vfp_get_float(i), i+1, vfp_get_float(i+1));
+}
+
+/*
+ * Process bitmask of exception conditions.
+ */
+static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs)
+{
+	int si_code = 0;
+
+	pr_debug("VFP: raising exceptions %08x\n", exceptions);
+
+	if (exceptions == (u32)-1) {
+		vfp_panic("unhandled bounce");
+		vfp_raise_sigfpe(0, regs);
+		return;
+	}
+
+	/*
+	 * If any of the status flags are set, update the FPSCR.
+	 * Comparison instructions always return at least one of
+	 * these flags set.
+	 */
+	if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
+		fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V);
+
+	fpscr |= exceptions;
+
+	fmxr(FPSCR, fpscr);
+
+#define RAISE(stat,en,sig)				\
+	if (exceptions & stat && fpscr & en)		\
+		si_code = sig;
+
+	/*
+	 * These are arranged in priority order, least to highest.
+	 */
+	RAISE(FPSCR_IXC, FPSCR_IXE, FPE_FLTRES);
+	RAISE(FPSCR_UFC, FPSCR_UFE, FPE_FLTUND);
+	RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF);
+	RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV);
+
+	if (si_code)
+		vfp_raise_sigfpe(si_code, regs);
+}
+
+/*
+ * Emulate a VFP instruction.
+ */
+static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
+{
+	u32 exceptions = (u32)-1;
+
+	pr_debug("VFP: emulate: INST=0x%08x SCR=0x%08x\n", inst, fpscr);
+
+	if (INST_CPRTDO(inst)) {
+		if (!INST_CPRT(inst)) {
+			/*
+			 * CPDO
+			 */
+			if (vfp_single(inst)) {
+				exceptions = vfp_single_cpdo(inst, fpscr);
+			} else {
+				exceptions = vfp_double_cpdo(inst, fpscr);
+			}
+		} else {
+			/*
+			 * A CPRT instruction can not appear in FPINST2, nor
+			 * can it cause an exception.  Therefore, we do not
+			 * have to emulate it.
+			 */
+		}
+	} else {
+		/*
+		 * A CPDT instruction can not appear in FPINST2, nor can
+		 * it cause an exception.  Therefore, we do not have to
+		 * emulate it.
+		 */
+	}
+	return exceptions;
+}
+
+/*
+ * Package up a bounce condition.
+ */
+void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
+{
+	u32 fpscr, orig_fpscr, exceptions, inst;
+
+	pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
+
+	/*
+	 * Enable access to the VFP so we can handle the bounce.
+	 */
+	fmxr(FPEXC, fpexc & ~(FPEXC_EXCEPTION|FPEXC_INV|FPEXC_UFC|FPEXC_IOC));
+
+	orig_fpscr = fpscr = fmrx(FPSCR);
+
+	/*
+	 * If we are running with inexact exceptions enabled, we need to
+	 * emulate the trigger instruction.  Note that as we're emulating
+	 * the trigger instruction, we need to increment PC.
+	 */
+	if (fpscr & FPSCR_IXE) {
+		regs->ARM_pc += 4;
+		goto emulate;
+	}
+
+	barrier();
+
+	/*
+	 * Modify fpscr to indicate the number of iterations remaining
+	 */
+	if (fpexc & FPEXC_EXCEPTION) {
+		u32 len;
+
+		len = fpexc + (1 << FPEXC_LENGTH_BIT);
+
+		fpscr &= ~FPSCR_LENGTH_MASK;
+		fpscr |= (len & FPEXC_LENGTH_MASK) << (FPSCR_LENGTH_BIT - FPEXC_LENGTH_BIT);
+	}
+
+	/*
+	 * Handle the first FP instruction.  We used to take note of the
+	 * FPEXC bounce reason, but this appears to be unreliable.
+	 * Emulate the bounced instruction instead.
+	 */
+	inst = fmrx(FPINST);
+	exceptions = vfp_emulate_instruction(inst, fpscr, regs);
+	if (exceptions)
+		vfp_raise_exceptions(exceptions, inst, orig_fpscr, regs);
+
+	/*
+	 * If there isn't a second FP instruction, exit now.
+	 */
+	if (!(fpexc & FPEXC_FPV2))
+		return;
+
+	/*
+	 * The barrier() here prevents fpinst2 being read
+	 * before the condition above.
+	 */
+	barrier();
+	trigger = fmrx(FPINST2);
+	fpscr = fmrx(FPSCR);
+
+ emulate:
+	exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
+	if (exceptions)
+		vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
+}
+ 
+/*
+ * VFP support code initialisation.
+ */
+static int __init vfp_init(void)
+{
+	unsigned int vfpsid;
+
+	/*
+	 * First check that there is a VFP that we can use.
+	 * The handler is already setup to just log calls, so
+	 * we just need to read the VFPSID register.
+	 */
+	vfpsid = fmrx(FPSID);
+
+	printk(KERN_INFO "VFP support v0.3: ");
+	if (VFP_arch) {
+		printk("not present\n");
+	} else if (vfpsid & FPSID_NODOUBLE) {
+		printk("no double precision support\n");
+	} else {
+		VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT;  /* Extract the architecture version */
+		printk("implementor %02x architecture %d part %02x variant %x rev %x\n",
+			(vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT,
+			(vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT,
+			(vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT,
+			(vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT,
+			(vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT);
+		vfp_vector = vfp_support_entry;
+	}
+	return 0;
+}
+
+late_initcall(vfp_init);
diff -Nru a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/vfp/vfpsingle.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,1224 @@
+/*
+ *  linux/arch/arm/vfp/vfpsingle.c
+ *
+ * This code is derived in part from John R. Housers softfloat library, which
+ * carries the following notice:
+ *
+ * ===========================================================================
+ * This C source file is part of the SoftFloat IEC/IEEE Floating-point
+ * Arithmetic Package, Release 2.
+ *
+ * Written by John R. Hauser.  This work was made possible in part by the
+ * International Computer Science Institute, located at Suite 600, 1947 Center
+ * Street, Berkeley, California 94704.  Funding was partially provided by the
+ * National Science Foundation under grant MIP-9311980.  The original version
+ * of this code was written as part of a project to build a fixed-point vector
+ * processor in collaboration with the University of California at Berkeley,
+ * overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
+ * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+ * arithmetic/softfloat.html'.
+ *
+ * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
+ * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+ * TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
+ * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+ * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+ *
+ * Derivative works are acceptable, even for commercial purposes, so long as
+ * (1) they include prominent notice that the work is derivative, and (2) they
+ * include prominent notice akin to these three paragraphs for those parts of
+ * this code that are retained.
+ * ===========================================================================
+ */
+#include <linux/kernel.h>
+#include <asm/bitops.h>
+#include <asm/ptrace.h>
+#include <asm/vfp.h>
+
+#include "vfpinstr.h"
+#include "vfp.h"
+
+static struct vfp_single vfp_single_default_qnan = {
+	.exponent	= 255,
+	.sign		= 0,
+	.significand	= VFP_SINGLE_SIGNIFICAND_QNAN,
+};
+
+static void vfp_single_dump(const char *str, struct vfp_single *s)
+{
+	pr_debug("VFP: %s: sign=%d exponent=%d significand=%08x\n",
+		 str, s->sign != 0, s->exponent, s->significand);
+}
+
+static void vfp_single_normalise_denormal(struct vfp_single *vs)
+{
+	int bits = 31 - fls(vs->significand);
+
+	vfp_single_dump("normalise_denormal: in", vs);
+
+	if (bits) {
+		vs->exponent -= bits - 1;
+		vs->significand <<= bits;
+	}
+
+	vfp_single_dump("normalise_denormal: out", vs);
+}
+
+#ifndef DEBUG
+#define vfp_single_normaliseround(sd,vsd,fpscr,except,func) __vfp_single_normaliseround(sd,vsd,fpscr,except)
+u32 __vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions)
+#else
+u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func)
+#endif
+{
+	u32 significand, incr, rmode;
+	int exponent, shift, underflow;
+
+	vfp_single_dump("pack: in", vs);
+
+	/*
+	 * Infinities and NaNs are a special case.
+	 */
+	if (vs->exponent == 255 && (vs->significand == 0 || exceptions))
+		goto pack;
+
+	/*
+	 * Special-case zero.
+	 */
+	if (vs->significand == 0) {
+		vs->exponent = 0;
+		goto pack;
+	}
+
+	exponent = vs->exponent;
+	significand = vs->significand;
+
+	/*
+	 * Normalise first.  Note that we shift the significand up to
+	 * bit 31, so we have VFP_SINGLE_LOW_BITS + 1 below the least
+	 * significant bit.
+	 */
+	shift = 32 - fls(significand);
+	if (shift < 32 && shift) {
+		exponent -= shift;
+		significand <<= shift;
+	}
+
+#ifdef DEBUG
+	vs->exponent = exponent;
+	vs->significand = significand;
+	vfp_single_dump("pack: normalised", vs);
+#endif
+
+	/*
+	 * Tiny number?
+	 */
+	underflow = exponent < 0;
+	if (underflow) {
+		significand = vfp_shiftright32jamming(significand, -exponent);
+		exponent = 0;
+#ifdef DEBUG
+		vs->exponent = exponent;
+		vs->significand = significand;
+		vfp_single_dump("pack: tiny number", vs);
+#endif
+		if (!(significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1)))
+			underflow = 0;
+	}
+
+	/*
+	 * Select rounding increment.
+	 */
+	incr = 0;
+	rmode = fpscr & FPSCR_RMODE_MASK;
+
+	if (rmode == FPSCR_ROUND_NEAREST) {
+		incr = 1 << VFP_SINGLE_LOW_BITS;
+		if ((significand & (1 << (VFP_SINGLE_LOW_BITS + 1))) == 0)
+			incr -= 1;
+	} else if (rmode == FPSCR_ROUND_TOZERO) {
+		incr = 0;
+	} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0))
+		incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1;
+
+	pr_debug("VFP: rounding increment = 0x%08x\n", incr);
+
+	/*
+	 * Is our rounding going to overflow?
+	 */
+	if ((significand + incr) < significand) {
+		exponent += 1;
+		significand = (significand >> 1) | (significand & 1);
+		incr >>= 1;
+#ifdef DEBUG
+		vs->exponent = exponent;
+		vs->significand = significand;
+		vfp_single_dump("pack: overflow", vs);
+#endif
+	}
+
+	/*
+	 * If any of the low bits (which will be shifted out of the
+	 * number) are non-zero, the result is inexact.
+	 */
+	if (significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1))
+		exceptions |= FPSCR_IXC;
+
+	/*
+	 * Do our rounding.
+	 */
+	significand += incr;
+
+	/*
+	 * Infinity?
+	 */
+	if (exponent >= 254) {
+		exceptions |= FPSCR_OFC | FPSCR_IXC;
+		if (incr == 0) {
+			vs->exponent = 253;
+			vs->significand = 0x7fffffff;
+		} else {
+			vs->exponent = 255;		/* infinity */
+			vs->significand = 0;
+		}
+	} else {
+		if (significand >> (VFP_SINGLE_LOW_BITS + 1) == 0)
+			exponent = 0;
+		if (exponent || significand > 0x80000000)
+			underflow = 0;
+		if (underflow)
+			exceptions |= FPSCR_UFC;
+		vs->exponent = exponent;
+		vs->significand = significand >> 1;
+	}
+
+ pack:
+	vfp_single_dump("pack: final", vs);
+	{
+		s32 d = vfp_single_pack(vs);
+		pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func,
+			 sd, d, exceptions);
+		vfp_put_float(sd, d);
+	}
+
+	return exceptions;
+}
+
+/*
+ * Propagate the NaN, setting exceptions if it is signalling.
+ * 'n' is always a NaN.  'm' may be a number, NaN or infinity.
+ */
+static u32
+vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
+		  struct vfp_single *vsm, u32 fpscr)
+{
+	struct vfp_single *nan;
+	int tn, tm = 0;
+
+	tn = vfp_single_type(vsn);
+
+	if (vsm)
+		tm = vfp_single_type(vsm);
+
+	if (fpscr & FPSCR_DEFAULT_NAN)
+		/*
+		 * Default NaN mode - always returns a quiet NaN
+		 */
+		nan = &vfp_single_default_qnan;
+	else {
+		/*
+		 * Contemporary mode - select the first signalling
+		 * NAN, or if neither are signalling, the first
+		 * quiet NAN.
+		 */
+		if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
+			nan = vsn;
+		else
+			nan = vsm;
+		/*
+		 * Make the NaN quiet.
+		 */
+		nan->significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
+	}
+
+	*vsd = *nan;
+
+	/*
+	 * If one was a signalling NAN, raise invalid operation.
+	 */
+	return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : 0x100;
+}
+
+
+/*
+ * Extended operations
+ */
+static u32 vfp_single_fabs(int sd, int unused, s32 m, u32 fpscr)
+{
+	vfp_put_float(sd, vfp_single_packed_abs(m));
+	return 0;
+}
+
+static u32 vfp_single_fcpy(int sd, int unused, s32 m, u32 fpscr)
+{
+	vfp_put_float(sd, m);
+	return 0;
+}
+
+static u32 vfp_single_fneg(int sd, int unused, s32 m, u32 fpscr)
+{
+	vfp_put_float(sd, vfp_single_packed_negate(m));
+	return 0;
+}
+
+static const u16 sqrt_oddadjust[] = {
+	0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0,
+	0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67
+};
+
+static const u16 sqrt_evenadjust[] = {
+	0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e,
+	0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002
+};
+
+u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
+{
+	int index;
+	u32 z, a;
+
+	if ((significand & 0xc0000000) != 0x40000000) {
+		printk(KERN_WARNING "VFP: estimate_sqrt: invalid significand\n");
+	}
+
+	a = significand << 1;
+	index = (a >> 27) & 15;
+	if (exponent & 1) {
+		z = 0x4000 + (a >> 17) - sqrt_oddadjust[index];
+		z = ((a / z) << 14) + (z << 15);
+		a >>= 1;
+	} else {
+		z = 0x8000 + (a >> 17) - sqrt_evenadjust[index];
+		z = a / z + z;
+		z = (z >= 0x20000) ? 0xffff8000 : (z << 15);
+		if (z <= a)
+			return (s32)a >> 1;
+	}
+	return (u32)(((u64)a << 31) / z) + (z >> 1);
+}
+
+static u32 vfp_single_fsqrt(int sd, int unused, s32 m, u32 fpscr)
+{
+	struct vfp_single vsm, vsd;
+	int ret, tm;
+
+	vfp_single_unpack(&vsm, m);
+	tm = vfp_single_type(&vsm);
+	if (tm & (VFP_NAN|VFP_INFINITY)) {
+		struct vfp_single *vsp = &vsd;
+
+		if (tm & VFP_NAN)
+			ret = vfp_propagate_nan(vsp, &vsm, NULL, fpscr);
+		else if (vsm.sign == 0) {
+ sqrt_copy:
+			vsp = &vsm;
+			ret = 0;
+		} else {
+ sqrt_invalid:
+			vsp = &vfp_single_default_qnan;
+			ret = FPSCR_IOC;
+		}
+		vfp_put_float(sd, vfp_single_pack(vsp));
+		return ret;
+	}
+
+	/*
+	 * sqrt(+/- 0) == +/- 0
+	 */
+	if (tm & VFP_ZERO)
+		goto sqrt_copy;
+
+	/*
+	 * Normalise a denormalised number
+	 */
+	if (tm & VFP_DENORMAL)
+		vfp_single_normalise_denormal(&vsm);
+
+	/*
+	 * sqrt(<0) = invalid
+	 */
+	if (vsm.sign)
+		goto sqrt_invalid;
+
+	vfp_single_dump("sqrt", &vsm);
+
+	/*
+	 * Estimate the square root.
+	 */
+	vsd.sign = 0;
+	vsd.exponent = ((vsm.exponent - 127) >> 1) + 127;
+	vsd.significand = vfp_estimate_sqrt_significand(vsm.exponent, vsm.significand) + 2;
+
+	vfp_single_dump("sqrt estimate", &vsd);
+
+	/*
+	 * And now adjust.
+	 */
+	if ((vsd.significand & VFP_SINGLE_LOW_BITS_MASK) <= 5) {
+		if (vsd.significand < 2) {
+			vsd.significand = 0xffffffff;
+		} else {
+			u64 term;
+			s64 rem;
+			vsm.significand <<= !(vsm.exponent & 1);
+			term = (u64)vsd.significand * vsd.significand;
+			rem = ((u64)vsm.significand << 32) - term;
+
+			pr_debug("VFP: term=%016llx rem=%016llx\n", term, rem);
+
+			while (rem < 0) {
+				vsd.significand -= 1;
+				rem += ((u64)vsd.significand << 1) | 1;
+			}
+			vsd.significand |= rem != 0;
+		}
+	}
+	vsd.significand = vfp_shiftright32jamming(vsd.significand, 1);
+
+	return vfp_single_normaliseround(sd, &vsd, fpscr, 0, "fsqrt");
+}
+
+/*
+ * Equal	:= ZC
+ * Less than	:= N
+ * Greater than	:= C
+ * Unordered	:= CV
+ */
+static u32 vfp_compare(int sd, int signal_on_qnan, s32 m, u32 fpscr)
+{
+	s32 d;
+	u32 ret = 0;
+
+	d = vfp_get_float(sd);
+	if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) {
+		ret |= FPSCR_C | FPSCR_V;
+		if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
+			/*
+			 * Signalling NaN, or signalling on quiet NaN
+			 */
+			ret |= FPSCR_IOC;
+	}
+
+	if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) {
+		ret |= FPSCR_C | FPSCR_V;
+		if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
+			/*
+			 * Signalling NaN, or signalling on quiet NaN
+			 */
+			ret |= FPSCR_IOC;
+	}
+
+	if (ret == 0) {
+		if (d == m || vfp_single_packed_abs(d | m) == 0) {
+			/*
+			 * equal
+			 */
+			ret |= FPSCR_Z | FPSCR_C;
+		} else if (vfp_single_packed_sign(d ^ m)) {
+			/*
+			 * different signs
+			 */
+			if (vfp_single_packed_sign(d))
+				/*
+				 * d is negative, so d < m
+				 */
+				ret |= FPSCR_N;
+			else
+				/*
+				 * d is positive, so d > m
+				 */
+				ret |= FPSCR_C;
+		} else if ((vfp_single_packed_sign(d) != 0) ^ (d < m)) {
+			/*
+			 * d < m
+			 */
+			ret |= FPSCR_N;
+		} else if ((vfp_single_packed_sign(d) != 0) ^ (d > m)) {
+			/*
+			 * d > m
+			 */
+			ret |= FPSCR_C;
+		}
+	}
+	return ret;
+}
+
+static u32 vfp_single_fcmp(int sd, int unused, s32 m, u32 fpscr)
+{
+	return vfp_compare(sd, 0, m, fpscr);
+}
+
+static u32 vfp_single_fcmpe(int sd, int unused, s32 m, u32 fpscr)
+{
+	return vfp_compare(sd, 1, m, fpscr);
+}
+
+static u32 vfp_single_fcmpz(int sd, int unused, s32 m, u32 fpscr)
+{
+	return vfp_compare(sd, 0, 0, fpscr);
+}
+
+static u32 vfp_single_fcmpez(int sd, int unused, s32 m, u32 fpscr)
+{
+	return vfp_compare(sd, 1, 0, fpscr);
+}
+
+static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr)
+{
+	struct vfp_single vsm;
+	struct vfp_double vdd;
+	int tm;
+	u32 exceptions = 0;
+
+	vfp_single_unpack(&vsm, m);
+
+	tm = vfp_single_type(&vsm);
+
+	/*
+	 * If we have a signalling NaN, signal invalid operation.
+	 */
+	if (tm == VFP_SNAN)
+		exceptions = FPSCR_IOC;
+
+	if (tm & VFP_DENORMAL)
+		vfp_single_normalise_denormal(&vsm);
+
+	vdd.sign = vsm.sign;
+	vdd.significand = (u64)vsm.significand << 32;
+
+	/*
+	 * If we have an infinity or NaN, the exponent must be 2047.
+	 */
+	if (tm & (VFP_INFINITY|VFP_NAN)) {
+		vdd.exponent = 2047;
+		if (tm & VFP_NAN)
+			vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
+		goto pack_nan;
+	} else if (tm & VFP_ZERO)
+		vdd.exponent = 0;
+	else
+		vdd.exponent = vsm.exponent + (1023 - 127);
+
+	/*
+	 * Technically, if bit 0 of dd is set, this is an invalid
+	 * instruction.  However, we ignore this for efficiency.
+	 */
+	return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd");
+
+ pack_nan:
+	vfp_put_double(dd, vfp_double_pack(&vdd));
+	return exceptions;
+}
+
+static u32 vfp_single_fuito(int sd, int unused, s32 m, u32 fpscr)
+{
+	struct vfp_single vs;
+
+	vs.sign = 0;
+	vs.exponent = 127 + 31 - 1;
+	vs.significand = (u32)m;
+
+	return vfp_single_normaliseround(sd, &vs, fpscr, 0, "fuito");
+}
+
+static u32 vfp_single_fsito(int sd, int unused, s32 m, u32 fpscr)
+{
+	struct vfp_single vs;
+
+	vs.sign = (m & 0x80000000) >> 16;
+	vs.exponent = 127 + 31 - 1;
+	vs.significand = vs.sign ? -m : m;
+
+	return vfp_single_normaliseround(sd, &vs, fpscr, 0, "fsito");
+}
+
+static u32 vfp_single_ftoui(int sd, int unused, s32 m, u32 fpscr)
+{
+	struct vfp_single vsm;
+	u32 d, exceptions = 0;
+	int rmode = fpscr & FPSCR_RMODE_MASK;
+	int tm;
+
+	vfp_single_unpack(&vsm, m);
+	vfp_single_dump("VSM", &vsm);
+
+	/*
+	 * Do we have a denormalised number?
+	 */
+	tm = vfp_single_type(&vsm);
+	if (tm & VFP_DENORMAL)
+		exceptions |= FPSCR_IDC;
+
+	if (tm & VFP_NAN)
+		vsm.sign = 0;
+
+	if (vsm.exponent >= 127 + 32) {
+		d = vsm.sign ? 0 : 0xffffffff;
+		exceptions = FPSCR_IOC;
+	} else if (vsm.exponent >= 127 - 1) {
+		int shift = 127 + 31 - vsm.exponent;
+		u32 rem, incr = 0;
+
+		/*
+		 * 2^0 <= m < 2^32-2^8
+		 */
+		d = (vsm.significand << 1) >> shift;
+		rem = vsm.significand << (33 - shift);
+
+		if (rmode == FPSCR_ROUND_NEAREST) {
+			incr = 0x80000000;
+			if ((d & 1) == 0)
+				incr -= 1;
+		} else if (rmode == FPSCR_ROUND_TOZERO) {
+			incr = 0;
+		} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
+			incr = ~0;
+		}
+
+		if ((rem + incr) < rem) {
+			if (d < 0xffffffff)
+				d += 1;
+			else
+				exceptions |= FPSCR_IOC;
+		}
+
+		if (d && vsm.sign) {
+			d = 0;
+			exceptions |= FPSCR_IOC;
+		} else if (rem)
+			exceptions |= FPSCR_IXC;
+	} else {
+		d = 0;
+		if (vsm.exponent | vsm.significand) {
+			exceptions |= FPSCR_IXC;
+			if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
+				d = 1;
+			else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) {
+				d = 0;
+				exceptions |= FPSCR_IOC;
+			}
+		}
+	}
+
+	pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
+
+	vfp_put_float(sd, d);
+
+	return exceptions;
+}
+
+static u32 vfp_single_ftouiz(int sd, int unused, s32 m, u32 fpscr)
+{
+	return vfp_single_ftoui(sd, unused, m, FPSCR_ROUND_TOZERO);
+}
+
+static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr)
+{
+	struct vfp_single vsm;
+	u32 d, exceptions = 0;
+	int rmode = fpscr & FPSCR_RMODE_MASK;
+
+	vfp_single_unpack(&vsm, m);
+	vfp_single_dump("VSM", &vsm);
+
+	/*
+	 * Do we have a denormalised number?
+	 */
+	if (vfp_single_type(&vsm) & VFP_DENORMAL)
+		exceptions |= FPSCR_IDC;
+
+	if (vsm.exponent >= 127 + 32) {
+		/*
+		 * m >= 2^31-2^7: invalid
+		 */
+		d = 0x7fffffff;
+		if (vsm.sign)
+			d = ~d;
+		exceptions |= FPSCR_IOC;
+	} else if (vsm.exponent >= 127 - 1) {
+		int shift = 127 + 31 - vsm.exponent;
+		u32 rem, incr = 0;
+
+		/* 2^0 <= m <= 2^31-2^7 */
+		d = (vsm.significand << 1) >> shift;
+		rem = vsm.significand << (33 - shift);
+
+		if (rmode == FPSCR_ROUND_NEAREST) {
+			incr = 0x80000000;
+			if ((d & 1) == 0)
+				incr -= 1;
+		} else if (rmode == FPSCR_ROUND_TOZERO) {
+			incr = 0;
+		} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
+			incr = ~0;
+		}
+
+		if ((rem + incr) < rem && d < 0xffffffff)
+			d += 1;
+		if (d > 0x7fffffff + (vsm.sign != 0)) {
+			d = 0x7fffffff + (vsm.sign != 0);
+			exceptions |= FPSCR_IOC;
+		} else if (rem)
+			exceptions |= FPSCR_IXC;
+
+		if (vsm.sign)
+			d = -d;
+	} else {
+		d = 0;
+		if (vsm.exponent | vsm.significand) {
+			exceptions |= FPSCR_IXC;
+			if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
+				d = 1;
+			else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign)
+				d = -1;
+		}
+	}
+
+	pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
+
+	vfp_put_float(sd, (s32)d);
+
+	return exceptions;
+}
+
+static u32 vfp_single_ftosiz(int sd, int unused, s32 m, u32 fpscr)
+{
+	return vfp_single_ftosi(sd, unused, m, FPSCR_ROUND_TOZERO);
+}
+
+static u32 (* const fop_extfns[32])(int sd, int unused, s32 m, u32 fpscr) = {
+	[FEXT_TO_IDX(FEXT_FCPY)]	= vfp_single_fcpy,
+	[FEXT_TO_IDX(FEXT_FABS)]	= vfp_single_fabs,
+	[FEXT_TO_IDX(FEXT_FNEG)]	= vfp_single_fneg,
+	[FEXT_TO_IDX(FEXT_FSQRT)]	= vfp_single_fsqrt,
+	[FEXT_TO_IDX(FEXT_FCMP)]	= vfp_single_fcmp,
+	[FEXT_TO_IDX(FEXT_FCMPE)]	= vfp_single_fcmpe,
+	[FEXT_TO_IDX(FEXT_FCMPZ)]	= vfp_single_fcmpz,
+	[FEXT_TO_IDX(FEXT_FCMPEZ)]	= vfp_single_fcmpez,
+	[FEXT_TO_IDX(FEXT_FCVT)]	= vfp_single_fcvtd,
+	[FEXT_TO_IDX(FEXT_FUITO)]	= vfp_single_fuito,
+	[FEXT_TO_IDX(FEXT_FSITO)]	= vfp_single_fsito,
+	[FEXT_TO_IDX(FEXT_FTOUI)]	= vfp_single_ftoui,
+	[FEXT_TO_IDX(FEXT_FTOUIZ)]	= vfp_single_ftouiz,
+	[FEXT_TO_IDX(FEXT_FTOSI)]	= vfp_single_ftosi,
+	[FEXT_TO_IDX(FEXT_FTOSIZ)]	= vfp_single_ftosiz,
+};
+
+
+
+
+
+static u32
+vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn,
+			  struct vfp_single *vsm, u32 fpscr)
+{
+	struct vfp_single *vsp;
+	u32 exceptions = 0;
+	int tn, tm;
+
+	tn = vfp_single_type(vsn);
+	tm = vfp_single_type(vsm);
+
+	if (tn & tm & VFP_INFINITY) {
+		/*
+		 * Two infinities.  Are they different signs?
+		 */
+		if (vsn->sign ^ vsm->sign) {
+			/*
+			 * different signs -> invalid
+			 */
+			exceptions = FPSCR_IOC;
+			vsp = &vfp_single_default_qnan;
+		} else {
+			/*
+			 * same signs -> valid
+			 */
+			vsp = vsn;
+		}
+	} else if (tn & VFP_INFINITY && tm & VFP_NUMBER) {
+		/*
+		 * One infinity and one number -> infinity
+		 */
+		vsp = vsn;
+	} else {
+		/*
+		 * 'n' is a NaN of some type
+		 */
+		return vfp_propagate_nan(vsd, vsn, vsm, fpscr);
+	}
+	*vsd = *vsp;
+	return exceptions;
+}
+
+static u32
+vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
+	       struct vfp_single *vsm, u32 fpscr)
+{
+	u32 exp_diff, m_sig;
+
+	if (vsn->significand & 0x80000000 ||
+	    vsm->significand & 0x80000000) {
+		pr_info("VFP: bad FP values in %s\n", __func__);
+		vfp_single_dump("VSN", vsn);
+		vfp_single_dump("VSM", vsm);
+	}
+
+	/*
+	 * Ensure that 'n' is the largest magnitude number.  Note that
+	 * if 'n' and 'm' have equal exponents, we do not swap them.
+	 * This ensures that NaN propagation works correctly.
+	 */
+	if (vsn->exponent < vsm->exponent) {
+		struct vfp_single *t = vsn;
+		vsn = vsm;
+		vsm = t;
+	}
+
+	/*
+	 * Is 'n' an infinity or a NaN?  Note that 'm' may be a number,
+	 * infinity or a NaN here.
+	 */
+	if (vsn->exponent == 255)
+		return vfp_single_fadd_nonnumber(vsd, vsn, vsm, fpscr);
+
+	/*
+	 * We have two proper numbers, where 'vsn' is the larger magnitude.
+	 *
+	 * Copy 'n' to 'd' before doing the arithmetic.
+	 */
+	*vsd = *vsn;
+
+	/*
+	 * Align both numbers.
+	 */
+	exp_diff = vsn->exponent - vsm->exponent;
+	m_sig = vfp_shiftright32jamming(vsm->significand, exp_diff);
+
+	/*
+	 * If the signs are different, we are really subtracting.
+	 */
+	if (vsn->sign ^ vsm->sign) {
+		m_sig = vsn->significand - m_sig;
+		if ((s32)m_sig < 0) {
+			vsd->sign = vfp_sign_negate(vsd->sign);
+			m_sig = -m_sig;
+		} else if (m_sig == 0) {
+			vsd->sign = (fpscr & FPSCR_RMODE_MASK) ==
+				      FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
+		}
+	} else {
+		m_sig = vsn->significand + m_sig;
+	}
+	vsd->significand = m_sig;
+
+	return 0;
+}
+
+static u32
+vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr)
+{
+	vfp_single_dump("VSN", vsn);
+	vfp_single_dump("VSM", vsm);
+
+	/*
+	 * Ensure that 'n' is the largest magnitude number.  Note that
+	 * if 'n' and 'm' have equal exponents, we do not swap them.
+	 * This ensures that NaN propagation works correctly.
+	 */
+	if (vsn->exponent < vsm->exponent) {
+		struct vfp_single *t = vsn;
+		vsn = vsm;
+		vsm = t;
+		pr_debug("VFP: swapping M <-> N\n");
+	}
+
+	vsd->sign = vsn->sign ^ vsm->sign;
+
+	/*
+	 * If 'n' is an infinity or NaN, handle it.  'm' may be anything.
+	 */
+	if (vsn->exponent == 255) {
+		if (vsn->significand || (vsm->exponent == 255 && vsm->significand))
+			return vfp_propagate_nan(vsd, vsn, vsm, fpscr);
+		if ((vsm->exponent | vsm->significand) == 0) {
+			*vsd = vfp_single_default_qnan;
+			return FPSCR_IOC;
+		}
+		vsd->exponent = vsn->exponent;
+		vsd->significand = 0;
+		return 0;
+	}
+
+	/*
+	 * If 'm' is zero, the result is always zero.  In this case,
+	 * 'n' may be zero or a number, but it doesn't matter which.
+	 */
+	if ((vsm->exponent | vsm->significand) == 0) {
+		vsd->exponent = 0;
+		vsd->significand = 0;
+		return 0;
+	}
+
+	/*
+	 * We add 2 to the destination exponent for the same reason as
+	 * the addition case - though this time we have +1 from each
+	 * input operand.
+	 */
+	vsd->exponent = vsn->exponent + vsm->exponent - 127 + 2;
+	vsd->significand = vfp_hi64to32jamming((u64)vsn->significand * vsm->significand);
+
+	vfp_single_dump("VSD", vsd);
+	return 0;
+}
+
+#define NEG_MULTIPLY	(1 << 0)
+#define NEG_SUBTRACT	(1 << 1)
+
+static u32
+vfp_single_multiply_accumulate(int sd, int sn, s32 m, u32 fpscr, u32 negate, char *func)
+{
+	struct vfp_single vsd, vsp, vsn, vsm;
+	u32 exceptions;
+	s32 v;
+
+	v = vfp_get_float(sn);
+	pr_debug("VFP: s%u = %08x\n", sn, v);
+	vfp_single_unpack(&vsn, v);
+	if (vsn.exponent == 0 && vsn.significand)
+		vfp_single_normalise_denormal(&vsn);
+
+	vfp_single_unpack(&vsm, m);
+	if (vsm.exponent == 0 && vsm.significand)
+		vfp_single_normalise_denormal(&vsm);
+
+	exceptions = vfp_single_multiply(&vsp, &vsn, &vsm, fpscr);
+	if (negate & NEG_MULTIPLY)
+		vsp.sign = vfp_sign_negate(vsp.sign);
+
+	v = vfp_get_float(sd);
+	pr_debug("VFP: s%u = %08x\n", sd, v);
+	vfp_single_unpack(&vsn, v);
+	if (negate & NEG_SUBTRACT)
+		vsn.sign = vfp_sign_negate(vsn.sign);
+
+	exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr);
+
+	return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, func);
+}
+
+/*
+ * Standard operations
+ */
+
+/*
+ * sd = sd + (sn * sm)
+ */
+static u32 vfp_single_fmac(int sd, int sn, s32 m, u32 fpscr)
+{
+	return vfp_single_multiply_accumulate(sd, sn, m, fpscr, 0, "fmac");
+}
+
+/*
+ * sd = sd - (sn * sm)
+ */
+static u32 vfp_single_fnmac(int sd, int sn, s32 m, u32 fpscr)
+{
+	return vfp_single_multiply_accumulate(sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac");
+}
+
+/*
+ * sd = -sd + (sn * sm)
+ */
+static u32 vfp_single_fmsc(int sd, int sn, s32 m, u32 fpscr)
+{
+	return vfp_single_multiply_accumulate(sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc");
+}
+
+/*
+ * sd = -sd - (sn * sm)
+ */
+static u32 vfp_single_fnmsc(int sd, int sn, s32 m, u32 fpscr)
+{
+	return vfp_single_multiply_accumulate(sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
+}
+
+/*
+ * sd = sn * sm
+ */
+static u32 vfp_single_fmul(int sd, int sn, s32 m, u32 fpscr)
+{
+	struct vfp_single vsd, vsn, vsm;
+	u32 exceptions;
+	s32 n = vfp_get_float(sn);
+
+	pr_debug("VFP: s%u = %08x\n", sn, n);
+
+	vfp_single_unpack(&vsn, n);
+	if (vsn.exponent == 0 && vsn.significand)
+		vfp_single_normalise_denormal(&vsn);
+
+	vfp_single_unpack(&vsm, m);
+	if (vsm.exponent == 0 && vsm.significand)
+		vfp_single_normalise_denormal(&vsm);
+
+	exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr);
+	return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fmul");
+}
+
+/*
+ * sd = -(sn * sm)
+ */
+static u32 vfp_single_fnmul(int sd, int sn, s32 m, u32 fpscr)
+{
+	struct vfp_single vsd, vsn, vsm;
+	u32 exceptions;
+	s32 n = vfp_get_float(sn);
+
+	pr_debug("VFP: s%u = %08x\n", sn, n);
+
+	vfp_single_unpack(&vsn, n);
+	if (vsn.exponent == 0 && vsn.significand)
+		vfp_single_normalise_denormal(&vsn);
+
+	vfp_single_unpack(&vsm, m);
+	if (vsm.exponent == 0 && vsm.significand)
+		vfp_single_normalise_denormal(&vsm);
+
+	exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr);
+	vsd.sign = vfp_sign_negate(vsd.sign);
+	return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fnmul");
+}
+
+/*
+ * sd = sn + sm
+ */
+static u32 vfp_single_fadd(int sd, int sn, s32 m, u32 fpscr)
+{
+	struct vfp_single vsd, vsn, vsm;
+	u32 exceptions;
+	s32 n = vfp_get_float(sn);
+
+	pr_debug("VFP: s%u = %08x\n", sn, n);
+
+	/*
+	 * Unpack and normalise denormals.
+	 */
+	vfp_single_unpack(&vsn, n);
+	if (vsn.exponent == 0 && vsn.significand)
+		vfp_single_normalise_denormal(&vsn);
+
+	vfp_single_unpack(&vsm, m);
+	if (vsm.exponent == 0 && vsm.significand)
+		vfp_single_normalise_denormal(&vsm);
+
+	exceptions = vfp_single_add(&vsd, &vsn, &vsm, fpscr);
+
+	return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fadd");
+}
+
+/*
+ * sd = sn - sm
+ */
+static u32 vfp_single_fsub(int sd, int sn, s32 m, u32 fpscr)
+{
+	/*
+	 * Subtraction is addition with one sign inverted.
+	 */
+	return vfp_single_fadd(sd, sn, vfp_single_packed_negate(m), fpscr);
+}
+
+/*
+ * sd = sn / sm
+ */
+static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr)
+{
+	struct vfp_single vsd, vsn, vsm;
+	u32 exceptions = 0;
+	s32 n = vfp_get_float(sn);
+	int tm, tn;
+
+	pr_debug("VFP: s%u = %08x\n", sn, n);
+
+	vfp_single_unpack(&vsn, n);
+	vfp_single_unpack(&vsm, m);
+
+	vsd.sign = vsn.sign ^ vsm.sign;
+
+	tn = vfp_single_type(&vsn);
+	tm = vfp_single_type(&vsm);
+
+	/*
+	 * Is n a NAN?
+	 */
+	if (tn & VFP_NAN)
+		goto vsn_nan;
+
+	/*
+	 * Is m a NAN?
+	 */
+	if (tm & VFP_NAN)
+		goto vsm_nan;
+
+	/*
+	 * If n and m are infinity, the result is invalid
+	 * If n and m are zero, the result is invalid
+	 */
+	if (tm & tn & (VFP_INFINITY|VFP_ZERO))
+		goto invalid;
+
+	/*
+	 * If n is infinity, the result is infinity
+	 */
+	if (tn & VFP_INFINITY)
+		goto infinity;
+
+	/*
+	 * If m is zero, raise div0 exception
+	 */
+	if (tm & VFP_ZERO)
+		goto divzero;
+
+	/*
+	 * If m is infinity, or n is zero, the result is zero
+	 */
+	if (tm & VFP_INFINITY || tn & VFP_ZERO)
+		goto zero;
+
+	if (tn & VFP_DENORMAL)
+		vfp_single_normalise_denormal(&vsn);
+	if (tm & VFP_DENORMAL)
+		vfp_single_normalise_denormal(&vsm);
+
+	/*
+	 * Ok, we have two numbers, we can perform division.
+	 */
+	vsd.exponent = vsn.exponent - vsm.exponent + 127 - 1;
+	vsm.significand <<= 1;
+	if (vsm.significand <= (2 * vsn.significand)) {
+		vsn.significand >>= 1;
+		vsd.exponent++;
+	}
+	vsd.significand = ((u64)vsn.significand << 32) / vsm.significand;
+	if ((vsd.significand & 0x3f) == 0)
+		vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32);
+
+	return vfp_single_normaliseround(sd, &vsd, fpscr, 0, "fdiv");
+
+ vsn_nan:
+	exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr);
+ pack:
+	vfp_put_float(sd, vfp_single_pack(&vsd));
+	return exceptions;
+
+ vsm_nan:
+	exceptions = vfp_propagate_nan(&vsd, &vsm, &vsn, fpscr);
+	goto pack;
+
+ zero:
+	vsd.exponent = 0;
+	vsd.significand = 0;
+	goto pack;
+
+ divzero:
+	exceptions = FPSCR_DZC;
+ infinity:
+	vsd.exponent = 255;
+	vsd.significand = 0;
+	goto pack;
+
+ invalid:
+	vfp_put_float(sd, vfp_single_pack(&vfp_single_default_qnan));
+	return FPSCR_IOC;
+}
+
+static u32 (* const fop_fns[16])(int sd, int sn, s32 m, u32 fpscr) = {
+	[FOP_TO_IDX(FOP_FMAC)]	= vfp_single_fmac,
+	[FOP_TO_IDX(FOP_FNMAC)]	= vfp_single_fnmac,
+	[FOP_TO_IDX(FOP_FMSC)]	= vfp_single_fmsc,
+	[FOP_TO_IDX(FOP_FNMSC)]	= vfp_single_fnmsc,
+	[FOP_TO_IDX(FOP_FMUL)]	= vfp_single_fmul,
+	[FOP_TO_IDX(FOP_FNMUL)]	= vfp_single_fnmul,
+	[FOP_TO_IDX(FOP_FADD)]	= vfp_single_fadd,
+	[FOP_TO_IDX(FOP_FSUB)]	= vfp_single_fsub,
+	[FOP_TO_IDX(FOP_FDIV)]	= vfp_single_fdiv,
+};
+
+#define FREG_BANK(x)	((x) & 0x18)
+#define FREG_IDX(x)	((x) & 7)
+
+u32 vfp_single_cpdo(u32 inst, u32 fpscr)
+{
+	u32 op = inst & FOP_MASK;
+	u32 exceptions = 0;
+	unsigned int sd = vfp_get_sd(inst);
+	unsigned int sn = vfp_get_sn(inst);
+	unsigned int sm = vfp_get_sm(inst);
+	unsigned int vecitr, veclen, vecstride;
+	u32 (*fop)(int, int, s32, u32);
+
+	veclen = fpscr & FPSCR_LENGTH_MASK;
+	vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
+
+	/*
+	 * If destination bank is zero, vector length is always '1'.
+	 * ARM DDI0100F C5.1.3, C5.3.2.
+	 */
+	if (FREG_BANK(sd) == 0)
+		veclen = 0;
+
+	pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
+		 (veclen >> FPSCR_LENGTH_BIT) + 1);
+
+	fop = (op == FOP_EXT) ? fop_extfns[sn] : fop_fns[FOP_TO_IDX(op)];
+	if (!fop)
+		goto invalid;
+
+	for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
+		s32 m = vfp_get_float(sm);
+		u32 except;
+
+		if (op == FOP_EXT)
+			pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n",
+				 vecitr >> FPSCR_LENGTH_BIT, sd, sn, sm, m);
+		else
+			pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n",
+				 vecitr >> FPSCR_LENGTH_BIT, sd, sn,
+				 FOP_TO_IDX(op), sm, m);
+
+		except = fop(sd, sn, m, fpscr);
+		pr_debug("VFP: itr%d: exceptions=%08x\n",
+			 vecitr >> FPSCR_LENGTH_BIT, except);
+
+		exceptions |= except;
+
+		/*
+		 * This ensures that comparisons only operate on scalars;
+		 * comparisons always return with one FPSCR status bit set.
+		 */
+		if (except & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
+			break;
+
+		/*
+		 * CHECK: It appears to be undefined whether we stop when
+		 * we encounter an exception.  We continue.
+		 */
+
+		sd = FREG_BANK(sd) + ((FREG_IDX(sd) + vecstride) & 7);
+		sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
+		if (FREG_BANK(sm) != 0)
+			sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7);
+	}
+	return exceptions;
+
+ invalid:
+	return (u32)-1;
+}
diff -Nru a/arch/arm26/kernel/init_task.c b/arch/arm26/kernel/init_task.c
--- a/arch/arm26/kernel/init_task.c	2004-06-23 19:04:26 -07:00
+++ b/arch/arm26/kernel/init_task.c	2004-06-23 19:04:26 -07:00
@@ -10,6 +10,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/init_task.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
--- a/arch/cris/kernel/process.c	2004-06-23 19:04:27 -07:00
+++ b/arch/cris/kernel/process.c	2004-06-23 19:04:27 -07:00
@@ -112,6 +112,7 @@
 #include <linux/fs.h>
 #include <linux/user.h>
 #include <linux/elfcore.h>
+#include <linux/mqueue.h>
 
 //#define DEBUG
 
diff -Nru a/arch/h8300/Kconfig b/arch/h8300/Kconfig
--- a/arch/h8300/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/arch/h8300/Kconfig	2004-06-23 19:04:28 -07:00
@@ -223,7 +223,7 @@
 
 config CONFIG_SH_STANDARD_BIOS
 	bool "Use gdb protocol serial console"
-	depends on (!H8300H_SIM && H8S_SIM)
+	depends on (!H8300H_SIM && !H8S_SIM)
 	help
 	  serial console output using GDB protocol.
 	  Require eCos/RedBoot
diff -Nru a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c
--- a/arch/h8300/kernel/init_task.c	2004-06-23 19:04:26 -07:00
+++ b/arch/h8300/kernel/init_task.c	2004-06-23 19:04:26 -07:00
@@ -7,6 +7,7 @@
 #include <linux/init.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
--- a/arch/h8300/kernel/ptrace.c	2004-06-23 19:04:26 -07:00
+++ b/arch/h8300/kernel/ptrace.c	2004-06-23 19:04:26 -07:00
@@ -116,18 +116,36 @@
 		case PTRACE_PEEKUSR: {
 			unsigned long tmp;
 			
-			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
+			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
 				ret = -EIO;
+				break ;
+			}
 			
-			tmp = 0;  /* Default return condition */
+		        ret = 0;  /* Default return condition */
 			addr = addr >> 2; /* temporary hack. */
+
 			if (addr < H8300_REGS_NO)
 				tmp = h8300_get_reg(child, addr);
 			else {
-				ret = -EIO;
-				break ;
+				switch(addr) {
+				case 49:
+					tmp = child->mm->start_code;
+					break ;
+				case 50:
+					tmp = child->mm->start_data;
+					break ;
+				case 51:
+					tmp = child->mm->end_code;
+					break ;
+				case 52:
+					tmp = child->mm->end_data;
+					break ;
+				default:
+					ret = -EIO;
+				}
 			}
-			ret = put_user(tmp,(unsigned long *) data);
+			if (!ret)
+				ret = put_user(tmp,(unsigned long *) data);
 			break ;
 		}
 
diff -Nru a/arch/h8300/platform/h8s/entry.S b/arch/h8300/platform/h8s/entry.S
--- a/arch/h8300/platform/h8s/entry.S	2004-06-23 19:04:28 -07:00
+++ b/arch/h8300/platform/h8s/entry.S	2004-06-23 19:04:28 -07:00
@@ -83,6 +83,7 @@
 	mov.l	@(LER0-LER1:16,sp),er1		/* restore ER0 */
 	mov.l	er1,@er0
 	mov.w	@(LEXR-LER1:16,sp),r1		/* restore EXR */
+	mov.b	r1l,r1h
 	mov.w	r1,@(8:16,er0)
 	mov.w	@(LCCR-LER1:16,sp),r1		/* restore the RET addr */
 	mov.b	r1l,r1h
@@ -213,7 +214,6 @@
 	mov.l	er0,@(LER0:16,sp)		/* save the return value */
 	jsr	@SYMBOL_NAME(syscall_trace)
 	bra	SYMBOL_NAME(ret_from_exception):8
-
 
 SYMBOL_NAME_LABEL(ret_from_fork)
 	mov.l	er2,er0
diff -Nru a/arch/h8300/platform/h8s/ptrace_h8s.c b/arch/h8300/platform/h8s/ptrace_h8s.c
--- a/arch/h8300/platform/h8s/ptrace_h8s.c	2004-06-23 19:04:26 -07:00
+++ b/arch/h8300/platform/h8s/ptrace_h8s.c	2004-06-23 19:04:26 -07:00
@@ -23,7 +23,7 @@
 static const int h8300_register_offset[] = {
 	PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
 	PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
-	PT_REG(ccr), PT_REG(pc), PT_REG(exr)
+	PT_REG(ccr), PT_REG(pc),  0,           PT_REG(exr)
 };
 
 /* read register */
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/Kconfig	2004-06-23 19:04:25 -07:00
@@ -436,7 +436,8 @@
 	  Choose N to continue using the legacy 8254 timer.
 
 config HPET_EMULATE_RTC
-	def_bool HPET_TIMER && RTC=y
+	bool "Provide RTC interrupt"
+	depends on HPET_TIMER && RTC=y
 
 config SMP
 	bool "Symmetric multi-processing support"
@@ -1333,12 +1334,6 @@
 config X86_TRAMPOLINE
 	bool
 	depends on X86_SMP || (X86_VOYAGER && SMP)
-	default y
-
-# std_resources is overridden for pc9800, but that's not
-# a currently selectable arch choice
-config X86_STD_RESOURCES
-	bool
 	default y
 
 config PC
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/Makefile	2004-06-23 19:04:26 -07:00
@@ -121,22 +121,23 @@
 
 all: bzImage
 
-BOOTIMAGE=arch/i386/boot/bzImage
-zImage zlilo zdisk: BOOTIMAGE=arch/i386/boot/zImage
+# KBUILD_IMAGE specify target image being built
+                    KBUILD_IMAGE := $(boot)/bzImage
+zImage zlilo zdisk: KBUILD_IMAGE := arch/i386/boot/zImage
 
 zImage bzImage: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
+	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
 
 compressed: zImage
 
 zlilo bzlilo: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zlilo
+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zlilo
 
 zdisk bzdisk: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk
 
 install fdimage fdimage144 fdimage288: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
 
 prepare: include/asm-$(ARCH)/asm_offsets.h
 CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
diff -Nru a/arch/i386/boot98/Makefile b/arch/i386/boot98/Makefile
--- a/arch/i386/boot98/Makefile	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,102 +0,0 @@
-#
-# arch/i386/boot/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1994 by Linus Torvalds
-#
-
-# ROOT_DEV specifies the default root-device when making the image.
-# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
-# the default of FLOPPY is used by 'build'.
-
-ROOT_DEV := CURRENT
-
-# If you want to preset the SVGA mode, uncomment the next line and
-# set SVGA_MODE to whatever number you want.
-# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
-# The number is the same as you would ordinarily press at bootup.
-
-SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
-
-# If you want the RAM disk device, define this to be the size in blocks.
-
-#RAMDISK := -DRAMDISK=512
-
-targets		:= vmlinux.bin bootsect bootsect.o setup setup.o \
-		   zImage bzImage
-subdir- 	:= compressed
-
-host-progs	:= tools/build
-
-# ---------------------------------------------------------------------------
-
-$(obj)/zImage:  IMAGE_OFFSET := 0x1000
-$(obj)/zImage:  EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK)
-$(obj)/bzImage: IMAGE_OFFSET := 0x100000
-$(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
-$(obj)/bzImage: BUILDFLAGS   := -b
-
-quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
-	    $(obj)/vmlinux.bin $(ROOT_DEV) > $@
-
-$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
-			      $(obj)/vmlinux.bin $(obj)/tools/build FORCE
-	$(call if_changed,image)
-	@echo 'Kernel: $@ is ready'
-
-$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
-	$(call if_changed,objcopy)
-
-LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
-LDFLAGS_setup	 := -Ttext 0x0 -s --oformat binary -e begtext
-
-$(obj)/setup $(obj)/bootsect: %: %.o FORCE
-	$(call if_changed,ld)
-
-$(obj)/compressed/vmlinux: FORCE
-	$(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
-
-# Set this if you want to pass append arguments to the zdisk/fdimage kernel
-FDARGS = 
-
-$(obj)/mtools.conf: $(src)/mtools.conf.in
-	sed -e 's|@OBJ@|$(obj)|g' < $< > $@
-
-# This requires write access to /dev/fd0
-zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
-	MTOOLSRC=$(obj)/mtools.conf mformat a:			; sync
-	syslinux /dev/fd0					; sync
-	echo 'default linux $(FDARGS)' | \
-		MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
-	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
-
-# These require being root or having syslinux 2.02 or higher installed
-fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
-	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
-	MTOOLSRC=$(obj)/mtools.conf mformat v:			; sync
-	syslinux $(obj)/fdimage					; sync
-	echo 'default linux $(FDARGS)' | \
-		MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
-	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
-
-fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
-	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
-	MTOOLSRC=$(obj)/mtools.conf mformat w:			; sync
-	syslinux $(obj)/fdimage					; sync
-	echo 'default linux $(FDARGS)' | \
-		MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
-	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
-
-zlilo: $(BOOTIMAGE)
-	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
-	if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
-	cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz
-	cp System.map $(INSTALL_PATH)/
-	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-
-install: $(BOOTIMAGE)
-	sh $(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
diff -Nru a/arch/i386/boot98/bootsect.S b/arch/i386/boot98/bootsect.S
--- a/arch/i386/boot98/bootsect.S	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,397 +0,0 @@
-/*	
- *	bootsect.S - boot sector for NEC PC-9800 series
- *
- *	Linux/98 project at Kyoto University Microcomputer Club (KMC)
- *		    FUJITA Norimasa, TAKAI Kousuke  1997-1998
- *	rewritten by TAKAI Kousuke (as86 -> gas), Nov 1999
- *
- * Based on:
- *	bootsect.S		Copyright (C) 1991, 1992 Linus Torvalds
- *	modified by Drew Eckhardt
- *	modified by Bruce Evans (bde)
- *
- * bootsect.S is loaded at 0x1FC00 or 0x1FE00 by the bios-startup routines,
- * and moves itself out of the way to address 0x90000, and jumps there.
- *
- * It then loads 'setup' directly after itself (0x90200), and the system
- * at 0x10000, using BIOS interrupts. 
- *
- * NOTE! currently system is at most (8*65536-4096) bytes long. This should 
- * be no problem, even in the future. I want to keep it simple. This 508 kB
- * kernel size should be enough, especially as this doesn't contain the
- * buffer cache as in minix (and especially now that the kernel is 
- * compressed :-)
- *
- * The loader has been made as simple as possible, and continuous
- * read errors will result in a unbreakable loop. Reboot by hand. It
- * loads pretty fast by getting whole tracks at a time whenever possible.
- */
-
-#include <linux/config.h>		/* for CONFIG_ROOT_RDONLY */
-#include <asm/boot.h>
-
-SETUPSECTS	= 4			/* default nr of setup-sectors */
-BOOTSEG		= 0x1FC0		/* original address of boot-sector */
-INITSEG		= DEF_INITSEG		/* we move boot here - out of the way */
-SETUPSEG	= DEF_SETUPSEG		/* setup starts here */
-SYSSEG		= DEF_SYSSEG		/* system loaded at 0x10000 (65536) */
-SYSSIZE		= DEF_SYSSIZE		/* system size: # of 16-byte clicks */
-					/* to be loaded */
-ROOT_DEV	= 0 			/* ROOT_DEV is now written by "build" */
-SWAP_DEV	= 0			/* SWAP_DEV is now written by "build" */
-
-#ifndef SVGA_MODE
-#define SVGA_MODE ASK_VGA
-#endif
-
-#ifndef RAMDISK
-#define RAMDISK 0
-#endif 
-
-#ifndef ROOT_RDONLY
-#define ROOT_RDONLY 1
-#endif
-
-/* normal/hireso text VRAM segments */
-#define NORMAL_TEXT	0xa000
-#define HIRESO_TEXT	0xe000
-
-/* bios work area addresses */
-#define EXPMMSZ		0x0401
-#define BIOS_FLAG	0x0501
-#define	DISK_BOOT	0x0584
-
-.code16
-.text
-
-.global _start
-_start:
-
-#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
-	int	$0x3
-#endif
-	jmp	real_start
-	.ascii	"Linux 98"
-	.word	0
-real_start:
-	xorw	%di, %di		/* %di = 0 */
-	movw	%di, %ss		/* %ss = 0 */
-	movw	$0x03F0, %sp
-	pushw	%cx			/* for hint */
-
-	movw	$0x0A00, %ax		/* normal mode defaults (80x25) */
-
-	testb	$0x08, %ss:BIOS_FLAG	/* check hi-reso bit */
-	jnz	set_crt_mode
-/*
- * Hi-Reso (high-resolution) machine.
- *
- * Some hi-reso machines have no RAMs on bank 8/A (0x080000 - 0x0BFFFF).
- * On such machines we get two RAM banks from top of protect menory and
- * map them on bank 8/A.
- * These work-around must be done before moving myself on INITSEG (0x090000-).
- */
-	movw	$(HIRESO_TEXT >> 8), %cs:(vram + 1)	/* text VRAM segment */
-
-	/* set memory window */
-	movb	$0x08, %al
-	outb	%al, $0x91		/* map native RAM (if any) */
-	movb	$0x0A, %al
-	outb	%al, $0x93
-
-	/* check bank ram A */
-	pushw	$0xA500
-	popw	%ds
-	movw	(%di), %cx		/* %si == 0 from entry */
-	notw	%cx
-	movw	%cx, (%di)
-
-	movw	$0x43F, %dx		/* cache flush for 486 and up. */
-	movb	$0xA0, %al
-	outb	%al, %dx
-	
-	cmpw	%cx, (%di)
-	je	hireso_done
-
-	/* 
-	 * Write test failed; we have no native RAM on 080000h - 0BFFFFh.
-	 * Take 256KB of RAM from top of protected memory.
-	 */
-	movb	%ss:EXPMMSZ, %al
-	subb	$2, %al			/* reduce 2 x 128KB */
-	movb	%al, %ss:EXPMMSZ
-	addb	%al, %al
-	addb	$0x10, %al
-	outb	%al, $0x91
-	addb	$2, %al
-	outb	%al, $0x93
-
-hireso_done:
-	movb	$0x10, %al		/* CRT mode 80x31, %ah still 0Ah */
-
-set_crt_mode:
-	int	$0x18			/* set CRT mode */
-
-	movb	$0x0C, %ah		/* turn on text displaying */
-	int	$0x18
-
-	xorw	%dx, %dx		/* position cursor to home */
-	movb	$0x13, %ah
-	int	$0x18
-
-	movb	$0x11, %ah		/* turn cursor displaying on */
-	int	$0x18
-
-	/* move 1 kilobytes from [BOOTSEG:0000h] to [INITSEG:0000h] */
-	cld
-	xorw	%si, %si
-	pushw	$INITSEG
-	popw	%es
-	movw	$512, %cx		/* %di == 0 from entry */
-	rep
-	cs
-	movsw
-
-	ljmp	$INITSEG, $go
-
-go:
-	pushw	%cs
-	popw	%ds		/* %ds = %cs */
-
-	popw	%dx		/* %dh = saved %ch passed from BIOS */
-	movb	%ss:DISK_BOOT, %al
-	andb	$0xf0, %al	/* %al = Device Address */
-	movb	$18, %ch	/* 18 secs/track,  512 b/sec (1440 KB) */
-	cmpb	$0x30, %al
-	je	try512
-	cmpb	$0x90, %al	/* 1 MB I/F, 1 MB floppy */
-	je	try1.2M
-	cmpb	$0xf0, %al	/* 640 KB I/F, 1 MB floppy */
-	je	try1.2M
-	movb	$9, %ch		/*  9 secs/track,  512 b/sec ( 720 KB) */
-	cmpb	$0x10, %al	/* 1 MB I/F, 640 KB floppy */
-	je	try512
-	cmpb	$0x70, %al	/* 640 KB I/F, 640 KB floppy */
-	jne	error		/* unknown device? */
-
-	/* XXX: Does it make sense to support 8 secs/track, 512 b/sec 
-		(640 KB) floppy? */
-
-try512:	movb	$2, %cl		/* 512 b/sec */
-lasttry:call	tryload
-/*
- * Display error message and halt
- */
-error:	movw	$error_msg, %si
-	call	print
-wait_reboot:
-	movb	$0x0, %ah
-	int	$0x18			/* wait keyboard input */
-1:	movb	$0, %al
-	outb	%al, $0xF0		/* reset CPU */
-	jmp	1b			/* just in case... */
-
-try1.2M:cmpb	$2, %dh
-	je	try2HC
-	movw	$0x0803, %cx	/*  8 secs/track, 1024 b/sec (1232 KB) */
-	call	tryload
-	movb	$15, %ch	/* 15 secs/track,  512 b/sec (1200 KB) */
-	jmp	try512
-try2HC:	movw	$0x0F02, %cx	/* 15 secs/track,  512 b/sec (1200 KB) */
-	call	tryload
-	movw	$0x0803, %cx	/*  8 secs/track, 1024 b/sec (1232 KB) */
-	jmp	lasttry
-
-/*
- * Try to load SETUP and SYSTEM provided geometry information in %cx.
- * This routine *will not* return on successful load...
- */
-tryload:
-	movw	%cx, sectlen
-	movb	%ss:DISK_BOOT, %al
-	movb	$0x7, %ah		/* recalibrate the drive */
-	int	$0x1b
-	jc	error			/* recalibration should succeed */
-
-	/*
-	 * Load SETUP into memory. It is assumed that SETUP fits into
-	 * first cylinder (2 tracks, 9KB on 2DD, 15-18KB on 2HD).
-	 */
-	movb	$0, %bl
-	movb	setup_sects, %bh
-	incb	%bh
-	shlw	%bx			/* %bx = (setup_sects + 1) * 512 */
-	movw	$128, %bp
-	shlw	%cl, %bp		/* %bp = <sector size> */
-	subw	%bp, %bx		/* length to load */
-	movw	$0x0002, %dx		/* head 0, sector 2 */
-	movb	%cl, %ch		/* `N' for sector address */
-	movb	$0, %cl			/* cylinder 0 */
-	pushw	%cs
-	popw	%es			/* %es = %cs (= INITSEG) */
-	movb	$0xd6, %ah		/* read, multi-track, MFM */
-	int	$0x1b			/* load it! */
-	jc	read_error
-
-	movw	$loading_msg, %si
-	call	print
-
-	movw	$SYSSEG, %ax
-	movw	%ax, %es		/* %es = SYSSEG */
-
-/*
- * This routine loads the system at address 0x10000, making sure
- * no 64kB boundaries are crossed. We try to load it as fast as
- * possible, loading whole tracks whenever we can.
- *
- * in:	es - starting address segment (normally 0x1000)
- */
-	movb	%ch, %cl
-	addb	$7, %cl			/* %cl = log2 <sector_size> */
-	shrw	%cl, %bx		/* %bx = # of phys. sectors in SETUP */
-	addb	%bl, %dl		/* %dl = start sector # of SYSTEM */
-	decb	%dl			/* %dl is 0-based in below loop */
-
-rp_read_newseg:
-	xorw	%bp, %bp		/* = starting address within segment */
-#ifdef __BIG_KERNEL__
-	bootsect_kludge = 0x220		/* 0x200 (size of bootsector) + 0x20 (offset */
-	lcall	*bootsect_kludge	/* of bootsect_kludge in setup.S */
-#else
-	movw	%es, %ax
-	subw	$SYSSEG, %ax
-#endif
-	cmpw	syssize, %ax
-	ja	boot			/* done! */
-
-rp_read:
-	movb	sectors, %al
-	addb	%al, %al
-	movb	%al, %ch		/* # of sectors on both surface */
-	subb	%dl, %al		/* # of sectors left on this track */
-	movb	$0, %ah
-	shlw	%cl, %ax		/* # of bytes left on this track */
-	movw	%ax, %bx		/* transfer length */
-	addw	%bp, %ax		/* cross 64K boundary? */
-	jnc	1f			/* ok. */
-	jz	1f			/* also ok. */
-	/*
-	 * Oops, we are crossing 64K boundary...
-	 * Adjust transfer length to make transfer fit in the boundary.
-	 *
-	 * Note: sector size is assumed to be a measure of 65536.
-	 */
-	xorw	%bx, %bx
-	subw	%bp, %bx
-1:	pushw	%dx
-	movw	$dot_msg, %si		/* give progress message */
-	call	print
-	xchgw	%ax, %dx
-	movb	$0, %ah
-	divb	sectors
-	xchgb	%al, %ah
-	xchgw	%ax, %dx		/* %dh = head # / %dl = sector # */
-	incb	%dl			/* fix %dl to 1-based */
-	pushw	%cx
-	movw	cylinder, %cx
-	movb	$0xd6, %ah		/* read, multi-track, seek, MFM */
-	movb	%ss:DISK_BOOT, %al
-	int	$0x1b
-	popw	%cx
-	popw	%dx
-	jc	read_error
-	movw	%bx, %ax		/* # of bytes just read */
-	shrw	%cl, %ax		/* %ax = # of sectors just read */
-	addb	%al, %dl		/* advance sector # */
-	cmpb	%ch, %dl		/* %ch = # of sectors/cylinder */
-	jb	2f
-	incb	cylinder		/* next cylinder */
-	xorb	%dl, %dl		/* sector 0 */
-2:	addw	%bx, %bp		/* advance offset pointer */
-	jnc	rp_read
-	/* offset pointer wrapped; advance segment pointer. */
-	movw	%es, %ax
-	addw	$0x1000, %ax
-	movw	%ax, %es
-	jmp	rp_read_newseg
-
-read_error:
-	ret
-
-boot:	movw	%cs, %ax		/* = INITSEG */
-	/* movw	%ax, %ds */
-	movw	%ax, %ss
-	movw	$0x4000, %sp		/* 0x4000 is arbitrary value >=
-					 * length of bootsect + length of
-					 * setup + room for stack;
-					 * PC-9800 never have BIOS workareas
-					 * on high memory.
-					 */
-/*
- * After that we check which root-device to use. If the device is
- * not defined, /dev/fd0 (2, 0) will be used.
- */
-	cmpw	$0, root_dev
-	jne	3f
-	movb	$2, root_dev+1
-3:
-
-/*
- * After that (everything loaded), we jump to the setup-routine
- * loaded directly after the bootblock:
- */
-	ljmp	$SETUPSEG, $0
-
-/*
- * Subroutine for print string on console.
- *	%cs:%si	- pointer to message
- */
-print:
-	pushaw
-	pushw	%ds
-	pushw	%es
-	pushw	%cs
-	popw	%ds
-	lesw	curpos, %di		/* %es:%di = current text VRAM addr. */
-1:	xorw	%ax, %ax
-	lodsb
-	testb	%al, %al
-	jz	2f			/* end of string */
-	stosw					/* character code */
-	movb	$0xE1, %es:0x2000-2(%di)	/* character attribute */
-	jmp	1b
-2:	movw	%di, %dx
-	movb	$0x13, %ah
-	int	$0x18			/* move cursor to current point */
-	popw	%es
-	popw	%ds
-	popaw
-	ret
-
-loading_msg:
-	.string	"Loading"
-dot_msg:
-	.string	"."
-error_msg:
-	.string	"Read Error!"
-
-	.org	490
-
-curpos:	.word	160		/* current cursor position */
-vram:	.word	NORMAL_TEXT	/* text VRAM segment */
-
-cylinder:	.byte	0	/* current cylinder (lower byte)	*/
-sectlen:	.byte	0	/* (log2 of <sector size>) - 7		*/
-sectors:	.byte	0x0F	/* default is 2HD (15 sector/track)	*/
-
-# XXX: This is a fairly snug fit.
-
-.org 497
-setup_sects:	.byte SETUPSECTS
-root_flags:	.word ROOT_RDONLY
-syssize:	.word SYSSIZE
-swap_dev:	.word SWAP_DEV
-ram_size:	.word RAMDISK
-vid_mode:	.word SVGA_MODE
-root_dev:	.word ROOT_DEV
-boot_flag:	.word 0xAA55
diff -Nru a/arch/i386/boot98/install.sh b/arch/i386/boot98/install.sh
--- a/arch/i386/boot98/install.sh	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,40 +0,0 @@
-#!/bin/sh
-#
-# arch/i386/boot/install.sh
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1995 by Linus Torvalds
-#
-# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
-#
-# "make install" script for i386 architecture
-#
-# Arguments:
-#   $1 - kernel version
-#   $2 - kernel image file
-#   $3 - kernel map file
-#   $4 - default install path (blank if root directory)
-#
-
-# User may have a custom install script
-
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
-
-# Default install - same as make zlilo
-
-if [ -f $4/vmlinuz ]; then
-	mv $4/vmlinuz $4/vmlinuz.old
-fi
-
-if [ -f $4/System.map ]; then
-	mv $4/System.map $4/System.old
-fi
-
-cat $2 > $4/vmlinuz
-cp $3 $4/System.map
-
-if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
diff -Nru a/arch/i386/boot98/mtools.conf.in b/arch/i386/boot98/mtools.conf.in
--- a/arch/i386/boot98/mtools.conf.in	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,17 +0,0 @@
-#
-# mtools configuration file for "make (b)zdisk"
-#
-
-# Actual floppy drive
-drive a:
-  file="/dev/fd0"
-
-# 1.44 MB floppy disk image
-drive v:
-  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
-
-# 2.88 MB floppy disk image (mostly for virtual uses)
-drive w:
-  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
-
-
diff -Nru a/arch/i386/boot98/setup.S b/arch/i386/boot98/setup.S
--- a/arch/i386/boot98/setup.S	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,876 +0,0 @@
-/*
- *	setup.S		Copyright (C) 1991, 1992 Linus Torvalds
- *
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * This code asks the bios for memory/disk/other parameters, and
- * puts them in a "safe" place: 0x90000-0x901FF, ie where the
- * boot-block used to be. It is then up to the protected mode
- * system to read them from there before the area is overwritten
- * for buffer-blocks.
- *
- * Move PS/2 aux init code to psaux.c
- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
- *
- * some changes and additional features by Christoph Niemann,
- * March 1993/June 1994 (Christoph.Niemann@linux.org)
- *
- * add APM BIOS checking by Stephen Rothwell, May 1994
- * (sfr@canb.auug.org.au)
- *
- * High load stuff, initrd support and position independency
- * by Hans Lermen & Werner Almesberger, February 1996
- * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
- *
- * Video handling moved to video.S by Martin Mares, March 1996
- * <mj@k332.feld.cvut.cz>
- *
- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
- * parsons) to avoid loadlin confusion, July 1997
- *
- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
- * <stiker@northlink.com>
- *
- * Fix to work around buggy BIOSes which dont use carry bit correctly
- * and/or report extended memory in CX/DX for e801h memory size detection 
- * call.  As a result the kernel got wrong figures.  The int15/e801h docs
- * from Ralf Brown interrupt list seem to indicate AX/BX should be used
- * anyway.  So to avoid breaking many machines (presumably there was a reason
- * to orginally use CX/DX instead of AX/BX), we do a kludge to see
- * if CX/DX have been changed in the e801 call and if so use AX/BX .
- * Michael Miller, April 2001 <michaelm@mjmm.org>
- *
- * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
- * by Robert Schwebel, December 2001 <robert@schwebel.de>
- *
- * Heavily modified for NEC PC-9800 series by Kyoto University Microcomputer
- * Club (KMC) Linux/98 project <seraphim@kmc.kyoto-u.ac.jp>, 1997-1999
- */
-
-#include <linux/config.h>
-#include <asm/segment.h>
-#include <linux/version.h>
-#include <linux/compile.h>
-#include <asm/boot.h>
-#include <asm/e820.h>
-#include <asm/page.h>
-	
-/* Signature words to ensure LILO loaded us right */
-#define SIG1	0xAA55
-#define SIG2	0x5A5A
-
-#define HIRESO_TEXT	0xe000
-#define NORMAL_TEXT	0xa000
-
-#define BIOS_FLAG2	0x0400
-#define BIOS_FLAG5	0x0458
-#define RDISK_EQUIP	0x0488
-#define BIOS_FLAG	0x0501
-#define KB_SHFT_STS	0x053a
-#define DISK_EQUIP	0x055c
-
-INITSEG  = DEF_INITSEG		# 0x9000, we move boot here, out of the way
-SYSSEG   = DEF_SYSSEG		# 0x1000, system loaded at 0x10000 (65536).
-SETUPSEG = DEF_SETUPSEG		# 0x9020, this is the current segment
-				# ... and the former contents of CS
-
-DELTA_INITSEG = SETUPSEG - INITSEG	# 0x0020
-
-.code16
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-start:
-	jmp	trampoline
-
-# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
-
-		.ascii	"HdrS"		# header signature
-		.word	0x0203		# header version number (>= 0x0105)
-					# or else old loadlin-1.5 will fail)
-realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
-start_sys_seg:	.word	SYSSEG
-		.word	kernel_version	# pointing to kernel version string
-					# above section of header is compatible
-					# with loadlin-1.5 (header v1.5). Don't
-					# change it.
-
-type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,
-					#      Bootlin, SYSLX, bootsect...)
-					# See Documentation/i386/boot.txt for
-					# assigned ids
-	
-# flags, unused bits must be zero (RFU) bit within loadflags
-loadflags:
-LOADED_HIGH	= 1			# If set, the kernel is loaded high
-CAN_USE_HEAP	= 0x80			# If set, the loader also has set
-					# heap_end_ptr to tell how much
-					# space behind setup.S can be used for
-					# heap purposes.
-					# Only the loader knows what is free
-#ifndef __BIG_KERNEL__
-		.byte	0
-#else
-		.byte	LOADED_HIGH
-#endif
-
-setup_move_size: .word  0x8000		# size to move, when setup is not
-					# loaded at 0x90000. We will move setup 
-					# to 0x90000 then just before jumping
-					# into the kernel. However, only the
-					# loader knows how much data behind
-					# us also needs to be loaded.
-
-code32_start:				# here loaders can put a different
-					# start address for 32-bit code.
-#ifndef __BIG_KERNEL__
-		.long	0x1000		#   0x1000 = default for zImage
-#else
-		.long	0x100000	# 0x100000 = default for big kernel
-#endif
-
-ramdisk_image:	.long	0		# address of loaded ramdisk image
-					# Here the loader puts the 32-bit
-					# address where it loaded the image.
-					# This only will be read by the kernel.
-
-ramdisk_size:	.long	0		# its size in bytes
-
-bootsect_kludge:
-		.long	0		# obsolete
-
-heap_end_ptr:	.word	modelist+1024	# (Header version 0x0201 or later)
-					# space from here (exclusive) down to
-					# end of setup code can be used by setup
-					# for local heap purposes.
-
-pad1:		.word	0
-cmd_line_ptr:	.long 0			# (Header version 0x0202 or later)
-					# If nonzero, a 32-bit pointer
-					# to the kernel command line.
-					# The command line should be
-					# located between the start of
-					# setup and the end of low
-					# memory (0xa0000), or it may
-					# get overwritten before it
-					# gets read.  If this field is
-					# used, there is no longer
-					# anything magical about the
-					# 0x90000 segment; the setup
-					# can be located anywhere in
-					# low memory 0x10000 or higher.
-
-ramdisk_max:	.long MAXMEM-1		# (Header version 0x0203 or later)
-					# The highest safe address for
-					# the contents of an initrd
-
-trampoline:	call	start_of_setup
-		.space	1024
-# End of setup header #####################################################
-
-start_of_setup:
-# Set %ds = %cs, we know that SETUPSEG = %cs at this point
-	movw	%cs, %ax		# aka SETUPSEG
-	movw	%ax, %ds
-# Check signature at end of setup
-	cmpw	$SIG1, setup_sig1
-	jne	bad_sig
-
-	cmpw	$SIG2, setup_sig2
-	jne	bad_sig
-
-	jmp	good_sig1
-
-# Routine to print asciiz string at ds:si
-prtstr:
-	lodsb
-	andb	%al, %al
-	jz	fin
-
-	call	prtchr
-	jmp	prtstr
-
-fin:	ret
-
-no_sig_mess: .string	"No setup signature found ..."
-
-good_sig1:
-	jmp	good_sig
-
-# We now have to find the rest of the setup code/data
-bad_sig:
-	movw	%cs, %ax			# SETUPSEG
-	subw	$DELTA_INITSEG, %ax		# INITSEG
-	movw	%ax, %ds
-	xorb	%bh, %bh
-	movb	(497), %bl			# get setup sect from bootsect
-	subw	$4, %bx				# LILO loads 4 sectors of setup
-	shlw	$8, %bx				# convert to words (1sect=2^8 words)
-	movw	%bx, %cx
-	shrw	$3, %bx				# convert to segment
-	addw	$SYSSEG, %bx
-	movw	%bx, %cs:start_sys_seg
-# Move rest of setup code/data to here
-	movw	$2048, %di			# four sectors loaded by LILO
-	subw	%si, %si
-	pushw	%cs
-	popw	%es
-	movw	$SYSSEG, %ax
-	movw	%ax, %ds
-	rep
-	movsw
-	movw	%cs, %ax			# aka SETUPSEG
-	movw	%ax, %ds
-	cmpw	$SIG1, setup_sig1
-	jne	no_sig
-
-	cmpw	$SIG2, setup_sig2
-	jne	no_sig
-
-	jmp	good_sig
-
-no_sig:
-	lea	no_sig_mess, %si
-	call	prtstr
-
-no_sig_loop:
-	hlt
-	jmp	no_sig_loop
-
-good_sig:
-	movw	%cs, %ax			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %ax 		# aka INITSEG
-	movw	%ax, %ds
-# Check if an old loader tries to load a big-kernel
-	testb	$LOADED_HIGH, %cs:loadflags	# Do we have a big kernel?
-	jz	loader_ok			# No, no danger for old loaders.
-
-	cmpb	$0, %cs:type_of_loader 		# Do we have a loader that
-						# can deal with us?
-	jnz	loader_ok			# Yes, continue.
-
-	pushw	%cs				# No, we have an old loader,
-	popw	%ds				# die. 
-	lea	loader_panic_mess, %si
-	call	prtstr
-
-	jmp	no_sig_loop
-
-loader_panic_mess: .string "Wrong loader, giving up..."
-
-loader_ok:
-# Get memory size (extended mem, kB)
-
-# On PC-9800, memory size detection is done completely in 32-bit
-# kernel initialize code (kernel/setup.c).
-	pushw	%es
-	xorl	%eax, %eax
-	movw	%ax, %es
-	movb	%al, (E820NR)		# PC-9800 has no E820
-	movb	%es:(0x401), %al
-	shll	$7, %eax
-	addw	$1024, %ax
-	movw	%ax, (2)
-	movl	%eax, (0x1e0)
-	movw	%es:(0x594), %ax
-	shll	$10, %eax
-	addl	%eax, (0x1e0)
-	popw	%es
-
-# Check for video adapter and its parameters and allow the
-# user to browse video modes.
-	call	video				# NOTE: we need %ds pointing
-						# to bootsector
-
-# Get text video mode
-	movb	$0x0B, %ah
-	int	$0x18		# CRT mode sense
-	movw	$(20 << 8) + 40, %cx
-	testb	$0x10, %al
-	jnz	3f
-	movb	$20, %ch
-	testb	$0x01, %al
-	jnz	1f
-	movb	$25, %ch
-	jmp	1f
-3:	# If bit 4 was 1, it means either 1) 31 lines for hi-reso mode,
-	# or 2) 30 lines for PC-9821.
-	movb	$31, %ch	# hireso mode value
-	pushw	$0
-	popw	%es
-	testb	$0x08, %es:BIOS_FLAG
-	jnz	1f
-	movb	$30, %ch
-1:	# Now we got # of rows in %ch
-	movb	%ch, (14)
-
-	testb	$0x02, %al
-	jnz	2f
-	movb	$80, %cl
-2:	# Now we got # of columns in %cl
-	movb	%cl, (7)
-
-	# Next, get horizontal frequency if supported
-	movw	$0x3100, %ax
-	int	$0x18		# Call CRT bios
-	movb	%al, (6)	# If 31h is unsupported, %al remains 0
-
-# Get hd0-3 data...
-	pushw	%ds				# aka INITSEG
-	popw	%es
-	xorw	%ax, %ax
-	movw	%ax, %ds
-	cld
-	movw	$0x0080, %di
-	movb	DISK_EQUIP+1, %ah
-	movb	$0x80, %al
-
-get_hd_info:
-	shrb	%ah
-	pushw	%ax
-	jnc	1f
-	movb	$0x84, %ah
-	int	$0x1b
-	jnc	2f				# Success
-1:	xorw	%cx, %cx			# `0 cylinders' means no drive
-2:	# Attention! Work area (drive_info) is arranged for PC-9800.
-	movw	%cx, %ax			# # of cylinders
-	stosw
-	movw	%dx, %ax			# # of sectors / # of heads
-	stosw
-	movw	%bx, %ax			# sector size in bytes
-	stosw
-	popw	%ax
-	incb	%al
-	cmpb	$0x84, %al
-	jb	get_hd_info
-
-# Get fd data...
-	movw	DISK_EQUIP, %ax
-	andw	$0xf00f, %ax
-	orb	%al, %ah
-	movb	RDISK_EQUIP, %al
-	notb	%al
-	andb	%al, %ah			# ignore all `RAM drive'
-
-	movb	$0x30, %al
-
-get_fd_info:
-	shrb	%ah
-	pushw	%ax
-	jnc	1f
-	movb	$0xc4, %ah
-	int	$0x1b
-	movb	%ah, %al
-	andb	$4, %al				# 1.44MB support flag
-	shrb	%al
-	addb	$2, %al				# %al = 2 (1.2MB) or 4 (1.44MB)
-	jmp	2f
-1:	movb	$0, %al				# no drive
-2:	stosb
-	popw	%ax
-	incb	%al
-	testb	$0x04, %al
-	jz	get_fd_info
-
-	addb	$(0xb0 - 0x34), %al
-	jnc	get_fd_info			# check FDs on 640KB I/F
-
-	pushw	%es
-	popw	%ds				# %ds got bootsector again
-#if 0
-	mov	$0, (0x1ff)			# default is no pointing device
-#endif
-
-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
-# Then check for an APM BIOS...
-						# %ds points to the bootsector
-	movw	$0, 0x40			# version = 0 means no APM BIOS
-	movw	$0x09a00, %ax			# APM BIOS installation check
-	xorw	%bx, %bx
-	int	$0x1f
-	jc	done_apm_bios			# Nope, no APM BIOS
-
-	cmpw	$0x0504d, %bx			# Check for "PM" signature
-	jne	done_apm_bios			# No signature, no APM BIOS
-
-	testb	$0x02, %cl			# Is 32 bit supported?
-	je	done_apm_bios			# No 32-bit, no (good) APM BIOS
-
-	movw	$0x09a04, %ax			# Disconnect first just in case
-	xorw	%bx, %bx
-	int	$0x1f				# ignore return code
-	movw	$0x09a03, %ax			# 32 bit connect
-	xorl	%ebx, %ebx
-	int	$0x1f
-	jc	no_32_apm_bios			# Ack, error.
-
-	movw	%ax,  (66)			# BIOS code segment
-	movl	%ebx, (68)			# BIOS entry point offset
-	movw	%cx,  (72)			# BIOS 16 bit code segment
-	movw	%dx,  (74)			# BIOS data segment
-	movl	%esi, (78)			# BIOS code segment length
-	movw	%di,  (82)			# BIOS data segment length
-# Redo the installation check as the 32 bit connect
-# modifies the flags returned on some BIOSs
-	movw	$0x09a00, %ax			# APM BIOS installation check
-	xorw	%bx, %bx
-	int	$0x1f
-	jc	apm_disconnect			# error -> shouldn't happen
-
-	cmpw	$0x0504d, %bx			# check for "PM" signature
-	jne	apm_disconnect			# no sig -> shouldn't happen
-
-	movw	%ax, (64)			# record the APM BIOS version
-	movw	%cx, (76)			# and flags
-	jmp	done_apm_bios
-
-apm_disconnect:					# Tidy up
-	movw	$0x09a04, %ax			# Disconnect
-	xorw	%bx, %bx
-	int	$0x1f				# ignore return code
-
-	jmp	done_apm_bios
-
-no_32_apm_bios:
-	andw	$0xfffd, (76)			# remove 32 bit support bit
-done_apm_bios:
-#endif
-
-# Pass cursor position to kernel...
-	movw	%cs:cursor_address, %ax
-	shrw	%ax		# cursor_address is 2 bytes unit
-	movb	$80, %cl
-	divb	%cl
-	xchgb	%al, %ah	# (0) = %al = X, (1) = %ah = Y
-	movw	%ax, (0)
-
-#if 0
-	movw	$msg_cpos, %si
-	call	prtstr_cs
-	call	prthex
-	call	prtstr_cs
-	movw	%ds, %ax
-	call	prthex
-	call	prtstr_cs
-	movb	$0x11, %ah
-	int	$0x18
-	movb	$0, %ah
-	int	$0x18
-	.section .rodata, "a"
-msg_cpos:	.string	"Cursor position: 0x"
-		.string	", %ds:0x"
-		.string	"\r\n"
-	.previous
-#endif
-
-# Now we want to move to protected mode ...
-	cmpw	$0, %cs:realmode_swtch
-	jz	rmodeswtch_normal
-
-	lcall	*%cs:realmode_swtch
-
-	jmp	rmodeswtch_end
-
-rmodeswtch_normal:
-        pushw	%cs
-	call	default_switch
-
-rmodeswtch_end:
-# we get the code32 start address and modify the below 'jmpi'
-# (loader may have changed it)
-	movl	%cs:code32_start, %eax
-	movl	%eax, %cs:code32
-
-# Now we move the system to its rightful place ... but we check if we have a
-# big-kernel. In that case we *must* not move it ...
-	testb	$LOADED_HIGH, %cs:loadflags
-	jz	do_move0			# .. then we have a normal low
-						# loaded zImage
-						# .. or else we have a high
-						# loaded bzImage
-	jmp	end_move			# ... and we skip moving
-
-do_move0:
-	movw	$0x100, %ax			# start of destination segment
-	movw	%cs, %bp			# aka SETUPSEG
-	subw	$DELTA_INITSEG, %bp		# aka INITSEG
-	movw	%cs:start_sys_seg, %bx		# start of source segment
-	cld
-do_move:
-	movw	%ax, %es			# destination segment
-	incb	%ah				# instead of add ax,#0x100
-	movw	%bx, %ds			# source segment
-	addw	$0x100, %bx
-	subw	%di, %di
-	subw	%si, %si
-	movw 	$0x800, %cx
-	rep
-	movsw
-	cmpw	%bp, %bx			# assume start_sys_seg > 0x200,
-						# so we will perhaps read one
-						# page more than needed, but
-						# never overwrite INITSEG
-						# because destination is a
-						# minimum one page below source
-	jb	do_move
-
-end_move:
-# then we load the segment descriptors
-	movw	%cs, %ax			# aka SETUPSEG
-	movw	%ax, %ds
-               
-# Check whether we need to be downward compatible with version <=201
-	cmpl	$0, cmd_line_ptr
-	jne	end_move_self		# loader uses version >=202 features
-	cmpb	$0x20, type_of_loader
-	je	end_move_self		# bootsect loader, we know of it
- 
-# Boot loader does not support boot protocol version 2.02.
-# If we have our code not at 0x90000, we need to move it there now.
-# We also then need to move the params behind it (commandline)
-# Because we would overwrite the code on the current IP, we move
-# it in two steps, jumping high after the first one.
-	movw	%cs, %ax
-	cmpw	$SETUPSEG, %ax
-	je	end_move_self
-
-	cli					# make sure we really have
-						# interrupts disabled !
-						# because after this the stack
-						# should not be used
-	subw	$DELTA_INITSEG, %ax		# aka INITSEG
-	movw	%ss, %dx
-	cmpw	%ax, %dx
-	jb	move_self_1
-
-	addw	$INITSEG, %dx
-	subw	%ax, %dx			# this will go into %ss after
-						# the move
-move_self_1:
-	movw	%ax, %ds
-	movw	$INITSEG, %ax			# real INITSEG
-	movw	%ax, %es
-	movw	%cs:setup_move_size, %cx
-	std					# we have to move up, so we use
-						# direction down because the
-						# areas may overlap
-	movw	%cx, %di
-	decw	%di
-	movw	%di, %si
-	subw	$move_self_here+0x200, %cx
-	rep
-	movsb
-	ljmp	$SETUPSEG, $move_self_here
-
-move_self_here:
-	movw	$move_self_here+0x200, %cx
-	rep
-	movsb
-	movw	$SETUPSEG, %ax
-	movw	%ax, %ds
-	movw	%dx, %ss
-
-end_move_self:					# now we are at the right place
-	lidt	idt_48				# load idt with 0,0
-	xorl	%eax, %eax			# Compute gdt_base
-	movw	%ds, %ax			# (Convert %ds:gdt to a linear ptr)
-	shll	$4, %eax
-	addl	$gdt, %eax
-	movl	%eax, (gdt_48+2)
-	lgdt	gdt_48				# load gdt with whatever is
-						# appropriate
-
-# that was painless, now we enable A20
-
-	outb	%al, $0xf2			# A20 on
-	movb	$0x02, %al
-	outb	%al, $0xf6			# also A20 on; making ITF's
-						# way our model
-
-	# PC-9800 seems to enable A20 at the moment of `outb';
-	# so we don't wait unlike IBM PCs (see ../setup.S).
-
-# enable DMA to access memory over 0x100000 (1MB).
-
-	movw	$0x439, %dx
-	inb	%dx, %al
-	andb	$(~4), %al
-	outb	%al, %dx
-
-# Set DMA to increment its bank address automatically at 16MB boundary.
-# Initial setting is 64KB boundary mode so that we can't run DMA crossing
-# physical address 0xXXXXFFFF.
-
-	movb	$0x0c, %al
-	outb	%al, $0x29			# ch. 0
-	movb	$0x0d, %al
-	outb	%al, $0x29			# ch. 1
-	movb	$0x0e, %al
-	outb	%al, $0x29			# ch. 2
-	movb	$0x0f, %al
-	outb	%al, $0x29			# ch. 3
-	movb	$0x50, %al
-	outb	%al, $0x11			# reinitialize DMAC
-
-# make sure any possible coprocessor is properly reset..
-	movb	$0, %al
-	outb	%al, $0xf8
-	outb	%al, $0x5f			# delay
-
-# well, that went ok, I hope. Now we mask all interrupts - the rest
-# is done in init_IRQ().
-	movb	$0xFF, %al			# mask all interrupts for now
-	outb	%al, $0x0A
-	outb	%al, $0x5f			# delay
-	
-	movb	$0x7F, %al			# mask all irq's but irq7 which
-	outb	%al, $0x02			# is cascaded
-
-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-# need no steenking BIOS anyway (except for the initial loading :-).
-# The BIOS-routine wants lots of unnecessary data, and it's less
-# "interesting" anyway. This is how REAL programmers do it.
-#
-# Well, now's the time to actually move into protected mode. To make
-# things as simple as possible, we do no register set-up or anything,
-# we let the gnu-compiled 32-bit programs do that. We just jump to
-# absolute address 0x1000 (or the loader supplied one),
-# in 32-bit protected mode.
-#
-# Note that the short jump isn't strictly needed, although there are
-# reasons why it might be a good idea. It won't hurt in any case.
-	movw	$1, %ax				# protected mode (PE) bit
-	lmsw	%ax				# This is it!
-	jmp	flush_instr
-
-flush_instr:
-	xorw	%bx, %bx			# Flag to indicate a boot
-	xorl	%esi, %esi			# Pointer to real-mode code
-	movw	%cs, %si
-	subw	$DELTA_INITSEG, %si
-	shll	$4, %esi			# Convert to 32-bit pointer
-# NOTE: For high loaded big kernels we need a
-#	jmpi    0x100000,__BOOT_CS
-#
-#	but we yet haven't reloaded the CS register, so the default size 
-#	of the target offset still is 16 bit.
-#       However, using an operand prefix (0x66), the CPU will properly
-#	take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
-#	Manual, Mixing 16-bit and 32-bit code, page 16-6)
-
-	.byte 0x66, 0xea			# prefix + jmpi-opcode
-code32:	.long	0x1000				# will be set to 0x100000
-						# for big kernels
-	.word	__BOOT_CS
-
-# Here's a bunch of information about your current kernel..
-kernel_version:	.ascii	UTS_RELEASE
-		.ascii	" ("
-		.ascii	LINUX_COMPILE_BY
-		.ascii	"@"
-		.ascii	LINUX_COMPILE_HOST
-		.ascii	") "
-		.ascii	UTS_VERSION
-		.byte	0
-
-# This is the default real mode switch routine.
-# to be called just before protected mode transition
-default_switch:
-	cli					# no interrupts allowed !
-	outb	%al, $0x50			# disable NMI for bootup
-						# sequence
-	lret
-
-
-# This routine prints one character (in %al) on console.
-# PC-9800 doesn't have BIOS-function to do it like IBM PC's INT 10h - 0Eh,
-# so we hardcode `prtchr' subroutine here.
-prtchr:
-	pushaw
-	pushw	%es
-	cmpb	$0, %cs:prtchr_initialized
-	jnz	prtchr_ok
-	xorw	%cx, %cx
-	movw	%cx, %es
-	testb	$0x8, %es:BIOS_FLAG
-	jz	1f
-	movb	$(HIRESO_TEXT >> 8), %cs:cursor_address+3
-	movw	$(80 * 31 * 2), %cs:max_cursor_offset
-1:	pushw	%ax
-	call	get_cursor_position
-	movw	%ax, %cs:cursor_address
-	popw	%ax
-	movb	$1, %cs:prtchr_initialized
-prtchr_ok:
-	lesw	%cs:cursor_address, %di
-	movw	$160, %bx
-	movb	$0, %ah
-	cmpb	$13, %al
-	je	do_cr
-	cmpb	$10, %al
-	je	do_lf
-
-	# normal (printable) character
-	stosw
-	movb	$0xe1, %es:0x2000-2(%di)
-	jmp	1f
-
-do_cr:	movw	%di, %ax
-	divb	%bl				# %al = Y, %ah = X * 2
-	mulb	%bl
-	movw	%ax, %dx
-	jmp	2f
-
-do_lf:	addw	%bx, %di
-1:	movw	%cs:max_cursor_offset, %cx
-	cmpw	%cx, %di
-	movw	%di, %dx
-	jb	2f
-	# cursor reaches bottom of screen; scroll it
-	subw	%bx, %dx
-	xorw	%di, %di
-	movw	%bx, %si
-	cld
-	subw	%bx, %cx
-	shrw	%cx
-	pushw	%cx
-	rep; es; movsw
-	movb	$32, %al			# clear bottom line characters
-	movb	$80, %cl
-	rep; stosw
-	movw	$0x2000, %di
-	popw	%cx
-	leaw	(%bx,%di), %si
-	rep; es; movsw
-	movb	$0xe1, %al			# clear bottom line attributes
-	movb	$80, %cl
-	rep; stosw
-2:	movw	%dx, %cs:cursor_address
-	movb	$0x13, %ah			# move cursor to right position
-	int	$0x18
-	popw	%es
-	popaw
-	ret
-
-cursor_address:
-	.word	0
-	.word	NORMAL_TEXT
-max_cursor_offset:
-	.word	80 * 25 * 2			# for normal 80x25 mode
-
-# putstr may called without running through start_of_setup (via bootsect_panic)
-# so we should initialize ourselves on demand.
-prtchr_initialized:
-	.byte	0
-
-# This routine queries GDC (graphic display controller) for current cursor
-# position. Cursor position is returned in %ax (CPU offset address).
-get_cursor_position:
-1:	inb	$0x60, %al
-	outb	%al, $0x5f			# delay
-	outb	%al, $0x5f			# delay
-	testb	$0x04, %al			# Is FIFO empty?
-	jz	1b				# no -> wait until empty
-
-	movb	$0xe0, %al			# CSRR command
-	outb	%al, $0x62			# command write
-	outb	%al, $0x5f			# delay
-	outb	%al, $0x5f			# delay
-
-2:	inb	$0x60, %al
-	outb	%al, $0x5f			# delay
-	outb	%al, $0x5f			# delay
-	testb	$0x01, %al			# Is DATA READY?
-	jz	2b				# no -> wait until ready
-
-	inb	$0x62, %al			# read xAD (L)
-	outb	%al, $0x5f			# delay
-	outb	%al, $0x5f			# delay
-	movb	%al, %ah
-	inb	$0x62, %al			# read xAD (H)
-	outb	%al, $0x5f			# delay
-	outb	%al, $0x5f			# delay
-	xchgb	%al, %ah			# correct byte order
-	pushw	%ax
-	inb	$0x62, %al			# read yAD (L)
-	outb	%al, $0x5f			# delay
-	outb	%al, $0x5f			# delay
-	inb	$0x62, %al			# read yAD (M)
-	outb	%al, $0x5f			# delay
-	outb	%al, $0x5f			# delay
-	inb	$0x62, %al			# read yAD (H)
-						# yAD is not our interest,
-						# so discard it.
-	popw	%ax
-	addw	%ax, %ax			# convert to CPU address
-	ret
-
-# Descriptor tables
-#
-# NOTE: The intel manual says gdt should be sixteen bytes aligned for
-# efficiency reasons.  However, there are machines which are known not
-# to boot with misaligned GDTs, so alter this at your peril!  If you alter
-# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
-# empty GDT entries (one for NULL and one reserved).
-#
-# NOTE:	On some CPUs, the GDT must be 8 byte aligned.  This is
-# true for the Voyager Quad CPU card which will not boot without
-# This directive.  16 byte aligment is recommended by intel.
-#
-	.align 16
-gdt:
-	.fill GDT_ENTRY_BOOT_CS,8,0
-
-	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
-	.word	0				# base address = 0
-	.word	0x9A00				# code read/exec
-	.word	0x00CF				# granularity = 4096, 386
-						#  (+5th nibble of limit)
-
-	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
-	.word	0				# base address = 0
-	.word	0x9200				# data read/write
-	.word	0x00CF				# granularity = 4096, 386
-						#  (+5th nibble of limit)
-gdt_end:
-	.align	4
-	
-	.word	0				# alignment byte
-idt_48:
-	.word	0				# idt limit = 0
-	.word	0, 0				# idt base = 0L
-
-	.word	0				# alignment byte
-gdt_48:
-	.word	gdt_end - gdt - 1		# gdt limit
-	.word	0, 0				# gdt base (filled in later)
-
-# Include video setup & detection code
-
-#include "video.S"
-
-# Setup signature -- must be last
-setup_sig1:	.word	SIG1
-setup_sig2:	.word	SIG2
-
-# After this point, there is some free space which is used by the video mode
-# handling code to store the temporary mode table (not used by the kernel).
-
-modelist:
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff -Nru a/arch/i386/boot98/video.S b/arch/i386/boot98/video.S
--- a/arch/i386/boot98/video.S	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,262 +0,0 @@
-/*	video.S
- *
- *  Video mode setup, etc. for NEC PC-9800 series.
- *
- *  Copyright (C) 1997,98,99  Linux/98 project  <seraphim@kmc.kyoto-u.ac.jp>
- *
- *  Based on the video.S for IBM PC:
- *	copyright (C) Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- */
-
-/* Positions of various video parameters passed to the kernel */
-/* (see also include/linux/tty.h) */
-#define PARAM_CURSOR_POS	0x00
-#define PARAM_VIDEO_PAGE	0x04
-#define PARAM_VIDEO_MODE	0x06
-#define PARAM_VIDEO_COLS	0x07
-#define PARAM_VIDEO_EGA_BX	0x0a
-#define PARAM_VIDEO_LINES	0x0e
-#define PARAM_HAVE_VGA		0x0f
-#define PARAM_FONT_POINTS	0x10
-
-#define PARAM_VIDEO98_COMPAT	0x0a
-#define PARAM_VIDEO98_HIRESO	0x0b
-#define PARAM_VIDEO98_MACHTYPE	0x0c
-#define PARAM_VIDEO98_LINES	0x0e
-#define PARAM_VIDEO98_COLS	0x0f
-
-# PARAM_LFB_* and PARAM_VESAPM_* are unused on PC-9800.
-
-# This is the main entry point called by setup.S
-# %ds *must* be pointing to the bootsector
-video:	xorw	%ax, %ax
-	movw	%ax, %es			# %es = 0
-
-	movb	%es:BIOS_FLAG, %al
-	movb	%al, PARAM_VIDEO_MODE
-
-	movb	$0, PARAM_VIDEO98_HIRESO	# 0 = normal
-	movw	$NORMAL_TEXT, PARAM_VIDEO_PAGE
-	testb	$0x8, %al
-	movw	$(80 * 256 + 25), %ax
-	jz	1f
-	# hireso machine.
-	movb	$1, PARAM_VIDEO98_HIRESO	# !0 = hi-reso
-	movb	$(HIRESO_TEXT >> 8), PARAM_VIDEO_PAGE + 1
-	movw	$(80 * 256 + 31), %ax
-1:	movw	%ax, PARAM_VIDEO98_LINES	# also sets VIDEO98_COLS
-
-	movb	$0xc0, %ch			# 400-line graphic mode
-	movb	$0x42, %ah
-	int	$0x18
-
-	movw	$80, PARAM_VIDEO_COLS
-
-	movw	$msg_probing, %si
-	call	prtstr_cs
-
-# Check vendor from font pattern of `A'...
-
-1:	inb	$0x60, %al			# wait V-sync
-	testb	$0x20, %al
-	jnz	1b
-2:	inb	$0x60, %al
-	testb	$0x20, %al
-	jz	2b
-
-	movb	$0x00, %al			# select font of `A'
-	outb	%al, $0xa1
-	movb	$0x41, %al
-	outb	%al, $0xa3
-
-	movw	$8, %cx
-	movw	PARAM_VIDEO_PAGE, %ax
-	cmpw	$NORMAL_TEXT, %ax
-	je	3f
-	movb	$24, %cl			# for hi-reso machine
-3:	addw	$0x400, %ax			# %ax = CG window segment
-	pushw	%ds
-	movw	%ax, %ds
-	xorw	%dx, %dx			# get sum of `A' pattern...
-	xorw	%si, %si
-4:	lodsw
-	addw	%ax, %dx
-	loop	4b
-	popw	%ds
-
-	movw	%dx, %ax
-	movw	$msg_nec, %si
-	xorw	%bx, %bx			# vendor info will go into %bx
-	testb	$8, %es:BIOS_FLAG
-	jnz	check_hireso_vendor
-	cmpw	$0xc7f8, %ax
-	je	5f
-	jmp	6f
-check_hireso_vendor:
-	cmpw	$0x9639, %ax			# XXX: NOT VERIFIED!!!
-	je	5f
-6:	incw	%bx				# compatible machine
-	movw	$msg_compat, %si
-5:	movb	%bl, PARAM_VIDEO98_COMPAT
-	call	prtstr_cs
-
-	movw	$msg_fontdata, %si
-	call	prtstr_cs			# " (CG sum of A = 0x"
-	movw	%dx, %ax
-	call	prthex
-	call	prtstr_cs			# ") PC-98"
-
-	movb	$'0', %al
-	pushw	%ds
-	pushw	$0xf8e8
-	popw	%ds
-	cmpw	$0x2198, (0)
-	popw	%ds
-	jne	7f
-	movb	$'2', %al
-7:	call	prtchr
-	call	prtstr_cs			# "1 "
-
-	movb	$0, PARAM_VIDEO98_MACHTYPE
-#if 0	/* XXX - This check is bogus? [0000:BIOS_FLAG2]-bit7 does NOT
-		 indicate whether it is a note machine, but merely indicates
-		 whether it has ``RAM drive''. */
-# check note machine
-	testb	$0x80, %es:BIOS_FLAG2
-	jnz	is_note
-	pushw	%ds
-	pushw	$0xfd80
-	popw	%ds
-	movb	(4), %al
-	popw	%ds
-	cmpb	$0x20, %al			# EPSON note A
-	je	epson_note
-	cmpb	$0x22, %al			# EPSON note W
-	je	epson_note
-	cmpb	$0x27, %al			# EPSON note AE
-	je	epson_note
-	cmpb	$0x2a, %al			# EPSON note WR
-	jne	note_done
-epson_note:
-	movb	$1, PARAM_VIDEO98_MACHTYPE
-	movw	$msg_note, %si
-	call	prtstr_cs
-note_done:
-#endif
-	
-# print h98 ? (only NEC)
-	cmpb	$0, PARAM_VIDEO98_COMPAT
-	jnz	8f				# not NEC -> not H98
-
-	testb	$0x80, %es:BIOS_FLAG5
-	jz	8f				# have NESA bus -> H98
-	movw	$msg_h98, %si
-	call	prtstr_cs
-	orb	$2, PARAM_VIDEO98_MACHTYPE
-8:	testb	$0x40, %es:BIOS_FLAG5
-	jz	9f
-	movw	$msg_gs, %si
-	call	prtstr_cs			# only prints it :-)
-9:
-	movw	$msg_normal, %si		# "normal"
-	testb	$0x8, %es:BIOS_FLAG
-	jz	1f
-	movw	$msg_hireso, %si
-1:	call	prtstr_cs
-
-	movw	$msg_sysclk, %si
-	call	prtstr_cs
-	movb	$'5', %al
-	testb	$0x80, %es:BIOS_FLAG
-	jz	2f
-	movb	$'8', %al
-2:	call	prtchr
-	call	prtstr_cs
-
-#if 0
-	testb	$0x40, %es:(0x45c)
-	jz	no_30line			# no 30-line support
-
-	movb	%es:KB_SHFT_STS, %al
-	testb	$0x01, %al			# is SHIFT key pressed?
-	jz	no_30line
-
-	testb	$0x10, %al			# is CTRL key pressed?
-	jnz	line40
-
-	# switch to 30-line mode
-	movb	$30, PARAM_VIDEO98_LINES
-	movw	$msg_30line, %si
-	jmp	3f
-
-line40:
-	movb	$37, PARAM_VIDEO98_LINES
-	movw	$40, PARAM_VIDEO_LINES
-	movw	$msg_40line, %si
-3:	call	prtstr_cs
-
-	movb	$0x32, %bh
-	movw	$0x300c, %ax
-	int	$0x18				# switch video mode
-	movb	$0x0c, %ah
-	int	$0x18				# turn on text plane
-	movw	%cs:cursor_address, %dx
-	movb	$0x13, %ah
-	int	$0x18				# move cursor to correct place
-	mov	$0x11, %ah
-	int	$0x18				# turn on text plane
-
-	call	prtstr_cs			# "Ok.\r\n"
-no_30line:
-#endif
-	ret
-
-prtstr_cs:
-	pushw	%ds
-	pushw	%cs
-	popw	%ds
-	call	prtstr
-	popw	%ds
-	ret
-
-# prthex is for debugging purposes, and prints %ax in hexadecimal.
-prthex:	pushw	%cx
-	movw	$4, %cx
-1:	rolw	$4, %ax
-	pushw	%ax
-	andb	$0xf, %al
-	cmpb	$10, %al
-	sbbb	$0x69, %al
-	das
-	call	prtchr
-	popw	%ax
-	loop	1b
-	popw	%cx
-	ret
-
-msg_probing:	.string	"Probing machine: "
-
-msg_nec:	.string	"NEC"
-msg_compat:	.string	"compatible"
-
-msg_fontdata:	.string	" (CG sum of A = 0x"
-		.string	") PC-98"
-		.string	"1 "
-
-msg_gs:		.string	"(GS) "
-msg_h98:	.string	"(H98) "
-
-msg_normal:	.string	"normal"
-msg_hireso:	.string	"Hi-reso"
-
-msg_sysclk:	.string	" mode, system clock "
-		.string	"MHz\r\n"
-
-#if 0
-msg_40line:	# cpp will concat following lines, so the assembler can deal.
-		.ascii	"\
-Video mode will be adjusted to 37-line (so-called ``40-line'') mode later.\r\n\
-THIS MODE MAY DAMAGE YOUR MONITOR PHYSICALLY. USE AT YOUR OWN RISK.\r\n"
-msg_30line:	.string	"Switching video mode to 30-line (640x480) mode... "
-		.string	"Ok.\r\n"
-#endif
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/kernel/Makefile	2004-06-23 19:04:25 -07:00
@@ -31,7 +31,6 @@
 obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
-obj-$(CONFIG_X86_STD_RESOURCES)	+= std_resources.o
 
 EXTRA_AFLAGS   := -traditional
 
diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
--- a/arch/i386/kernel/acpi/boot.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/kernel/acpi/boot.c	2004-06-23 19:04:28 -07:00
@@ -28,7 +28,9 @@
 #include <linux/acpi.h>
 #include <linux/efi.h>
 #include <linux/irq.h>
-#include <asm/pgalloc.h>
+#include <linux/module.h>
+
+#include <asm/pgtable.h>
 #include <asm/io_apic.h>
 #include <asm/apic.h>
 #include <asm/io.h>
@@ -436,6 +438,38 @@
 		*irq = gsi;
 	return 0;
 }
+
+unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
+{
+	unsigned int irq;
+
+#ifdef CONFIG_PCI
+	/*
+	 * Make sure all (legacy) PCI IRQs are set as level-triggered.
+	 */
+	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+		static u16 irq_mask;
+		extern void eisa_set_level_irq(unsigned int irq);
+
+		if (edge_level == ACPI_LEVEL_SENSITIVE) {
+			if ((gsi < 16) && !((1 << gsi) & irq_mask)) {
+				Dprintk(KERN_DEBUG PREFIX "Setting GSI %u as level-triggered\n", gsi);
+				irq_mask |= (1 << gsi);
+				eisa_set_level_irq(gsi);
+			}
+		}
+	}
+#endif
+
+#ifdef CONFIG_X86_IO_APIC
+	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
+		mp_register_gsi(gsi, edge_level, active_high_low);
+	}
+#endif
+	acpi_gsi_to_irq(gsi, &irq);
+	return irq;
+}
+EXPORT_SYMBOL(acpi_register_gsi);
 
 static unsigned long __init
 acpi_scan_rsdp (
diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
--- a/arch/i386/kernel/apic.c	2004-06-23 19:04:29 -07:00
+++ b/arch/i386/kernel/apic.c	2004-06-23 19:04:29 -07:00
@@ -31,7 +31,6 @@
 #include <asm/smp.h>
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
-#include <asm/pgalloc.h>
 #include <asm/desc.h>
 #include <asm/arch_hooks.h>
 #include <asm/hpet.h>
@@ -79,6 +78,17 @@
 	if (!APIC_INTEGRATED(ver))		/* 82489DX */
 		v |= APIC_LVT_LEVEL_TRIGGER;
 	apic_write_around(APIC_LVT0, v);
+}
+
+int get_physical_broadcast(void)
+{
+	unsigned int lvr, version;
+	lvr = apic_read(APIC_LVR);
+	version = GET_APIC_VERSION(lvr);
+	if (version >= 0x14)
+		return 0xff;
+	else
+		return 0xf;
 }
 
 int get_maxlvt(void)
diff -Nru a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
--- a/arch/i386/kernel/cpuid.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/kernel/cpuid.c	2004-06-23 19:04:25 -07:00
@@ -36,12 +36,17 @@
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+static struct class_simple *cpuid_class;
+
 #ifdef CONFIG_SMP
 
 struct cpuid_command {
@@ -153,20 +158,84 @@
 	.open = cpuid_open,
 };
 
+static int cpuid_class_simple_device_add(int i) 
+{
+	int err = 0;
+	struct class_device *class_err;
+
+	class_err = class_simple_device_add(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
+	if (IS_ERR(class_err))
+		err = PTR_ERR(class_err);
+	return err;
+}
+
+static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+		cpuid_class_simple_device_add(cpu);
+		break;
+	case CPU_DEAD:
+		class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block cpuid_class_cpu_notifier =
+{
+	.notifier_call = cpuid_class_cpu_callback,
+};
+
 int __init cpuid_init(void)
 {
+	int i, err = 0;
+	i = 0;
+
 	if (register_chrdev(CPUID_MAJOR, "cpu/cpuid", &cpuid_fops)) {
 		printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n",
 		       CPUID_MAJOR);
-		return -EBUSY;
+		err = -EBUSY;
+		goto out;
+	}
+	cpuid_class = class_simple_create(THIS_MODULE, "cpuid");
+	if (IS_ERR(cpuid_class)) {
+		err = PTR_ERR(cpuid_class);
+		goto out_chrdev;
 	}
+	for_each_online_cpu(i) {
+		err = cpuid_class_simple_device_add(i);
+		if (err != 0) 
+			goto out_class;
+	}
+	register_cpu_notifier(&cpuid_class_cpu_notifier);
 
-	return 0;
+	err = 0;
+	goto out;
+
+out_class:
+	i = 0;
+	for_each_online_cpu(i) {
+		class_simple_device_remove(MKDEV(CPUID_MAJOR, i));
+	}
+	class_simple_destroy(cpuid_class);
+out_chrdev:
+	unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");	
+out:
+	return err;
 }
 
 void __exit cpuid_exit(void)
 {
+	int cpu = 0;
+
+	for_each_online_cpu(cpu)
+		class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
+	class_simple_destroy(cpuid_class);
 	unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
+	unregister_cpu_notifier(&cpuid_class_cpu_notifier);
 }
 
 module_init(cpuid_init);
diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/kernel/dmi_scan.c	2004-06-23 19:04:26 -07:00
@@ -10,6 +10,7 @@
 #include <asm/io.h>
 #include <linux/pm.h>
 #include <asm/system.h>
+#include <linux/dmi.h>
 #include <linux/bootmem.h>
 
 unsigned long dmi_broken;
@@ -139,21 +140,6 @@
 	return -1;
 }
 
-
-enum
-{
-	DMI_BIOS_VENDOR,
-	DMI_BIOS_VERSION,
-	DMI_BIOS_DATE,
-	DMI_SYS_VENDOR,
-	DMI_PRODUCT_NAME,
-	DMI_PRODUCT_VERSION,
-	DMI_BOARD_VENDOR,
-	DMI_BOARD_NAME,
-	DMI_BOARD_VERSION,
-	DMI_STRING_MAX
-};
-
 static char *dmi_ident[DMI_STRING_MAX];
 
 /*
@@ -176,26 +162,11 @@
 }
 
 /*
- *	DMI callbacks for problem boards
+ * Ugly compatibility crap.
  */
-
-struct dmi_strmatch
-{
-	u8 slot;
-	char *substr;
-};
-
-#define NONE	255
-
-struct dmi_blacklist
-{
-	int (*callback)(struct dmi_blacklist *);
-	char *ident;
-	struct dmi_strmatch matches[4];
-};
-
-#define NO_MATCH	{ NONE, NULL}
-#define MATCH(a,b)	{ a, b }
+#define dmi_blacklist	dmi_system_id
+#define NO_MATCH	{ DMI_NONE, NULL}
+#define MATCH		DMI_MATCH
 
 /* 
  * Reboot options and system auto-detection code provided by
@@ -343,23 +314,6 @@
 }
 
 /*
- * Work around broken HP Pavilion Notebooks which assign USB to
- * IRQ 9 even though it is actually wired to IRQ 11
- */
-static __init int fix_broken_hp_bios_irq9(struct dmi_blacklist *d)
-{
-#ifdef CONFIG_PCI
-	extern int broken_hp_bios_irq9;
-	if (broken_hp_bios_irq9 == 0)
-	{
-		broken_hp_bios_irq9 = 1;
-		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
-	}
-#endif
-	return 0;
-}
-
-/*
  *  Check for clue free BIOS implementations who use
  *  the following QA technique
  *
@@ -546,15 +500,21 @@
 
 #ifdef	CONFIG_ACPI_PCI
 static __init int disable_acpi_irq(struct dmi_blacklist *d) 
-{ 
-	printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n", d->ident); 	
-	acpi_noirq_set();
+{
+	if (!acpi_force) {
+		printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
+		       d->ident); 	
+		acpi_noirq_set();
+	}
 	return 0;
 }
 static __init int disable_acpi_pci(struct dmi_blacklist *d) 
-{ 
-	printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", d->ident); 	
-	acpi_disable_pci();
+{
+	if (!acpi_force) {
+		printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
+		       d->ident); 	
+		acpi_disable_pci();
+	}
 	return 0;
 }  
 #endif
@@ -839,14 +799,6 @@
 			NO_MATCH, NO_MATCH
 			} },
 	 
-	{ fix_broken_hp_bios_irq9, "HP Pavilion N5400 Series Laptop", {
-			MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-			MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
-			MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
-			MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736")
-			} },
- 
-
 	/*
 	 *	Generic per vendor APM settings
 	 */
@@ -1048,9 +1000,6 @@
 
 static __init void dmi_check_blacklist(void)
 {
-	struct dmi_blacklist *d;
-	int i;
-		
 #ifdef	CONFIG_ACPI_BOOT
 #define	ACPI_BLACKLIST_CUTOFF_YEAR	2001
 
@@ -1072,25 +1021,7 @@
 		}
 	}
 #endif
-
-	d=&dmi_blacklist[0];
-	while(d->callback)
-	{
-		for(i=0;i<4;i++)
-		{
-			int s = d->matches[i].slot;
-			if(s==NONE)
-				continue;
-			if(dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
-				continue;
-			/* No match */
-			goto fail;
-		}
-		if(d->callback(d))
-			return;
-fail:			
-		d++;
-	}
+ 	dmi_check_system(dmi_blacklist);
 }
 
 	
@@ -1157,3 +1088,52 @@
 }
 
 EXPORT_SYMBOL(is_unsafe_smbus);
+
+
+/**
+ *	dmi_check_system - check system DMI data
+ *	@list: array of dmi_system_id structures to match against
+ *
+ *	Walk the blacklist table running matching functions until someone
+ *	returns non zero or we hit the end. Callback function is called for
+ *	each successfull match. Returns the number of matches.
+ */
+int dmi_check_system(struct dmi_system_id *list)
+{
+	int i, count = 0;
+	struct dmi_system_id *d = list;
+
+	while (d->ident) {
+		for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
+			int s = d->matches[i].slot;
+			if (s == DMI_NONE)
+				continue;
+			if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
+				continue;
+			/* No match */
+			goto fail;
+		}
+		if (d->callback && d->callback(d))
+			break;
+		count++;
+fail:		d++;
+	}
+
+	return count;
+}
+
+EXPORT_SYMBOL(dmi_check_system);
+
+/**
+ *	dmi_get_system_info - return DMI data value
+ *	@field: data index (see enum dmi_filed)
+ *
+ *	Returns one DMI data value, can be used to perform
+ *	complex DMI data checks.
+ */
+char * dmi_get_system_info(int field)
+{
+	return dmi_ident[field];
+}
+
+EXPORT_SYMBOL(dmi_get_system_info);
diff -Nru a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
--- a/arch/i386/kernel/efi.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/kernel/efi.c	2004-06-23 19:04:28 -07:00
@@ -37,7 +37,6 @@
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/desc.h>
-#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 
 #define EFI_DEBUG	0
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	2004-06-23 19:04:29 -07:00
+++ b/arch/i386/kernel/i386_ksyms.c	2004-06-23 19:04:29 -07:00
@@ -29,7 +29,6 @@
 #include <asm/mmx.h>
 #include <asm/desc.h>
 #include <asm/pgtable.h>
-#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/nmi.h>
 #include <asm/ist.h>
diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
--- a/arch/i386/kernel/i8259.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/kernel/i8259.c	2004-06-23 19:04:28 -07:00
@@ -317,16 +317,11 @@
  * be shot.
  */
  
-/*
- * =PC9800NOTE= In NEC PC-9800, we use irq8 instead of irq13!
- */
 
 static irqreturn_t math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
 {
 	extern void math_error(void *);
-#ifndef CONFIG_X86_PC9800
 	outb(0,0xF0);
-#endif
 	if (ignore_fpu_irq || !boot_cpu_data.hard_math)
 		return IRQ_NONE;
 	math_error((void *)regs->eip);
diff -Nru a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
--- a/arch/i386/kernel/init_task.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/kernel/init_task.c	2004-06-23 19:04:28 -07:00
@@ -4,6 +4,7 @@
 #include <linux/init.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/kernel/io_apic.c	2004-06-23 19:04:26 -07:00
@@ -41,10 +41,6 @@
 
 #include "io_ports.h"
 
-#undef APIC_LOCKUP_DEBUG
-
-#define APIC_LOCKUP_DEBUG
-
 static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
 
 /*
@@ -127,83 +123,47 @@
 	}
 }
 
-/* mask = 1 */
-static void __mask_IO_APIC_irq (unsigned int irq)
+static void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable)
 {
-	int pin;
 	struct irq_pin_list *entry = irq_2_pin + irq;
+	unsigned int pin, reg;
 
 	for (;;) {
-		unsigned int reg;
 		pin = entry->pin;
 		if (pin == -1)
 			break;
 		reg = io_apic_read(entry->apic, 0x10 + pin*2);
-		io_apic_modify(entry->apic, 0x10 + pin*2, reg |= 0x00010000);
+		reg &= ~disable;
+		reg |= enable;
+		io_apic_modify(entry->apic, 0x10 + pin*2, reg);
 		if (!entry->next)
 			break;
 		entry = irq_2_pin + entry->next;
 	}
-	io_apic_sync(entry->apic);
+}
+
+/* mask = 1 */
+static void __mask_IO_APIC_irq (unsigned int irq)
+{
+	__modify_IO_APIC_irq(irq, 0x00010000, 0);
 }
 
 /* mask = 0 */
 static void __unmask_IO_APIC_irq (unsigned int irq)
 {
-	int pin;
-	struct irq_pin_list *entry = irq_2_pin + irq;
-
-	for (;;) {
-		unsigned int reg;
-		pin = entry->pin;
-		if (pin == -1)
-			break;
-		reg = io_apic_read(entry->apic, 0x10 + pin*2);
-		io_apic_modify(entry->apic, 0x10 + pin*2, reg &= 0xfffeffff);
-		if (!entry->next)
-			break;
-		entry = irq_2_pin + entry->next;
-	}
+	__modify_IO_APIC_irq(irq, 0, 0x00010000);
 }
 
 /* mask = 1, trigger = 0 */
 static void __mask_and_edge_IO_APIC_irq (unsigned int irq)
 {
-	int pin;
-	struct irq_pin_list *entry = irq_2_pin + irq;
-
-	for (;;) {
-		unsigned int reg;
-		pin = entry->pin;
-		if (pin == -1)
-			break;
-		reg = io_apic_read(entry->apic, 0x10 + pin*2);
-		reg = (reg & 0xffff7fff) | 0x00010000;
-		io_apic_modify(entry->apic, 0x10 + pin*2, reg);
-		if (!entry->next)
-			break;
-		entry = irq_2_pin + entry->next;
-	}
+	__modify_IO_APIC_irq(irq, 0x00010000, 0x00008000);
 }
 
 /* mask = 0, trigger = 1 */
 static void __unmask_and_level_IO_APIC_irq (unsigned int irq)
 {
-	int pin;
-	struct irq_pin_list *entry = irq_2_pin + irq;
-
-	for (;;) {
-		unsigned int reg;
-		pin = entry->pin;
-		if (pin == -1)
-			break;
-		reg = io_apic_read(entry->apic, 0x10 + pin*2);
-		reg = (reg & 0xfffeffff) | 0x00008000;
-		io_apic_modify(entry->apic, 0x10 + pin*2, reg);
-		if (!entry->next)
-			break;
-		entry = irq_2_pin + entry->next;
-	}
+	__modify_IO_APIC_irq(irq, 0x00008000, 0x00010000);
 }
 
 static void mask_IO_APIC_irq (unsigned int irq)
@@ -1366,7 +1326,7 @@
 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
 	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
 	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
-	if (reg_00.bits.ID >= APIC_BROADCAST_ID)
+	if (reg_00.bits.ID >= get_physical_broadcast())
 		UNEXPECTED_IO_APIC();
 	if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
 		UNEXPECTED_IO_APIC();
@@ -1682,7 +1642,7 @@
 		
 		old_id = mp_ioapics[apic].mpc_apicid;
 
-		if (mp_ioapics[apic].mpc_apicid >= APIC_BROADCAST_ID) {
+		if (mp_ioapics[apic].mpc_apicid >= get_physical_broadcast()) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
 				apic, mp_ioapics[apic].mpc_apicid);
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
@@ -1703,10 +1663,10 @@
 					mp_ioapics[apic].mpc_apicid)) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
 				apic, mp_ioapics[apic].mpc_apicid);
-			for (i = 0; i < APIC_BROADCAST_ID; i++)
+			for (i = 0; i < get_physical_broadcast(); i++)
 				if (!physid_isset(i, phys_id_present_map))
 					break;
-			if (i >= APIC_BROADCAST_ID)
+			if (i >= get_physical_broadcast())
 				panic("Max APIC ID exceeded!\n");
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
 				i);
@@ -1893,30 +1853,11 @@
 	ack_APIC_irq();
 
 	if (!(v & (1 << (i & 0x1f)))) {
-#ifdef APIC_LOCKUP_DEBUG
-		struct irq_pin_list *entry;
-#endif
-
 #ifdef APIC_MISMATCH_DEBUG
 		atomic_inc(&irq_mis_count);
 #endif
 		spin_lock(&ioapic_lock);
 		__mask_and_edge_IO_APIC_irq(irq);
-#ifdef APIC_LOCKUP_DEBUG
-		for (entry = irq_2_pin + irq;;) {
-			unsigned int reg;
-
-			if (entry->pin == -1)
-				break;
-			reg = io_apic_read(entry->apic, 0x10 + entry->pin * 2);
-			if (reg & 0x00004000)
-				printk(KERN_CRIT "Aieee!!!  Remote IRR"
-					" still set after unlock!\n");
-			if (!entry->next)
-				break;
-			entry = irq_2_pin + entry->next;
-		}
-#endif
 		__unmask_and_level_IO_APIC_irq(irq);
 		spin_unlock(&ioapic_lock);
 	}
@@ -2322,8 +2263,6 @@
 
 #ifdef CONFIG_ACPI_BOOT
 
-#define IO_APIC_MAX_ID APIC_BROADCAST_ID
-
 int __init io_apic_get_unique_id (int ioapic, int apic_id)
 {
 	union IO_APIC_reg_00 reg_00;
@@ -2348,7 +2287,7 @@
 	reg_00.raw = io_apic_read(ioapic, 0);
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
-	if (apic_id >= IO_APIC_MAX_ID) {
+	if (apic_id >= get_physical_broadcast()) {
 		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
 			"%d\n", ioapic, apic_id, reg_00.bits.ID);
 		apic_id = reg_00.bits.ID;
@@ -2360,12 +2299,12 @@
 	 */
 	if (check_apicid_used(apic_id_map, apic_id)) {
 
-		for (i = 0; i < IO_APIC_MAX_ID; i++) {
+		for (i = 0; i < get_physical_broadcast(); i++) {
 			if (!check_apicid_used(apic_id_map, i))
 				break;
 		}
 
-		if (i == IO_APIC_MAX_ID)
+		if (i == get_physical_broadcast())
 			panic("Max apic_id exceeded!\n");
 
 		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/kernel/irq.c	2004-06-23 19:04:25 -07:00
@@ -41,7 +41,6 @@
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/delay.h>
 #include <asm/desc.h>
 #include <asm/irq.h>
diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
--- a/arch/i386/kernel/mpparse.c	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/kernel/mpparse.c	2004-06-23 19:04:26 -07:00
@@ -23,12 +23,12 @@
 #include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
+#include <linux/bitops.h>
 
 #include <asm/smp.h>
 #include <asm/acpi.h>
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
-#include <asm/pgalloc.h>
 #include <asm/io_apic.h>
 
 #include <mach_apic.h>
@@ -104,6 +104,21 @@
 static int mpc_record; 
 static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
 
+#ifdef CONFIG_X86_NUMAQ
+static int MP_valid_apicid(int apicid, int version)
+{
+	return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
+}
+#else
+static int MP_valid_apicid(int apicid, int version)
+{
+	if (version >= 0x14)
+		return apicid < 0xff;
+	else
+		return apicid < 0xf;
+}
+#endif
+
 void __init MP_processor_info (struct mpc_config_processor *m)
 {
  	int ver, apicid;
@@ -180,14 +195,14 @@
 		return;
 	}
 	num_processors++;
+	ver = m->mpc_apicver;
 
-	if (MAX_APICS - m->mpc_apicid <= 0) {
+	if (!MP_valid_apicid(apicid, ver)) {
 		printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
 			m->mpc_apicid, MAX_APICS);
 		--num_processors;
 		return;
 	}
-	ver = m->mpc_apicver;
 
 	tmp = apicid_to_cpu_present(apicid);
 	physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
@@ -844,7 +859,7 @@
 	MP_processor_info(&processor);
 }
 
-#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
 
 #define MP_ISA_BUS		0
 #define MP_MAX_IOAPIC_PIN	127
@@ -857,7 +872,7 @@
 } mp_ioapic_routing[MAX_IO_APICS];
 
 
-static int __init mp_find_ioapic (
+static int mp_find_ioapic (
 	int			gsi)
 {
 	int			i = 0;
@@ -1000,14 +1015,23 @@
 	for (i = 0; i < 16; i++) {
 		int idx;
 
-		for (idx = 0; idx < mp_irq_entries; idx++)
-			if (mp_irqs[idx].mpc_srcbus == MP_ISA_BUS &&
-				(mp_irqs[idx].mpc_srcbusirq == i ||
-				mp_irqs[idx].mpc_dstirq == i))
-					break;
+		for (idx = 0; idx < mp_irq_entries; idx++) {
+			struct mpc_config_intsrc *irq = mp_irqs + idx;
 
-		if (idx != mp_irq_entries)
-			continue;			  /* IRQ already used */
+			/* Do we already have a mapping for this ISA IRQ? */
+			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+				break;
+
+			/* Do we already have a mapping for this IOAPIC pin */
+			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+				(irq->mpc_dstirq == i))
+				break;
+		}
+
+		if (idx != mp_irq_entries) {
+			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+			continue;			/* IRQ already used */
+		}
 
 		intsrc.mpc_irqtype = mp_INT;
 		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
@@ -1025,96 +1049,56 @@
 	}
 }
 
-extern FADT_DESCRIPTOR acpi_fadt;
-
-#ifdef CONFIG_ACPI_PCI
-
 int (*platform_rename_gsi)(int ioapic, int gsi);
 
-void __init mp_parse_prt (void)
+void mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
 {
-	struct list_head	*node = NULL;
-	struct acpi_prt_entry	*entry = NULL;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
-	int			gsi = 0;
 	int			idx, bit = 0;
-	int			edge_level = 0;
-	int			active_high_low = 0;
 
-	/*
-	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
-	 * routing for all entries.
-	 */
-	list_for_each(node, &acpi_prt.entries) {
-		entry = list_entry(node, struct acpi_prt_entry, node);
+#ifdef CONFIG_ACPI_BUS
+	/* Don't set up the ACPI SCI because it's already set up */
+	if (acpi_fadt.sci_int == gsi)
+		return;
+#endif
 
-		/* Need to get gsi for dynamic entry */
-		if (entry->link.handle) {
-			gsi = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
-			if (!gsi)
-				continue;
-		}
-		else {
-			/* Hardwired GSI. Assume PCI standard settings */
-			gsi = entry->link.index;
-			edge_level = 1;
-			active_high_low = 1;
-		}
+	ioapic = mp_find_ioapic(gsi);
+	if (ioapic < 0) {
+		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+		return;
+	}
 
-		/* Don't set up the ACPI SCI because it's already set up */
-                if (acpi_fadt.sci_int == gsi) {
-			/* we still need to set entry's irq */
-			acpi_gsi_to_irq(gsi, &entry->irq);
-			continue;
-                }
-	
-		ioapic = mp_find_ioapic(gsi);
-		if (ioapic < 0)
-			continue;
-		ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
-
-		if (platform_rename_gsi)
-			gsi = platform_rename_gsi(ioapic, gsi);
-
-		/* 
-		 * Avoid pin reprogramming.  PRTs typically include entries  
-		 * with redundant pin->gsi mappings (but unique PCI devices);
-		 * we only only program the IOAPIC on the first.
-		 */
-		bit = ioapic_pin % 32;
-		idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
-		if (idx > 3) {
-			printk(KERN_ERR "Invalid reference to IOAPIC pin "
-				"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
-				ioapic_pin);
-			continue;
-		}
-		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
-				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-			acpi_gsi_to_irq(gsi, &entry->irq);
-			continue;
-		}
+	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
 
-		mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+	if (platform_rename_gsi)
+		gsi = platform_rename_gsi(ioapic, gsi);
 
-		if (!io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, edge_level, active_high_low)) {
-			acpi_gsi_to_irq(gsi, &entry->irq);
-		}
-		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d %s %s\n",
-			entry->id.segment, entry->id.bus,
-			entry->id.device, ('A' + entry->pin),
-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
-			entry->irq, edge_level ? "level" : "edge",
-			active_high_low ? "low" : "high");
+	/* 
+	 * Avoid pin reprogramming.  PRTs typically include entries  
+	 * with redundant pin->gsi mappings (but unique PCI devices);
+	 * we only program the IOAPIC on the first.
+	 */
+	bit = ioapic_pin % 32;
+	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+	if (idx > 3) {
+		printk(KERN_ERR "Invalid reference to IOAPIC pin "
+			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
+			ioapic_pin);
+		return;
+	}
+	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+		return;
 	}
 
-	print_IO_APIC();
+	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 
-	return;
+	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+		    edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
+		    active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
 }
 
-#endif /*CONFIG_ACPI_PCI*/
-#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
+#endif /*CONFIG_X86_IO_APIC && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)*/
 #endif /*CONFIG_ACPI_BOOT*/
diff -Nru a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
--- a/arch/i386/kernel/msr.c	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/kernel/msr.c	2004-06-23 19:04:26 -07:00
@@ -35,12 +35,17 @@
 #include <linux/smp_lock.h>
 #include <linux/major.h>
 #include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+static struct class_simple *msr_class;
+
 /* Note: "err" is handled in a funny way below.  Otherwise one version
    of gcc or another breaks. */
 
@@ -255,20 +260,82 @@
 	.open = msr_open,
 };
 
+static int msr_class_simple_device_add(int i)
+{
+	int err = 0;
+	struct class_device *class_err;
+
+	class_err = class_simple_device_add(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
+	if (IS_ERR(class_err)) 
+		err = PTR_ERR(class_err);
+	return err;
+}
+
+static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+		msr_class_simple_device_add(cpu);
+		break;
+	case CPU_DEAD:
+		class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));	
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block msr_class_cpu_notifier =
+{
+	.notifier_call = msr_class_cpu_callback,
+};
+
 int __init msr_init(void)
 {
+	int i, err = 0;
+	i = 0;
+
 	if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
 		printk(KERN_ERR "msr: unable to get major %d for msr\n",
 		       MSR_MAJOR);
-		return -EBUSY;
+		err = -EBUSY;
+		goto out;
+	}
+	msr_class = class_simple_create(THIS_MODULE, "msr");
+	if (IS_ERR(msr_class)) {
+		err = PTR_ERR(msr_class);
+		goto out_chrdev;
 	}
+	for_each_online_cpu(i) {
+		err = msr_class_simple_device_add(i);
+		if (err != 0)
+			goto out_class;
+	}
+	register_cpu_notifier(&msr_class_cpu_notifier);
 
-	return 0;
+	err = 0;
+	goto out;
+
+out_class:
+	i = 0;
+	for_each_online_cpu(i)
+		class_simple_device_remove(MKDEV(MSR_MAJOR, i));
+	class_simple_destroy(msr_class);
+out_chrdev:
+	unregister_chrdev(MSR_MAJOR, "cpu/msr");
+out:
+	return err;
 }
 
 void __exit msr_exit(void)
 {
+	int cpu = 0;
+	for_each_online_cpu(cpu)
+		class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
+	class_simple_destroy(msr_class);
 	unregister_chrdev(MSR_MAJOR, "cpu/msr");
+	unregister_cpu_notifier(&msr_class_cpu_notifier);
 }
 
 module_init(msr_init);
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	2004-06-23 19:04:27 -07:00
+++ b/arch/i386/kernel/setup.c	2004-06-23 19:04:27 -07:00
@@ -47,7 +47,7 @@
 #include <asm/sections.h>
 #include <asm/io_apic.h>
 #include <asm/ist.h>
-#include <asm/std_resources.h>
+#include <asm/io.h>
 #include "setup_arch_pre.h"
 
 /* This value is set up by the early boot code to point to the value
@@ -57,8 +57,6 @@
 
 int disable_pse __initdata = 0;
 
-static inline char * __init machine_specific_memory_setup(void);
-
 /*
  * Machine setup..
  */
@@ -133,8 +131,203 @@
 
 unsigned char __initdata boot_params[PARAM_SIZE];
 
-static struct resource code_resource = { "Kernel code", 0x100000, 0 };
-static struct resource data_resource = { "Kernel data", 0, 0 };
+static struct resource data_resource = {
+	.name	= "Kernel data",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource code_resource = {
+	.name	= "Kernel code",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource system_rom_resource = {
+	.name	= "System ROM",
+	.start	= 0xf0000,
+	.end	= 0xfffff,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+};
+
+static struct resource extension_rom_resource = {
+	.name	= "Extension ROM",
+	.start	= 0xe0000,
+	.end	= 0xeffff,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+};
+
+static struct resource adapter_rom_resources[] = { {
+	.name 	= "Adapter ROM",
+	.start	= 0xc8000,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+	.name 	= "Adapter ROM",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+	.name 	= "Adapter ROM",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+	.name 	= "Adapter ROM",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+	.name 	= "Adapter ROM",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+}, {
+	.name 	= "Adapter ROM",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+} };
+
+#define ADAPTER_ROM_RESOURCES \
+	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
+
+static struct resource video_rom_resource = {
+	.name 	= "Video ROM",
+	.start	= 0xc0000,
+	.end	= 0xc7fff,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+};
+
+static struct resource video_ram_resource = {
+	.name	= "Video RAM area",
+	.start	= 0xa0000,
+	.end	= 0xbffff,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource standard_io_resources[] = { {
+	.name	= "dma1",
+	.start	= 0x0000,
+	.end	= 0x001f,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+	.name	= "pic1",
+	.start	= 0x0020,
+	.end	= 0x0021,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+	.name	= "timer",
+	.start	= 0x0040,
+	.end	= 0x005f,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+	.name	= "keyboard",
+	.start	= 0x0060,
+	.end	= 0x006f,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+	.name	= "dma page reg",
+	.start	= 0x0080,
+	.end	= 0x008f,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+	.name	= "pic2",
+	.start	= 0x00a0,
+	.end	= 0x00a1,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+	.name	= "dma2",
+	.start	= 0x00c0,
+	.end	= 0x00df,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+	.name	= "fpu",
+	.start	= 0x00f0,
+	.end	= 0x00ff,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+} };
+
+#define STANDARD_IO_RESOURCES \
+	(sizeof standard_io_resources / sizeof standard_io_resources[0])
+
+#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
+
+static int __init romchecksum(unsigned char *rom, unsigned long length)
+{
+	unsigned char *p, sum = 0;
+
+	for (p = rom; p < rom + length; p++)
+		sum += *p;
+	return sum == 0;
+}
+
+static void __init probe_roms(void)
+{
+	unsigned long start, length, upper;
+	unsigned char *rom;
+	int	      i;
+
+	/* video rom */
+	upper = adapter_rom_resources[0].start;
+	for (start = video_rom_resource.start; start < upper; start += 2048) {
+		rom = isa_bus_to_virt(start);
+		if (!romsignature(rom))
+			continue;
+
+		video_rom_resource.start = start;
+
+		/* 0 < length <= 0x7f * 512, historically */
+		length = rom[2] * 512;
+
+		/* if checksum okay, trust length byte */
+		if (length && romchecksum(rom, length))
+			video_rom_resource.end = start + length - 1;
+
+		request_resource(&iomem_resource, &video_rom_resource);
+		break;
+	}
+
+	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
+	if (start < upper)
+		start = upper;
+
+	/* system rom */
+	request_resource(&iomem_resource, &system_rom_resource);
+	upper = system_rom_resource.start;
+
+	/* check for extension rom (ignore length byte!) */
+	rom = isa_bus_to_virt(extension_rom_resource.start);
+	if (romsignature(rom)) {
+		length = extension_rom_resource.end - extension_rom_resource.start + 1;
+		if (romchecksum(rom, length)) {
+			request_resource(&iomem_resource, &extension_rom_resource);
+			upper = extension_rom_resource.start;
+		}
+	}
+
+	/* check for adapter roms on 2k boundaries */
+	for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
+		rom = isa_bus_to_virt(start);
+		if (!romsignature(rom))
+			continue;
+
+		/* 0 < length <= 0x7f * 512, historically */
+		length = rom[2] * 512;
+
+		/* but accept any length that fits if checksum okay */
+		if (!length || start + length > upper || !romchecksum(rom, length))
+			continue;
+
+		adapter_rom_resources[i].start = start;
+		adapter_rom_resources[i].end = start + length - 1;
+		request_resource(&iomem_resource, &adapter_rom_resources[i]);
+
+		start = adapter_rom_resources[i++].end & ~2047UL;
+	}
+}
 
 static void __init limit_regions(unsigned long long size)
 {
@@ -465,14 +658,6 @@
  */
 #define LOWMEMSIZE()	(0x9f000)
 
-static void __init setup_memory_region(void)
-{
-	char *who = machine_specific_memory_setup();
-	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
-	print_memory_map(who);
-} /* setup_memory_region */
-
-
 static void __init parse_cmdline_early (char ** cmdline_p)
 {
 	char c = ' ', *to = command_line, *from = saved_command_line;
@@ -948,6 +1133,7 @@
 static void __init register_memory(unsigned long max_low_pfn)
 {
 	unsigned long low_mem_size;
+	int	      i;
 
 	if (efi_enabled)
 		efi_initialize_iomem_resources(&code_resource, &data_resource);
@@ -955,10 +1141,11 @@
 		legacy_init_iomem_resources(&code_resource, &data_resource);
 
 	/* EFI systems may still have VGA */
-	request_graphics_resource();
+	request_resource(&iomem_resource, &video_ram_resource);
 
 	/* request I/O space for devices used on all i[345]86 PCs */
-	request_standard_io_resources();
+	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+		request_resource(&ioport_resource, &standard_io_resources[i]);
 
 	/* Tell the PCI layer not to allocate too close to the RAM area.. */
 	low_mem_size = ((max_low_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff;
@@ -1073,6 +1260,8 @@
 
 __setup("noreplacement", noreplacement_setup); 
 
+static char * __init machine_specific_memory_setup(void);
+
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -1123,8 +1312,10 @@
 	ARCH_SETUP
 	if (efi_enabled)
 		efi_init();
-	else
-		setup_memory_region();
+	else {
+		printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+		print_memory_map(machine_specific_memory_setup());
+	}
 
 	copy_edd();
 
diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
--- a/arch/i386/kernel/signal.c	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/kernel/signal.c	2004-06-23 19:04:26 -07:00
@@ -56,16 +56,15 @@
 }
 
 asmlinkage int
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
+sys_rt_sigsuspend(struct pt_regs regs)
 {
-	struct pt_regs * regs = (struct pt_regs *) &unewset;
 	sigset_t saveset, newset;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
+	if (regs.ecx != sizeof(sigset_t))
 		return -EINVAL;
 
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
+	if (copy_from_user(&newset, (sigset_t __user *)regs.ebx, sizeof(newset)))
 		return -EFAULT;
 	sigdelsetmask(&newset, ~_BLOCKABLE);
 
@@ -75,11 +74,11 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs->eax = -EINTR;
+	regs.eax = -EINTR;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(regs, &saveset))
+		if (do_signal(&regs, &saveset))
 			return -EINTR;
 	}
 }
@@ -117,10 +116,11 @@
 }
 
 asmlinkage int
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+sys_sigaltstack(struct pt_regs regs)
 {
-	struct pt_regs *regs = (struct pt_regs *) &uss;
-	return do_sigaltstack(uss, uoss, regs->esp);
+	const stack_t __user *uss = (const stack_t __user *)regs.ebx;
+	stack_t __user *uoss = (stack_t __user *)regs.ecx;
+	return do_sigaltstack(uss, uoss, regs.esp);
 }
 
 
diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
--- a/arch/i386/kernel/smp.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/kernel/smp.c	2004-06-23 19:04:25 -07:00
@@ -21,7 +21,6 @@
 #include <linux/interrupt.h>
 
 #include <asm/mtrr.h>
-#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <mach_ipi.h>
 #include <mach_apic.h>
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c	2004-06-23 19:04:27 -07:00
+++ b/arch/i386/kernel/smpboot.c	2004-06-23 19:04:27 -07:00
@@ -47,7 +47,6 @@
 
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
-#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/desc.h>
 #include <asm/arch_hooks.h>
diff -Nru a/arch/i386/kernel/std_resources.c b/arch/i386/kernel/std_resources.c
--- a/arch/i386/kernel/std_resources.c	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,204 +0,0 @@
-/*
- *  Machine specific resource allocation for generic.
- */
-
-#include <linux/ioport.h>
-#include <asm/io.h>
-#include <asm/std_resources.h>
-
-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
-
-static struct resource system_rom_resource = {
-	.name	= "System ROM",
-	.start	= 0xf0000,
-	.end	= 0xfffff,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-};
-
-static struct resource extension_rom_resource = {
-	.name	= "Extension ROM",
-	.start	= 0xe0000,
-	.end	= 0xeffff,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-};
-
-static struct resource adapter_rom_resources[] = { {
-	.name 	= "Adapter ROM",
-	.start	= 0xc8000,
-	.end	= 0,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-	.name 	= "Adapter ROM",
-	.start	= 0,
-	.end	= 0,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-	.name 	= "Adapter ROM",
-	.start	= 0,
-	.end	= 0,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-	.name 	= "Adapter ROM",
-	.start	= 0,
-	.end	= 0,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-	.name 	= "Adapter ROM",
-	.start	= 0,
-	.end	= 0,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-}, {
-	.name 	= "Adapter ROM",
-	.start	= 0,
-	.end	= 0,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-} };
-
-#define ADAPTER_ROM_RESOURCES \
-	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
-
-static struct resource video_rom_resource = {
-	.name 	= "Video ROM",
-	.start	= 0xc0000,
-	.end	= 0xc7fff,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
-};
-
-static struct resource vram_resource = {
-	.name	= "Video RAM area",
-	.start	= 0xa0000,
-	.end	= 0xbffff,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
-};
-
-static struct resource standard_io_resources[] = { {
-	.name	= "dma1",
-	.start	= 0x0000,
-	.end	= 0x001f,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-	.name	= "pic1",
-	.start	= 0x0020,
-	.end	= 0x0021,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-	.name	= "timer",
-	.start	= 0x0040,
-	.end	= 0x005f,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-	.name	= "keyboard",
-	.start	= 0x0060,
-	.end	= 0x006f,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-	.name	= "dma page reg",
-	.start	= 0x0080,
-	.end	= 0x008f,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-	.name	= "pic2",
-	.start	= 0x00a0,
-	.end	= 0x00a1,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-	.name	= "dma2",
-	.start	= 0x00c0,
-	.end	= 0x00df,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
-}, {
-	.name	= "fpu",
-	.start	= 0x00f0,
-	.end	= 0x00ff,
-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
-} };
-
-#define STANDARD_IO_RESOURCES \
-	(sizeof standard_io_resources / sizeof standard_io_resources[0])
-
-static int __init checksum(unsigned char *rom, unsigned long length)
-{
-	unsigned char *p, sum = 0;
-
-	for (p = rom; p < rom + length; p++)
-		sum += *p;
-	return sum == 0;
-}
-
-void __init probe_roms(void)
-{
-	unsigned long start, length, upper;
-	unsigned char *rom;
-	int	      i;
-
-	/* video rom */
-	upper = adapter_rom_resources[0].start;
-	for (start = video_rom_resource.start; start < upper; start += 2048) {
-		rom = isa_bus_to_virt(start);
-		if (!romsignature(rom))
-			continue;
-
-		video_rom_resource.start = start;
-
-		/* 0 < length <= 0x7f * 512, historically */
-		length = rom[2] * 512;
-
-		/* if checksum okay, trust length byte */
-		if (length && checksum(rom, length))
-			video_rom_resource.end = start + length - 1;
-
-		request_resource(&iomem_resource, &video_rom_resource);
-		break;
-	}
-
-	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
-	if (start < upper)
-		start = upper;
-
-	/* system rom */
-	request_resource(&iomem_resource, &system_rom_resource);
-	upper = system_rom_resource.start;
-
-	/* check for extension rom (ignore length byte!) */
-	rom = isa_bus_to_virt(extension_rom_resource.start);
-	if (romsignature(rom)) {
-		length = extension_rom_resource.end - extension_rom_resource.start + 1;
-		if (checksum(rom, length)) {
-			request_resource(&iomem_resource, &extension_rom_resource);
-			upper = extension_rom_resource.start;
-		}
-	}
-
-	/* check for adapter roms on 2k boundaries */
-	for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
-		rom = isa_bus_to_virt(start);
-		if (!romsignature(rom))
-			continue;
-
-		/* 0 < length <= 0x7f * 512, historically */
-		length = rom[2] * 512;
-
-		/* but accept any length that fits if checksum okay */
-		if (!length || start + length > upper || !checksum(rom, length))
-			continue;
-
-		adapter_rom_resources[i].start = start;
-		adapter_rom_resources[i].end = start + length - 1;
-		request_resource(&iomem_resource, &adapter_rom_resources[i]);
-
-		start = adapter_rom_resources[i++].end & ~2047UL;
-	}
-}
-
-void __init request_graphics_resource(void)
-{
-	request_resource(&iomem_resource, &vram_resource);
-}
-
-void __init request_standard_io_resources(void)
-{
-	int i;
-
-	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
-		request_resource(&ioport_resource, &standard_io_resources[i]);
-}
diff -Nru a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
--- a/arch/i386/kernel/time_hpet.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/kernel/time_hpet.c	2004-06-23 19:04:25 -07:00
@@ -21,6 +21,7 @@
 #include <linux/config.h>
 
 #include <asm/hpet.h>
+#include <linux/hpet.h>
 
 unsigned long hpet_period;	/* fsecs / HPET clock */
 unsigned long hpet_tick;	/* hpet clks count per tick */
@@ -135,6 +136,51 @@
 	hpet_writel(cfg, HPET_CFG);
 
 	use_hpet = 1;
+
+#ifdef	CONFIG_HPET
+	{
+		struct hpet_data	hd;
+		unsigned int 		ntimer;
+
+		memset(&hd, 0, sizeof (hd));
+
+		ntimer = hpet_readl(HPET_ID);
+		ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
+		ntimer++;
+
+		/*
+		 * Register with driver.
+		 * Timer0 and Timer1 is used by platform.
+		 */
+		hd.hd_address = hpet_virt_address;
+		hd.hd_nirqs = ntimer;
+		hd.hd_flags = HPET_DATA_PLATFORM;
+#ifndef	CONFIG_HPET_EMULATE_RTC
+		hd.hd_state = 0x1;
+#else
+		hd.hd_state = 0x3;
+#endif
+		hd.hd_irq[0] = HPET_LEGACY_8254;
+		hd.hd_irq[1] = HPET_LEGACY_RTC;
+		if (ntimer > 2) {
+			struct hpet		*hpet;
+			struct hpet_timer	*timer;
+			int			i;
+
+			hpet = (struct hpet *) hpet_virt_address;
+
+			for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer;
+				timer++, i++)
+				hd.hd_irq[i] = (timer->hpet_config &
+					Tn_INT_ROUTE_CNF_MASK) >>
+					Tn_INT_ROUTE_CNF_SHIFT;
+
+		}
+
+		hpet_alloc(&hd);
+	}
+#endif
+
 #ifdef CONFIG_X86_LOCAL_APIC
 	wait_timer_tick = wait_hpet_tick;
 #endif
diff -Nru a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c
--- a/arch/i386/kernel/timers/timer_pm.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/kernel/timers/timer_pm.c	2004-06-23 19:04:25 -07:00
@@ -21,6 +21,14 @@
 #include <asm/io.h>
 #include <asm/arch_hooks.h>
 
+#include <linux/timex.h>
+#include "mach_timer.h"
+
+/* Number of PMTMR ticks expected during calibration run */
+#define PMTMR_TICKS_PER_SEC 3579545
+#define PMTMR_EXPECTED_RATE \
+  ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10))
+
 
 /* The I/O port the PMTMR resides at.
  * The location is detected during setup_arch(),
@@ -57,6 +65,33 @@
 	return v2 & ACPI_PM_MASK;
 }
 
+
+/*
+ * Some boards have the PMTMR running way too fast. We check
+ * the PMTMR rate against PIT channel 2 to catch these cases.
+ */
+static int verify_pmtmr_rate(void)
+{
+	u32 value1, value2;
+	unsigned long count, delta;
+
+	mach_prepare_counter();
+	value1 = read_pmtmr();
+	mach_countup(&count);
+	value2 = read_pmtmr();
+	delta = (value2 - value1) & ACPI_PM_MASK;
+
+	/* Check that the PMTMR delta is within 5% of what we expect */
+	if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 ||
+	    delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
+		printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% of normal - aborting.\n", 100UL * delta / PMTMR_EXPECTED_RATE);
+		return -1;
+	}
+
+	return 0;
+}
+
+
 static int init_pmtmr(char* override)
 {
 	u32 value1, value2;
@@ -89,6 +124,9 @@
 	return -ENODEV;
 
 pm_good:
+	if (verify_pmtmr_rate() != 0)
+		return -ENODEV;
+
 	init_cpu_khz();
 	return 0;
 }
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/kernel/traps.c	2004-06-23 19:04:25 -07:00
@@ -47,7 +47,6 @@
 #include <asm/nmi.h>
 
 #include <asm/smp.h>
-#include <asm/pgalloc.h>
 #include <asm/arch_hooks.h>
 
 #include <linux/irq.h>
@@ -163,7 +162,6 @@
 			break;
 		printk(" =======================\n");
 	}
-	printk("\n");
 }
 
 void show_stack(struct task_struct *task, unsigned long *esp)
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/kernel/vm86.c	2004-06-23 19:04:25 -07:00
@@ -44,7 +44,6 @@
 #include <linux/ptrace.h>
 
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <asm/irq.h>
@@ -178,8 +177,9 @@
 static int do_vm86_irq_handling(int subfunction, int irqnumber);
 static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk);
 
-asmlinkage int sys_vm86old(struct vm86_struct __user * v86)
+asmlinkage int sys_vm86old(struct pt_regs regs)
 {
+	struct vm86_struct __user *v86 = (struct vm86_struct __user *)regs.ebx;
 	struct kernel_vm86_struct info; /* declare this _on top_,
 					 * this avoids wasting of stack space.
 					 * This remains on the stack until we
@@ -198,7 +198,7 @@
 	if (tmp)
 		goto out;
 	memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus);
-	info.regs32 = (struct pt_regs *) &v86;
+	info.regs32 = &regs;
 	tsk->thread.vm86_info = v86;
 	do_sys_vm86(&info, tsk);
 	ret = 0;	/* we never return here */
@@ -207,7 +207,7 @@
 }
 
 
-asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct __user * v86)
+asmlinkage int sys_vm86(struct pt_regs regs)
 {
 	struct kernel_vm86_struct info; /* declare this _on top_,
 					 * this avoids wasting of stack space.
@@ -216,14 +216,15 @@
 					 */
 	struct task_struct *tsk;
 	int tmp, ret;
+	struct vm86plus_struct __user *v86;
 
 	tsk = current;
-	switch (subfunction) {
+	switch (regs.ebx) {
 		case VM86_REQUEST_IRQ:
 		case VM86_FREE_IRQ:
 		case VM86_GET_IRQ_BITS:
 		case VM86_GET_AND_RESET_IRQ:
-			ret = do_vm86_irq_handling(subfunction,(int)v86);
+			ret = do_vm86_irq_handling(regs.ebx, (int)regs.ecx);
 			goto out;
 		case VM86_PLUS_INSTALL_CHECK:
 			/* NOTE: on old vm86 stuff this will return the error
@@ -239,13 +240,14 @@
 	ret = -EPERM;
 	if (tsk->thread.saved_esp0)
 		goto out;
+	v86 = (struct vm86plus_struct __user *)regs.ecx;
 	tmp  = copy_from_user(&info, v86, VM86_REGS_SIZE1);
 	tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
 		(long)&info.regs32 - (long)&info.regs.VM86_REGS_PART2);
 	ret = -EFAULT;
 	if (tmp)
 		goto out;
-	info.regs32 = (struct pt_regs *) &subfunction;
+	info.regs32 = &regs;
 	info.vm86plus.is_vm86pus = 1;
 	tsk->thread.vm86_info = (struct vm86_struct __user *)v86;
 	do_sys_vm86(&info, tsk);
@@ -486,9 +488,10 @@
  * in userspace is always better than an Oops anyway.) [KD]
  */
 static void do_int(struct kernel_vm86_regs *regs, int i,
-    unsigned char * ssp, unsigned short sp)
+    unsigned char __user * ssp, unsigned short sp)
 {
-	unsigned long *intr_ptr, segoffs;
+	unsigned long __user *intr_ptr;
+	unsigned long segoffs;
 
 	if (regs->cs == BIOSSEG)
 		goto cannot_handle;
@@ -496,7 +499,7 @@
 		goto cannot_handle;
 	if (i==0x21 && is_revectored(AH(regs),&KVM86->int21_revectored))
 		goto cannot_handle;
-	intr_ptr = (unsigned long *) (i << 2);
+	intr_ptr = (unsigned long __user *) (i << 2);
 	if (get_user(segoffs, intr_ptr))
 		goto cannot_handle;
 	if ((segoffs >> 16) == BIOSSEG)
@@ -521,7 +524,7 @@
 	if (VMPI.is_vm86pus) {
 		if ( (trapno==3) || (trapno==1) )
 			return_to_32bit(regs, VM86_TRAP + (trapno << 8));
-		do_int(regs, trapno, (unsigned char *) (regs->ss << 4), SP(regs));
+		do_int(regs, trapno, (unsigned char __user *) (regs->ss << 4), SP(regs));
 		return 0;
 	}
 	if (trapno !=1)
@@ -541,7 +544,9 @@
 
 void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
 {
-	unsigned char *csp, *ssp, opcode;
+	unsigned char opcode;
+	unsigned char __user *csp;
+	unsigned char __user *ssp;
 	unsigned short ip, sp;
 	int data32, pref_done;
 
@@ -553,8 +558,8 @@
 		return_to_32bit(regs, VM86_PICRETURN); \
 	return; } while (0)
 
-	csp = (unsigned char *) (regs->cs << 4);
-	ssp = (unsigned char *) (regs->ss << 4);
+	csp = (unsigned char __user *) (regs->cs << 4);
+	ssp = (unsigned char __user *) (regs->ss << 4);
 	sp = SP(regs);
 	ip = IP(regs);
 
diff -Nru a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile
--- a/arch/i386/lib/Makefile	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/lib/Makefile	2004-06-23 19:04:25 -07:00
@@ -3,9 +3,8 @@
 #
 
 
-lib-y = checksum.o delay.o \
-	usercopy.o getuser.o \
-	memcpy.o strstr.o
+lib-y = checksum.o delay.o usercopy.o getuser.o memcpy.o strstr.o \
+	bitops.o
 
 lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
 lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff -Nru a/arch/i386/lib/bitops.c b/arch/i386/lib/bitops.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/i386/lib/bitops.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,70 @@
+#include <linux/bitops.h>
+#include <linux/module.h>
+
+/**
+ * find_next_bit - find the first set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+int find_next_bit(const unsigned long *addr, int size, int offset)
+{
+	const unsigned long *p = addr + (offset >> 5);
+	int set = 0, bit = offset & 31, res;
+
+	if (bit) {
+		/*
+		 * Look for nonzero in the first 32 bits:
+		 */
+		__asm__("bsfl %1,%0\n\t"
+			"jne 1f\n\t"
+			"movl $32, %0\n"
+			"1:"
+			: "=r" (set)
+			: "r" (*p >> bit));
+		if (set < (32 - bit))
+			return set + offset;
+		set = 32 - bit;
+		p++;
+	}
+	/*
+	 * No set bit yet, search remaining full words for a bit
+	 */
+	res = find_first_bit (p, size - 32 * (p - addr));
+	return (offset + set + res);
+}
+EXPORT_SYMBOL(find_next_bit);
+
+/**
+ * find_next_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+int find_next_zero_bit(const unsigned long *addr, int size, int offset)
+{
+	unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
+	int set = 0, bit = offset & 31, res;
+
+	if (bit) {
+		/*
+		 * Look for zero in the first 32 bits.
+		 */
+		__asm__("bsfl %1,%0\n\t"
+			"jne 1f\n\t"
+			"movl $32, %0\n"
+			"1:"
+			: "=r" (set)
+			: "r" (~(*p >> bit)));
+		if (set < (32 - bit))
+			return set + offset;
+		set = 32 - bit;
+		p++;
+	}
+	/*
+	 * No zero yet, search remaining full bytes for a zero
+	 */
+	res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
+	return (offset + set + res);
+}
+EXPORT_SYMBOL(find_next_zero_bit);
diff -Nru a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c
--- a/arch/i386/lib/delay.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/lib/delay.c	2004-06-23 19:04:28 -07:00
@@ -31,15 +31,16 @@
 inline void __const_udelay(unsigned long xloops)
 {
 	int d0;
+	xloops *= 4;
 	__asm__("mull %0"
 		:"=d" (xloops), "=&a" (d0)
-		:"1" (xloops),"0" (current_cpu_data.loops_per_jiffy));
-        __delay(xloops * HZ);
+		:"1" (xloops),"0" (current_cpu_data.loops_per_jiffy * (HZ/4)));
+        __delay(++xloops);
 }
 
 void __udelay(unsigned long usecs)
 {
-	__const_udelay(usecs * 0x000010c6);  /* 2**32 / 1000000 */
+	__const_udelay(usecs * 0x000010c7);  /* 2**32 / 1000000 (rounded up) */
 }
 
 void __ndelay(unsigned long nsecs)
diff -Nru a/arch/i386/mach-pc9800/Makefile b/arch/i386/mach-pc9800/Makefile
--- a/arch/i386/mach-pc9800/Makefile	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-obj-y				:= setup.o topology.o std_resources.o
diff -Nru a/arch/i386/mach-pc9800/setup.c b/arch/i386/mach-pc9800/setup.c
--- a/arch/i386/mach-pc9800/setup.c	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,117 +0,0 @@
-/*
- *	Machine specific setup for pc9800
- */
-
-#include <linux/config.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/apm_bios.h>
-#include <asm/setup.h>
-#include <asm/arch_hooks.h>
-
-struct sys_desc_table_struct {
-	unsigned short length;
-	unsigned char table[0];
-};
-
-/**
- * pre_intr_init_hook - initialisation prior to setting up interrupt vectors
- *
- * Description:
- *	Perform any necessary interrupt initialisation prior to setting up
- *	the "ordinary" interrupt call gates.  For legacy reasons, the ISA
- *	interrupts should be initialised here if the machine emulates a PC
- *	in any way.
- **/
-void __init pre_intr_init_hook(void)
-{
-	init_ISA_irqs();
-}
-
-/*
- * IRQ7 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq7 = { no_action, 0, 0, "cascade", NULL, NULL};
-
-/**
- * intr_init_hook - post gate setup interrupt initialisation
- *
- * Description:
- *	Fill in any interrupts that may have been left out by the general
- *	init_IRQ() routine.  interrupts having to do with the machine rather
- *	than the devices on the I/O bus (like APIC interrupts in intel MP
- *	systems) are started here.
- **/
-void __init intr_init_hook(void)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
-	apic_intr_init();
-#endif
-
-	setup_irq(7, &irq7);
-}
-
-/**
- * pre_setup_arch_hook - hook called prior to any setup_arch() execution
- *
- * Description:
- *	generally used to activate any machine specific identification
- *	routines that may be needed before setup_arch() runs.  On VISWS
- *	this is used to get the board revision and type.
- **/
-void __init pre_setup_arch_hook(void)
-{
-	SYS_DESC_TABLE.length = 0;
-	MCA_bus = 0;
-	/* In PC-9800, APM BIOS version is written in BCD...?? */
-	APM_BIOS_INFO.version = (APM_BIOS_INFO.version & 0xff00)
-				| ((APM_BIOS_INFO.version & 0x00f0) >> 4);
-}
-
-/**
- * trap_init_hook - initialise system specific traps
- *
- * Description:
- *	Called as the final act of trap_init().  Used in VISWS to initialise
- *	the various board specific APIC traps.
- **/
-void __init trap_init_hook(void)
-{
-}
-
-static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
-
-/**
- * time_init_hook - do any specific initialisations for the system timer.
- *
- * Description:
- *	Must plug the system timer interrupt source at HZ into the IRQ listed
- *	in irq_vectors.h:TIMER_IRQ
- **/
-void __init time_init_hook(void)
-{
-	setup_irq(0, &irq0);
-}
-
-#ifdef CONFIG_MCA
-/**
- * mca_nmi_hook - hook into MCA specific NMI chain
- *
- * Description:
- *	The MCA (Microchannel Architecture) has an NMI chain for NMI sources
- *	along the MCA bus.  Use this to hook into that chain if you will need
- *	it.
- **/
-void __init mca_nmi_hook(void)
-{
-	/* If I recall correctly, there's a whole bunch of other things that
-	 * we can do to check for NMI problems, but that's all I know about
-	 * at the moment.
-	 */
-
-	printk("NMI generated from unknown source!\n");
-}
-#endif
diff -Nru a/arch/i386/mach-pc9800/std_resources.c b/arch/i386/mach-pc9800/std_resources.c
--- a/arch/i386/mach-pc9800/std_resources.c	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,195 +0,0 @@
-/*
- *  Machine specific resource allocation for PC-9800.
- *  Written by Osamu Tomita <tomita@cinet.co.jp>
- */
-
-#include <linux/ioport.h>
-#include <asm/io.h>
-#include <asm/std_resources.h>
-
-static char str_pic1[] = "pic1";
-static char str_dma[] = "dma";
-static char str_pic2[] = "pic2";
-static char str_calender_clock[] = "calender clock";
-static char str_system[] = "system";
-static char str_nmi_control[] = "nmi control";
-static char str_kanji_rom[] = "kanji rom";
-static char str_keyboard[] = "keyboard";
-static char str_text_gdc[] = "text gdc";
-static char str_crtc[] = "crtc";
-static char str_timer[] = "timer";
-static char str_graphic_gdc[] = "graphic gdc";
-static char str_dma_ex_bank[] = "dma ex. bank";
-static char str_beep_freq[] = "beep freq.";
-static char str_mouse_pio[] = "mouse pio";
-struct resource standard_io_resources[] = {
-	{ str_pic1, 0x00, 0x00, IORESOURCE_BUSY },
-	{ str_dma, 0x01, 0x01, IORESOURCE_BUSY },
-	{ str_pic1, 0x02, 0x02, IORESOURCE_BUSY },
-	{ str_dma, 0x03, 0x03, IORESOURCE_BUSY },
-	{ str_dma, 0x05, 0x05, IORESOURCE_BUSY },
-	{ str_dma, 0x07, 0x07, IORESOURCE_BUSY },
-	{ str_pic2, 0x08, 0x08, IORESOURCE_BUSY },
-	{ str_dma, 0x09, 0x09, IORESOURCE_BUSY },
-	{ str_pic2, 0x0a, 0x0a, IORESOURCE_BUSY },
-	{ str_dma, 0x0b, 0x0b, IORESOURCE_BUSY },
-	{ str_dma, 0x0d, 0x0d, IORESOURCE_BUSY },
-	{ str_dma, 0x0f, 0x0f, IORESOURCE_BUSY },
-	{ str_dma, 0x11, 0x11, IORESOURCE_BUSY },
-	{ str_dma, 0x13, 0x13, IORESOURCE_BUSY },
-	{ str_dma, 0x15, 0x15, IORESOURCE_BUSY },
-	{ str_dma, 0x17, 0x17, IORESOURCE_BUSY },
-	{ str_dma, 0x19, 0x19, IORESOURCE_BUSY },
-	{ str_dma, 0x1b, 0x1b, IORESOURCE_BUSY },
-	{ str_dma, 0x1d, 0x1d, IORESOURCE_BUSY },
-	{ str_dma, 0x1f, 0x1f, IORESOURCE_BUSY },
-	{ str_calender_clock, 0x20, 0x20, 0 },
-	{ str_dma, 0x21, 0x21, IORESOURCE_BUSY },
-	{ str_calender_clock, 0x22, 0x22, 0 },
-	{ str_dma, 0x23, 0x23, IORESOURCE_BUSY },
-	{ str_dma, 0x25, 0x25, IORESOURCE_BUSY },
-	{ str_dma, 0x27, 0x27, IORESOURCE_BUSY },
-	{ str_dma, 0x29, 0x29, IORESOURCE_BUSY },
-	{ str_dma, 0x2b, 0x2b, IORESOURCE_BUSY },
-	{ str_dma, 0x2d, 0x2d, IORESOURCE_BUSY },
-	{ str_system, 0x31, 0x31, IORESOURCE_BUSY },
-	{ str_system, 0x33, 0x33, IORESOURCE_BUSY },
-	{ str_system, 0x35, 0x35, IORESOURCE_BUSY },
-	{ str_system, 0x37, 0x37, IORESOURCE_BUSY },
-	{ str_nmi_control, 0x50, 0x50, IORESOURCE_BUSY },
-	{ str_nmi_control, 0x52, 0x52, IORESOURCE_BUSY },
-	{ "time stamp", 0x5c, 0x5f, IORESOURCE_BUSY },
-	{ str_kanji_rom, 0xa1, 0xa1, IORESOURCE_BUSY },
-	{ str_kanji_rom, 0xa3, 0xa3, IORESOURCE_BUSY },
-	{ str_kanji_rom, 0xa5, 0xa5, IORESOURCE_BUSY },
-	{ str_kanji_rom, 0xa7, 0xa7, IORESOURCE_BUSY },
-	{ str_kanji_rom, 0xa9, 0xa9, IORESOURCE_BUSY },
-	{ str_keyboard, 0x41, 0x41, IORESOURCE_BUSY },
-	{ str_keyboard, 0x43, 0x43, IORESOURCE_BUSY },
-	{ str_text_gdc, 0x60, 0x60, IORESOURCE_BUSY },
-	{ str_text_gdc, 0x62, 0x62, IORESOURCE_BUSY },
-	{ str_text_gdc, 0x64, 0x64, IORESOURCE_BUSY },
-	{ str_text_gdc, 0x66, 0x66, IORESOURCE_BUSY },
-	{ str_text_gdc, 0x68, 0x68, IORESOURCE_BUSY },
-	{ str_text_gdc, 0x6a, 0x6a, IORESOURCE_BUSY },
-	{ str_text_gdc, 0x6c, 0x6c, IORESOURCE_BUSY },
-	{ str_text_gdc, 0x6e, 0x6e, IORESOURCE_BUSY },
-	{ str_crtc, 0x70, 0x70, IORESOURCE_BUSY },
-	{ str_crtc, 0x72, 0x72, IORESOURCE_BUSY },
-	{ str_crtc, 0x74, 0x74, IORESOURCE_BUSY },
-	{ str_crtc, 0x74, 0x74, IORESOURCE_BUSY },
-	{ str_crtc, 0x76, 0x76, IORESOURCE_BUSY },
-	{ str_crtc, 0x78, 0x78, IORESOURCE_BUSY },
-	{ str_crtc, 0x7a, 0x7a, IORESOURCE_BUSY },
-	{ str_timer, 0x71, 0x71, IORESOURCE_BUSY },
-	{ str_timer, 0x73, 0x73, IORESOURCE_BUSY },
-	{ str_timer, 0x75, 0x75, IORESOURCE_BUSY },
-	{ str_timer, 0x77, 0x77, IORESOURCE_BUSY },
-	{ str_graphic_gdc, 0xa0, 0xa0, IORESOURCE_BUSY },
-	{ str_graphic_gdc, 0xa2, 0xa2, IORESOURCE_BUSY },
-	{ str_graphic_gdc, 0xa4, 0xa4, IORESOURCE_BUSY },
-	{ str_graphic_gdc, 0xa6, 0xa6, IORESOURCE_BUSY },
-	{ "cpu", 0xf0, 0xf7, IORESOURCE_BUSY },
-	{ "fpu", 0xf8, 0xff, IORESOURCE_BUSY },
-	{ str_dma_ex_bank, 0x0e05, 0x0e05, 0 },
-	{ str_dma_ex_bank, 0x0e07, 0x0e07, 0 },
-	{ str_dma_ex_bank, 0x0e09, 0x0e09, 0 },
-	{ str_dma_ex_bank, 0x0e0b, 0x0e0b, 0 },
-	{ str_beep_freq, 0x3fd9, 0x3fd9, IORESOURCE_BUSY },
-	{ str_beep_freq, 0x3fdb, 0x3fdb, IORESOURCE_BUSY },
-	{ str_beep_freq, 0x3fdd, 0x3fdd, IORESOURCE_BUSY },
-	{ str_beep_freq, 0x3fdf, 0x3fdf, IORESOURCE_BUSY },
-	/* All PC-9800 have (exactly) one mouse interface.  */
-	{ str_mouse_pio, 0x7fd9, 0x7fd9, 0 },
-	{ str_mouse_pio, 0x7fdb, 0x7fdb, 0 },
-	{ str_mouse_pio, 0x7fdd, 0x7fdd, 0 },
-	{ str_mouse_pio, 0x7fdf, 0x7fdf, 0 },
-	{ "mouse timer", 0xbfdb, 0xbfdb, 0 },
-	{ "mouse irq", 0x98d7, 0x98d7, 0 },
-};
-
-#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
-
-static struct resource tvram_resource = { "Text VRAM/CG window", 0xa0000, 0xa4fff, IORESOURCE_BUSY };
-static struct resource gvram_brg_resource = { "Graphic VRAM (B/R/G)", 0xa8000, 0xbffff, IORESOURCE_BUSY };
-static struct resource gvram_e_resource = { "Graphic VRAM (E)", 0xe0000, 0xe7fff, IORESOURCE_BUSY };
-
-/* System ROM resources */
-#define MAXROMS 6
-static struct resource rom_resources[MAXROMS] = {
-	{ "System ROM", 0xe8000, 0xfffff, IORESOURCE_BUSY }
-};
-
-void __init probe_roms(void)
-{
-	int i;
-	__u8 *xrom_id;
-	int roms = 1;
-
-	request_resource(&iomem_resource, rom_resources+0);
-
-	xrom_id = (__u8 *) isa_bus_to_virt(PC9800SCA_XROM_ID + 0x10);
-
-	for (i = 0; i < 16; i++) {
-		if (xrom_id[i] & 0x80) {
-			int j;
-
-			for (j = i + 1; j < 16 && (xrom_id[j] & 0x80); j++)
-				;
-			rom_resources[roms].start = 0x0d0000 + i * 0x001000;
-			rom_resources[roms].end = 0x0d0000 + j * 0x001000 - 1;
-			rom_resources[roms].name = "Extension ROM";
-			rom_resources[roms].flags = IORESOURCE_BUSY;
-
-			request_resource(&iomem_resource,
-					  rom_resources + roms);
-			if (++roms >= MAXROMS)
-				return;
-		}
-	}
-}
-
-void __init request_graphics_resource(void)
-{
-	int i;
-
-	if (PC9800_HIGHRESO_P()) {
-		tvram_resource.start = 0xe0000;
-		tvram_resource.end   = 0xe4fff;
-		gvram_brg_resource.name  = "Graphic VRAM";
-		gvram_brg_resource.start = 0xc0000;
-		gvram_brg_resource.end   = 0xdffff;
-	}
-
-	request_resource(&iomem_resource, &tvram_resource);
-	request_resource(&iomem_resource, &gvram_brg_resource);
-	if (!PC9800_HIGHRESO_P())
-		request_resource(&iomem_resource, &gvram_e_resource);
-
-	if (PC9800_HIGHRESO_P() || PC9800_9821_P()) {
-		static char graphics[] = "graphics";
-		static struct resource graphics_resources[] = {
-			{ graphics, 0x9a0, 0x9a0, 0 },
-			{ graphics, 0x9a2, 0x9a2, 0 },
-			{ graphics, 0x9a4, 0x9a4, 0 },
-			{ graphics, 0x9a6, 0x9a6, 0 },
-			{ graphics, 0x9a8, 0x9a8, 0 },
-			{ graphics, 0x9aa, 0x9aa, 0 },
-			{ graphics, 0x9ac, 0x9ac, 0 },
-			{ graphics, 0x9ae, 0x9ae, 0 },
-		};
-
-#define GRAPHICS_RESOURCES (sizeof(graphics_resources)/sizeof(struct resource))
-
-		for (i = 0; i < GRAPHICS_RESOURCES; i++)
-			request_resource(&ioport_resource, graphics_resources + i);
-	}
-}
-
-void __init request_standard_io_resources(void)
-{
-	int i;
-
-	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
-		request_resource(&ioport_resource, standard_io_resources+i);
-}
diff -Nru a/arch/i386/mach-pc9800/topology.c b/arch/i386/mach-pc9800/topology.c
--- a/arch/i386/mach-pc9800/topology.c	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,44 +0,0 @@
-/*
- * arch/i386/mach-pc9800/topology.c - Populate driverfs with topology information
- *
- * Written by: Matthew Dobson, IBM Corporation
- * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL
- *
- * Copyright (C) 2002, IBM Corp.
- *
- * All rights reserved.          
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Modify for PC-9800 by Osamu Tomita <tomita@cinet.co.jp>
- *
- */
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <asm/cpu.h>
-
-struct i386_cpu cpu_devices[NR_CPUS];
-
-static int __init topology_init(void)
-{
-	int i;
-
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_possible(i)) arch_register_cpu(i);
-	return 0;
-}
-
-subsys_initcall(topology_init);
diff -Nru a/arch/i386/mach-visws/mpparse.c b/arch/i386/mach-visws/mpparse.c
--- a/arch/i386/mach-visws/mpparse.c	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/mach-visws/mpparse.c	2004-06-23 19:04:26 -07:00
@@ -57,12 +57,12 @@
 		boot_cpu_logical_apicid = logical_apicid;
 	}
 
-	if (m->mpc_apicid > MAX_APICS) {
+	ver = m->mpc_apicver;
+	if ((ver >= 0x14 && m->mpc_apicid >= 0xff) || m->mpc_apicid >= 0xf) {
 		printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
 			m->mpc_apicid, MAX_APICS);
 		return;
 	}
-	ver = m->mpc_apicver;
 
 	apic_cpus = apicid_to_cpu_present(m->mpc_apicid);
 	physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus);
diff -Nru a/arch/i386/mach-visws/traps.c b/arch/i386/mach-visws/traps.c
--- a/arch/i386/mach-visws/traps.c	2004-06-23 19:04:27 -07:00
+++ b/arch/i386/mach-visws/traps.c	2004-06-23 19:04:27 -07:00
@@ -8,7 +8,6 @@
 #include <linux/pci_ids.h>
 
 #include <asm/io.h>
-#include <asm/pgalloc.h>
 #include <asm/arch_hooks.h>
 #include <asm/apic.h>
 #include "cobalt.h"
diff -Nru a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c
--- a/arch/i386/mach-voyager/voyager_basic.c	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/mach-voyager/voyager_basic.c	2004-06-23 19:04:26 -07:00
@@ -24,7 +24,6 @@
 #include <linux/reboot.h>
 #include <linux/sysrq.h>
 #include <asm/io.h>
-#include <asm/pgalloc.h>
 #include <asm/voyager.h>
 #include <asm/vic.h>
 #include <linux/pm.h>
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	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/mach-voyager/voyager_smp.c	2004-06-23 19:04:26 -07:00
@@ -24,7 +24,6 @@
 #include <asm/desc.h>
 #include <asm/voyager.h>
 #include <asm/vic.h>
-#include <asm/pgalloc.h>
 #include <asm/mtrr.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
diff -Nru a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c
--- a/arch/i386/mach-voyager/voyager_thread.c	2004-06-23 19:04:27 -07:00
+++ b/arch/i386/mach-voyager/voyager_thread.c	2004-06-23 19:04:27 -07:00
@@ -28,7 +28,6 @@
 #include <asm/desc.h>
 #include <asm/voyager.h>
 #include <asm/vic.h>
-#include <asm/pgalloc.h>
 #include <asm/mtrr.h>
 #include <asm/msr.h>
 
diff -Nru a/arch/i386/math-emu/errors.c b/arch/i386/math-emu/errors.c
--- a/arch/i386/math-emu/errors.c	2004-06-23 19:04:27 -07:00
+++ b/arch/i386/math-emu/errors.c	2004-06-23 19:04:27 -07:00
@@ -41,18 +41,18 @@
 
   RE_ENTRANT_CHECK_OFF;
   /* No need to verify_area(), we have previously fetched these bytes. */
-  printk("Unimplemented FPU Opcode at eip=%p : ", (void *) address);
+  printk("Unimplemented FPU Opcode at eip=%p : ", (void __user *) address);
   if ( FPU_CS == __USER_CS )
     {
       while ( 1 )
 	{
-	  FPU_get_user(byte1, (u_char *) address);
+	  FPU_get_user(byte1, (u_char __user *) address);
 	  if ( (byte1 & 0xf8) == 0xd8 ) break;
 	  printk("[%02x]", byte1);
 	  address++;
 	}
       printk("%02x ", byte1);
-      FPU_get_user(FPU_modrm, 1 + (u_char *) address);
+      FPU_get_user(FPU_modrm, 1 + (u_char __user *) address);
       
       if (FPU_modrm >= 0300)
 	printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
@@ -98,7 +98,7 @@
 #define MAX_PRINTED_BYTES 20
       for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
 	{
-	  FPU_get_user(byte1, (u_char *) address);
+	  FPU_get_user(byte1, (u_char __user *) address);
 	  if ( (byte1 & 0xf8) == 0xd8 )
 	    {
 	      printk(" %02x", byte1);
@@ -111,7 +111,7 @@
 	printk(" [more..]\n");
       else
 	{
-	  FPU_get_user(FPU_modrm, 1 + (u_char *) address);
+	  FPU_get_user(FPU_modrm, 1 + (u_char __user *) address);
 	  
 	  if (FPU_modrm >= 0300)
 	    printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
diff -Nru a/arch/i386/math-emu/fpu_arith.c b/arch/i386/math-emu/fpu_arith.c
--- a/arch/i386/math-emu/fpu_arith.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/math-emu/fpu_arith.c	2004-06-23 19:04:28 -07:00
@@ -16,7 +16,7 @@
 #include "status_w.h"
 
 
-void fadd__()
+void fadd__(void)
 {
   /* fadd st,st(i) */
   int i = FPU_rm;
@@ -25,7 +25,7 @@
 }
 
 
-void fmul__()
+void fmul__(void)
 {
   /* fmul st,st(i) */
   int i = FPU_rm;
@@ -35,7 +35,7 @@
 
 
 
-void fsub__()
+void fsub__(void)
 {
   /* fsub st,st(i) */
   clear_C1();
@@ -43,7 +43,7 @@
 }
 
 
-void fsubr_()
+void fsubr_(void)
 {
   /* fsubr st,st(i) */
   clear_C1();
@@ -51,7 +51,7 @@
 }
 
 
-void fdiv__()
+void fdiv__(void)
 {
   /* fdiv st,st(i) */
   clear_C1();
@@ -59,7 +59,7 @@
 }
 
 
-void fdivr_()
+void fdivr_(void)
 {
   /* fdivr st,st(i) */
   clear_C1();
@@ -68,7 +68,7 @@
 
 
 
-void fadd_i()
+void fadd_i(void)
 {
   /* fadd st(i),st */
   int i = FPU_rm;
@@ -77,7 +77,7 @@
 }
 
 
-void fmul_i()
+void fmul_i(void)
 {
   /* fmul st(i),st */
   clear_C1();
@@ -85,7 +85,7 @@
 }
 
 
-void fsubri()
+void fsubri(void)
 {
   /* fsubr st(i),st */
   clear_C1();
@@ -93,7 +93,7 @@
 }
 
 
-void fsub_i()
+void fsub_i(void)
 {
   /* fsub st(i),st */
   clear_C1();
@@ -101,7 +101,7 @@
 }
 
 
-void fdivri()
+void fdivri(void)
 {
   /* fdivr st(i),st */
   clear_C1();
@@ -109,7 +109,7 @@
 }
 
 
-void fdiv_i()
+void fdiv_i(void)
 {
   /* fdiv st(i),st */
   clear_C1();
@@ -118,7 +118,7 @@
 
 
 
-void faddp_()
+void faddp_(void)
 {
   /* faddp st(i),st */
   int i = FPU_rm;
@@ -128,7 +128,7 @@
 }
 
 
-void fmulp_()
+void fmulp_(void)
 {
   /* fmulp st(i),st */
   clear_C1();
@@ -138,7 +138,7 @@
 
 
 
-void fsubrp()
+void fsubrp(void)
 {
   /* fsubrp st(i),st */
   clear_C1();
@@ -147,7 +147,7 @@
 }
 
 
-void fsubp_()
+void fsubp_(void)
 {
   /* fsubp st(i),st */
   clear_C1();
@@ -156,7 +156,7 @@
 }
 
 
-void fdivrp()
+void fdivrp(void)
 {
   /* fdivrp st(i),st */
   clear_C1();
@@ -165,7 +165,7 @@
 }
 
 
-void fdivp_()
+void fdivp_(void)
 {
   /* fdivp st(i),st */
   clear_C1();
diff -Nru a/arch/i386/math-emu/fpu_aux.c b/arch/i386/math-emu/fpu_aux.c
--- a/arch/i386/math-emu/fpu_aux.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/math-emu/fpu_aux.c	2004-06-23 19:04:25 -07:00
@@ -30,7 +30,7 @@
 }
 
 /* Needs to be externally visible */
-void finit()
+void finit(void)
 {
   control_word = 0x037f;
   partial_status = 0;
@@ -58,7 +58,7 @@
   fsetpm, FPU_illegal, FPU_illegal, FPU_illegal
 };
 
-void finit_()
+void finit_(void)
 {
   (finit_table[FPU_rm])();
 }
@@ -75,7 +75,7 @@
   FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal
 };
 
-void fstsw_()
+void fstsw_(void)
 {
   (fstsw_table[FPU_rm])();
 }
@@ -86,13 +86,13 @@
   FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal
 };
 
-void fp_nop()
+void fp_nop(void)
 {
   (fp_nop_table[FPU_rm])();
 }
 
 
-void fld_i_()
+void fld_i_(void)
 {
   FPU_REG *st_new_ptr;
   int i;
@@ -124,7 +124,7 @@
 }
 
 
-void fxch_i()
+void fxch_i(void)
 {
   /* fxch st(i) */
   FPU_REG t;
@@ -173,14 +173,14 @@
 }
 
 
-void ffree_()
+void ffree_(void)
 {
   /* ffree st(i) */
   FPU_settagi(FPU_rm, TAG_Empty);
 }
 
 
-void ffreep()
+void ffreep(void)
 {
   /* ffree st(i) + pop - unofficial code */
   FPU_settagi(FPU_rm, TAG_Empty);
@@ -188,14 +188,14 @@
 }
 
 
-void fst_i_()
+void fst_i_(void)
 {
   /* fst st(i) */
   FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm);
 }
 
 
-void fstp_i()
+void fstp_i(void)
 {
   /* fstp st(i) */
   FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm);
diff -Nru a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c
--- a/arch/i386/math-emu/fpu_entry.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/math-emu/fpu_entry.c	2004-06-23 19:04:28 -07:00
@@ -128,7 +128,7 @@
 u_char emulating=0;
 #endif /* RE_ENTRANT_CHECKING */
 
-static int valid_prefix(u_char *Byte, u_char **fpu_eip,
+static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
 			overrides *override);
 
 asmlinkage void math_emulate(long arg)
@@ -140,7 +140,7 @@
   FPU_REG loaded_data;
   FPU_REG *st0_ptr;
   u_char	  loaded_tag, st0_tag;
-  void *data_address;
+  void __user *data_address;
   struct address data_sel_off;
   struct address entry_sel_off;
   unsigned long code_base = 0;
@@ -192,7 +192,8 @@
 	  math_abort(FPU_info, SIGILL);
 	}
 
-      if ( SEG_D_SIZE(code_descriptor = LDT_DESCRIPTOR(FPU_CS)) )
+      code_descriptor = LDT_DESCRIPTOR(FPU_CS);
+      if ( SEG_D_SIZE(code_descriptor) )
 	{
 	  /* The above test may be wrong, the book is not clear */
 	  /* Segmented 32 bit protected mode */
@@ -214,7 +215,7 @@
   if (current->ptrace & PT_PTRACED)
     FPU_lookahead = 0;
 
-  if ( !valid_prefix(&byte1, (u_char **)&FPU_EIP,
+  if ( !valid_prefix(&byte1, (u_char __user **)&FPU_EIP,
 		     &addr_modes.override) )
     {
       RE_ENTRANT_CHECK_OFF;
@@ -257,7 +258,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_code_verify_area(1);
-  FPU_get_user(FPU_modrm, (u_char *) FPU_EIP);
+  FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
   RE_ENTRANT_CHECK_ON;
   FPU_EIP++;
 
@@ -336,23 +337,23 @@
 	      switch ( (byte1 >> 1) & 3 )
 		{
 		case 0:
-		  unmasked = FPU_load_single((float *)data_address,
+		  unmasked = FPU_load_single((float __user *)data_address,
 					     &loaded_data);
 		  loaded_tag = unmasked & 0xff;
 		  unmasked &= ~0xff;
 		  break;
 		case 1:
-		  loaded_tag = FPU_load_int32((long *)data_address, &loaded_data);
+		  loaded_tag = FPU_load_int32((long __user *)data_address, &loaded_data);
 		  break;
 		case 2:
-		  unmasked = FPU_load_double((double *)data_address,
+		  unmasked = FPU_load_double((double __user *)data_address,
 					     &loaded_data);
 		  loaded_tag = unmasked & 0xff;
 		  unmasked &= ~0xff;
 		  break;
 		case 3:
 		default:  /* Used here to suppress gcc warnings. */
-		  loaded_tag = FPU_load_int16((short *)data_address, &loaded_data);
+		  loaded_tag = FPU_load_int16((short __user *)data_address, &loaded_data);
 		  break;
 		}
 
@@ -563,7 +564,7 @@
   if (FPU_lookahead && !need_resched())
     {
       FPU_ORIG_EIP = FPU_EIP - code_base;
-      if ( valid_prefix(&byte1, (u_char **)&FPU_EIP,
+      if ( valid_prefix(&byte1, (u_char __user **)&FPU_EIP,
 			&addr_modes.override) )
 	goto do_another_FPU_instruction;
     }
@@ -579,11 +580,11 @@
    all prefix bytes, further changes are needed in the emulator code
    which accesses user address space. Access to separate segments is
    important for msdos emulation. */
-static int valid_prefix(u_char *Byte, u_char **fpu_eip,
+static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
 			overrides *override)
 {
   u_char byte;
-  u_char *ip = *fpu_eip;
+  u_char __user *ip = *fpu_eip;
 
   *override = (overrides) { 0, 0, PREFIX_DEFAULT };       /* defaults */
 
@@ -679,9 +680,9 @@
 #define sstatus_word() \
   ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
 
-int restore_i387_soft(void *s387, struct _fpstate *buf)
+int restore_i387_soft(void *s387, struct _fpstate __user *buf)
 {
-  u_char *d = (u_char *)buf;
+  u_char __user *d = (u_char __user *)buf;
   int offset, other, i, tags, regnr, tag, newtop;
 
   RE_ENTRANT_CHECK_OFF;
@@ -725,9 +726,9 @@
 }
 
 
-int save_i387_soft(void *s387, struct _fpstate * buf)
+int save_i387_soft(void *s387, struct _fpstate __user * buf)
 {
-  u_char *d = (u_char *)buf;
+  u_char __user *d = (u_char __user *)buf;
   int offset = (S387->ftop & 7) * 10, other = 80 - offset;
 
   RE_ENTRANT_CHECK_OFF;
diff -Nru a/arch/i386/math-emu/fpu_etc.c b/arch/i386/math-emu/fpu_etc.c
--- a/arch/i386/math-emu/fpu_etc.c	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/math-emu/fpu_etc.c	2004-06-23 19:04:26 -07:00
@@ -137,7 +137,7 @@
   ftst_, fxam, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal
 };
 
-void FPU_etc()
+void FPU_etc(void)
 {
   (fp_etc_table[FPU_rm])(&st(0), FPU_gettag0());
 }
diff -Nru a/arch/i386/math-emu/fpu_proto.h b/arch/i386/math-emu/fpu_proto.h
--- a/arch/i386/math-emu/fpu_proto.h	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/math-emu/fpu_proto.h	2004-06-23 19:04:28 -07:00
@@ -77,13 +77,13 @@
 extern void FPU_triga(void);
 extern void FPU_trigb(void);
 /* get_address.c */
-extern void *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
+extern void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
 			 struct address *addr, fpu_addr_modes addr_modes);
-extern void *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
+extern void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
 			    struct address *addr, fpu_addr_modes addr_modes);
 /* load_store.c */
 extern int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
-			    void *data_address);
+			    void __user *data_address);
 /* poly_2xm1.c */
 extern int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result);
 /* poly_atan.c */
@@ -112,26 +112,26 @@
 /* reg_constant.c */
 extern void fconst(void);
 /* reg_ld_str.c */
-extern int FPU_load_extended(long double *s, int stnr);
-extern int FPU_load_double(double *dfloat, FPU_REG *loaded_data);
-extern int FPU_load_single(float *single, FPU_REG *loaded_data);
-extern int FPU_load_int64(long long *_s);
-extern int FPU_load_int32(long *_s, FPU_REG *loaded_data);
-extern int FPU_load_int16(short *_s, FPU_REG *loaded_data);
-extern int FPU_load_bcd(u_char *s);
+extern int FPU_load_extended(long double __user *s, int stnr);
+extern int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data);
+extern int FPU_load_single(float __user *single, FPU_REG *loaded_data);
+extern int FPU_load_int64(long long __user *_s);
+extern int FPU_load_int32(long __user *_s, FPU_REG *loaded_data);
+extern int FPU_load_int16(short __user *_s, FPU_REG *loaded_data);
+extern int FPU_load_bcd(u_char __user *s);
 extern int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag,
-			      long double *d);
-extern int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double *dfloat);
-extern int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float *single);
-extern int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long *d);
-extern int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long *d);
-extern int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short *d);
-extern int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char *d);
+			      long double __user *d);
+extern int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat);
+extern int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single);
+extern int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d);
+extern int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d);
+extern int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d);
+extern int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d);
 extern int FPU_round_to_int(FPU_REG *r, u_char tag);
-extern u_char *fldenv(fpu_addr_modes addr_modes, u_char *s);
-extern void frstor(fpu_addr_modes addr_modes, u_char *data_address);
-extern u_char *fstenv(fpu_addr_modes addr_modes, u_char *d);
-extern void fsave(fpu_addr_modes addr_modes, u_char *data_address);
+extern u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s);
+extern void frstor(fpu_addr_modes addr_modes, u_char __user *data_address);
+extern u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d);
+extern void fsave(fpu_addr_modes addr_modes, u_char __user *data_address);
 extern int FPU_tagof(FPU_REG *ptr);
 /* reg_mul.c */
 extern int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w);
diff -Nru a/arch/i386/math-emu/fpu_system.h b/arch/i386/math-emu/fpu_system.h
--- a/arch/i386/math-emu/fpu_system.h	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/math-emu/fpu_system.h	2004-06-23 19:04:26 -07:00
@@ -80,7 +80,7 @@
 /* A simpler test than verify_area() can probably be done for
    FPU_code_verify_area() because the only possible error is to step
    past the upper boundary of a legal code area. */
-#define	FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void *)FPU_EIP,z)
+#define	FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void __user *)FPU_EIP,z)
 #endif
 
 #define FPU_get_user(x,y)       get_user((x),(y))
diff -Nru a/arch/i386/math-emu/get_address.c b/arch/i386/math-emu/get_address.c
--- a/arch/i386/math-emu/get_address.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/math-emu/get_address.c	2004-06-23 19:04:28 -07:00
@@ -82,7 +82,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_code_verify_area(1);
-  FPU_get_user(base, (u_char *) (*fpu_eip));   /* The SIB byte */
+  FPU_get_user(base, (u_char __user *) (*fpu_eip));   /* The SIB byte */
   RE_ENTRANT_CHECK_ON;
   (*fpu_eip)++;
   ss = base >> 6;
@@ -112,7 +112,7 @@
       long displacement;
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(1);
-      FPU_get_user(displacement, (signed char *) (*fpu_eip));
+      FPU_get_user(displacement, (signed char __user *) (*fpu_eip));
       offset += displacement;
       RE_ENTRANT_CHECK_ON;
       (*fpu_eip)++;
@@ -123,7 +123,7 @@
       long displacement;
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(4);
-      FPU_get_user(displacement, (long *) (*fpu_eip));
+      FPU_get_user(displacement, (long __user *) (*fpu_eip));
       offset += displacement;
       RE_ENTRANT_CHECK_ON;
       (*fpu_eip) += 4;
@@ -241,7 +241,7 @@
 
 */
 
-void *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
+void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
 		  struct address *addr,
 		  fpu_addr_modes addr_modes)
 {
@@ -277,24 +277,24 @@
 	      /* Special case: disp32 */
 	      RE_ENTRANT_CHECK_OFF;
 	      FPU_code_verify_area(4);
-	      FPU_get_user(address, (unsigned long *) (*fpu_eip));
+	      FPU_get_user(address, (unsigned long __user *) (*fpu_eip));
 	      (*fpu_eip) += 4;
 	      RE_ENTRANT_CHECK_ON;
 	      addr->offset = address;
-	      return (void *) address;
+	      return (void __user *) address;
 	    }
 	  else
 	    {
 	      address = *cpu_reg_ptr;  /* Just return the contents
 					  of the cpu register */
 	      addr->offset = address;
-	      return (void *) address;
+	      return (void __user *) address;
 	    }
 	case 1:
 	  /* 8 bit signed displacement */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(1);
-	  FPU_get_user(address, (signed char *) (*fpu_eip));
+	  FPU_get_user(address, (signed char __user *) (*fpu_eip));
 	  RE_ENTRANT_CHECK_ON;
 	  (*fpu_eip)++;
 	  break;
@@ -302,7 +302,7 @@
 	  /* 32 bit displacement */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(4);
-	  FPU_get_user(address, (long *) (*fpu_eip));
+	  FPU_get_user(address, (long __user *) (*fpu_eip));
 	  (*fpu_eip) += 4;
 	  RE_ENTRANT_CHECK_ON;
 	  break;
@@ -331,11 +331,11 @@
       EXCEPTION(EX_INTERNAL|0x133);
     }
 
-  return (void *)address;
+  return (void __user *)address;
 }
 
 
-void *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
+void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
 		     struct address *addr,
 		     fpu_addr_modes addr_modes)
 {
@@ -363,7 +363,7 @@
 	  /* Special case: disp16 */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(2);
-	  FPU_get_user(address, (unsigned short *) (*fpu_eip));
+	  FPU_get_user(address, (unsigned short __user *) (*fpu_eip));
 	  (*fpu_eip) += 2;
 	  RE_ENTRANT_CHECK_ON;
 	  goto add_segment;
@@ -373,7 +373,7 @@
       /* 8 bit signed displacement */
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(1);
-      FPU_get_user(address, (signed char *) (*fpu_eip));
+      FPU_get_user(address, (signed char __user *) (*fpu_eip));
       RE_ENTRANT_CHECK_ON;
       (*fpu_eip)++;
       break;
@@ -381,7 +381,7 @@
       /* 16 bit displacement */
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(2);
-      FPU_get_user(address, (unsigned short *) (*fpu_eip));
+      FPU_get_user(address, (unsigned short __user *) (*fpu_eip));
       (*fpu_eip) += 2;
       RE_ENTRANT_CHECK_ON;
       break;
@@ -445,5 +445,5 @@
       EXCEPTION(EX_INTERNAL|0x131);
     }
 
-  return (void *)address ;
+  return (void __user *)address ;
 }
diff -Nru a/arch/i386/math-emu/load_store.c b/arch/i386/math-emu/load_store.c
--- a/arch/i386/math-emu/load_store.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/math-emu/load_store.c	2004-06-23 19:04:25 -07:00
@@ -61,7 +61,7 @@
 };
 
 int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
-		     void *data_address)
+		     void __user *data_address)
 {
   FPU_REG loaded_data;
   FPU_REG *st0_ptr;
@@ -119,7 +119,7 @@
     {
     case 000:       /* fld m32real */
       clear_C1();
-      loaded_tag = FPU_load_single((float *)data_address, &loaded_data);
+      loaded_tag = FPU_load_single((float __user *)data_address, &loaded_data);
       if ( (loaded_tag == TAG_Special)
 	   && isNaN(&loaded_data)
 	   && (real_1op_NaN(&loaded_data) < 0) )
@@ -131,12 +131,12 @@
       break;
     case 001:      /* fild m32int */
       clear_C1();
-      loaded_tag = FPU_load_int32((long *)data_address, &loaded_data);
+      loaded_tag = FPU_load_int32((long __user *)data_address, &loaded_data);
       FPU_copy_to_reg0(&loaded_data, loaded_tag);
       break;
     case 002:      /* fld m64real */
       clear_C1();
-      loaded_tag = FPU_load_double((double *)data_address, &loaded_data);
+      loaded_tag = FPU_load_double((double __user *)data_address, &loaded_data);
       if ( (loaded_tag == TAG_Special)
 	   && isNaN(&loaded_data)
 	   && (real_1op_NaN(&loaded_data) < 0) )
@@ -148,68 +148,68 @@
       break;
     case 003:      /* fild m16int */
       clear_C1();
-      loaded_tag = FPU_load_int16((short *)data_address, &loaded_data);
+      loaded_tag = FPU_load_int16((short __user *)data_address, &loaded_data);
       FPU_copy_to_reg0(&loaded_data, loaded_tag);
       break;
     case 010:      /* fst m32real */
       clear_C1();
-      FPU_store_single(st0_ptr, st0_tag, (float *)data_address);
+      FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address);
       break;
     case 011:      /* fist m32int */
       clear_C1();
-      FPU_store_int32(st0_ptr, st0_tag, (long *)data_address);
+      FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address);
       break;
     case 012:     /* fst m64real */
       clear_C1();
-      FPU_store_double(st0_ptr, st0_tag, (double *)data_address);
+      FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address);
       break;
     case 013:     /* fist m16int */
       clear_C1();
-      FPU_store_int16(st0_ptr, st0_tag, (short *)data_address);
+      FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address);
       break;
     case 014:     /* fstp m32real */
       clear_C1();
-      if ( FPU_store_single(st0_ptr, st0_tag, (float *)data_address) )
+      if ( FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 015:     /* fistp m32int */
       clear_C1();
-      if ( FPU_store_int32(st0_ptr, st0_tag, (long *)data_address) )
+      if ( FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 016:     /* fstp m64real */
       clear_C1();
-      if ( FPU_store_double(st0_ptr, st0_tag, (double *)data_address) )
+      if ( FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 017:     /* fistp m16int */
       clear_C1();
-      if ( FPU_store_int16(st0_ptr, st0_tag, (short *)data_address) )
+      if ( FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 020:     /* fldenv  m14/28byte */
-      fldenv(addr_modes, (u_char *)data_address);
+      fldenv(addr_modes, (u_char __user *)data_address);
       /* Ensure that the values just loaded are not changed by
 	 fix-up operations. */
       return 1;
     case 022:     /* frstor m94/108byte */
-      frstor(addr_modes, (u_char *)data_address);
+      frstor(addr_modes, (u_char __user *)data_address);
       /* Ensure that the values just loaded are not changed by
 	 fix-up operations. */
       return 1;
     case 023:     /* fbld m80dec */
       clear_C1();
-      loaded_tag = FPU_load_bcd((u_char *)data_address);
+      loaded_tag = FPU_load_bcd((u_char __user *)data_address);
       FPU_settag0(loaded_tag);
       break;
     case 024:     /* fldcw */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_READ, data_address, 2);
-      FPU_get_user(control_word, (unsigned short *) data_address);
+      FPU_get_user(control_word, (unsigned short __user *) data_address);
       RE_ENTRANT_CHECK_ON;
       if ( partial_status & ~control_word & CW_Exceptions )
 	partial_status |= (SW_Summary | SW_Backward);
@@ -221,47 +221,47 @@
       return 1;
     case 025:      /* fld m80real */
       clear_C1();
-      loaded_tag = FPU_load_extended((long double *)data_address, 0);
+      loaded_tag = FPU_load_extended((long double __user *)data_address, 0);
       FPU_settag0(loaded_tag);
       break;
     case 027:      /* fild m64int */
       clear_C1();
-      loaded_tag = FPU_load_int64((long long *)data_address);
+      loaded_tag = FPU_load_int64((long long __user *)data_address);
       FPU_settag0(loaded_tag);
       break;
     case 030:     /* fstenv  m14/28byte */
-      fstenv(addr_modes, (u_char *)data_address);
+      fstenv(addr_modes, (u_char __user *)data_address);
       return 1;
     case 032:      /* fsave */
-      fsave(addr_modes, (u_char *)data_address);
+      fsave(addr_modes, (u_char __user *)data_address);
       return 1;
     case 033:      /* fbstp m80dec */
       clear_C1();
-      if ( FPU_store_bcd(st0_ptr, st0_tag, (u_char *)data_address) )
+      if ( FPU_store_bcd(st0_ptr, st0_tag, (u_char __user *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 034:      /* fstcw m16int */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,data_address,2);
-      FPU_put_user(control_word, (unsigned short *) data_address);
+      FPU_put_user(control_word, (unsigned short __user *) data_address);
       RE_ENTRANT_CHECK_ON;
       return 1;
     case 035:      /* fstp m80real */
       clear_C1();
-      if ( FPU_store_extended(st0_ptr, st0_tag, (long double *)data_address) )
+      if ( FPU_store_extended(st0_ptr, st0_tag, (long double __user *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 036:      /* fstsw m2byte */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,data_address,2);
-      FPU_put_user(status_word(),(unsigned short *) data_address);
+      FPU_put_user(status_word(),(unsigned short __user *) data_address);
       RE_ENTRANT_CHECK_ON;
       return 1;
     case 037:      /* fistp m64int */
       clear_C1();
-      if ( FPU_store_int64(st0_ptr, st0_tag, (long long *)data_address) )
+      if ( FPU_store_int64(st0_ptr, st0_tag, (long long __user *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
diff -Nru a/arch/i386/math-emu/reg_compare.c b/arch/i386/math-emu/reg_compare.c
--- a/arch/i386/math-emu/reg_compare.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/math-emu/reg_compare.c	2004-06-23 19:04:28 -07:00
@@ -324,14 +324,14 @@
 
 /*---------------------------------------------------------------------------*/
 
-void fcom_st()
+void fcom_st(void)
 {
   /* fcom st(i) */
   compare_st_st(FPU_rm);
 }
 
 
-void fcompst()
+void fcompst(void)
 {
   /* fcomp st(i) */
   if ( !compare_st_st(FPU_rm) )
@@ -339,7 +339,7 @@
 }
 
 
-void fcompp()
+void fcompp(void)
 {
   /* fcompp */
   if (FPU_rm != 1)
@@ -352,7 +352,7 @@
 }
 
 
-void fucom_()
+void fucom_(void)
 {
   /* fucom st(i) */
   compare_u_st_st(FPU_rm);
@@ -360,7 +360,7 @@
 }
 
 
-void fucomp()
+void fucomp(void)
 {
   /* fucomp st(i) */
   if ( !compare_u_st_st(FPU_rm) )
@@ -368,7 +368,7 @@
 }
 
 
-void fucompp()
+void fucompp(void)
 {
   /* fucompp */
   if (FPU_rm == 1)
diff -Nru a/arch/i386/math-emu/reg_ld_str.c b/arch/i386/math-emu/reg_ld_str.c
--- a/arch/i386/math-emu/reg_ld_str.c	2004-06-23 19:04:27 -07:00
+++ b/arch/i386/math-emu/reg_ld_str.c	2004-06-23 19:04:27 -07:00
@@ -86,7 +86,7 @@
 
 
 /* Get a long double from user memory */
-int FPU_load_extended(long double *s, int stnr)
+int FPU_load_extended(long double __user *s, int stnr)
 {
   FPU_REG *sti_ptr = &st(stnr);
 
@@ -100,15 +100,15 @@
 
 
 /* Get a double from user memory */
-int FPU_load_double(double *dfloat, FPU_REG *loaded_data)
+int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data)
 {
   int exp, tag, negative;
   unsigned m64, l64;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, dfloat, 8);
-  FPU_get_user(m64, 1 + (unsigned long *) dfloat);
-  FPU_get_user(l64, (unsigned long *) dfloat);
+  FPU_get_user(m64, 1 + (unsigned long __user *) dfloat);
+  FPU_get_user(l64, (unsigned long __user *) dfloat);
   RE_ENTRANT_CHECK_ON;
 
   negative = (m64 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
@@ -172,14 +172,14 @@
 
 
 /* Get a float from user memory */
-int FPU_load_single(float *single, FPU_REG *loaded_data)
+int FPU_load_single(float __user *single, FPU_REG *loaded_data)
 {
   unsigned m32;
   int exp, tag, negative;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, single, 4);
-  FPU_get_user(m32, (unsigned long *) single);
+  FPU_get_user(m32, (unsigned long __user *) single);
   RE_ENTRANT_CHECK_ON;
 
   negative = (m32 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
@@ -236,7 +236,7 @@
 
 
 /* Get a long long from user memory */
-int FPU_load_int64(long long *_s)
+int FPU_load_int64(long long __user *_s)
 {
   long long s;
   int sign;
@@ -268,7 +268,7 @@
 
 
 /* Get a long from user memory */
-int FPU_load_int32(long *_s, FPU_REG *loaded_data)
+int FPU_load_int32(long __user *_s, FPU_REG *loaded_data)
 {
   long s;
   int negative;
@@ -297,7 +297,7 @@
 
 
 /* Get a short from user memory */
-int FPU_load_int16(short *_s, FPU_REG *loaded_data)
+int FPU_load_int16(short __user *_s, FPU_REG *loaded_data)
 {
   int s, negative;
 
@@ -326,7 +326,7 @@
 
 
 /* Get a packed bcd array from user memory */
-int FPU_load_bcd(u_char *s)
+int FPU_load_bcd(u_char __user *s)
 {
   FPU_REG *st0_ptr = &st(0);
   int pos;
@@ -341,7 +341,7 @@
     {
       l *= 10;
       RE_ENTRANT_CHECK_OFF;
-      FPU_get_user(bcd, (u_char *) s+pos);
+      FPU_get_user(bcd, s+pos);
       RE_ENTRANT_CHECK_ON;
       l += bcd >> 4;
       l *= 10;
@@ -349,7 +349,7 @@
     }
  
   RE_ENTRANT_CHECK_OFF;
-  FPU_get_user(sign, (u_char *) s+9);
+  FPU_get_user(sign, s+9);
   sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive;
   RE_ENTRANT_CHECK_ON;
 
@@ -369,7 +369,7 @@
 /*===========================================================================*/
 
 /* Put a long double into user memory */
-int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double *d)
+int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user *d)
 {
   /*
     The only exception raised by an attempt to store to an
@@ -382,9 +382,9 @@
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE, d, 10);
 
-      FPU_put_user(st0_ptr->sigl, (unsigned long *) d);
-      FPU_put_user(st0_ptr->sigh, (unsigned long *) ((u_char *)d + 4));
-      FPU_put_user(exponent16(st0_ptr), (unsigned short *) ((u_char *)d + 8));
+      FPU_put_user(st0_ptr->sigl, (unsigned long __user *) d);
+      FPU_put_user(st0_ptr->sigh, (unsigned long __user *) ((u_char __user *)d + 4));
+      FPU_put_user(exponent16(st0_ptr), (unsigned short __user *) ((u_char __user *)d + 8));
       RE_ENTRANT_CHECK_ON;
 
       return 1;
@@ -398,9 +398,9 @@
       /* Put out the QNaN indefinite */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,d,10);
-      FPU_put_user(0, (unsigned long *) d);
-      FPU_put_user(0xc0000000, 1 + (unsigned long *) d);
-      FPU_put_user(0xffff, 4 + (short *) d);
+      FPU_put_user(0, (unsigned long __user *) d);
+      FPU_put_user(0xc0000000, 1 + (unsigned long __user *) d);
+      FPU_put_user(0xffff, 4 + (short __user *) d);
       RE_ENTRANT_CHECK_ON;
       return 1;
     }
@@ -411,7 +411,7 @@
 
 
 /* Put a double into user memory */
-int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double *dfloat)
+int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
 {
   unsigned long l[2];
   unsigned long increment = 0;	/* avoid gcc warnings */
@@ -607,9 +607,9 @@
 	  /* The masked response */
 	  /* Put out the QNaN indefinite */
 	  RE_ENTRANT_CHECK_OFF;
-	  FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8);
-	  FPU_put_user(0, (unsigned long *) dfloat);
-	  FPU_put_user(0xfff80000, 1 + (unsigned long *) dfloat);
+	  FPU_verify_area(VERIFY_WRITE,dfloat,8);
+	  FPU_put_user(0, (unsigned long __user *) dfloat);
+	  FPU_put_user(0xfff80000, 1 + (unsigned long __user *) dfloat);
 	  RE_ENTRANT_CHECK_ON;
 	  return 1;
 	}
@@ -620,9 +620,9 @@
     l[1] |= 0x80000000;
 
   RE_ENTRANT_CHECK_OFF;
-  FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8);
-  FPU_put_user(l[0], (unsigned long *)dfloat);
-  FPU_put_user(l[1], 1 + (unsigned long *)dfloat);
+  FPU_verify_area(VERIFY_WRITE,dfloat,8);
+  FPU_put_user(l[0], (unsigned long __user *)dfloat);
+  FPU_put_user(l[1], 1 + (unsigned long __user *)dfloat);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -630,7 +630,7 @@
 
 
 /* Put a float into user memory */
-int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float *single)
+int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single)
 {
   long templ = 0;
   unsigned long increment = 0;     	/* avoid gcc warnings */
@@ -826,8 +826,8 @@
 	  /* The masked response */
 	  /* Put out the QNaN indefinite */
 	  RE_ENTRANT_CHECK_OFF;
-	  FPU_verify_area(VERIFY_WRITE,(void *)single,4);
-	  FPU_put_user(0xffc00000, (unsigned long *) single);
+	  FPU_verify_area(VERIFY_WRITE,single,4);
+	  FPU_put_user(0xffc00000, (unsigned long __user *) single);
 	  RE_ENTRANT_CHECK_ON;
 	  return 1;
 	}
@@ -845,8 +845,8 @@
     templ |= 0x80000000;
 
   RE_ENTRANT_CHECK_OFF;
-  FPU_verify_area(VERIFY_WRITE,(void *)single,4);
-  FPU_put_user(templ,(unsigned long *) single);
+  FPU_verify_area(VERIFY_WRITE,single,4);
+  FPU_put_user(templ,(unsigned long __user *) single);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -854,7 +854,7 @@
 
 
 /* Put a long long into user memory */
-int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long *d)
+int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d)
 {
   FPU_REG t;
   long long tll;
@@ -906,7 +906,7 @@
     }
 
   RE_ENTRANT_CHECK_OFF;
-  FPU_verify_area(VERIFY_WRITE,(void *)d,8);
+  FPU_verify_area(VERIFY_WRITE,d,8);
   copy_to_user(d, &tll, 8);
   RE_ENTRANT_CHECK_ON;
 
@@ -915,7 +915,7 @@
 
 
 /* Put a long into user memory */
-int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long *d)
+int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d)
 {
   FPU_REG t;
   int precision_loss;
@@ -964,7 +964,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,d,4);
-  FPU_put_user(t.sigl, (unsigned long *) d);
+  FPU_put_user(t.sigl, (unsigned long __user *) d);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -972,7 +972,7 @@
 
 
 /* Put a short into user memory */
-int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short *d)
+int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d)
 {
   FPU_REG t;
   int precision_loss;
@@ -1021,7 +1021,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,d,2);
-  FPU_put_user((short)t.sigl,(short *) d);
+  FPU_put_user((short)t.sigl, d);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -1029,7 +1029,7 @@
 
 
 /* Put a packed bcd array into user memory */
-int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char *d)
+int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d)
 {
   FPU_REG t;
   unsigned long long ll;
@@ -1071,10 +1071,10 @@
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_verify_area(VERIFY_WRITE,d,10);
 	  for ( i = 0; i < 7; i++)
-	    FPU_put_user(0, (u_char *) d+i); /* These bytes "undefined" */
-	  FPU_put_user(0xc0, (u_char *) d+7); /* This byte "undefined" */
-	  FPU_put_user(0xff, (u_char *) d+8);
-	  FPU_put_user(0xff, (u_char *) d+9);
+	    FPU_put_user(0, d+i); /* These bytes "undefined" */
+	  FPU_put_user(0xc0, d+7); /* This byte "undefined" */
+	  FPU_put_user(0xff, d+8);
+	  FPU_put_user(0xff, d+9);
 	  RE_ENTRANT_CHECK_ON;
 	  return 1;
 	}
@@ -1095,11 +1095,11 @@
       b = FPU_div_small(&ll, 10);
       b |= (FPU_div_small(&ll, 10)) << 4;
       RE_ENTRANT_CHECK_OFF;
-      FPU_put_user(b,(u_char *) d+i);
+      FPU_put_user(b, d+i);
       RE_ENTRANT_CHECK_ON;
     }
   RE_ENTRANT_CHECK_OFF;
-  FPU_put_user(sign,(u_char *) d+9);
+  FPU_put_user(sign, d+9);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -1175,7 +1175,7 @@
 
 /*===========================================================================*/
 
-u_char *fldenv(fpu_addr_modes addr_modes, u_char *s)
+u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s)
 {
   unsigned short tag_word = 0;
   u_char tag;
@@ -1187,13 +1187,13 @@
     {
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_READ, s, 0x0e);
-      FPU_get_user(control_word, (unsigned short *) s);
-      FPU_get_user(partial_status, (unsigned short *) (s+2));
-      FPU_get_user(tag_word, (unsigned short *) (s+4));
-      FPU_get_user(instruction_address.offset, (unsigned short *) (s+6));
-      FPU_get_user(instruction_address.selector, (unsigned short *) (s+8));
-      FPU_get_user(operand_address.offset, (unsigned short *) (s+0x0a));
-      FPU_get_user(operand_address.selector, (unsigned short *) (s+0x0c));
+      FPU_get_user(control_word, (unsigned short __user *) s);
+      FPU_get_user(partial_status, (unsigned short __user *) (s+2));
+      FPU_get_user(tag_word, (unsigned short __user *) (s+4));
+      FPU_get_user(instruction_address.offset, (unsigned short __user *) (s+6));
+      FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+8));
+      FPU_get_user(operand_address.offset, (unsigned short __user *) (s+0x0a));
+      FPU_get_user(operand_address.selector, (unsigned short __user *) (s+0x0c));
       RE_ENTRANT_CHECK_ON;
       s += 0x0e;
       if ( addr_modes.default_mode == VM86 )
@@ -1207,14 +1207,14 @@
     {
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_READ, s, 0x1c);
-      FPU_get_user(control_word, (unsigned short *) s);
-      FPU_get_user(partial_status, (unsigned short *) (s+4));
-      FPU_get_user(tag_word, (unsigned short *) (s+8));
-      FPU_get_user(instruction_address.offset, (unsigned long *) (s+0x0c));
-      FPU_get_user(instruction_address.selector, (unsigned short *) (s+0x10));
-      FPU_get_user(instruction_address.opcode, (unsigned short *) (s+0x12));
-      FPU_get_user(operand_address.offset, (unsigned long *) (s+0x14));
-      FPU_get_user(operand_address.selector, (unsigned long *) (s+0x18));
+      FPU_get_user(control_word, (unsigned short __user *) s);
+      FPU_get_user(partial_status, (unsigned short __user *) (s+4));
+      FPU_get_user(tag_word, (unsigned short __user *) (s+8));
+      FPU_get_user(instruction_address.offset, (unsigned long __user *) (s+0x0c));
+      FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+0x10));
+      FPU_get_user(instruction_address.opcode, (unsigned short __user *) (s+0x12));
+      FPU_get_user(operand_address.offset, (unsigned long __user *) (s+0x14));
+      FPU_get_user(operand_address.selector, (unsigned long __user *) (s+0x18));
       RE_ENTRANT_CHECK_ON;
       s += 0x1c;
     }
@@ -1266,10 +1266,10 @@
 }
 
 
-void frstor(fpu_addr_modes addr_modes, u_char *data_address)
+void frstor(fpu_addr_modes addr_modes, u_char __user *data_address)
 {
   int i, regnr;
-  u_char *s = fldenv(addr_modes, data_address);
+  u_char __user *s = fldenv(addr_modes, data_address);
   int offset = (top & 7) * 10, other = 80 - offset;
 
   /* Copy all registers in stack order. */
@@ -1291,7 +1291,7 @@
 }
 
 
-u_char *fstenv(fpu_addr_modes addr_modes, u_char *d)
+u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
 {
   if ( (addr_modes.default_mode == VM86) ||
       ((addr_modes.default_mode == PM16)
@@ -1300,25 +1300,25 @@
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,d,14);
 #ifdef PECULIAR_486
-      FPU_put_user(control_word & ~0xe080, (unsigned long *) d);
+      FPU_put_user(control_word & ~0xe080, (unsigned long __user *) d);
 #else
-      FPU_put_user(control_word, (unsigned short *) d);
+      FPU_put_user(control_word, (unsigned short __user *) d);
 #endif /* PECULIAR_486 */
-      FPU_put_user(status_word(), (unsigned short *) (d+2));
-      FPU_put_user(fpu_tag_word, (unsigned short *) (d+4));
-      FPU_put_user(instruction_address.offset, (unsigned short *) (d+6));
-      FPU_put_user(operand_address.offset, (unsigned short *) (d+0x0a));
+      FPU_put_user(status_word(), (unsigned short __user *) (d+2));
+      FPU_put_user(fpu_tag_word, (unsigned short __user *) (d+4));
+      FPU_put_user(instruction_address.offset, (unsigned short __user *) (d+6));
+      FPU_put_user(operand_address.offset, (unsigned short __user *) (d+0x0a));
       if ( addr_modes.default_mode == VM86 )
 	{
 	  FPU_put_user((instruction_address.offset & 0xf0000) >> 4,
-		      (unsigned short *) (d+8));
+		      (unsigned short __user *) (d+8));
 	  FPU_put_user((operand_address.offset & 0xf0000) >> 4,
-		      (unsigned short *) (d+0x0c));
+		      (unsigned short __user *) (d+0x0c));
 	}
       else
 	{
-	  FPU_put_user(instruction_address.selector, (unsigned short *) (d+8));
-	  FPU_put_user(operand_address.selector, (unsigned short *) (d+0x0c));
+	  FPU_put_user(instruction_address.selector, (unsigned short __user *) (d+8));
+	  FPU_put_user(operand_address.selector, (unsigned short __user *) (d+0x0c));
 	}
       RE_ENTRANT_CHECK_ON;
       d += 0x0e;
@@ -1348,9 +1348,9 @@
 }
 
 
-void fsave(fpu_addr_modes addr_modes, u_char *data_address)
+void fsave(fpu_addr_modes addr_modes, u_char __user *data_address)
 {
-  u_char *d;
+  u_char __user *d;
   int offset = (top & 7) * 10, other = 80 - offset;
 
   d = fstenv(addr_modes, data_address);
diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
--- a/arch/i386/mm/fault.c	2004-06-23 19:04:25 -07:00
+++ b/arch/i386/mm/fault.c	2004-06-23 19:04:25 -07:00
@@ -24,7 +24,6 @@
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/hardirq.h>
 #include <asm/desc.h>
 
diff -Nru a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
--- a/arch/i386/mm/hugetlbpage.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/mm/hugetlbpage.c	2004-06-23 19:04:28 -07:00
@@ -15,7 +15,6 @@
 #include <linux/err.h>
 #include <linux/sysctl.h>
 #include <asm/mman.h>
-#include <asm/pgalloc.h>
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
@@ -245,8 +244,15 @@
 			ret = -ENOMEM;
 			goto out;
 		}
-		if (!pte_none(*pte))
-			continue;
+
+		if (!pte_none(*pte)) {
+			pmd_t *pmd = (pmd_t *) pte;
+
+			page = pmd_page(*pmd);
+			pmd_clear(pmd);
+			dec_page_state(nr_page_table_pages);
+			page_cache_release(page);
+		}
 
 		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
 			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/mm/init.c	2004-06-23 19:04:28 -07:00
@@ -32,7 +32,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/pgalloc.h>
 #include <asm/dma.h>
 #include <asm/fixmap.h>
 #include <asm/e820.h>
diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
--- a/arch/i386/mm/ioremap.c	2004-06-23 19:04:26 -07:00
+++ b/arch/i386/mm/ioremap.c	2004-06-23 19:04:26 -07:00
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <asm/io.h>
-#include <asm/pgalloc.h>
 #include <asm/fixmap.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
diff -Nru a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c
--- a/arch/i386/pci/acpi.c	2004-06-23 19:04:27 -07:00
+++ b/arch/i386/pci/acpi.c	2004-06-23 19:04:27 -07:00
@@ -1,6 +1,8 @@
 #include <linux/pci.h>
 #include <linux/acpi.h>
 #include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/hw_irq.h>
 #include "pci.h"
 
 struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
@@ -15,18 +17,31 @@
 
 static int __init pci_acpi_init(void)
 {
+	struct pci_dev *dev = NULL;
+
 	if (pcibios_scanned)
 		return 0;
 
-	if (!acpi_noirq) {
-		if (!acpi_pci_irq_init()) {
-			printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-			pcibios_scanned++;
-			pcibios_enable_irq = acpi_pci_irq_enable;
-		} else
-			printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");
+	if (acpi_noirq)
+		return 0;
 
-	}
+	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
+	acpi_irq_penalty_init();
+	pcibios_scanned++;
+	pcibios_enable_irq = acpi_pci_irq_enable;
+
+	/*
+	 * PCI IRQ routing is set up by pci_enable_device(), but we
+	 * also do it here in case there are still broken drivers that
+	 * don't use pci_enable_device().
+	 */
+	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+		acpi_pci_irq_enable(dev);
+
+#ifdef CONFIG_X86_IO_APIC
+	if (acpi_ioapic)
+		print_IO_APIC();
+#endif
 
 	return 0;
 }
diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
--- a/arch/i386/pci/irq.c	2004-06-23 19:04:29 -07:00
+++ b/arch/i386/pci/irq.c	2004-06-23 19:04:29 -07:00
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/dmi.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/io_apic.h>
@@ -22,7 +23,7 @@
 #define PIRQ_SIGNATURE	(('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
 #define PIRQ_VERSION 0x0100
 
-int broken_hp_bios_irq9;
+static int broken_hp_bios_irq9;
 
 static struct irq_routing_table *pirq_table;
 
@@ -893,6 +894,33 @@
 	}
 }
 
+/*
+ * Work around broken HP Pavilion Notebooks which assign USB to
+ * IRQ 9 even though it is actually wired to IRQ 11
+ */
+static int __init fix_broken_hp_bios_irq9(struct dmi_system_id *d)
+{
+	if (!broken_hp_bios_irq9) {
+		broken_hp_bios_irq9 = 1;
+		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
+	}
+	return 0;
+}
+
+static struct dmi_system_id __initdata pciirq_dmi_table[] = {
+	{
+		.callback = fix_broken_hp_bios_irq9,
+		.ident = "HP Pavilion N5400 Series Laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
+			DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
+		},
+	},
+	{ }
+};
+
 static int __init pcibios_irq_init(void)
 {
 	DBG("PCI: IRQ init\n");
@@ -900,6 +928,8 @@
 	if (pcibios_enable_irq || raw_pci_ops == NULL)
 		return 0;
 
+	dmi_check_system(pciirq_dmi_table);
+
 	pirq_table = pirq_find_routing_table();
 
 #ifdef CONFIG_PCI_BIOS
@@ -1000,7 +1030,7 @@
 	/* VIA bridges use interrupt line for apic/pci steering across
 	   the V-Link */
 	else if (interrupt_line_quirk)
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15);
 	return 0;
 }
 
diff -Nru a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c
--- a/arch/i386/pci/visws.c	2004-06-23 19:04:28 -07:00
+++ b/arch/i386/pci/visws.c	2004-06-23 19:04:28 -07:00
@@ -15,8 +15,6 @@
 #include "pci.h"
 
 
-int broken_hp_bios_irq9;
-
 extern struct pci_raw_ops pci_direct_conf1;
 
 static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/arch/ia64/Kconfig	2004-06-23 19:04:28 -07:00
@@ -149,20 +149,6 @@
 	default "6" if ITANIUM
 
 # align cache-sensitive data to 64 bytes
-config MCKINLEY_ASTEP_SPECIFIC
-	bool "McKinley A-step specific code"
-	depends on MCKINLEY
-	help
-	  Select this option to build a kernel for an IA-64 McKinley prototype
-	  system with any A-stepping CPU.
-
-config MCKINLEY_A0_SPECIFIC
-	bool "McKinley A0/A1-step specific code"
-	depends on MCKINLEY_ASTEP_SPECIFIC
-	help
-	  Select this option to build a kernel for an IA-64 McKinley prototype
-	  system with an A0 or A1 stepping CPU.
-
 config NUMA
 	bool "NUMA support"
 	depends on !IA64_HP_SIM
diff -Nru a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
--- a/arch/ia64/configs/sn2_defconfig	2004-06-23 19:04:25 -07:00
+++ b/arch/ia64/configs/sn2_defconfig	2004-06-23 19:04:25 -07:00
@@ -14,18 +14,22 @@
 #
 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=20
 CONFIG_HOTPLUG=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
 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
 
 #
@@ -60,7 +64,6 @@
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
 CONFIG_IA64_L1_CACHE_SHIFT=7
-# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set
 CONFIG_NUMA=y
 CONFIG_VIRTUAL_MEM_MAP=y
 CONFIG_DISCONTIGMEM=y
@@ -70,12 +73,17 @@
 CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=512
+# CONFIG_HOTPLUG_CPU is not set
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
 CONFIG_EFI_VARS=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
@@ -105,6 +113,7 @@
 #
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_USE_VECTOR is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
 
@@ -174,7 +183,6 @@
 #
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=m
 CONFIG_BLK_DEV_IDETAPE=m
 CONFIG_BLK_DEV_IDEFLOPPY=y
@@ -218,6 +226,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -243,7 +252,6 @@
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
@@ -281,7 +289,9 @@
 CONFIG_SCSI_SATA_SVW=m
 CONFIG_SCSI_ATA_PIIX=m
 CONFIG_SCSI_SATA_PROMISE=m
+# CONFIG_SCSI_SATA_SX4 is not set
 # CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIS is not set
 CONFIG_SCSI_SATA_VIA=m
 CONFIG_SCSI_SATA_VITESSE=y
 # CONFIG_SCSI_BUSLOGIC is not set
@@ -298,6 +308,7 @@
 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=y
@@ -343,6 +354,7 @@
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Networking support
@@ -389,8 +401,6 @@
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_TUNNEL=m
-# CONFIG_DECNET is not set
-CONFIG_BRIDGE=m
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 CONFIG_BRIDGE_NETFILTER=y
@@ -452,6 +462,7 @@
 CONFIG_IP_NF_ARP_MANGLE=m
 # CONFIG_IP_NF_COMPAT_IPCHAINS is not set
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
+# CONFIG_IP_NF_RAW is not set
 
 #
 # IPv6: Netfilter Configuration
@@ -471,7 +482,9 @@
 #
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
@@ -516,12 +529,14 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# 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=m
 CONFIG_BONDING=m
 CONFIG_EQUALIZER=m
@@ -529,6 +544,11 @@
 # CONFIG_ETHERTAP is not set
 
 #
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -582,7 +602,6 @@
 CONFIG_HAMACHI=m
 CONFIG_YELLOWFIN=m
 CONFIG_R8169=m
-CONFIG_SIS190=m
 CONFIG_SK98LIN=m
 CONFIG_TIGON3=y
 
@@ -591,6 +610,22 @@
 #
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI 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=m
@@ -602,45 +637,11 @@
 # CONFIG_PPP_BSDCOMP is not set
 # CONFIG_PPPOE is not set
 # CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
 CONFIG_NET_FC=y
 # 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
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
-
-#
 # ISDN subsystem
 #
 # CONFIG_ISDN is not set
@@ -703,6 +704,7 @@
 CONFIG_HW_CONSOLE=y
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
 # CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
@@ -713,18 +715,11 @@
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_HCDP=y
-CONFIG_SERIAL_8250_ACPI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 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
@@ -740,7 +735,6 @@
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
 CONFIG_EFI_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -852,6 +846,7 @@
 #
 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
@@ -897,7 +892,6 @@
 # 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
 
 #
@@ -968,6 +962,7 @@
 # Library routines
 #
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 
@@ -1019,4 +1014,5 @@
 # CONFIG_CRYPTO_ARC4 is not set
 CONFIG_CRYPTO_DEFLATE=m
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_TEST is not set
diff -Nru a/arch/ia64/defconfig b/arch/ia64/defconfig
--- a/arch/ia64/defconfig	2004-06-23 19:04:25 -07:00
+++ b/arch/ia64/defconfig	2004-06-23 19:04:25 -07:00
@@ -26,6 +26,7 @@
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
@@ -66,7 +67,6 @@
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
 CONFIG_IA64_L1_CACHE_SHIFT=7
-# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set
 # CONFIG_NUMA is not set
 CONFIG_VIRTUAL_MEM_MAP=y
 # CONFIG_IA64_CYCLONE is not set
@@ -74,6 +74,7 @@
 CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
+# CONFIG_HOTPLUG_CPU is not set
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
@@ -178,7 +179,6 @@
 #
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=m
@@ -220,6 +220,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -245,7 +246,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=y
 
@@ -282,6 +282,7 @@
 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_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
@@ -328,6 +329,7 @@
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Networking support
@@ -573,7 +575,12 @@
 #
 # IPMI
 #
-# CONFIG_IPMI_HANDLER is not set
+CONFIG_IPMI_HANDLER=m
+CONFIG_IPMI_PANIC_EVENT=y
+CONFIG_IPMI_PANIC_STRING=y
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
 
 #
 # Watchdog Cards
@@ -651,6 +658,7 @@
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
@@ -662,6 +670,7 @@
 # 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
@@ -688,6 +697,7 @@
 # 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_RIVA=m
 # CONFIG_FB_MATROX is not set
@@ -852,6 +862,7 @@
 # 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
 
@@ -901,6 +912,7 @@
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -998,7 +1010,6 @@
 # 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
 
 #
@@ -1083,7 +1094,7 @@
 # CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_IA64_PRINT_HAZARDS=y
-CONFIG_DISABLE_VHPT=y
+# CONFIG_DISABLE_VHPT is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_IA64_EARLY_PRINTK_VGA is not set
 # CONFIG_DEBUG_SLAB is not set
diff -Nru a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
--- a/arch/ia64/ia32/binfmt_elf32.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ia64/ia32/binfmt_elf32.c	2004-06-23 19:04:28 -07:00
@@ -197,6 +197,10 @@
 	}
 	up_write(&current->mm->mmap_sem);
 
+	/* Can't do it in ia64_elf32_init(). Needs to be done before calls to
+	   elf32_map() */
+	current->thread.ppl = ia32_init_pp_list();
+
 	return 0;
 }
 
diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S	2004-06-23 19:04:27 -07:00
+++ b/arch/ia64/ia32/ia32_entry.S	2004-06-23 19:04:27 -07:00
@@ -349,7 +349,7 @@
 	data8 sys_setfsuid	/* 16-bit version */
 	data8 sys_setfsgid	/* 16-bit version */
 	data8 sys_llseek	  /* 140 */
-	data8 sys32_getdents
+	data8 compat_sys_getdents
 	data8 compat_sys_select
 	data8 sys_flock
 	data8 sys32_msync
@@ -371,7 +371,7 @@
 	data8 sys_sched_get_priority_min	 /* 160 */
 	data8 sys32_sched_rr_get_interval
 	data8 compat_sys_nanosleep
-	data8 sys_mremap
+	data8 sys32_mremap
 	data8 sys_setresuid	/* 16-bit version */
 	data8 sys32_getresuid16	/* 16-bit version */	  /* 165 */
 	data8 sys_ni_syscall	/* vm86 */
@@ -428,7 +428,7 @@
 	data8 sys_pivot_root
 	data8 sys_mincore
 	data8 sys_madvise
-	data8 sys_getdents64	  /* 220 */
+	data8 compat_sys_getdents64	  /* 220 */
 	data8 compat_sys_fcntl64
 	data8 sys_ni_syscall		/* reserved for TUX */
 	data8 sys_ni_syscall		/* reserved for Security */
diff -Nru a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
--- a/arch/ia64/ia32/ia32_support.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ia64/ia32/ia32_support.c	2004-06-23 19:04:25 -07:00
@@ -218,6 +218,18 @@
 	ia32_exec_domain.signal_map = default_exec_domain.signal_map;
 	ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
 	register_exec_domain(&ia32_exec_domain);
+
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+	{
+		extern kmem_cache_t *partial_page_cachep;
+
+		partial_page_cachep = kmem_cache_create("partial_page_cache",
+							sizeof(struct partial_page), 0, 0,
+							NULL, NULL);
+		if (!partial_page_cachep)
+			panic("Cannot create partial page SLAB cache");
+	}
+#endif
 	return 0;
 }
 
diff -Nru a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
--- a/arch/ia64/ia32/ia32priv.h	2004-06-23 19:04:28 -07:00
+++ b/arch/ia64/ia32/ia32priv.h	2004-06-23 19:04:28 -07:00
@@ -1,5 +1,5 @@
-#ifndef _ASM_IA64_IA32_H
-#define _ASM_IA64_IA32_H
+#ifndef _ASM_IA64_IA32_PRIV_H
+#define _ASM_IA64_IA32_PRIV_H
 
 #include <linux/config.h>
 
@@ -9,6 +9,7 @@
 
 #include <linux/binfmts.h>
 #include <linux/compat.h>
+#include <linux/rbtree.h>
 
 #include <asm/processor.h>
 
@@ -16,12 +17,39 @@
  * 32 bit structures for IA32 support.
  */
 
-#define IA32_PAGE_SHIFT		12	/* 4KB pages */
 #define IA32_PAGE_SIZE		(1UL << IA32_PAGE_SHIFT)
 #define IA32_PAGE_MASK		(~(IA32_PAGE_SIZE - 1))
 #define IA32_PAGE_ALIGN(addr)	(((addr) + IA32_PAGE_SIZE - 1) & IA32_PAGE_MASK)
 #define IA32_CLOCKS_PER_SEC	100	/* Cast in stone for IA32 Linux */
 
+/*
+ * partially mapped pages provide precise accounting of which 4k sub pages
+ * are mapped and which ones are not, thereby improving IA-32 compatibility.
+ */
+struct partial_page {
+	struct partial_page	*next; /* linked list, sorted by address */
+	struct rb_node		pp_rb;
+	/* 64K is the largest "normal" page supported by ia64 ABI. So 4K*32
+	 * should suffice.*/
+	unsigned int		bitmap;
+	unsigned int		base;
+};
+
+struct partial_page_list {
+	struct partial_page	*pp_head; /* list head, points to the lowest
+					   * addressed partial page */
+	struct rb_root		ppl_rb;
+	struct partial_page	*pp_hint; /* pp_hint->next is the last
+					   * accessed partial page */
+	atomic_t		pp_count; /* reference count */
+};
+
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+struct partial_page_list* ia32_init_pp_list (void);
+#else
+# define ia32_init_pp_list()	0
+#endif
+
 /* sigcontext.h */
 /*
  * As documented in the iBCS2 standard..
@@ -528,4 +556,4 @@
 
 #endif /* !CONFIG_IA32_SUPPORT */
 
-#endif /* _ASM_IA64_IA32_H */
+#endif /* _ASM_IA64_IA32_PRIV_H */
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ia64/ia32/sys_ia32.c	2004-06-23 19:04:27 -07:00
@@ -8,6 +8,7 @@
  * Copyright (C) 1997		David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 2000-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2004		Gordon Jin <gordon.jin@intel.com>
  *
  * These routines maintain argument size conversion between 32bit and 64bit
  * environment.
@@ -48,6 +49,7 @@
 #include <linux/ipc.h>
 #include <linux/compat.h>
 #include <linux/vfs.h>
+#include <linux/mman.h>
 
 #include <asm/intrinsics.h>
 #include <asm/semaphore.h>
@@ -250,6 +252,508 @@
 	return ret;
 }
 
+/* SLAB cache for partial_page structures */
+kmem_cache_t *partial_page_cachep;
+
+/*
+ * init partial_page_list.
+ * return 0 means kmalloc fail.
+ */
+struct partial_page_list*
+ia32_init_pp_list(void)
+{
+	struct partial_page_list *p;
+
+	if ((p = kmalloc(sizeof(*p), GFP_KERNEL)) == NULL)
+		return p;
+	p->pp_head = 0;
+	p->ppl_rb = RB_ROOT;
+	p->pp_hint = 0;
+	atomic_set(&p->pp_count, 1);
+	return p;
+}
+
+/*
+ * Search for the partial page with @start in partial page list @ppl.
+ * If finds the partial page, return the found partial page.
+ * Else, return 0 and provide @pprev, @rb_link, @rb_parent to
+ * be used by later __ia32_insert_pp().
+ */
+static struct partial_page *
+__ia32_find_pp(struct partial_page_list *ppl, unsigned int start,
+	struct partial_page **pprev, struct rb_node ***rb_link,
+	struct rb_node **rb_parent)
+{
+	struct partial_page *pp;
+	struct rb_node **__rb_link, *__rb_parent, *rb_prev;
+
+	pp = ppl->pp_hint;
+	if (pp && pp->base == start)
+		return pp;
+
+	__rb_link = &ppl->ppl_rb.rb_node;
+	rb_prev = __rb_parent = NULL;
+
+	while (*__rb_link) {
+		__rb_parent = *__rb_link;
+		pp = rb_entry(__rb_parent, struct partial_page, pp_rb);
+
+		if (pp->base == start) {
+			ppl->pp_hint = pp;
+			return pp;
+		} else if (pp->base < start) {
+			rb_prev = __rb_parent;
+			__rb_link = &__rb_parent->rb_right;
+		} else {
+			__rb_link = &__rb_parent->rb_left;
+		}
+	}
+
+	*rb_link = __rb_link;
+	*rb_parent = __rb_parent;
+	*pprev = NULL;
+	if (rb_prev)
+		*pprev = rb_entry(rb_prev, struct partial_page, pp_rb);
+	return NULL;
+}
+
+/*
+ * insert @pp into @ppl.
+ */
+static void
+__ia32_insert_pp(struct partial_page_list *ppl, struct partial_page *pp,
+	 struct partial_page *prev, struct rb_node **rb_link,
+	struct rb_node *rb_parent)
+{
+	/* link list */
+	if (prev) {
+		pp->next = prev->next;
+		prev->next = pp;
+	} else {
+		ppl->pp_head = pp;
+		if (rb_parent)
+			pp->next = rb_entry(rb_parent,
+				struct partial_page, pp_rb);
+		else
+			pp->next = NULL;
+	}
+
+	/* link rb */
+	rb_link_node(&pp->pp_rb, rb_parent, rb_link);
+	rb_insert_color(&pp->pp_rb, &ppl->ppl_rb);
+
+	ppl->pp_hint = pp;
+}
+
+/*
+ * delete @pp from partial page list @ppl.
+ */
+static void
+__ia32_delete_pp(struct partial_page_list *ppl, struct partial_page *pp,
+	struct partial_page *prev)
+{
+	if (prev) {
+		prev->next = pp->next;
+		if (ppl->pp_hint == pp)
+			ppl->pp_hint = prev;
+	} else {
+		ppl->pp_head = pp->next;
+		if (ppl->pp_hint == pp)
+			ppl->pp_hint = pp->next;
+	}
+	rb_erase(&pp->pp_rb, &ppl->ppl_rb);
+	kmem_cache_free(partial_page_cachep, pp);
+}
+
+static struct partial_page *
+__pp_prev(struct partial_page *pp)
+{
+	struct rb_node *prev = rb_prev(&pp->pp_rb);
+	if (prev)
+		return rb_entry(prev, struct partial_page, pp_rb);
+	else
+		return NULL;
+}
+
+/*
+ * Delete partial pages with address between @start and @end.
+ * @start and @end are page aligned.
+ */
+static void
+__ia32_delete_pp_range(unsigned int start, unsigned int end)
+{
+	struct partial_page *pp, *prev;
+	struct rb_node **rb_link, *rb_parent;
+
+	if (start >= end)
+		return;
+
+	pp = __ia32_find_pp(current->thread.ppl, start, &prev,
+					&rb_link, &rb_parent);
+	if (pp)
+		prev = __pp_prev(pp);
+	else {
+		if (prev)
+			pp = prev->next;
+		else
+			pp = current->thread.ppl->pp_head;
+	}
+
+	while (pp && pp->base < end) {
+		struct partial_page *tmp = pp->next;
+		__ia32_delete_pp(current->thread.ppl, pp, prev);
+		pp = tmp;
+	}
+}
+
+/*
+ * Set the range between @start and @end in bitmap.
+ * @start and @end should be IA32 page aligned and in the same IA64 page.
+ */
+static int
+__ia32_set_pp(unsigned int start, unsigned int end, int flags)
+{
+	struct partial_page *pp, *prev;
+	struct rb_node ** rb_link, *rb_parent;
+	unsigned int pstart, start_bit, end_bit, i;
+
+	pstart = PAGE_START(start);
+	start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE;
+	end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE;
+	if (end_bit == 0)
+		end_bit = PAGE_SIZE / IA32_PAGE_SIZE;
+	pp = __ia32_find_pp(current->thread.ppl, pstart, &prev,
+					&rb_link, &rb_parent);
+	if (pp) {
+		for (i = start_bit; i < end_bit; i++)
+			set_bit(i, &pp->bitmap);
+		/*
+		 * Check: if this partial page has been set to a full page,
+		 * then delete it.
+		 */
+		if (find_first_zero_bit(&pp->bitmap, sizeof(pp->bitmap)*8) >=
+				PAGE_SIZE/IA32_PAGE_SIZE) {
+			__ia32_delete_pp(current->thread.ppl, pp, __pp_prev(pp));
+		}
+		return 0;
+	}
+
+	/*
+	 * MAP_FIXED may lead to overlapping mmap.
+	 * In this case, the requested mmap area may already mmaped as a full
+	 * page. So check vma before adding a new partial page.
+	 */
+	if (flags & MAP_FIXED) {
+		struct vm_area_struct *vma = find_vma(current->mm, pstart);
+		if (vma && vma->vm_start <= pstart)
+			return 0;
+	}
+
+	/* new a partial_page */
+	pp = kmem_cache_alloc(partial_page_cachep, GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
+	pp->base = pstart;
+	pp->bitmap = 0;
+	for (i=start_bit; i<end_bit; i++)
+		set_bit(i, &(pp->bitmap));
+	pp->next = NULL;
+	__ia32_insert_pp(current->thread.ppl, pp, prev, rb_link, rb_parent);
+	return 0;
+}
+
+/*
+ * @start and @end should be IA32 page aligned, but don't need to be in the
+ * same IA64 page. Split @start and @end to make sure they're in the same IA64
+ * page, then call __ia32_set_pp().
+ */
+static void
+ia32_set_pp(unsigned int start, unsigned int end, int flags)
+{
+	down_write(&current->mm->mmap_sem);
+	if (flags & MAP_FIXED) {
+		/*
+		 * MAP_FIXED may lead to overlapping mmap. When this happens,
+		 * a series of complete IA64 pages results in deletion of
+		 * old partial pages in that range.
+		 */
+		__ia32_delete_pp_range(PAGE_ALIGN(start), PAGE_START(end));
+	}
+
+	if (end < PAGE_ALIGN(start)) {
+		__ia32_set_pp(start, end, flags);
+	} else {
+		if (offset_in_page(start))
+			__ia32_set_pp(start, PAGE_ALIGN(start), flags);
+		if (offset_in_page(end))
+			__ia32_set_pp(PAGE_START(end), end, flags);
+	}
+	up_write(&current->mm->mmap_sem);
+}
+
+/*
+ * Unset the range between @start and @end in bitmap.
+ * @start and @end should be IA32 page aligned and in the same IA64 page.
+ * After doing that, if the bitmap is 0, then free the page and return 1,
+ * 	else return 0;
+ * If not find the partial page in the list, then
+ * 	If the vma exists, then the full page is set to a partial page;
+ *	Else return -ENOMEM.
+ */
+static int
+__ia32_unset_pp(unsigned int start, unsigned int end)
+{
+	struct partial_page *pp, *prev;
+	struct rb_node ** rb_link, *rb_parent;
+	unsigned int pstart, start_bit, end_bit, i;
+	struct vm_area_struct *vma;
+
+	pstart = PAGE_START(start);
+	start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE;
+	end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE;
+	if (end_bit == 0)
+		end_bit = PAGE_SIZE / IA32_PAGE_SIZE;
+
+	pp = __ia32_find_pp(current->thread.ppl, pstart, &prev,
+					&rb_link, &rb_parent);
+	if (pp) {
+		for (i = start_bit; i < end_bit; i++)
+			clear_bit(i, &pp->bitmap);
+		if (pp->bitmap == 0) {
+			__ia32_delete_pp(current->thread.ppl, pp, __pp_prev(pp));
+			return 1;
+		}
+		return 0;
+	}
+
+	vma = find_vma(current->mm, pstart);
+	if (!vma || vma->vm_start > pstart) {
+		return -ENOMEM;
+	}
+
+	/* new a partial_page */
+	pp = kmem_cache_alloc(partial_page_cachep, GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
+	pp->base = pstart;
+	pp->bitmap = 0;
+	for (i = 0; i < start_bit; i++)
+		set_bit(i, &(pp->bitmap));
+	for (i = end_bit; i < PAGE_SIZE / IA32_PAGE_SIZE; i++)
+		set_bit(i, &(pp->bitmap));
+	pp->next = NULL;
+	__ia32_insert_pp(current->thread.ppl, pp, prev, rb_link, rb_parent);
+	return 0;
+}
+
+/*
+ * Delete pp between PAGE_ALIGN(start) and PAGE_START(end) by calling
+ * __ia32_delete_pp_range(). Unset possible partial pages by calling
+ * __ia32_unset_pp().
+ * The returned value see __ia32_unset_pp().
+ */
+static int
+ia32_unset_pp(unsigned int *startp, unsigned int *endp)
+{
+	unsigned int start = *startp, end = *endp;
+	int ret = 0;
+
+	down_write(&current->mm->mmap_sem);
+
+	__ia32_delete_pp_range(PAGE_ALIGN(start), PAGE_START(end));
+
+	if (end < PAGE_ALIGN(start)) {
+		ret = __ia32_unset_pp(start, end);
+		if (ret == 1) {
+			*startp = PAGE_START(start);
+			*endp = PAGE_ALIGN(end);
+		}
+		if (ret == 0) {
+			/* to shortcut sys_munmap() in sys32_munmap() */
+			*startp = PAGE_START(start);
+			*endp = PAGE_START(end);
+		}
+	} else {
+		if (offset_in_page(start)) {
+			ret = __ia32_unset_pp(start, PAGE_ALIGN(start));
+			if (ret == 1)
+				*startp = PAGE_START(start);
+			if (ret == 0)
+				*startp = PAGE_ALIGN(start);
+			if (ret < 0)
+				goto out;
+		}
+		if (offset_in_page(end)) {
+			ret = __ia32_unset_pp(PAGE_START(end), end);
+			if (ret == 1)
+				*endp = PAGE_ALIGN(end);
+			if (ret == 0)
+				*endp = PAGE_START(end);
+		}
+	}
+
+ out:
+	up_write(&current->mm->mmap_sem);
+	return ret;
+}
+
+/*
+ * Compare the range between @start and @end with bitmap in partial page.
+ * @start and @end should be IA32 page aligned and in the same IA64 page.
+ */
+static int
+__ia32_compare_pp(unsigned int start, unsigned int end)
+{
+	struct partial_page *pp, *prev;
+	struct rb_node ** rb_link, *rb_parent;
+	unsigned int pstart, start_bit, end_bit, size;
+	unsigned int first_bit, next_zero_bit;	/* the first range in bitmap */
+
+	pstart = PAGE_START(start);
+
+	pp = __ia32_find_pp(current->thread.ppl, pstart, &prev,
+					&rb_link, &rb_parent);
+	if (!pp)
+		return 1;
+
+	start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE;
+	end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE;
+	size = sizeof(pp->bitmap) * 8;
+	first_bit = find_first_bit(&pp->bitmap, size);
+	next_zero_bit = find_next_zero_bit(&pp->bitmap, size, first_bit);
+	if ((start_bit < first_bit) || (end_bit > next_zero_bit)) {
+		/* exceeds the first range in bitmap */
+		return -ENOMEM;
+	} else if ((start_bit == first_bit) && (end_bit == next_zero_bit)) {
+		first_bit = find_next_bit(&pp->bitmap, size, next_zero_bit);
+		if ((next_zero_bit < first_bit) && (first_bit < size))
+			return 1;	/* has next range */
+		else
+			return 0; 	/* no next range */
+	} else
+		return 1;
+}
+
+/*
+ * @start and @end should be IA32 page aligned, but don't need to be in the
+ * same IA64 page. Split @start and @end to make sure they're in the same IA64
+ * page, then call __ia32_compare_pp().
+ *
+ * Take this as example: the range is the 1st and 2nd 4K page.
+ * Return 0 if they fit bitmap exactly, i.e. bitmap = 00000011;
+ * Return 1 if the range doesn't cover whole bitmap, e.g. bitmap = 00001111;
+ * Return -ENOMEM if the range exceeds the bitmap, e.g. bitmap = 00000001 or
+ * 	bitmap = 00000101.
+ */
+static int
+ia32_compare_pp(unsigned int *startp, unsigned int *endp)
+{
+	unsigned int start = *startp, end = *endp;
+	int retval = 0;
+
+	down_write(&current->mm->mmap_sem);
+
+	if (end < PAGE_ALIGN(start)) {
+		retval = __ia32_compare_pp(start, end);
+		if (retval == 0) {
+			*startp = PAGE_START(start);
+			*endp = PAGE_ALIGN(end);
+		}
+	} else {
+		if (offset_in_page(start)) {
+			retval = __ia32_compare_pp(start,
+						   PAGE_ALIGN(start));
+			if (retval == 0)
+				*startp = PAGE_START(start);
+			if (retval < 0)
+				goto out;
+		}
+		if (offset_in_page(end)) {
+			retval = __ia32_compare_pp(PAGE_START(end), end);
+			if (retval == 0)
+				*endp = PAGE_ALIGN(end);
+		}
+	}
+
+ out:
+	up_write(&current->mm->mmap_sem);
+	return retval;
+}
+
+static void
+__ia32_drop_pp_list(struct partial_page_list *ppl)
+{
+	struct partial_page *pp = ppl->pp_head;
+
+	while (pp) {
+		struct partial_page *next = pp->next;
+		kmem_cache_free(partial_page_cachep, pp);
+		pp = next;
+	}
+
+	kfree(ppl);
+}
+
+void
+ia32_drop_partial_page_list(struct task_struct *task)
+{
+	struct partial_page_list* ppl = task->thread.ppl;
+
+	if (ppl && atomic_dec_and_test(&ppl->pp_count))
+		__ia32_drop_pp_list(ppl);
+}
+
+/*
+ * Copy current->thread.ppl to ppl (already initialized).
+ */
+static int
+__ia32_copy_pp_list(struct partial_page_list *ppl)
+{
+	struct partial_page *pp, *tmp, *prev;
+	struct rb_node **rb_link, *rb_parent;
+
+	ppl->pp_head = NULL;
+	ppl->pp_hint = NULL;
+	ppl->ppl_rb = RB_ROOT;
+	rb_link = &ppl->ppl_rb.rb_node;
+	rb_parent = NULL;
+	prev = NULL;
+
+	for (pp = current->thread.ppl->pp_head; pp; pp = pp->next) {
+		tmp = kmem_cache_alloc(partial_page_cachep, GFP_KERNEL);
+		if (!tmp)
+			return -ENOMEM;
+		*tmp = *pp;
+		__ia32_insert_pp(ppl, tmp, prev, rb_link, rb_parent);
+		prev = tmp;
+		rb_link = &tmp->pp_rb.rb_right;
+		rb_parent = &tmp->pp_rb;
+	}
+	return 0;
+}
+
+int
+ia32_copy_partial_page_list(struct task_struct *p, unsigned long clone_flags)
+{
+	int retval = 0;
+
+	if (clone_flags & CLONE_VM) {
+		atomic_inc(&current->thread.ppl->pp_count);
+		p->thread.ppl = current->thread.ppl;
+	} else {
+		p->thread.ppl = ia32_init_pp_list();
+		if (!p->thread.ppl)
+			return -ENOMEM;
+		down_write(&current->mm->mmap_sem);
+		{
+			retval = __ia32_copy_pp_list(p->thread.ppl);
+		}
+		up_write(&current->mm->mmap_sem);
+	}
+
+	return retval;
+}
+
 static unsigned long
 emulate_mmap (struct file *file, unsigned long start, unsigned long len, int prot, int flags,
 	      loff_t off)
@@ -263,6 +767,7 @@
 	pend = PAGE_ALIGN(end);
 
 	if (flags & MAP_FIXED) {
+		ia32_set_pp((unsigned int)start, (unsigned int)end, flags);
 		if (start > pstart) {
 			if (flags & MAP_SHARED)
 				printk(KERN_INFO
@@ -274,7 +779,7 @@
 				return ret;
 			pstart += PAGE_SIZE;
 			if (pstart >= pend)
-				return start;	/* done */
+				goto out;	/* done */
 		}
 		if (end < pend) {
 			if (flags & MAP_SHARED)
@@ -287,7 +792,7 @@
 				return ret;
 			pend -= PAGE_SIZE;
 			if (pstart >= pend)
-				return start;	/* done */
+				goto out;	/* done */
 		}
 	} else {
 		/*
@@ -341,6 +846,10 @@
 		if (!(prot & PROT_WRITE) && sys_mprotect(pstart, pend - pstart, prot) < 0)
 			return -EINVAL;
 	}
+
+	if (!(flags & MAP_FIXED))
+		ia32_set_pp((unsigned int)start, (unsigned int)end, flags);
+out:
 	return start;
 }
 
@@ -478,11 +987,16 @@
 #if PAGE_SHIFT <= IA32_PAGE_SHIFT
 	ret = sys_munmap(start, end - start);
 #else
+	if (OFFSET4K(start))
+		return -EINVAL;
+
+	end = IA32_PAGE_ALIGN(end);
 	if (start >= end)
 		return -EINVAL;
 
-	start = PAGE_ALIGN(start);
-	end = PAGE_START(end);
+	ret = ia32_unset_pp(&start, &end);
+	if (ret < 0)
+		return ret;
 
 	if (start >= end)
 		return 0;
@@ -521,7 +1035,7 @@
 asmlinkage long
 sys32_mprotect (unsigned int start, unsigned int len, int prot)
 {
-	unsigned long end = start + len;
+	unsigned int end = start + len;
 #if PAGE_SHIFT > IA32_PAGE_SHIFT
 	long retval = 0;
 #endif
@@ -538,6 +1052,11 @@
 	if (end < start)
 		return -EINVAL;
 
+	retval = ia32_compare_pp(&start, &end);
+
+	if (retval < 0)
+		return retval;
+
 	down(&ia32_mmap_sem);
 	{
 		if (offset_in_page(start)) {
@@ -565,6 +1084,59 @@
 	up(&ia32_mmap_sem);
 	return retval;
 #endif
+}
+
+asmlinkage long
+sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len,
+		unsigned int flags, unsigned int new_addr)
+{
+	long ret;
+
+#if PAGE_SHIFT <= IA32_PAGE_SHIFT
+	ret = sys_mremap(addr, old_len, new_len, flags, new_addr);
+#else
+	unsigned int old_end, new_end;
+
+	if (OFFSET4K(addr))
+		return -EINVAL;
+
+	old_len = IA32_PAGE_ALIGN(old_len);
+	new_len = IA32_PAGE_ALIGN(new_len);
+	old_end = addr + old_len;
+	new_end = addr + new_len;
+
+	if (!new_len)
+		return -EINVAL;
+
+	if ((flags & MREMAP_FIXED) && (OFFSET4K(new_addr)))
+		return -EINVAL;
+
+	if (old_len >= new_len) {
+		ret = sys32_munmap(addr + new_len, old_len - new_len);
+		if (ret && old_len != new_len)
+			return ret;
+		ret = addr;
+		if (!(flags & MREMAP_FIXED) || (new_addr == addr))
+			return ret;
+		old_len = new_len;
+	}
+
+	addr = PAGE_START(addr);
+	old_len = PAGE_ALIGN(old_end) - addr;
+	new_len = PAGE_ALIGN(new_end) - addr;
+
+	down(&ia32_mmap_sem);
+	{
+		ret = sys_mremap(addr, old_len, new_len, flags, new_addr);
+	}
+	up(&ia32_mmap_sem);
+
+	if ((ret >= 0) && (old_len < new_len)) {
+		/* mremap expanded successfully */
+		ia32_set_pp(old_end, new_end, flags);
+	}
+#endif
+	return ret;
 }
 
 asmlinkage long
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ia64/kernel/acpi.c	2004-06-23 19:04:27 -07:00
@@ -521,9 +521,14 @@
 #endif /* CONFIG_ACPI_NUMA */
 
 unsigned int
-acpi_register_gsi (u32 gsi, int polarity, int trigger)
+acpi_register_gsi (u32 gsi, int edge_level, int active_high_low)
 {
-	return acpi_register_irq(gsi, polarity, trigger);
+	if (has_8259 && gsi < 16)
+		return isa_irq_to_vector(gsi);
+
+	return iosapic_register_intr(gsi,
+			(active_high_low == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+			(edge_level == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
 }
 EXPORT_SYMBOL(acpi_register_gsi);
 
@@ -548,7 +553,7 @@
 	if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES)
 		acpi_legacy_devices = 1;
 
-	acpi_register_gsi(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE);
+	acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
 	return 0;
 }
 
@@ -661,17 +666,5 @@
 	}
 	return 0;
 }
-
-int
-acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
-{
-	if (has_8259 && gsi < 16)
-		return isa_irq_to_vector(gsi);
-
-	return iosapic_register_intr(gsi,
-			(polarity == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
-			(trigger == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
-}
-EXPORT_SYMBOL(acpi_register_irq);
 
 #endif /* CONFIG_ACPI_BOOT */
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	2004-06-23 19:04:26 -07:00
+++ b/arch/ia64/kernel/entry.S	2004-06-23 19:04:26 -07:00
@@ -179,17 +179,19 @@
 	.body
 
 	adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13
+	movl r25=init_task
 	mov r27=IA64_KR(CURRENT_STACK)
+	adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
 	dep r20=0,in0,61,3		// physical address of "current"
 	;;
 	st8 [r22]=sp			// save kernel stack pointer of old task
 	shr.u r26=r20,IA64_GRANULE_SHIFT
-	adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
+	cmp.eq p7,p6=r25,in0
 	;;
 	/*
 	 * If we've already mapped this task's page, we can skip doing it again.
 	 */
-	cmp.eq p7,p6=r26,r27
+(p6)	cmp.eq p7,p6=r26,r27
 (p6)	br.cond.dpnt .map
 	;;
 .done:
diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
--- a/arch/ia64/kernel/head.S	2004-06-23 19:04:27 -07:00
+++ b/arch/ia64/kernel/head.S	2004-06-23 19:04:27 -07:00
@@ -154,6 +154,10 @@
 #endif
 	;;
 	tpa r3=r2		// r3 == phys addr of task struct
+	;;
+	shr.u r16=r3,IA64_GRANULE_SHIFT
+(isBP)	br.cond.dpnt .load_current // BP stack is on region 5 --- no need to map it
+
 	// load mapping for stack (virtaddr in r2, physaddr in r3)
 	rsm psr.ic
 	movl r17=PAGE_KERNEL
@@ -165,7 +169,6 @@
 	dep r2=-1,r3,61,3	// IMVA of task
 	;;
 	mov r17=rr[r2]
-	shr.u r16=r3,IA64_GRANULE_SHIFT
 	;;
 	dep r17=0,r17,8,24
 	;;
@@ -180,6 +183,7 @@
 	srlz.d
   	;;
 
+.load_current:
 	// load the "current" pointer (r13) and ar.k6 with the current task
 	mov IA64_KR(CURRENT)=r2		// virtual address
 	mov IA64_KR(CURRENT_STACK)=r16
diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c
--- a/arch/ia64/kernel/init_task.c	2004-06-23 19:04:29 -07:00
+++ b/arch/ia64/kernel/init_task.c	2004-06-23 19:04:29 -07:00
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init_task.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ia64/kernel/iosapic.c	2004-06-23 19:04:26 -07:00
@@ -100,7 +100,6 @@
 #endif
 
 static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
-extern cpumask_t	__cacheline_aligned pending_irq_cpumask[NR_IRQS];
 
 /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
 
@@ -335,21 +334,6 @@
 #endif
 }
 
-static inline void move_irq(int irq)
-{
-	/* note - we hold desc->lock */
-	cpumask_t tmp;
-	irq_desc_t *desc = irq_descp(irq);
-
-	if (!cpus_empty(pending_irq_cpumask[irq])) {
-		cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
-		if (unlikely(!cpus_empty(tmp))) {
-			desc->handler->set_affinity(irq, pending_irq_cpumask[irq]);
-		}
-		cpus_clear(pending_irq_cpumask[irq]);
-	}
-}
-
 /*
  * Handlers for level-triggered interrupts.
  */
@@ -483,7 +467,7 @@
 
 	index = find_iosapic(gsi);
 	if (index < 0) {
-		printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi);
+		printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", __FUNCTION__, gsi);
 		return;
 	}
 
@@ -512,6 +496,42 @@
 	}
 }
 
+static unsigned int
+get_target_cpu (void)
+{
+#ifdef CONFIG_SMP
+	static int cpu = -1;
+
+	/*
+	 * If the platform supports redirection via XTP, let it
+	 * distribute interrupts.
+	 */
+	if (smp_int_redirect & SMP_IRQ_REDIRECTION)
+		return hard_smp_processor_id();
+
+	/*
+	 * Some interrupts (ACPI SCI, for instance) are registered
+	 * before the BSP is marked as online.
+	 */
+	if (!cpu_online(smp_processor_id()))
+		return hard_smp_processor_id();
+
+	/*
+	 * Otherwise, round-robin interrupt vectors across all the
+	 * processors.  (It'd be nice if we could be smarter in the
+	 * case of NUMA.)
+	 */
+	do {
+		if (++cpu >= NR_CPUS)
+			cpu = 0;
+	} while (!cpu_online(cpu));
+
+	return cpu_physical_id(cpu);
+#else
+	return hard_smp_processor_id();
+#endif
+}
+
 /*
  * ACPI can describe IOSAPIC interrupts via static tables and namespace
  * methods.  This provides an interface to register those interrupts and
@@ -522,21 +542,35 @@
 		       unsigned long polarity, unsigned long trigger)
 {
 	int vector;
-	unsigned int dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff;
+	unsigned int dest;
+	unsigned long flags;
 
-	vector = gsi_to_vector(gsi);
-	if (vector < 0)
-		vector = assign_irq_vector(AUTO_ASSIGN);
+	/*
+	 * If this GSI has already been registered (i.e., it's a
+	 * shared interrupt, or we lost a race to register it),
+	 * don't touch the RTE.
+	 */
+	spin_lock_irqsave(&iosapic_lock, flags);
+	{
+		vector = gsi_to_vector(gsi);
+		if (vector > 0) {
+			spin_unlock_irqrestore(&iosapic_lock, flags);
+			return vector;
+		}
 
-	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
-		      polarity, trigger);
+		vector = assign_irq_vector(AUTO_ASSIGN);
+		dest = get_target_cpu();
+		register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
+			polarity, trigger);
+	}
+	spin_unlock_irqrestore(&iosapic_lock, flags);
 
-	printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
-	       gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
-	       (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
+	printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
+	       gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
+	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+	       cpu_logical_id(dest), dest, vector);
 
-	/* program the IOSAPIC routing table */
-	set_rte(vector, dest, 0);
+	set_rte(vector, dest, 1);
 	return vector;
 }
 
@@ -549,8 +583,9 @@
 				int iosapic_vector, u16 eid, u16 id,
 				unsigned long polarity, unsigned long trigger)
 {
+	static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"};
 	unsigned char delivery;
-	int vector;
+	int vector, mask = 0;
 	unsigned int dest = ((id << 8) | eid) & 0xffff;
 
 	switch (int_type) {
@@ -570,21 +605,22 @@
 	      case ACPI_INTERRUPT_CPEI:
 		vector = IA64_CPE_VECTOR;
 		delivery = IOSAPIC_LOWEST_PRIORITY;
+		mask = 1;
 		break;
 	      default:
-		printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type\n");
+		printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type);
 		return -1;
 	}
 
-	register_intr(gsi, vector, delivery, polarity,
-		      trigger);
+	register_intr(gsi, vector, delivery, polarity, trigger);
 
-	printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
-	       int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
-	       (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
+	printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
+	       int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",
+	       int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
+	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+	       cpu_logical_id(dest), dest, vector);
 
-	/* program the IOSAPIC routing table */
-	set_rte(vector, dest, 0);
+	set_rte(vector, dest, mask);
 	return vector;
 }
 
@@ -599,18 +635,18 @@
 			  unsigned long trigger)
 {
 	int vector;
-	unsigned int dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff;
+	unsigned int dest = hard_smp_processor_id();
 
 	vector = isa_irq_to_vector(isa_irq);
 
 	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
 
-	DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",
-	    isa_irq, gsi, polarity == IOSAPIC_POL_HIGH ? "high" : "low",
-	    trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector);
+	DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
+	    isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level",
+	    polarity == IOSAPIC_POL_HIGH ? "high" : "low",
+	    cpu_logical_id(dest), dest, vector);
 
-	/* program the IOSAPIC routing table */
-	set_rte(vector, dest, 0);
+	set_rte(vector, dest, 1);
 }
 
 void __init
@@ -665,104 +701,3 @@
 			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
 	}
 }
-
-void
-iosapic_enable_intr (unsigned int vector)
-{
-	unsigned int dest;
-	irq_desc_t *desc;
-
-	/*
-	 * In the case of a shared interrupt, do not re-route the vector, and
-	 * especially do not mask a running interrupt (startup will not get
-	 * called for a shared interrupt).
-	 */
-	desc = irq_descp(vector);
-	if (desc->action)
-		return;
-
-#ifdef CONFIG_SMP
-	/*
-	 * For platforms that do not support interrupt redirect via the XTP interface, we
-	 * can round-robin the PCI device interrupts to the processors
-	 */
-	if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {
-		static int cpu_index = -1;
-
-		do
-			if (++cpu_index >= NR_CPUS)
-				cpu_index = 0;
-		while (!cpu_online(cpu_index));
-
-		dest = cpu_physical_id(cpu_index) & 0xffff;
-	} else {
-		/*
-		 * Direct the interrupt vector to the current cpu, platform redirection
-		 * will distribute them.
-		 */
-		dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff;
-	}
-#else
-	/* direct the interrupt vector to the running cpu id */
-	dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff;
-#endif
-	set_rte(vector, dest, 1);
-
-	printk(KERN_INFO "IOSAPIC: vector %d -> CPU 0x%04x, enabled\n",
-	       vector, dest);
-}
-
-#ifdef CONFIG_ACPI_PCI
-
-void __init
-iosapic_parse_prt (void)
-{
-	struct acpi_prt_entry *entry;
-	struct list_head *node;
-	unsigned int gsi;
-	int vector;
-	char pci_id[16];
-	struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
-	irq_desc_t *idesc;
-
-	list_for_each(node, &acpi_prt.entries) {
-		entry = list_entry(node, struct acpi_prt_entry, node);
-
-		/* We're only interested in static (non-link) entries.  */
-		if (entry->link.handle)
-			continue;
-
-		gsi = entry->link.index;
-
-		vector = gsi_to_vector(gsi);
-		if (vector < 0) {
-			if (find_iosapic(gsi) < 0)
-				continue;
-
-			/* allocate a vector for this interrupt line */
-			if (pcat_compat && (gsi < 16))
-				vector = isa_irq_to_vector(gsi);
-			else
-				/* new GSI; allocate a vector for it */
-				vector = assign_irq_vector(AUTO_ASSIGN);
-
-			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
-				      IOSAPIC_LEVEL);
-		}
-		entry->irq = vector;
-		snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]",
-			 entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin);
-
-		/*
-		 * If vector was previously initialized to a different
-		 * handler, re-initialize.
-		 */
-		idesc = irq_descp(vector);
-		if (idesc->handler != irq_type)
-			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
-				      IOSAPIC_LEVEL);
-
-	}
-}
-
-#endif /* CONFIG_ACPI */
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ia64/kernel/irq.c	2004-06-23 19:04:28 -07:00
@@ -1018,6 +1018,22 @@
 	return full_count;
 }
 
+void move_irq(int irq)
+{
+	/* note - we hold desc->lock */
+	cpumask_t tmp;
+	irq_desc_t *desc = irq_descp(irq);
+
+	if (!cpus_empty(pending_irq_cpumask[irq])) {
+		cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
+		if (unlikely(!cpus_empty(tmp))) {
+			desc->handler->set_affinity(irq, pending_irq_cpumask[irq]);
+		}
+		cpus_clear(pending_irq_cpumask[irq]);
+	}
+}
+
+
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_HOTPLUG_CPU
diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
--- a/arch/ia64/kernel/mca.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ia64/kernel/mca.c	2004-06-23 19:04:26 -07:00
@@ -108,6 +108,7 @@
 #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */
 #define MIN_CPE_POLL_INTERVAL (2*60*HZ)  /* 2 minutes */
 #define CMC_POLL_INTERVAL     (1*60*HZ)  /* 1 minute */
+#define CPE_HISTORY_LENGTH    5
 #define CMC_HISTORY_LENGTH    5
 
 static struct timer_list cpe_poll_timer;
@@ -127,6 +128,8 @@
  */
 static int cpe_poll_enabled = 1;
 
+static int cpe_vector = -1;
+
 extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
 
 /*
@@ -267,20 +270,65 @@
  */
 #ifndef PLATFORM_MCA_HANDLERS
 
+#ifdef CONFIG_ACPI
+
 static irqreturn_t
 ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
-	IA64_MCA_DEBUG("%s: received interrupt. CPU:%d vector = %#x\n",
-		       __FUNCTION__, smp_processor_id(), cpe_irq);
+	static unsigned long	cpe_history[CPE_HISTORY_LENGTH];
+	static int		index;
+	static spinlock_t	cpe_history_lock = SPIN_LOCK_UNLOCKED;
+
+	IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n",
+		       __FUNCTION__, cpe_irq, smp_processor_id());
 
 	/* SAL spec states this should run w/ interrupts enabled */
 	local_irq_enable();
 
-	/* Get the CMC error record and log it */
+	/* Get the CPE error record and log it */
 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
+
+	spin_lock(&cpe_history_lock);
+	if (!cpe_poll_enabled && cpe_vector >= 0) {
+
+		int i, count = 1; /* we know 1 happened now */
+		unsigned long now = jiffies;
+
+		for (i = 0; i < CPE_HISTORY_LENGTH; i++) {
+			if (now - cpe_history[i] <= HZ)
+				count++;
+		}
+
+		IA64_MCA_DEBUG(KERN_INFO "CPE threshold %d/%d\n", count, CPE_HISTORY_LENGTH);
+		if (count >= CPE_HISTORY_LENGTH) {
+
+			cpe_poll_enabled = 1;
+			spin_unlock(&cpe_history_lock);
+			disable_irq_nosync(local_vector_to_irq(IA64_CPE_VECTOR));
+
+			/*
+			 * Corrected errors will still be corrected, but
+			 * make sure there's a log somewhere that indicates
+			 * something is generating more than we can handle.
+			 */
+			printk(KERN_WARNING "WARNING: Switching to polling CPE handler; error records may be lost\n");
+
+			mod_timer(&cpe_poll_timer, jiffies + MIN_CPE_POLL_INTERVAL);
+
+			/* lock already released, get out now */
+			return IRQ_HANDLED;
+		} else {
+			cpe_history[index++] = now;
+			if (index == CPE_HISTORY_LENGTH)
+				index = 0;
+		}
+	}
+	spin_unlock(&cpe_history_lock);
 	return IRQ_HANDLED;
 }
 
+#endif /* CONFIG_ACPI */
+
 static void
 show_min_state (pal_min_state_area_t *minstate)
 {
@@ -901,7 +949,7 @@
  * 	handled
  */
 static irqreturn_t
-ia64_mca_cmc_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
+ia64_mca_cmc_int_caller(int cmc_irq, void *arg, struct pt_regs *ptregs)
 {
 	static int start_count = -1;
 	unsigned int cpuid;
@@ -912,7 +960,7 @@
 	if (start_count == -1)
 		start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC);
 
-	ia64_mca_cmc_int_handler(cpe_irq, arg, ptregs);
+	ia64_mca_cmc_int_handler(cmc_irq, arg, ptregs);
 
 	for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++);
 
@@ -967,11 +1015,13 @@
  * Outputs
  * 	handled
  */
+#ifdef CONFIG_ACPI
+
 static irqreturn_t
 ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
 	static int start_count = -1;
-	static int poll_time = MAX_CPE_POLL_INTERVAL;
+	static int poll_time = MIN_CPE_POLL_INTERVAL;
 	unsigned int cpuid;
 
 	cpuid = smp_processor_id();
@@ -989,20 +1039,30 @@
 	} else {
 		/*
 		 * If a log was recorded, increase our polling frequency,
-		 * otherwise, backoff.
+		 * otherwise, backoff or return to interrupt mode.
 		 */
 		if (start_count != IA64_LOG_COUNT(SAL_INFO_TYPE_CPE)) {
 			poll_time = max(MIN_CPE_POLL_INTERVAL, poll_time / 2);
-		} else {
+		} else if (cpe_vector < 0) {
 			poll_time = min(MAX_CPE_POLL_INTERVAL, poll_time * 2);
+		} else {
+			poll_time = MIN_CPE_POLL_INTERVAL;
+
+			printk(KERN_WARNING "Returning to interrupt driven CPE handler\n");
+			enable_irq(local_vector_to_irq(IA64_CPE_VECTOR));
+			cpe_poll_enabled = 0;
 		}
+
+		if (cpe_poll_enabled)
+			mod_timer(&cpe_poll_timer, jiffies + poll_time);
 		start_count = -1;
-		mod_timer(&cpe_poll_timer, jiffies + poll_time);
 	}
 
 	return IRQ_HANDLED;
 }
 
+#endif /* CONFIG_ACPI */
+
 /*
  *  ia64_mca_cpe_poll
  *
@@ -1240,21 +1300,23 @@
 	register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
 
 #ifdef CONFIG_ACPI
-	/* Setup the CPE interrupt vector */
+	/* Setup the CPEI/P vector and handler */
 	{
 		irq_desc_t *desc;
 		unsigned int irq;
-		int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI);
 
-		if (cpev >= 0) {
+		cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
+
+		if (cpe_vector >= 0) {
 			for (irq = 0; irq < NR_IRQS; ++irq)
-				if (irq_to_vector(irq) == cpev) {
+				if (irq_to_vector(irq) == cpe_vector) {
 					desc = irq_descp(irq);
 					desc->status |= IRQ_PER_CPU;
 					setup_irq(irq, &mca_cpe_irqaction);
 				}
-			ia64_mca_register_cpev(cpev);
+			ia64_mca_register_cpev(cpe_vector);
 		}
+		register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
 	}
 #endif
 
@@ -1294,9 +1356,10 @@
 
 #ifdef CONFIG_ACPI
 	/* If platform doesn't support CPEI, get the timer going. */
-	if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) {
-		register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
+	if (cpe_vector < 0 && cpe_poll_enabled) {
 		ia64_mca_cpe_poll(0UL);
+	} else {
+		cpe_poll_enabled = 0;
 	}
 #endif
 
diff -Nru a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
--- a/arch/ia64/kernel/palinfo.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ia64/kernel/palinfo.c	2004-06-23 19:04:25 -07:00
@@ -515,10 +515,10 @@
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL,
-	"Enable Cache Line Repl. Exclusive",
 	"Enable Cache Line Repl. Shared",
+	"Enable Cache Line Repl. Exclusive",
 	"Disable Transaction Queuing",
-	"Disable Reponse Error Checking",
+	"Disable Response Error Checking",
 	"Disable Bus Error Checking",
 	"Disable Bus Requester Internal Error Signalling",
 	"Disable Bus Requester Error Signalling",
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ia64/kernel/perfmon.c	2004-06-23 19:04:28 -07:00
@@ -311,6 +311,7 @@
 	unsigned int		ctx_cpu;		/* cpu to which perfmon is applied (system wide) */
 
 	int			ctx_fd;			/* file descriptor used my this context */
+	pfm_ovfl_arg_t		ctx_ovfl_arg;		/* argument to custom buffer format handler */
 
 	pfm_buffer_fmt_t	*ctx_buf_fmt;		/* buffer format callbacks */
 	void			*ctx_smpl_hdr;		/* points to sampling buffer header kernel vaddr */
@@ -4584,31 +4585,6 @@
 	return 0;
 }
 
-static void
-pfm_force_cleanup(pfm_context_t *ctx, struct pt_regs *regs)
-{
-	struct task_struct *task = ctx->ctx_task;
-
-	ia64_psr(regs)->up = 0;
-	ia64_psr(regs)->sp = 1;
-
-	if (GET_PMU_OWNER() == task) {
-		DPRINT(("cleared ownership for [%d]\n", ctx->ctx_task->pid));
-		SET_PMU_OWNER(NULL, NULL);
-	}
-
-	/*
-	 * disconnect the task from the context and vice-versa
-	 */
-	PFM_SET_WORK_PENDING(task, 0);
-
-	task->thread.pfm_context  = NULL;
-	task->thread.flags       &= ~IA64_THREAD_PM_VALID;
-
-	DPRINT(("force cleanupf for [%d]\n",  task->pid));
-}
-
-
 
 /*
  * called only from exit_thread(): task == current
@@ -5185,7 +5161,7 @@
 static void
 pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs)
 {
-	pfm_ovfl_arg_t ovfl_arg;
+	pfm_ovfl_arg_t *ovfl_arg;
 	unsigned long mask;
 	unsigned long old_val, ovfl_val, new_val;
 	unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL, reset_pmds;
@@ -5272,7 +5248,8 @@
 		int j, k, ret = 0;
 		int this_cpu = smp_processor_id();
 
-		pmd_mask   = ovfl_pmds >> PMU_FIRST_COUNTER;
+		pmd_mask = ovfl_pmds >> PMU_FIRST_COUNTER;
+		ovfl_arg = &ctx->ctx_ovfl_arg;
 
 		prefetch(ctx->ctx_smpl_hdr);
 
@@ -5282,15 +5259,15 @@
 
 			if ((pmd_mask & 0x1) == 0) continue;
 
-			ovfl_arg.ovfl_pmd      = (unsigned char )i;
-			ovfl_arg.ovfl_notify   = ovfl_notify & mask ? 1 : 0;
-			ovfl_arg.active_set    = 0;
-			ovfl_arg.ovfl_ctrl.val = 0; /* module must fill in all fields */
-			ovfl_arg.smpl_pmds[0]  = smpl_pmds = ctx->ctx_pmds[i].smpl_pmds[0];
-
-			ovfl_arg.pmd_value      = ctx->ctx_pmds[i].val;
-			ovfl_arg.pmd_last_reset = ctx->ctx_pmds[i].lval;
-			ovfl_arg.pmd_eventid    = ctx->ctx_pmds[i].eventid;
+			ovfl_arg->ovfl_pmd      = (unsigned char )i;
+			ovfl_arg->ovfl_notify   = ovfl_notify & mask ? 1 : 0;
+			ovfl_arg->active_set    = 0;
+			ovfl_arg->ovfl_ctrl.val = 0; /* module must fill in all fields */
+			ovfl_arg->smpl_pmds[0]  = smpl_pmds = ctx->ctx_pmds[i].smpl_pmds[0];
+
+			ovfl_arg->pmd_value      = ctx->ctx_pmds[i].val;
+			ovfl_arg->pmd_last_reset = ctx->ctx_pmds[i].lval;
+			ovfl_arg->pmd_eventid    = ctx->ctx_pmds[i].eventid;
 
 			/*
 		 	 * copy values of pmds of interest. Sampling format may copy them
@@ -5299,8 +5276,8 @@
 			if (smpl_pmds) {
 				for(j=0, k=0; smpl_pmds; j++, smpl_pmds >>=1) {
 					if ((smpl_pmds & 0x1) == 0) continue;
-					ovfl_arg.smpl_pmds_values[k++] = PMD_IS_COUNTING(j) ?  pfm_read_soft_counter(ctx, j) : ia64_get_pmd(j);
-					DPRINT_ovfl(("smpl_pmd[%d]=pmd%u=0x%lx\n", k-1, j, ovfl_arg.smpl_pmds_values[k-1]));
+					ovfl_arg->smpl_pmds_values[k++] = PMD_IS_COUNTING(j) ?  pfm_read_soft_counter(ctx, j) : ia64_get_pmd(j);
+					DPRINT_ovfl(("smpl_pmd[%d]=pmd%u=0x%lx\n", k-1, j, ovfl_arg->smpl_pmds_values[k-1]));
 				}
 			}
 
@@ -5311,7 +5288,7 @@
 			/*
 		 	 * call custom buffer format record (handler) routine
 		 	 */
-			ret = (*ctx->ctx_buf_fmt->fmt_handler)(task, ctx->ctx_smpl_hdr, &ovfl_arg, regs, tstamp);
+			ret = (*ctx->ctx_buf_fmt->fmt_handler)(task, ctx->ctx_smpl_hdr, ovfl_arg, regs, tstamp);
 
 			end_cycles = ia64_get_itc();
 
@@ -5319,13 +5296,13 @@
 			 * For those controls, we take the union because they have
 			 * an all or nothing behavior.
 			 */
-			ovfl_ctrl.bits.notify_user     |= ovfl_arg.ovfl_ctrl.bits.notify_user;
-			ovfl_ctrl.bits.block_task      |= ovfl_arg.ovfl_ctrl.bits.block_task;
-			ovfl_ctrl.bits.mask_monitoring |= ovfl_arg.ovfl_ctrl.bits.mask_monitoring;
+			ovfl_ctrl.bits.notify_user     |= ovfl_arg->ovfl_ctrl.bits.notify_user;
+			ovfl_ctrl.bits.block_task      |= ovfl_arg->ovfl_ctrl.bits.block_task;
+			ovfl_ctrl.bits.mask_monitoring |= ovfl_arg->ovfl_ctrl.bits.mask_monitoring;
 			/*
 			 * build the bitmask of pmds to reset now
 			 */
-			if (ovfl_arg.ovfl_ctrl.bits.reset_ovfl_pmds) reset_pmds |= mask;
+			if (ovfl_arg->ovfl_ctrl.bits.reset_ovfl_pmds) reset_pmds |= mask;
 
 			pfm_stats[this_cpu].pfm_smpl_handler_cycles += end_cycles - start_cycles;
 		}
@@ -5793,6 +5770,32 @@
 }
 
 #ifdef CONFIG_SMP
+
+static void
+pfm_force_cleanup(pfm_context_t *ctx, struct pt_regs *regs)
+{
+	struct task_struct *task = ctx->ctx_task;
+
+	ia64_psr(regs)->up = 0;
+	ia64_psr(regs)->sp = 1;
+
+	if (GET_PMU_OWNER() == task) {
+		DPRINT(("cleared ownership for [%d]\n", ctx->ctx_task->pid));
+		SET_PMU_OWNER(NULL, NULL);
+	}
+
+	/*
+	 * disconnect the task from the context and vice-versa
+	 */
+	PFM_SET_WORK_PENDING(task, 0);
+
+	task->thread.pfm_context  = NULL;
+	task->thread.flags       &= ~IA64_THREAD_PM_VALID;
+
+	DPRINT(("force cleanup for [%d]\n",  task->pid));
+}
+
+
 /*
  * in 2.6, interrupts are masked when we come here and the runqueue lock is held
  */
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ia64/kernel/process.c	2004-06-23 19:04:27 -07:00
@@ -439,6 +439,10 @@
 		ia32_save_state(p);
 		if (clone_flags & CLONE_SETTLS)
 			retval = ia32_clone_tls(p, child_ptregs);
+
+		/* Copy partially mapped page list */
+		if (!retval)
+			retval = ia32_copy_partial_page_list(p, clone_flags);
 	}
 #endif
 
@@ -672,6 +676,8 @@
 	/* drop floating-point and debug-register state if it exists: */
 	current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
 	ia64_drop_fpu(current);
+	if (IS_IA32_PROCESS(ia64_task_regs(current)))
+		ia32_drop_partial_page_list(current);
 }
 
 /*
@@ -691,6 +697,8 @@
 	if (current->thread.flags & IA64_THREAD_DBG_VALID)
 		pfm_release_debug_registers(current);
 #endif
+	if (IS_IA32_PROCESS(ia64_task_regs(current)))
+		ia32_drop_partial_page_list(current);
 }
 
 unsigned long
diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
--- a/arch/ia64/kernel/unwind.c	2004-06-23 19:04:29 -07:00
+++ b/arch/ia64/kernel/unwind.c	2004-06-23 19:04:29 -07:00
@@ -385,9 +385,10 @@
 	}
 
 	if (write) {
-		if (read_only(addr))
-			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
-		else {
+		if (read_only(addr)) {
+			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
+				__FUNCTION__);
+		} else {
 			*addr = *val;
 			if (*nat)
 				*nat_addr |= nat_mask;
@@ -432,9 +433,10 @@
 		return -1;
 	}
 	if (write)
-		if (read_only(addr))
-			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
-		else
+		if (read_only(addr)) {
+			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
+				__FUNCTION__);
+		} else
 			*addr = *val;
 	else
 		*val = *addr;
@@ -480,9 +482,10 @@
 	}
 
 	if (write)
-		if (read_only(addr))
-			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
-		else
+		if (read_only(addr)) {
+			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
+				__FUNCTION__);
+		} else
 			*addr = *val;
 	else
 		*val = *addr;
@@ -576,9 +579,10 @@
 	}
 
 	if (write) {
-		if (read_only(addr))
-			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
-		else
+		if (read_only(addr)) {
+			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
+				__FUNCTION__);
+		} else
 			*addr = *val;
 	} else
 		*val = *addr;
@@ -596,9 +600,10 @@
 		addr = &info->sw->pr;
 
 	if (write) {
-		if (read_only(addr))
-			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
-		else
+		if (read_only(addr)) {
+			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
+				__FUNCTION__);
+		} else
 			*addr = *val;
 	} else
 		*val = *addr;
diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
--- a/arch/ia64/mm/discontig.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ia64/mm/discontig.c	2004-06-23 19:04:28 -07:00
@@ -154,6 +154,9 @@
 
 	memcpy(numa_slit, numa_slit_fix, sizeof (numa_slit));
 
+	for (i = nnode; i < numnodes; i++)
+		node_set_offline(i);
+
 	numnodes = nnode;
 
 	return;
diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
--- a/arch/ia64/mm/hugetlbpage.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ia64/mm/hugetlbpage.c	2004-06-23 19:04:27 -07:00
@@ -297,7 +297,7 @@
 				unlock_page(page);
 			} else {
 				hugetlb_put_quota(mapping);
-				free_huge_page(page);
+				page_cache_release(page);
 				goto out;
 			}
 		}
diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
--- a/arch/ia64/pci/pci.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ia64/pci/pci.c	2004-06-23 19:04:26 -07:00
@@ -134,10 +134,18 @@
 static int __init
 pci_acpi_init (void)
 {
-	if (!acpi_pci_irq_init())
-		printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-	else
-		printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");
+	struct pci_dev *dev = NULL;
+
+	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
+
+	/*
+	 * PCI IRQ routing is set up by pci_enable_device(), but we
+	 * also do it here in case there are still broken drivers that
+	 * don't use pci_enable_device().
+	 */
+	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+		acpi_pci_irq_enable(dev);
+
 	return 0;
 }
 
diff -Nru a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c
--- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	2004-06-23 19:04:28 -07:00
@@ -741,7 +741,7 @@
 			/* Is this PCI bus associated with this moduleid? */
 			moduleid = NODE_MODULEID(
 				nasid_to_cnodeid(pcibr_soft->bs_nasid));
-			if (modules[i]->id == moduleid) {
+			if (sn_modules[i]->id == moduleid) {
 				struct pcibr_list_s *new_element;
 
 				new_element = kmalloc(sizeof (struct pcibr_soft_s), GFP_KERNEL);
@@ -781,7 +781,7 @@
 				
 		/*
 		 * We now have a list of all the pci bridges associated with
-		 * the module_id, modules[i].  Call pci_bus_map_create() for
+		 * the module_id, sn_modules[i].  Call pci_bus_map_create() for
 		 * each pci bridge
 		 */
 		softlistp = first_in_list;
diff -Nru a/arch/ia64/sn/io/sn2/klgraph.c b/arch/ia64/sn/io/sn2/klgraph.c
--- a/arch/ia64/sn/io/sn2/klgraph.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ia64/sn/io/sn2/klgraph.c	2004-06-23 19:04:27 -07:00
@@ -527,7 +527,7 @@
 		/* Use module as module vertex fastinfo */
 
 		memset(buffer, 0, 16);
-		format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF);
+		format_module_id(buffer, sn_modules[cm]->id, MODULE_FORMAT_BRIEF);
 		sprintf(name, EDGE_LBL_MODULE "/%s", buffer);
 
 		rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl);
@@ -535,7 +535,7 @@
 		rc = rc;
 		HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, module_vhdl, NULL, "Created module path.\n");
 
-		hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]);
+		hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) sn_modules[cm]);
 
 		/* Add system controller */
 		sprintf(name,
diff -Nru a/arch/ia64/sn/io/sn2/ml_iograph.c b/arch/ia64/sn/io/sn2/ml_iograph.c
--- a/arch/ia64/sn/io/sn2/ml_iograph.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ia64/sn/io/sn2/ml_iograph.c	2004-06-23 19:04:25 -07:00
@@ -518,6 +518,14 @@
 	ASSERT(hubv != GRAPH_VERTEX_NONE);
 
 	/* 
+	 * attach our hub_provider information to hubv,
+	 * so we can use it as a crosstalk provider "master"
+	 * vertex.
+	 */
+	xtalk_provider_register(hubv, &hub_provider);
+	xtalk_provider_startup(hubv);
+
+	/* 
 	 * If nothing connected to this hub's xtalk port, we're done.
 	 */
 	early_probe_for_widget(hubv, &hwid);
@@ -526,14 +534,6 @@
 		return;
 		/* NOTREACHED */
 	}
-
-	/* 
-	 * attach our hub_provider information to hubv,
-	 * so we can use it as a crosstalk provider "master"
-	 * vertex.
-	 */
-	xtalk_provider_register(hubv, &hub_provider);
-	xtalk_provider_startup(hubv);
 
 	/*
 	 * Create a vertex to represent the crosstalk bus
diff -Nru a/arch/ia64/sn/io/sn2/module.c b/arch/ia64/sn/io/sn2/module.c
--- a/arch/ia64/sn/io/sn2/module.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ia64/sn/io/sn2/module.c	2004-06-23 19:04:25 -07:00
@@ -33,7 +33,7 @@
 #define DPRINTF(x...)
 #endif
 
-module_t	       *modules[MODULE_MAX];
+module_t	       *sn_modules[MODULE_MAX];
 int			nummodules;
 
 #define SN00_SERIAL_FUDGE	0x3b1af409d513c2
@@ -59,9 +59,9 @@
     int			i;
 
     for (i = 0; i < nummodules; i++)
-	if (modules[i]->id == id) {
-	    DPRINTF("module_lookup: found m=0x%p\n", modules[i]);
-	    return modules[i];
+	if (sn_modules[i]->id == id) {
+	    DPRINTF("module_lookup: found m=0x%p\n", sn_modules[i]);
+	    return sn_modules[i];
 	}
 
     return NULL;
@@ -104,10 +104,10 @@
 
 	/* Insert in sorted order by module number */
 
-	for (i = nummodules; i > 0 && modules[i - 1]->id > moduleid; i--)
-	    modules[i] = modules[i - 1];
+	for (i = nummodules; i > 0 && sn_modules[i - 1]->id > moduleid; i--)
+	    sn_modules[i] = sn_modules[i - 1];
 
-	modules[i] = m;
+	sn_modules[i] = m;
 	nummodules++;
     }
 
diff -Nru a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
--- a/arch/ia64/sn/kernel/irq.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ia64/sn/kernel/irq.c	2004-06-23 19:04:25 -07:00
@@ -41,6 +41,7 @@
 extern void pcibr_force_interrupt(pcibr_intr_t intr);
 extern int sn_force_interrupt_flag;
 struct irq_desc * sn_irq_desc(unsigned int irq);
+extern cpumask_t    __cacheline_aligned pending_irq_cpumask[NR_IRQS];
 
 struct sn_intr_list_t {
 	struct sn_intr_list_t *next;
@@ -71,6 +72,21 @@
 {
 }
 
+static inline void move_irq(int irq)
+{
+	/* note - we hold desc->lock */
+	cpumask_t tmp;
+	irq_desc_t *desc = irq_descp(irq);
+
+	if (!cpus_empty(pending_irq_cpumask[irq])) {
+		cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
+		if (unlikely(!cpus_empty(tmp))) {
+			desc->handler->set_affinity(irq, pending_irq_cpumask[irq]);
+		}
+		cpus_clear(pending_irq_cpumask[irq]);
+	}
+}
+
 static void
 sn_ack_irq(unsigned int irq)
 {
@@ -94,6 +110,7 @@
 	}
 	HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask );
 	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
+	move_irq(irq);
 }
 
 static void
diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
--- a/arch/ia64/sn/kernel/setup.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ia64/sn/kernel/setup.c	2004-06-23 19:04:26 -07:00
@@ -226,7 +226,25 @@
 			shub_1_1_found = 1;
 }
 
-
+/**
+ * sn_set_error_handling_features - Tell the SN prom how to handle certain
+ * error types.
+ */
+static void __init
+sn_set_error_handling_features(void)
+{
+	u64 ret;
+	u64 sn_ehf_bits[7];	/* see ia64_sn_set_error_handling_features */
+	memset(sn_ehf_bits, 0, sizeof(sn_ehf_bits));
+#define EHF(x) __set_bit(SN_SAL_EHF_ ## x, sn_ehf_bits)
+	EHF(MCA_SLV_TO_OS_INIT_SLV);
+	EHF(NO_RZ_TLBC);
+	// Uncomment once Jesse's code goes in - EHF(NO_RZ_IO_READ); 
+#undef	EHF
+	ret = ia64_sn_set_error_handling_features(sn_ehf_bits);
+	if (ret)
+		printk(KERN_ERR "%s: failed, return code %ld\n", __FUNCTION__, ret);
+}
 
 /**
  * sn_setup - SN platform setup routine
@@ -317,6 +335,9 @@
 		printk(KERN_DEBUG "sn_setup: setting master_node_bedrock_address to 0x%lx\n",
 		       master_node_bedrock_address);
 	}
+
+	/* Tell the prom how to handle certain error types */
+	sn_set_error_handling_features();
 
 	/*
 	 * we set the default root device to /dev/hda
diff -Nru a/arch/m68k/Makefile b/arch/m68k/Makefile
--- a/arch/m68k/Makefile	2004-06-23 19:04:28 -07:00
+++ b/arch/m68k/Makefile	2004-06-23 19:04:28 -07:00
@@ -28,6 +28,8 @@
 LDFLAGS_vmlinux = -N
 endif
 
+CHECK := $(CHECK) -D__mc68000__=1 -I$(shell $(CC) -print-file-name=include)
+
 # without -fno-strength-reduce the 53c7xx.c driver fails ;-(
 CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
 
diff -Nru a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S
--- a/arch/m68k/ifpsp060/iskeleton.S	2004-06-23 19:04:25 -07:00
+++ b/arch/m68k/ifpsp060/iskeleton.S	2004-06-23 19:04:25 -07:00
@@ -196,14 +196,57 @@
 | Expected outputs:
 |	d0 = 0 -> success; non-zero -> failure
 |
-| Linux/68k: As long as ints are disabled, no swapping out should
-| occur (hopefully...)
+| Linux/m68k: Make sure the page is properly paged in, so we use
+| plpaw and handle any exception here. The kernel must not be
+| preempted until _060_unlock_page(), so that the page stays mapped.
 |
 	.global		_060_real_lock_page
 _060_real_lock_page:
-	clr.l		%d0
+	move.l	%d2,-(%sp)
+	| load sfc/dfc
+	moveq	#5,%d0
+	tst.b	%d0
+	jne	1f
+	moveq	#1,%d0
+1:	movec.l	%dfc,%d2
+	movec.l	%d0,%dfc
+	movec.l	%d0,%sfc
+
+	clr.l	%d0
+	| prefetch address
+	.chip	68060
+	move.l	%a0,%a1
+1:	plpaw	(%a1)
+	addq.w	#1,%a0
+	tst.b	%d1
+	jeq	2f
+	addq.w	#2,%a0
+2:	plpaw	(%a0)
+3:	.chip	68k
+
+	| restore sfc/dfc
+	movec.l	%d2,%dfc
+	movec.l	%d2,%sfc
+	move.l	(%sp)+,%d2
 	rts
 
+.section __ex_table,"a"
+	.align	4
+	.long	1b,11f
+	.long	2b,21f
+.previous
+.section .fixup,"ax"
+	.even
+11:	move.l	#0x020003c0,%d0
+	or.l	%d2,%d0
+	swap	%d0
+	jra	3b
+21:	move.l	#0x02000bc0,%d0
+	or.l	%d2,%d0
+	swap	%d0
+	jra	3b
+.previous
+
 |
 | _060_unlock_page():
 |
@@ -216,8 +259,7 @@
 |	d0 = `xxxxxxff -> supervisor; `xxxxxx00 -> user
 |	d1 = `xxxxxxff -> longword; `xxxxxx00 -> word
 |
-| Linux/68k: As we do no special locking operation, also no unlocking
-| is needed...
+| Linux/m68k: perhaps reenable preemption here...
 
 	.global		_060_real_unlock_page
 _060_real_unlock_page:
diff -Nru a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
--- a/arch/m68k/kernel/process.c	2004-06-23 19:04:29 -07:00
+++ b/arch/m68k/kernel/process.c	2004-06-23 19:04:29 -07:00
@@ -26,6 +26,7 @@
 #include <linux/a.out.h>
 #include <linux/reboot.h>
 #include <linux/init_task.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
--- a/arch/m68k/kernel/signal.c	2004-06-23 19:04:27 -07:00
+++ b/arch/m68k/kernel/signal.c	2004-06-23 19:04:27 -07:00
@@ -228,8 +228,8 @@
 		goto out;
 
 	    __asm__ volatile (".chip 68k/68881\n\t"
-			      "fmovemx %0,%/fp0-%/fp1\n\t"
-			      "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
+			      "fmovemx %0,%%fp0-%%fp1\n\t"
+			      "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
 			      ".chip 68k"
 			      : /* no outputs */
 			      : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
@@ -258,7 +258,7 @@
 	if (FPU_IS_EMU) {
 		/* restore fpu control register */
 		if (__copy_from_user(current->thread.fpcntl,
-				&uc->uc_mcontext.fpregs.f_pcr, 12))
+				uc->uc_mcontext.fpregs.f_fpcntl, 12))
 			goto out;
 		/* restore all other fpu register */
 		if (__copy_from_user(current->thread.fp,
@@ -298,12 +298,12 @@
 				     sizeof(fpregs)))
 			goto out;
 		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %0,%/fp0-%/fp7\n\t"
-				  "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
+				  "fmovemx %0,%%fp0-%%fp7\n\t"
+				  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
 				  ".chip 68k"
 				  : /* no outputs */
 				  : "m" (*fpregs.f_fpregs),
-				    "m" (fpregs.f_pcr));
+				    "m" (*fpregs.f_fpcntl));
 	}
 	if (context_size &&
 	    __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
@@ -586,12 +586,12 @@
 				sc->sc_fpstate[0x38] |= 1 << 3;
 		}
 		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %/fp0-%/fp1,%0\n\t"
-				  "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
+				  "fmovemx %%fp0-%%fp1,%0\n\t"
+				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
 				  ".chip 68k"
-				  : /* no outputs */
-				  : "m" (*sc->sc_fpregs),
-				    "m" (*sc->sc_fpcntl)
+				  : "=m" (*sc->sc_fpregs),
+				    "=m" (*sc->sc_fpcntl)
+				  : /* no inputs */
 				  : "memory");
 	}
 }
@@ -604,7 +604,7 @@
 
 	if (FPU_IS_EMU) {
 		/* save fpu control register */
-		err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
+		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
 				current->thread.fpcntl, 12);
 		/* save all other fpu register */
 		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
@@ -631,12 +631,12 @@
 				fpstate[0x38] |= 1 << 3;
 		}
 		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %/fp0-%/fp7,%0\n\t"
-				  "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
+				  "fmovemx %%fp0-%%fp7,%0\n\t"
+				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
 				  ".chip 68k"
-				  : /* no outputs */
-				  : "m" (*fpregs.f_fpregs),
-				    "m" (fpregs.f_pcr)
+				  : "=m" (*fpregs.f_fpregs),
+				    "=m" (*fpregs.f_fpcntl)
+				  : /* no inputs */
 				  : "memory");
 		err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
 				    sizeof(fpregs));
diff -Nru a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
--- a/arch/m68k/kernel/traps.c	2004-06-23 19:04:29 -07:00
+++ b/arch/m68k/kernel/traps.c	2004-06-23 19:04:29 -07:00
@@ -329,7 +329,8 @@
 		 * fault during mem_read/mem_write in ifpsp060/os.S
 		 */
 		send_fault_sig(&fp->ptregs);
-	} else {
+	} else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
+		   send_fault_sig(&fp->ptregs) > 0) {
 		printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
 		printk( "68060 access error, fslw=%lx\n", fslw );
 		trap_c( fp );
@@ -517,7 +518,7 @@
 			if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
 				fp->un.fmt7.wb2s &= ~WBV_040;
 		}
-	} else {
+	} else if (send_fault_sig(&fp->ptregs) > 0) {
 		printk("68040 access error, ssw=%x\n", ssw);
 		trap_c(fp);
 	}
@@ -732,7 +733,7 @@
 				return;
 		} else if (!(mmusr & MMU_I)) {
 			/* probably a 020 cas fault */
-			if (!(ssw & RM))
+			if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
 				printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
 		} else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
 			printk("invalid %s access at %#lx from pc %#lx\n",
diff -Nru a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
--- a/arch/m68k/mac/iop.c	2004-06-23 19:04:28 -07:00
+++ b/arch/m68k/mac/iop.c	2004-06-23 19:04:28 -07:00
@@ -261,7 +261,7 @@
 		} else {
 			iop_base[IOP_NUM_ISM] = (struct mac_iop *) ISM_IOP_BASE_QUADRA;
 		}
-		iop_base[IOP_NUM_SCC]->status_ctrl = 0;
+		iop_base[IOP_NUM_ISM]->status_ctrl = 0;
 		iop_ism_present = 1;
 	} else {
 		iop_base[IOP_NUM_ISM] = NULL;
diff -Nru a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
--- a/arch/m68k/mm/memory.c	2004-06-23 19:04:27 -07:00
+++ b/arch/m68k/mm/memory.c	2004-06-23 19:04:27 -07:00
@@ -54,7 +54,7 @@
 
 	/* unreserve the page so it's possible to free that page */
 	PD_PAGE(dp)->flags &= ~(1 << PG_reserved);
-	atomic_set(&PD_PAGE(dp)->count, 1);
+	set_page_count(PD_PAGE(dp), 1);
 
 	return;
 }
diff -Nru a/arch/m68knommu/kernel/init_task.c b/arch/m68knommu/kernel/init_task.c
--- a/arch/m68knommu/kernel/init_task.c	2004-06-23 19:04:26 -07:00
+++ b/arch/m68knommu/kernel/init_task.c	2004-06-23 19:04:26 -07:00
@@ -7,6 +7,7 @@
 #include <linux/init.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig
--- a/arch/mips/Kconfig	2004-06-23 19:04:27 -07:00
+++ b/arch/mips/Kconfig	2004-06-23 19:04:27 -07:00
@@ -932,11 +932,6 @@
 	depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
 	default n
 
-config COBALT_LCD
-	bool
-	depends on MIPS_COBALT
-	default y
-
 config MIPS_GT96100
 	bool
 	depends on MIPS_EV96100
diff -Nru a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
--- a/arch/mips/configs/cobalt_defconfig	2004-06-23 19:04:26 -07:00
+++ b/arch/mips/configs/cobalt_defconfig	2004-06-23 19:04:26 -07:00
@@ -80,7 +80,6 @@
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_GT64111=y
-CONFIG_COBALT_LCD=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 # CONFIG_FB is not set
 
@@ -432,6 +431,7 @@
 #
 # CONFIG_WATCHDOG is not set
 CONFIG_RTC=y
+CONFIG_COBALT_LCD=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
diff -Nru a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
--- a/arch/mips/configs/ip22_defconfig	2004-06-23 19:04:26 -07:00
+++ b/arch/mips/configs/ip22_defconfig	2004-06-23 19:04:26 -07:00
@@ -583,7 +583,7 @@
 CONFIG_INDYDOG=m
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
-CONFIG_SGI_DS1286=y
+CONFIG_SGI_DS1286=m
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
diff -Nru a/arch/mips/defconfig b/arch/mips/defconfig
--- a/arch/mips/defconfig	2004-06-23 19:04:25 -07:00
+++ b/arch/mips/defconfig	2004-06-23 19:04:25 -07:00
@@ -583,7 +583,7 @@
 CONFIG_INDYDOG=m
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
-CONFIG_SGI_DS1286=y
+CONFIG_SGI_DS1286=m
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
diff -Nru a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c
--- a/arch/mips/kernel/init_task.c	2004-06-23 19:04:26 -07:00
+++ b/arch/mips/kernel/init_task.c	2004-06-23 19:04:26 -07:00
@@ -3,6 +3,7 @@
 #include <linux/sched.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
+#include <linux/mqueue.h>
 
 #include <asm/thread_info.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
--- a/arch/parisc/kernel/init_task.c	2004-06-23 19:04:27 -07:00
+++ b/arch/parisc/kernel/init_task.c	2004-06-23 19:04:27 -07:00
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/init_task.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig	2004-06-23 19:04:29 -07:00
+++ b/arch/ppc/Kconfig	2004-06-23 19:04:29 -07:00
@@ -72,8 +72,21 @@
 config 8xx
 	bool "8xx"
 
+config E500
+	bool "e500"
+
 endchoice
 
+config BOOKE
+	bool
+	depends on E500
+	default y
+
+config FSL_BOOKE
+	bool
+	depends on E500
+	default y
+
 config PTE_64BIT
 	bool
 	depends on 44x
@@ -96,6 +109,21 @@
 
 	  If in doubt, say Y here.
 
+config SPE
+	bool "SPE Support"
+	depends on E500
+	---help---
+	  This option enables kernel support for the Signal Processing
+	  Extensions (SPE) to the PowerPC processor. The kernel currently
+	  supports saving and restoring SPE registers, and turning on the
+	  'spe enable' bit so user processes can execute SPE instructions.
+
+	  This option is only usefully if you have a processor that supports
+	  SPE (e500, otherwise known as 85xx series), but does not have any
+	  affect on a non-spe cpu (it does, however add code to the kernel).
+
+	  If in doubt, say Y here.
+
 config TAU
 	bool "Thermal Management Support"
 	depends on 6xx && !8260
@@ -142,7 +170,7 @@
 
 config MATH_EMULATION
 	bool "Math emulation"
-	depends on 4xx || 8xx
+	depends on 4xx || 8xx || E500
 	---help---
 	  Some PowerPC chips designed for embedded applications do not have
 	  a floating-point unit and therefore do not implement the
@@ -198,6 +226,7 @@
 	  If in doubt, say Y here.
 
 source arch/ppc/platforms/4xx/Kconfig
+source arch/ppc/platforms/85xx/Kconfig
 
 config PPC64BRIDGE
 	bool
@@ -974,8 +1003,8 @@
 	bool
 
 config PCI
-	bool "PCI support" if 40x || 8260
-	default y if !40x && !8260 && !8xx && !APUS
+	bool "PCI support" if 40x || 8260 || 85xx
+	default y if !40x && !8260 && !8xx && !APUS && !85xx
 	default PCI_PERMEDIA if !4xx && !8260 && !8xx && APUS
 	default PCI_QSPAN if !4xx && !8260 && 8xx
 	help
@@ -1154,6 +1183,7 @@
 
 source "lib/Kconfig"
 
+source "arch/ppc/oprofile/Kconfig"
 
 menu "Kernel hacking"
 
@@ -1273,7 +1303,7 @@
 
 config PPC_OCP
 	bool
-	depends on IBM_OCP
+	depends on IBM_OCP || FSL_OCP
 	default y
 
 endmenu
diff -Nru a/arch/ppc/Makefile b/arch/ppc/Makefile
--- a/arch/ppc/Makefile	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc/Makefile	2004-06-23 19:04:25 -07:00
@@ -17,19 +17,24 @@
 CPPFLAGS	+= -Iarch/$(ARCH)
 AFLAGS		+= -Iarch/$(ARCH)
 cflags-y	+= -Iarch/$(ARCH) -msoft-float -pipe \
-		-ffixed-r2 -Wno-uninitialized -mmultiple -mstring
+		-ffixed-r2 -Wno-uninitialized -mmultiple
 CPP		= $(CC) -E $(CFLAGS)
 
+ifndef CONFIG_E500
+cflags-y	+= -mstring
+endif
+
 cflags-$(CONFIG_4xx)		+= -Wa,-m405
+cflags-$(CONFIG_E500)		+= -Wa,-me500
 cflags-$(CONFIG_PPC64BRIDGE)	+= -Wa,-mppc64bridge
 
 CFLAGS += $(cflags-y)
 
-
 head-y				:= arch/ppc/kernel/head.o
 head-$(CONFIG_8xx)		:= arch/ppc/kernel/head_8xx.o
 head-$(CONFIG_4xx)		:= arch/ppc/kernel/head_4xx.o
 head-$(CONFIG_44x)		:= arch/ppc/kernel/head_44x.o
+head-$(CONFIG_E500)		:= arch/ppc/kernel/head_e500.o
 
 head-$(CONFIG_6xx)		+= arch/ppc/kernel/idle_6xx.o
 head-$(CONFIG_POWER4)		+= arch/ppc/kernel/idle_power4.o
@@ -37,12 +42,15 @@
 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_85xx)		+= arch/ppc/platforms/85xx/
 core-$(CONFIG_MATH_EMULATION)	+= arch/ppc/math-emu/
 core-$(CONFIG_XMON)		+= arch/ppc/xmon/
 core-$(CONFIG_APUS)		+= arch/ppc/amiga/
 drivers-$(CONFIG_8xx)		+= arch/ppc/8xx_io/
 drivers-$(CONFIG_4xx)		+= arch/ppc/4xx_io/
 drivers-$(CONFIG_8260)		+= arch/ppc/8260_io/
+
+drivers-$(CONFIG_OPROFILE)	+= arch/ppc/oprofile/
 
 BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
 
diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
--- a/arch/ppc/kernel/Makefile	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc/kernel/Makefile	2004-06-23 19:04:28 -07:00
@@ -8,10 +8,14 @@
 ifdef CONFIG_4xx
 EXTRA_AFLAGS		:= -Wa,-m405
 endif
+ifdef CONFIG_E500
+EXTRA_AFLAGS		:= -Wa,-me500
+endif
 
 extra-$(CONFIG_PPC_STD_MMU)	:= head.o
 extra-$(CONFIG_40x)		:= head_4xx.o
 extra-$(CONFIG_44x)		:= head_44x.o
+extra-$(CONFIG_E500)		:= head_e500.o
 extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-$(CONFIG_6xx)		+= idle_6xx.o
 extra-$(CONFIG_POWER4)		+= idle_power4.o
diff -Nru a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
--- a/arch/ppc/kernel/align.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc/kernel/align.c	2004-06-23 19:04:25 -07:00
@@ -21,7 +21,7 @@
 	unsigned char flags;
 };
 
-#if defined(CONFIG_4xx) || defined(CONFIG_POWER4)
+#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) || defined(CONFIG_BOOKE)
 #define	OPCD(inst)	(((inst) & 0xFC000000) >> 26)
 #define	RS(inst)	(((inst) & 0x03E00000) >> 21)
 #define	RA(inst)	(((inst) & 0x001F0000) >> 16)
@@ -184,7 +184,7 @@
 fix_alignment(struct pt_regs *regs)
 {
 	int instr, nb, flags;
-#if defined(CONFIG_4xx) || defined(CONFIG_POWER4)
+#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) || defined(CONFIG_BOOKE)
 	int opcode, f1, f2, f3;
 #endif
 	int i, t;
@@ -199,8 +199,8 @@
 
 	CHECK_FULL_REGS(regs);
 
-#if defined(CONFIG_4xx) || defined(CONFIG_POWER4)
-	/* The 4xx-family processors have no DSISR register,
+#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) || defined(CONFIG_BOOKE)
+	/* The 4xx-family & Book-E processors have no DSISR register,
 	 * so we emulate it.
 	 * The POWER4 has a DSISR register but doesn't set it on
 	 * an alignment fault.  -- paulus
@@ -250,7 +250,7 @@
 
 	flags = aligninfo[instr].flags;
 
-	/* For the 4xx-family processors, the 'dar' field of the
+	/* For the 4xx-family & Book-E processors, the 'dar' field of the
 	 * pt_regs structure is overloaded and is really from the DEAR.
 	 */
 
diff -Nru a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
--- a/arch/ppc/kernel/asm-offsets.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc/kernel/asm-offsets.c	2004-06-23 19:04:27 -07:00
@@ -44,7 +44,7 @@
 	DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
 	DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
 	DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 	DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
 	DEFINE(PT_PTRACED, PT_PTRACED);
 #endif
@@ -54,6 +54,12 @@
 	DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
 	DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+	DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0]));
+	DEFINE(THREAD_ACC, offsetof(struct thread_struct, acc));
+	DEFINE(THREAD_SPEFSCR, offsetof(struct thread_struct, spefscr));
+	DEFINE(THREAD_USED_SPE, offsetof(struct thread_struct, used_spe));
+#endif /* CONFIG_SPE */
 	/* Interrupt register frame */
 	DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
 	DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
diff -Nru a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
--- a/arch/ppc/kernel/cputable.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc/kernel/cputable.c	2004-06-23 19:04:27 -07:00
@@ -34,7 +34,8 @@
 extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
 
 #define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \
-		     !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4))
+		     !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
+		     !defined(CONFIG_BOOKE))
 
 /* This table only contains "desktop" CPUs, it need to be filled with embedded
  * ones as well...
@@ -561,6 +562,16 @@
         0, /*__setup_cpu_440 */
     },
 #endif /* CONFIG_44x */
+#ifdef CONFIG_E500
+    { /* e500 */
+        0xffff0000, 0x80200000, "e500",
+	/* xxx - galak: add CPU_FTR_CAN_DOZE */
+        CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
+        PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+        32, 32,
+        0, /*__setup_cpu_e500 */
+    },
+#endif
 #if !CLASSIC_PPC
     {	/* default match */
     	0x00000000, 0x00000000, "(generic PPC)",
diff -Nru a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
--- a/arch/ppc/kernel/entry.S	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc/kernel/entry.S	2004-06-23 19:04:28 -07:00
@@ -36,7 +36,7 @@
 #undef SHOW_SYSCALLS_TASK
 
 /*
- * MSR_KERNEL is > 0x10000 on 4xx since it include MSR_CE.
+ * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
  */
 #if MSR_KERNEL >= 0x10000
 #define LOAD_MSR_KERNEL(r, x)	lis r,(x)@h; ori r,r,(x)@l
@@ -45,7 +45,7 @@
 #endif
 
 #ifdef CONFIG_BOOKE
-#define	COR	r8
+#define	COR	r8	/* Critical Offset Register (COR) */
 #define BOOKE_LOAD_COR	lis COR,crit_save@ha
 #define BOOKE_REST_COR	mfspr COR,SPRG2
 #define BOOKE_SAVE_COR	mtspr SPRG2,COR
@@ -241,11 +241,11 @@
 	andi.	r0,r9,(_TIF_SYSCALL_TRACE|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
 	bne-	syscall_exit_work
 syscall_exit_cont:
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 	/* If the process has its own DBCR0 value, load it up */
 	lwz	r0,PTRACE(r2)
 	andi.	r0,r0,PT_PTRACED
-	bnel-	load_4xx_dbcr0
+	bnel-	load_dbcr0
 #endif
 	stwcx.	r0,0,r1			/* to clear the reservation */
 	lwz	r4,_LINK(r1)
@@ -510,7 +510,12 @@
 	stw	r12,THREAD+THREAD_VRSAVE(r2)
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif /* CONFIG_ALTIVEC */
-	and.	r0,r0,r11	/* FP or altivec enabled? */
+#ifdef CONFIG_SPE
+	oris	r0,r0,MSR_SPE@h	 /* Disable SPE */
+	mfspr	r12,SPRN_SPEFSCR /* save spefscr register value */
+	stw	r12,THREAD+THREAD_SPEFSCR(r2)
+#endif /* CONFIG_SPE */
+	and.	r0,r0,r11	/* FP or altivec or SPE enabled? */
 	beq+	1f
 	andc	r11,r11,r0
 	MTMSRD(r11)
@@ -543,6 +548,10 @@
 	mtspr	SPRN_VRSAVE,r0		/* if G4, restore VRSAVE reg */
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+	lwz	r0,THREAD+THREAD_SPEFSCR(r2)
+	mtspr	SPRN_SPEFSCR,r0		/* restore SPEFSCR reg */
+#endif /* CONFIG_SPE */
 
 	lwz	r0,_CCR(r1)
 	mtcrf	0xFF,r0
@@ -589,11 +598,11 @@
 	bne	do_work
 
 restore_user:
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 	/* Check whether this process has its own DBCR0 value */
 	lwz	r0,PTRACE(r2)
 	andi.	r0,r0,PT_PTRACED
-	bnel-	load_4xx_dbcr0
+	bnel-	load_dbcr0
 #endif
 
 #ifdef CONFIG_PREEMPT
@@ -645,7 +654,7 @@
 	PPC405_ERR77(0,r1)
 	stwcx.	r0,0,r1			/* to clear the reservation */
 
-#ifndef CONFIG_4xx
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
 	lwz	r9,_MSR(r1)
 	andi.	r10,r9,MSR_RI		/* check if this exception occurred */
 	beql	nonrecoverable		/* at a bad place (MSR:RI = 0) */
@@ -681,9 +690,9 @@
 	SYNC
 	RFI
 
-#else /* CONFIG_4xx */
+#else /* !(CONFIG_4xx || CONFIG_BOOKE) */
 	/*
-	 * This is a bit different on 4xx because 4xx doesn't have
+	 * This is a bit different on 4xx/Book-E because it doesn't have
 	 * the RI bit in the MSR.
 	 * The TLB miss handler checks if we have interrupted
 	 * the exception exit path and restarts it if so
@@ -720,6 +729,9 @@
  * give the wrong answer).
  * We have to restore various SPRs that may have been in use at the
  * time of the critical interrupt.
+ *
+ * Note that SPRG6 is used for machine check on CONFIG_BOOKE parts and
+ * thus not saved in the critical handler
  */
 	.globl	ret_from_crit_exc
 ret_from_crit_exc:
@@ -866,7 +878,7 @@
  * Load the DBCR0 value for a task that is being ptraced,
  * having first saved away the global DBCR0.
  */
-load_4xx_dbcr0:
+load_dbcr0:
 	mfmsr	r0		/* first disable debug exceptions */
 	rlwinm	r0,r0,0,~MSR_DE
 	mtmsr	r0
@@ -885,7 +897,7 @@
 	blr
 
 	.comm	global_dbcr0,8
-#endif /* CONFIG_4xx */
+#endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
 
 do_work:			/* r10 contains MSR_KERNEL here */
 	andi.	r0,r9,_TIF_NEED_RESCHED
diff -Nru a/arch/ppc/kernel/head_e500.S b/arch/ppc/kernel/head_e500.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/kernel/head_e500.S	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,1329 @@
+/*
+ * arch/ppc/kernel/head_e500.S
+ *
+ * Kernel execution entry point code.
+ *
+ *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
+ *      Initial PowerPC version.
+ *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
+ *      Rewritten for PReP
+ *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ *      Low-level exception handers, MMU support, and rewrite.
+ *    Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
+ *      PowerPC 8xx modifications.
+ *    Copyright (c) 1998-1999 TiVo, Inc.
+ *      PowerPC 403GCX modifications.
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *      PowerPC 403GCX/405GP modifications.
+ *    Copyright 2000 MontaVista Software Inc.
+ *	PPC405 modifications
+ *      PowerPC 403GCX/405GP modifications.
+ * 	Author: MontaVista Software, Inc.
+ *         	frank_rowand@mvista.com or source@mvista.com
+ * 	   	debbie_chu@mvista.com
+ *    Copyright 2002-2004 MontaVista Software, Inc.
+ *      PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org>
+ *    Copyright 2004 Freescale Semiconductor, Inc
+ *      PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+/*
+ * Macros
+ */
+
+#define SET_IVOR(vector_number, vector_label)		\
+		li	r26,vector_label@l; 		\
+		mtspr	SPRN_IVOR##vector_number,r26;	\
+		sync
+
+/* As with the other PowerPC ports, it is expected that when code
+ * execution begins here, the following registers contain valid, yet
+ * optional, information:
+ *
+ *   r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
+ *   r4 - Starting address of the init RAM disk
+ *   r5 - Ending address of the init RAM disk
+ *   r6 - Start of kernel command line string (e.g. "mem=128")
+ *   r7 - End of kernel command line string
+ *
+ */
+	.text
+_GLOBAL(_stext)
+_GLOBAL(_start)
+	/*
+	 * Reserve a word at a fixed location to store the address
+	 * of abatron_pteptrs
+	 */
+	nop
+/*
+ * Save parameters we are passed
+ */
+	mr	r31,r3
+	mr	r30,r4
+	mr	r29,r5
+	mr	r28,r6
+	mr	r27,r7
+	li	r24,0		/* CPU number */
+
+/* We try to not make any assumptions about how the boot loader
+ * setup or used the TLBs.  We invalidate all mappings from the
+ * boot loader and load a single entry in TLB1[0] to map the
+ * first 16M of kernel memory.  Any boot info passed from the
+ * bootloader needs to live in this first 16M.
+ *
+ * Requirement on bootloader:
+ *  - The page we're executing in needs to reside in TLB1 and
+ *    have IPROT=1.  If not an invalidate broadcast could
+ *    evict the entry we're currently executing in.
+ *
+ *  r3 = Index of TLB1 were executing in
+ *  r4 = Current MSR[IS]
+ *  r5 = Index of TLB1 temp mapping
+ *
+ * Later in mapin_ram we will correctly map lowmem, and resize TLB1[0]
+ * if needed
+ */
+
+/* 1. Find the index of the entry we're executing in */
+	bl	invstr				/* Find our address */
+invstr:	mflr	r6				/* Make it accessible */
+	mfmsr	r7
+	rlwinm	r4,r7,27,31,31			/* extract MSR[IS] */
+	mfspr	r7, SPRN_PID0
+	slwi	r7,r7,16
+	or	r7,r7,r4
+	mtspr	SPRN_MAS6,r7
+	tlbsx	0,r6				/* search MSR[IS], SPID=PID0 */
+	mfspr	r7,SPRN_MAS1
+	andis.	r7,r7,MAS1_VALID@h
+	bne	match_TLB
+	mfspr	r7,SPRN_PID1
+	slwi	r7,r7,16
+	or	r7,r7,r4
+	mtspr	SPRN_MAS6,r7
+	tlbsx	0,r6				/* search MSR[IS], SPID=PID1 */
+	mfspr	r7,SPRN_MAS1
+	andis.	r7,r7,MAS1_VALID@h
+	bne	match_TLB
+	mfspr	r7, SPRN_PID2
+	slwi	r7,r7,16
+	or	r7,r7,r4
+	mtspr	SPRN_MAS6,r7
+	tlbsx	0,r6				/* Fall through, we had to match */
+match_TLB:
+	mfspr	r7,SPRN_MAS0
+	rlwinm	r3,r7,16,28,31			/* Extract MAS0(Entry) */
+
+	mfspr	r7,SPRN_MAS1			/* Insure IPROT set */
+	oris	r7,r7,MAS1_IPROT@h
+	mtspr	SPRN_MAS1,r7
+	tlbwe
+
+/* 2. Invalidate all entries except the entry we're executing in */
+	mfspr	r9,SPRN_TLB1CFG
+	andi.	r9,r9,0xfff
+	li	r6,0				/* Set Entry counter to 0 */
+1:	lis	r7,0x1000			/* Set MAS0(TLBSEL) = 1 */
+	rlwimi	r7,r6,16,12,15			/* Setup MAS0 = TLBSEL | ESEL(r6) */
+	mtspr	SPRN_MAS0,r7
+	tlbre
+	mfspr	r7,SPRN_MAS1
+	rlwinm	r7,r7,0,2,31			/* Clear MAS1 Valid and IPROT */
+	cmpw	r3,r6
+	beq	skpinv				/* Dont update the current execution TLB */
+	mtspr	SPRN_MAS1,r7
+	tlbwe
+	isync
+skpinv:	addi	r6,r6,1				/* Increment */
+	cmpw	r6,r9				/* Are we done? */
+	bne	1b				/* If not, repeat */
+
+	/* Invalidate TLB0 */
+	li      r6,0x04
+	tlbivax 0,r6
+#ifdef CONFIG_SMP
+	tlbsync
+#endif
+	/* Invalidate TLB1 */
+	li      r6,0x0c
+	tlbivax 0,r6
+#ifdef CONFIG_SMP
+	tlbsync
+#endif
+	msync
+
+/* 3. Setup a temp mapping and jump to it */
+	andi.	r5, r3, 0x1	/* Find an entry not used and is non-zero */
+	addi	r5, r5, 0x1
+	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
+	rlwimi	r7,r3,16,12,15	/* Setup MAS0 = TLBSEL | ESEL(r3) */
+	mtspr	SPRN_MAS0,r7
+	tlbre
+
+	/* Just modify the entry ID and EPN for the temp mapping */
+	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
+	rlwimi	r7,r5,16,12,15	/* Setup MAS0 = TLBSEL | ESEL(r5) */
+	mtspr	SPRN_MAS0,r7
+	xori	r6,r4,1		/* Setup TMP mapping in the other Address space */
+	slwi	r6,r6,12
+	oris	r6,r6,(MAS1_VALID|MAS1_IPROT)@h
+	ori	r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
+	mtspr	SPRN_MAS1,r6
+	mfspr	r6,SPRN_MAS2
+	li	r7,0		/* temp EPN = 0 */
+	rlwimi	r7,r6,0,20,31
+	mtspr	SPRN_MAS2,r7
+	tlbwe
+
+	xori	r6,r4,1
+	slwi	r6,r6,5		/* setup new context with other address space */
+	bl	1f		/* Find our address */
+1:	mflr	r9
+	rlwimi	r7,r9,0,20,31
+	addi	r7,r7,24
+	mtspr	SRR0,r7
+	mtspr	SRR1,r6
+	rfi
+
+/* 4. Clear out PIDs & Search info */
+	li	r6,0
+	mtspr	SPRN_PID0,r6
+	mtspr	SPRN_PID1,r6
+	mtspr	SPRN_PID2,r6
+	mtspr	SPRN_MAS6,r6
+
+/* 5. Invalidate mapping we started in */
+	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
+	rlwimi	r7,r3,16,12,15	/* Setup MAS0 = TLBSEL | ESEL(r3) */
+	mtspr	SPRN_MAS0,r7
+	tlbre
+	li	r6,0
+	mtspr	SPRN_MAS1,r6
+	tlbwe
+	/* Invalidate TLB1 */
+	li      r9,0x0c
+	tlbivax 0,r9
+#ifdef CONFIG_SMP
+	tlbsync
+#endif
+	msync
+
+/* 6. Setup KERNELBASE mapping in TLB1[0] */
+	lis	r6,0x1000		/* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
+	mtspr	SPRN_MAS0,r6
+	lis	r6,(MAS1_VALID|MAS1_IPROT)@h
+	ori	r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_16M))@l
+	mtspr	SPRN_MAS1,r6
+	li	r7,0
+	lis	r6,KERNELBASE@h
+	ori	r6,r6,KERNELBASE@l
+	rlwimi	r6,r7,0,20,31
+	mtspr	SPRN_MAS2,r6
+	li	r7,(MAS3_SX|MAS3_SW|MAS3_SR)
+	mtspr	SPRN_MAS3,r7
+	tlbwe
+
+/* 7. Jump to KERNELBASE mapping */
+	li	r7,0
+	bl	1f			/* Find our address */
+1:	mflr	r9
+	rlwimi	r6,r9,0,20,31
+	addi	r6,r6,24
+	mtspr	SRR0,r6
+	mtspr	SRR1,r7
+	rfi				/* start execution out of TLB1[0] entry */
+
+/* 8. Clear out the temp mapping */
+	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
+	rlwimi	r7,r5,16,12,15	/* Setup MAS0 = TLBSEL | ESEL(r5) */
+	mtspr	SPRN_MAS0,r7
+	tlbre
+	mtspr	SPRN_MAS1,r8
+	tlbwe
+	/* Invalidate TLB1 */
+	li      r9,0x0c
+	tlbivax 0,r9
+#ifdef CONFIG_SMP
+	tlbsync
+#endif
+	msync
+
+	/* Establish the interrupt vector offsets */
+	SET_IVOR(0,  CriticalInput);
+	SET_IVOR(1,  MachineCheck);
+	SET_IVOR(2,  DataStorage);
+	SET_IVOR(3,  InstructionStorage);
+	SET_IVOR(4,  ExternalInput);
+	SET_IVOR(5,  Alignment);
+	SET_IVOR(6,  Program);
+	SET_IVOR(7,  FloatingPointUnavailable);
+	SET_IVOR(8,  SystemCall);
+	SET_IVOR(9,  AuxillaryProcessorUnavailable);
+	SET_IVOR(10, Decrementer);
+	SET_IVOR(11, FixedIntervalTimer);
+	SET_IVOR(12, WatchdogTimer);
+	SET_IVOR(13, DataTLBError);
+	SET_IVOR(14, InstructionTLBError);
+	SET_IVOR(15, Debug);
+	SET_IVOR(32, SPEUnavailable);
+	SET_IVOR(33, SPEFloatingPointData);
+	SET_IVOR(34, SPEFloatingPointRound);
+	SET_IVOR(35, PerformanceMonitor);
+
+	/* Establish the interrupt vector base */
+	lis	r4,interrupt_base@h	/* IVPR only uses the high 16-bits */
+	mtspr	SPRN_IVPR,r4
+
+	/* Setup the defaults for TLB entries */
+	li	r2,MAS4_TSIZED(BOOKE_PAGESZ_4K)
+   	mtspr	SPRN_MAS4, r2
+
+#if 0
+	/* Enable DOZE */
+	mfspr	r2,SPRN_HID0
+	oris	r2,r2,HID0_DOZE@h
+	mtspr	SPRN_HID0, r2
+#endif
+
+	/*
+	 * This is where the main kernel code starts.
+	 */
+
+	/* ptr to current */
+	lis	r2,init_task@h
+	ori	r2,r2,init_task@l
+
+	/* ptr to current thread */
+	addi	r4,r2,THREAD	/* init task's THREAD */
+	mtspr	SPRG3,r4
+
+	/* stack */
+	lis	r1,init_thread_union@h
+	ori	r1,r1,init_thread_union@l
+	li	r0,0
+	stwu	r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
+
+	bl	early_init
+
+	mfspr	r3,SPRN_TLB1CFG
+	andi.	r3,r3,0xfff
+	lis	r4,num_tlbcam_entries@ha
+	stw	r3,num_tlbcam_entries@l(r4)
+/*
+ * Decide what sort of machine this is and initialize the MMU.
+ */
+	mr	r3,r31
+	mr	r4,r30
+	mr	r5,r29
+	mr	r6,r28
+	mr	r7,r27
+	bl	machine_init
+	bl	MMU_init
+
+	/* Setup PTE pointers for the Abatron bdiGDB */
+	lis	r6, swapper_pg_dir@h
+	ori	r6, r6, swapper_pg_dir@l
+	lis	r5, abatron_pteptrs@h
+	ori	r5, r5, abatron_pteptrs@l
+	lis	r4, KERNELBASE@h
+	ori	r4, r4, KERNELBASE@l
+	stw	r5, 0(r4)	/* Save abatron_pteptrs at a fixed location */
+	stw	r6, 0(r5)
+
+	/* Let's move on */
+	lis	r4,start_kernel@h
+	ori	r4,r4,start_kernel@l
+	lis	r3,MSR_KERNEL@h
+	ori	r3,r3,MSR_KERNEL@l
+	mtspr	SRR0,r4
+	mtspr	SRR1,r3
+	rfi			/* change context and jump to start_kernel */
+
+/*
+ * Interrupt vector entry code
+ *
+ * The Book E MMUs are always on so we don't need to handle
+ * interrupts in real mode as with previous PPC processors. In
+ * this case we handle interrupts in the kernel virtual address
+ * space.
+ *
+ * Interrupt vectors are dynamically placed relative to the
+ * interrupt prefix as determined by the address of interrupt_base.
+ * The interrupt vectors offsets are programmed using the labels
+ * for each interrupt vector entry.
+ *
+ * Interrupt vectors must be aligned on a 16 byte boundary.
+ * We align on a 32 byte cache line boundary for good measure.
+ */
+
+#define NORMAL_EXCEPTION_PROLOG						     \
+	mtspr	SPRN_SPRG0,r10;		/* save two registers to work with */\
+	mtspr	SPRN_SPRG1,r11;						     \
+	mtspr	SPRN_SPRG4W,r1;						     \
+	mfcr	r10;			/* save CR in r10 for now	   */\
+	mfspr	r11,SPRN_SRR1;		/* check whether user or kernel    */\
+	andi.	r11,r11,MSR_PR;						     \
+	beq	1f;							     \
+	mfspr	r1,SPRG3;		/* if from user, start at top of   */\
+	lwz	r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
+	addi	r1,r1,THREAD_SIZE;					     \
+1:	subi	r1,r1,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
+	tophys(r11,r1);							     \
+	stw	r10,_CCR(r11);          /* save various registers	   */\
+	stw	r12,GPR12(r11);						     \
+	stw	r9,GPR9(r11);						     \
+	mfspr	r10,SPRG0;						     \
+	stw	r10,GPR10(r11);						     \
+	mfspr	r12,SPRG1;						     \
+	stw	r12,GPR11(r11);						     \
+	mflr	r10;							     \
+	stw	r10,_LINK(r11);						     \
+	mfspr	r10,SPRG4R;						     \
+	mfspr	r12,SRR0;						     \
+	stw	r10,GPR1(r11);						     \
+	mfspr	r9,SRR1;						     \
+	stw	r10,0(r11);						     \
+	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
+	stw	r0,GPR0(r11);						     \
+	SAVE_4GPRS(3, r11);						     \
+	SAVE_2GPRS(7, r11)
+
+/*
+ * Exception prolog for critical exceptions.  This is a little different
+ * from the normal exception prolog above since a critical exception
+ * can potentially occur at any point during normal exception processing.
+ * Thus we cannot use the same SPRG registers as the normal prolog above.
+ * Instead we use a couple of words of memory at low physical addresses.
+ * This is OK since we don't support SMP on these processors. For Book E
+ * processors, we also have a reserved register (SPRG2) that is only used
+ * in critical exceptions so we can free up a GPR to use as the base for
+ * indirect access to the critical exception save area.  This is necessary
+ * since the MMU is always on and the save area is offset from KERNELBASE.
+ */
+#define CRITICAL_EXCEPTION_PROLOG					     \
+	mtspr	SPRG2,r8;		/* SPRG2 only used in criticals */   \
+	lis	r8,crit_save@ha;					     \
+	stw	r10,crit_r10@l(r8);					     \
+	stw	r11,crit_r11@l(r8);					     \
+	mfspr	r10,SPRG0;						     \
+	stw	r10,crit_sprg0@l(r8);					     \
+	mfspr	r10,SPRG1;						     \
+	stw	r10,crit_sprg1@l(r8);					     \
+	mfspr	r10,SPRG4R;						     \
+	stw	r10,crit_sprg4@l(r8);					     \
+	mfspr	r10,SPRG5R;						     \
+	stw	r10,crit_sprg5@l(r8);					     \
+	mfspr	r10,SPRG7R;						     \
+	stw	r10,crit_sprg7@l(r8);					     \
+	mfspr	r10,SPRN_PID;						     \
+	stw	r10,crit_pid@l(r8);					     \
+	mfspr	r10,SRR0;						     \
+	stw	r10,crit_srr0@l(r8);					     \
+	mfspr	r10,SRR1;						     \
+	stw	r10,crit_srr1@l(r8);					     \
+	mfspr	r8,SPRG2;		/* SPRG2 only used in criticals */   \
+	mfcr	r10;			/* save CR in r10 for now	   */\
+	mfspr	r11,SPRN_CSRR1;		/* check whether user or kernel    */\
+	andi.	r11,r11,MSR_PR;						     \
+	lis	r11,critical_stack_top@h;				     \
+	ori	r11,r11,critical_stack_top@l;				     \
+	beq	1f;							     \
+	/* COMING FROM USER MODE */					     \
+	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
+	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
+	addi	r11,r11,THREAD_SIZE;					     \
+1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
+	stw	r10,_CCR(r11);          /* save various registers	   */\
+	stw	r12,GPR12(r11);						     \
+	stw	r9,GPR9(r11);						     \
+	mflr	r10;							     \
+	stw	r10,_LINK(r11);						     \
+	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
+	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
+	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
+	stw	r9,_ESR(r11);		/* exception was taken		   */\
+	mfspr	r12,CSRR0;						     \
+	stw	r1,GPR1(r11);						     \
+	mfspr	r9,CSRR1;						     \
+	stw	r1,0(r11);						     \
+	tovirt(r1,r11);							     \
+	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
+	stw	r0,GPR0(r11);						     \
+	SAVE_4GPRS(3, r11);						     \
+	SAVE_2GPRS(7, r11)
+
+/*
+ * Exception prolog for machine check exceptions.  This is similar to
+ * the critical exception prolog, except that machine check exceptions
+ * have their own save area.  For Book E processors, we also have a
+ * reserved register (SPRG6) that is only used in machine check exceptions
+ * so we can free up a GPR to use as the base for indirect access to the
+ * machine check exception save area.  This is necessary since the MMU
+ * is always on and the save area is offset from KERNELBASE.
+ */
+#define MCHECK_EXCEPTION_PROLOG					     \
+	mtspr	SPRG6W,r8;		/* SPRG6 used in machine checks */   \
+	lis	r8,mcheck_save@ha;					     \
+	stw	r10,mcheck_r10@l(r8);					     \
+	stw	r11,mcheck_r11@l(r8);					     \
+	mfspr	r10,SPRG0;						     \
+	stw	r10,mcheck_sprg0@l(r8);					     \
+	mfspr	r10,SPRG1;						     \
+	stw	r10,mcheck_sprg1@l(r8);					     \
+	mfspr	r10,SPRG4R;						     \
+	stw	r10,mcheck_sprg4@l(r8);					     \
+	mfspr	r10,SPRG5R;						     \
+	stw	r10,mcheck_sprg5@l(r8);					     \
+	mfspr	r10,SPRG7R;						     \
+	stw	r10,mcheck_sprg7@l(r8);					     \
+	mfspr	r10,SPRN_PID;						     \
+	stw	r10,mcheck_pid@l(r8);					     \
+	mfspr	r10,SRR0;						     \
+	stw	r10,mcheck_srr0@l(r8);					     \
+	mfspr	r10,SRR1;						     \
+	stw	r10,mcheck_srr1@l(r8);					     \
+	mfspr	r10,CSRR0;						     \
+	stw	r10,mcheck_csrr0@l(r8);					     \
+	mfspr	r10,CSRR1;						     \
+	stw	r10,mcheck_csrr1@l(r8);					     \
+	mfspr	r8,SPRG6R;		/* SPRG6 used in machine checks */   \
+	mfcr	r10;			/* save CR in r10 for now	   */\
+	mfspr	r11,SPRN_MCSRR1;	/* check whether user or kernel    */\
+	andi.	r11,r11,MSR_PR;						     \
+	lis	r11,mcheck_stack_top@h;					     \
+	ori	r11,r11,mcheck_stack_top@l;				     \
+	beq	1f;							     \
+	/* COMING FROM USER MODE */					     \
+	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
+	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
+	addi	r11,r11,THREAD_SIZE;					     \
+1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
+	stw	r10,_CCR(r11);          /* save various registers	   */\
+	stw	r12,GPR12(r11);						     \
+	stw	r9,GPR9(r11);						     \
+	mflr	r10;							     \
+	stw	r10,_LINK(r11);						     \
+	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
+	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
+	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
+	stw	r9,_ESR(r11);		/* exception was taken		   */\
+	mfspr	r12,MCSRR0;						     \
+	stw	r1,GPR1(r11);						     \
+	mfspr	r9,MCSRR1;						     \
+	stw	r1,0(r11);						     \
+	tovirt(r1,r11);							     \
+	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
+	stw	r0,GPR0(r11);						     \
+	SAVE_4GPRS(3, r11);						     \
+	SAVE_2GPRS(7, r11)
+
+/*
+ * Exception vectors.
+ */
+#define	START_EXCEPTION(label)						     \
+        .align 5;              						     \
+label:
+
+#define FINISH_EXCEPTION(func)					\
+	bl	transfer_to_handler_full;			\
+	.long	func;						\
+	.long	ret_from_except_full
+
+#define EXCEPTION(n, label, hdlr, xfer)				\
+	START_EXCEPTION(label);					\
+	NORMAL_EXCEPTION_PROLOG;				\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
+	xfer(n, hdlr)
+
+#define CRITICAL_EXCEPTION(n, label, hdlr)			\
+	START_EXCEPTION(label);					\
+	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)
+
+#define MCHECK_EXCEPTION(n, label, hdlr)			\
+	START_EXCEPTION(label);					\
+	MCHECK_EXCEPTION_PROLOG;				\
+	mfspr	r5,SPRN_ESR;					\
+	stw	r5,_ESR(r11);					\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
+	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+			  NOCOPY, mcheck_transfer_to_handler,   \
+			  ret_from_mcheck_exc)
+
+#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)	\
+	li	r10,trap;					\
+	stw	r10,TRAP(r11);					\
+	lis	r10,msr@h;					\
+	ori	r10,r10,msr@l;					\
+	copyee(r10, r9);					\
+	bl	tfer;		 				\
+	.long	hdlr;						\
+	.long	ret
+
+#define COPY_EE(d, s)		rlwimi d,s,0,16,16
+#define NOCOPY(d, s)
+
+#define EXC_XFER_STD(n, hdlr)		\
+	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
+			  ret_from_except_full)
+
+#define EXC_XFER_LITE(n, hdlr)		\
+	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
+			  ret_from_except)
+
+#define EXC_XFER_EE(n, hdlr)		\
+	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
+			  ret_from_except_full)
+
+#define EXC_XFER_EE_LITE(n, hdlr)	\
+	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
+			  ret_from_except)
+
+interrupt_base:
+	/* Critical Input Interrupt */
+	CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
+
+	/* Machine Check Interrupt */
+	MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+
+	/* Data Storage Interrupt */
+	START_EXCEPTION(DataStorage)
+	mtspr	SPRG0, r10		/* Save some working registers */
+	mtspr	SPRG1, r11
+	mtspr	SPRG4W, r12
+	mtspr	SPRG5W, r13
+	mfcr	r11
+	mtspr	SPRG7W, r11
+
+	/*
+	 * Check if it was a store fault, if not then bail
+	 * because a user tried to access a kernel or
+	 * read-protected page.  Otherwise, get the
+	 * offending address and handle it.
+	 */
+	mfspr	r10, SPRN_ESR
+	andis.	r10, r10, ESR_ST@h
+	beq	2f
+
+	mfspr	r10, SPRN_DEAR		/* Get faulting address */
+
+	/* If we are faulting a kernel address, we have to use the
+	 * kernel page tables.
+	 */
+	lis	r11, TASK_SIZE@h
+	ori	r11, r11, TASK_SIZE@l
+	cmplw	0, r10, r11
+	bge	2f
+
+	/* Get the PGD for the current thread */
+3:
+	mfspr	r11,SPRG3
+	lwz	r11,PGDIR(r11)
+4:
+	rlwimi	r11, r10, 12, 20, 29	/* Create L1 (pgdir/pmd) address */
+	lwz	r11, 0(r11)		/* Get L1 entry */
+	rlwinm.	r12, r11, 0, 0, 19	/* Extract L2 (pte) base address */
+	beq	2f			/* Bail if no table */
+
+	rlwimi	r12, r10, 22, 20, 29	/* Compute PTE address */
+	lwz	r11, 0(r12)		/* Get Linux PTE */
+
+	/* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */
+	andi.	r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE
+	cmpwi	0, r13, _PAGE_RW|_PAGE_USER
+	bne	2f			/* Bail if not */
+
+	/* Update 'changed'. */
+	ori	r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
+	stw	r11, 0(r12)		/* Update Linux page table */
+
+	/* MAS2 not updated as the entry does exist in the tlb, this
+	   fault taken to detect state transition (eg: COW -> DIRTY)
+	 */
+	lis	r12, MAS3_RPN@h
+	ori	r12, r12, _PAGE_HWEXEC | MAS3_RPN@l
+	and	r11, r11, r12
+	rlwimi	r11, r11, 31, 27, 27	/* SX <- _PAGE_HWEXEC */
+	ori     r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */
+
+	/* update search PID in MAS6, AS = 0 */
+	mfspr	r12, SPRN_PID0
+	slwi	r12, r12, 16
+	mtspr	SPRN_MAS6, r12
+
+	/* find the TLB index that caused the fault.  It has to be here. */
+	tlbsx	0, r10
+
+	mtspr	SPRN_MAS3,r11
+	tlbwe
+
+	/* Done...restore registers and get out of here.  */
+	mfspr	r11, SPRG7R
+	mtcr	r11
+	mfspr	r13, SPRG5R
+	mfspr	r12, SPRG4R
+	mfspr	r11, SPRG1
+	mfspr	r10, SPRG0
+	rfi			/* Force context change */
+
+2:
+	/*
+	 * The bailout.  Restore registers to pre-exception conditions
+	 * and call the heavyweights to help us out.
+	 */
+	mfspr	r11, SPRG7R
+	mtcr	r11
+	mfspr	r13, SPRG5R
+	mfspr	r12, SPRG4R
+	mfspr	r11, SPRG1
+	mfspr	r10, SPRG0
+	b	data_access
+
+	/* Instruction Storage Interrupt */
+	START_EXCEPTION(InstructionStorage)
+	NORMAL_EXCEPTION_PROLOG
+	mfspr	r5,SPRN_ESR		/* Grab the ESR and save it */
+	stw	r5,_ESR(r11)
+	mr      r4,r12                  /* Pass SRR0 as arg2 */
+	li      r5,0                    /* Pass zero as arg3 */
+	EXC_XFER_EE_LITE(0x0400, handle_page_fault)
+
+	/* External Input Interrupt */
+	EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
+
+	/* Alignment Interrupt */
+	START_EXCEPTION(Alignment)
+	NORMAL_EXCEPTION_PROLOG
+	mfspr   r4,SPRN_DEAR            /* Grab the DEAR and save it */
+	stw     r4,_DEAR(r11)
+	addi    r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_EE(0x0600, AlignmentException)
+
+	/* Program Interrupt */
+	START_EXCEPTION(Program)
+	NORMAL_EXCEPTION_PROLOG
+	mfspr	r4,SPRN_ESR		/* Grab the ESR and save it */
+	stw	r4,_ESR(r11)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_STD(0x0700, ProgramCheckException)
+
+	/* Floating Point Unavailable Interrupt */
+	EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
+
+	/* System Call Interrupt */
+	START_EXCEPTION(SystemCall)
+	NORMAL_EXCEPTION_PROLOG
+	EXC_XFER_EE_LITE(0x0c00, DoSyscall)
+
+	/* Auxillary Processor Unavailable Interrupt */
+	EXCEPTION(0x2900, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE)
+
+	/* Decrementer Interrupt */
+	START_EXCEPTION(Decrementer)
+	NORMAL_EXCEPTION_PROLOG
+	lis     r0,TSR_DIS@h            /* Setup the DEC interrupt mask */
+	mtspr   SPRN_TSR,r0		/* Clear the DEC interrupt */
+	addi    r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_LITE(0x0900, timer_interrupt)
+
+	/* Fixed Internal Timer Interrupt */
+	/* TODO: Add FIT support */
+	EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE)
+
+	/* Watchdog Timer Interrupt */
+	/* TODO: Add watchdog support */
+	CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException)
+
+	/* Data TLB Error Interrupt */
+	START_EXCEPTION(DataTLBError)
+	mtspr	SPRG0, r10		/* Save some working registers */
+	mtspr	SPRG1, r11
+	mtspr	SPRG4W, r12
+	mtspr	SPRG5W, r13
+	mfcr	r11
+	mtspr	SPRG7W, r11
+	mfspr	r10, SPRN_DEAR		/* Get faulting address */
+
+	/* If we are faulting a kernel address, we have to use the
+	 * kernel page tables.
+	 */
+	lis	r11, TASK_SIZE@h
+	ori	r11, r11, TASK_SIZE@l
+	cmplw	5, r10, r11
+	blt	5, 3f
+	lis	r11, swapper_pg_dir@h
+	ori	r11, r11, swapper_pg_dir@l
+
+	mfspr	r12,SPRN_MAS1		/* Set TID to 0 */
+	li	r13,MAS1_TID@l
+	andc	r12,r12,r13
+	mtspr	SPRN_MAS1,r12
+
+	b	4f
+
+	/* Get the PGD for the current thread */
+3:
+	mfspr	r11,SPRG3
+	lwz	r11,PGDIR(r11)
+
+4:
+	rlwimi	r11, r10, 12, 20, 29	/* Create L1 (pgdir/pmd) address */
+	lwz	r11, 0(r11)		/* Get L1 entry */
+	rlwinm.	r12, r11, 0, 0, 19	/* Extract L2 (pte) base address */
+	beq	2f			/* Bail if no table */
+
+	rlwimi	r12, r10, 22, 20, 29	/* Compute PTE address */
+	lwz	r11, 0(r12)		/* Get Linux PTE */
+	andi.	r13, r11, _PAGE_PRESENT
+	beq	2f
+
+	ori	r11, r11, _PAGE_ACCESSED
+	stw	r11, 0(r12)
+
+	 /* Jump to common tlb load */
+	b	finish_tlb_load
+2:
+	/* The bailout.  Restore registers to pre-exception conditions
+	 * and call the heavyweights to help us out.
+	 */
+	mfspr	r11, SPRG7R
+	mtcr	r11
+	mfspr	r13, SPRG5R
+	mfspr	r12, SPRG4R
+	mfspr	r11, SPRG1
+	mfspr	r10, SPRG0
+	b	data_access
+
+	/* Instruction TLB Error Interrupt */
+	/*
+	 * Nearly the same as above, except we get our
+	 * information from different registers and bailout
+	 * to a different point.
+	 */
+	START_EXCEPTION(InstructionTLBError)
+	mtspr	SPRG0, r10		/* Save some working registers */
+	mtspr	SPRG1, r11
+	mtspr	SPRG4W, r12
+	mtspr	SPRG5W, r13
+	mfcr	r11
+	mtspr	SPRG7W, r11
+	mfspr	r10, SRR0		/* Get faulting address */
+
+	/* If we are faulting a kernel address, we have to use the
+	 * kernel page tables.
+	 */
+	lis	r11, TASK_SIZE@h
+	ori	r11, r11, TASK_SIZE@l
+	cmplw	5, r10, r11
+	blt	5, 3f
+	lis	r11, swapper_pg_dir@h
+	ori	r11, r11, swapper_pg_dir@l
+
+	mfspr	r12,SPRN_MAS1		/* Set TID to 0 */
+	li	r13,MAS1_TID@l
+	andc	r12,r12,r13
+	mtspr	SPRN_MAS1,r12
+
+	b	4f
+
+	/* Get the PGD for the current thread */
+3:
+	mfspr	r11,SPRG3
+	lwz	r11,PGDIR(r11)
+
+4:
+	rlwimi	r11, r10, 12, 20, 29	/* Create L1 (pgdir/pmd) address */
+	lwz	r11, 0(r11)		/* Get L1 entry */
+	rlwinm.	r12, r11, 0, 0, 19	/* Extract L2 (pte) base address */
+	beq	2f			/* Bail if no table */
+
+	rlwimi	r12, r10, 22, 20, 29	/* Compute PTE address */
+	lwz	r11, 0(r12)		/* Get Linux PTE */
+	andi.	r13, r11, _PAGE_PRESENT
+	beq	2f
+
+	ori	r11, r11, _PAGE_ACCESSED
+	stw	r11, 0(r12)
+
+	/* Jump to common TLB load point */
+	b	finish_tlb_load
+
+2:
+	/* The bailout.  Restore registers to pre-exception conditions
+	 * and call the heavyweights to help us out.
+	 */
+	mfspr	r11, SPRG7R
+	mtcr	r11
+	mfspr	r13, SPRG5R
+	mfspr	r12, SPRG4R
+	mfspr	r11, SPRG1
+	mfspr	r10, SPRG0
+	b	InstructionStorage
+
+#ifdef CONFIG_SPE
+	/* SPE Unavailable */
+	START_EXCEPTION(SPEUnavailable)
+	NORMAL_EXCEPTION_PROLOG
+	bne	load_up_spe
+	addi    r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_EE_LITE(0x2010, KernelSPE)
+#else
+	EXCEPTION(0x2020, SPEUnavailable, UnknownException, EXC_XFER_EE)
+#endif /* CONFIG_SPE */
+
+	/* SPE Floating Point Data */
+#ifdef CONFIG_SPE
+	EXCEPTION(0x2030, SPEFloatingPointData, SPEFloatingPointException, EXC_XFER_EE);
+#else
+	EXCEPTION(0x2040, SPEFloatingPointData, UnknownException, EXC_XFER_EE)
+#endif /* CONFIG_SPE */
+
+	/* SPE Floating Point Round */
+	EXCEPTION(0x2050, SPEFloatingPointRound, UnknownException, EXC_XFER_EE)
+
+	/* Performance Monitor */
+	EXCEPTION(0x2060, PerformanceMonitor, UnknownException, EXC_XFER_EE)
+
+/* Check for a single step debug exception while in an exception
+ * handler before state has been saved.  This is to catch the case
+ * where an instruction that we are trying to single step causes
+ * an exception (eg ITLB/DTLB miss) and thus the first instruction of
+ * the exception handler generates a single step debug exception.
+ *
+ * If we get a debug trap on the first instruction of an exception handler,
+ * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
+ * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
+ * The exception handler was handling a non-critical interrupt, so it will
+ * save (and later restore) the MSR via SPRN_SRR1, which will still have
+ * the MSR_DE bit set.
+ */
+	/* Debug Interrupt */
+	START_EXCEPTION(Debug)
+	CRITICAL_EXCEPTION_PROLOG
+
+	/*
+	 * If this is a single step or branch-taken exception in an
+	 * exception entry sequence, it was probably meant to apply to
+	 * the code where the exception occurred (since exception entry
+	 * doesn't turn off DE automatically).  We simulate the effect
+	 * of turning off DE on entry to an exception handler by turning
+	 * off DE in the CSRR1 value and clearing the debug status.
+	 */
+	mfspr	r10,SPRN_DBSR		/* check single-step/branch taken */
+	andis.	r10,r10,(DBSR_IC|DBSR_BT)@h
+	beq+	1f
+	andi.	r0,r9,MSR_PR		/* check supervisor */
+	beq	2f			/* branch if we need to fix it up... */
+
+	/* continue normal handling for a critical exception... */
+1:	mfspr	r4,SPRN_DBSR
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(DebugException, 0x2002, \
+		(MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+		NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+
+	/* here it looks like we got an inappropriate debug exception. */
+2:	rlwinm	r9,r9,0,~MSR_DE		/* clear DE in the CSRR1 value */
+	mtspr	SPRN_DBSR,r10		/* clear the IC/BT debug intr status */
+	/* restore state and get out */
+	lwz	r10,_CCR(r11)
+	lwz	r0,GPR0(r11)
+	lwz	r1,GPR1(r11)
+	mtcrf	0x80,r10
+	mtspr	CSRR0,r12
+	mtspr	CSRR1,r9
+	lwz	r9,GPR9(r11)
+
+	mtspr	SPRG2,r8;		/* SPRG2 only used in criticals */
+	lis	r8,crit_save@ha;
+	lwz	r10,crit_r10@l(r8)
+	lwz	r11,crit_r11@l(r8)
+	mfspr	r8,SPRG2
+
+	rfci
+	b	.
+
+/*
+ * Local functions
+ */
+	/*
+	 * Data TLB exceptions will bail out to this point
+	 * if they can't resolve the lightweight TLB fault.
+	 */
+data_access:
+	NORMAL_EXCEPTION_PROLOG
+	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it, pass arg3 */
+	stw	r5,_ESR(r11)
+	mfspr	r4,SPRN_DEAR		/* Grab the DEAR, save it, pass arg2 */
+	andis.	r10,r5,(ESR_ILK|ESR_DLK)@h
+	bne	1f
+	EXC_XFER_EE_LITE(0x0300, handle_page_fault)
+1:
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_EE_LITE(0x0300, CacheLockingException)
+
+/*
+
+ * Both the instruction and data TLB miss get to this
+ * point to load the TLB.
+ * 	r10 - EA of fault
+ * 	r11 - TLB (info from Linux PTE)
+ * 	r12, r13 - available to use
+ * 	CR5 - results of addr < TASK_SIZE
+ *	MAS0, MAS1 - loaded with proper value when we get here
+ *	MAS2, MAS3 - will need additional info from Linux PTE
+ *	Upon exit, we reload everything and RFI.
+ */
+finish_tlb_load:
+	/*
+	 * We set execute, because we don't have the granularity to
+	 * properly set this at the page level (Linux problem).
+	 * Many of these bits are software only.  Bits we don't set
+	 * here we (properly should) assume have the appropriate value.
+	 */
+
+	mfspr	r12, SPRN_MAS2
+	rlwimi	r12, r11, 26, 27, 31	/* extract WIMGE from pte */
+	mtspr	SPRN_MAS2, r12
+
+	bge	5, 1f
+
+	/* addr > TASK_SIZE */
+	li	r10, (MAS3_UX | MAS3_UW | MAS3_UR)
+	andi.	r13, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC)
+	andi.	r12, r11, _PAGE_USER	/* Test for _PAGE_USER */
+	iseleq	r12, 0, r10
+	and	r10, r12, r13
+	srwi	r12, r10, 1
+	or	r12, r12, r10	/* Copy user perms into supervisor */
+	b	2f
+
+	/* addr <= TASK_SIZE */
+1:	rlwinm	r12, r11, 31, 29, 29	/* Extract _PAGE_HWWRITE into SW */
+	ori	r12, r12, (MAS3_SX | MAS3_SR)
+
+2:	rlwimi	r11, r12, 0, 20, 31	/* Extract RPN from PTE and merge with perms */
+	mtspr	SPRN_MAS3, r11
+	tlbwe
+
+	/* Done...restore registers and get out of here.  */
+	mfspr	r11, SPRG7R
+	mtcr	r11
+	mfspr	r13, SPRG5R
+	mfspr	r12, SPRG4R
+	mfspr	r11, SPRG1
+	mfspr	r10, SPRG0
+	rfi					/* Force context change */
+
+#ifdef CONFIG_SPE
+/* Note that the SPE support is closely modeled after the AltiVec
+ * support.  Changes to one are likely to be applicable to the
+ * other!  */
+load_up_spe:
+/*
+ * Disable SPE for the task which had SPE previously,
+ * and save its SPE registers in its thread_struct.
+ * Enables SPE for use in the kernel on return.
+ * On SMP we know the SPE units are free, since we give it up every
+ * switch.  -- Kumar
+ */
+	mfmsr	r5
+	oris	r5,r5,MSR_SPE@h
+	mtmsr	r5			/* enable use of SPE now */
+	isync
+/*
+ * For SMP, we don't do lazy SPE switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another.  Instead we call giveup_spe in switch_to.
+ */
+#ifndef CONFIG_SMP
+	lis	r3,last_task_used_spe@ha
+	lwz	r4,last_task_used_spe@l(r3)
+	cmpi	0,r4,0
+	beq	1f
+	addi	r4,r4,THREAD	/* want THREAD of last_task_used_spe */
+	SAVE_32EVR(0,r10,r4)
+   	evxor	evr10, evr10, evr10	/* clear out evr10 */
+	evmwumiaa evr10, evr10, evr10	/* evr10 <- ACC = 0 * 0 + ACC */
+	li	r5,THREAD_ACC
+   	evstddx	evr10, r4, r5		/* save off accumulator */
+	lwz	r5,PT_REGS(r4)
+	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+	lis	r10,MSR_SPE@h
+	andc	r4,r4,r10	/* disable SPE for previous task */
+	stw	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+	/* enable use of SPE after return */
+	oris	r9,r9,MSR_SPE@h
+	mfspr	r5,SPRG3		/* current task's THREAD (phys) */
+	li	r4,1
+	li	r10,THREAD_ACC
+	stw	r4,THREAD_USED_SPE(r5)
+	evlddx	evr4,r10,r5
+	evmra	evr4,evr4
+	REST_32EVR(0,r10,r5)
+#ifndef CONFIG_SMP
+	subi	r4,r5,THREAD
+	stw	r4,last_task_used_spe@l(r3)
+#endif /* CONFIG_SMP */
+	/* restore registers and return */
+2:	REST_4GPRS(3, r11)
+	lwz	r10,_CCR(r11)
+	REST_GPR(1, r11)
+	mtcr	r10
+	lwz	r10,_LINK(r11)
+	mtlr	r10
+	REST_GPR(10, r11)
+	mtspr	SRR1,r9
+	mtspr	SRR0,r12
+	REST_GPR(9, r11)
+	REST_GPR(12, r11)
+	lwz	r11,GPR11(r11)
+	SYNC
+	rfi
+
+
+
+/*
+ * SPE unavailable trap from kernel - print a message, but let
+ * the task use SPE in the kernel until it returns to user mode.
+ */
+KernelSPE:
+	lwz	r3,_MSR(r1)
+	oris	r3,r3,MSR_SPE@h
+	stw	r3,_MSR(r1)	/* enable use of SPE after return */
+	lis	r3,87f@h
+	ori	r3,r3,87f@l
+	mr	r4,r2		/* current */
+	lwz	r5,_NIP(r1)
+	bl	printk
+	b	ret_from_except
+87:	.string	"SPE used in kernel  (task=%p, pc=%x)  \n"
+	.align	4,0
+
+#endif /* CONFIG_SPE */
+
+/*
+ * Global functions
+ */
+
+/*
+ * extern void loadcam_entry(unsigned int index)
+ *
+ * Load TLBCAM[index] entry in to the L2 CAM MMU
+ */
+_GLOBAL(loadcam_entry)
+	lis	r4,TLBCAM@ha
+	addi	r4,r4,TLBCAM@l
+	mulli	r5,r3,20
+	add	r3,r5,r4
+	lwz	r4,0(r3)
+	mtspr	SPRN_MAS0,r4
+	lwz	r4,4(r3)
+	mtspr	SPRN_MAS1,r4
+	lwz	r4,8(r3)
+	mtspr	SPRN_MAS2,r4
+	lwz	r4,12(r3)
+	mtspr	SPRN_MAS3,r4
+	tlbwe
+	isync
+	blr
+
+/*
+ * extern void giveup_altivec(struct task_struct *prev)
+ *
+ * The e500 core does not have an AltiVec unit.
+ */
+_GLOBAL(giveup_altivec)
+	blr
+
+#ifdef CONFIG_SPE
+/*
+ * extern void giveup_spe(struct task_struct *prev)
+ *
+ */
+_GLOBAL(giveup_spe)
+	mfmsr	r5
+	oris	r5,r5,MSR_SPE@h
+	SYNC
+	mtmsr	r5			/* enable use of SPE now */
+	isync
+	cmpi	0,r3,0
+	beqlr-				/* if no previous owner, done */
+	addi	r3,r3,THREAD		/* want THREAD of task */
+	lwz	r5,PT_REGS(r3)
+	cmpi	0,r5,0
+	SAVE_32EVR(0, r4, r3)
+   	evxor	evr6, evr6, evr6	/* clear out evr6 */
+	evmwumiaa evr6, evr6, evr6	/* evr6 <- ACC = 0 * 0 + ACC */
+	li	r4,THREAD_ACC
+   	evstddx	evr6, r4, r3		/* save off accumulator */
+	beq	1f
+	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+	lis	r3,MSR_SPE@h
+	andc	r4,r4,r3		/* disable SPE for previous task */
+	stw	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+	li	r5,0
+	lis	r4,last_task_used_spe@ha
+	stw	r5,last_task_used_spe@l(r4)
+#endif /* CONFIG_SMP */
+	blr
+#endif /* CONFIG_SPE */
+
+/*
+ * extern void giveup_fpu(struct task_struct *prev)
+ *
+ * The e500 core does not have an FPU.
+ */
+_GLOBAL(giveup_fpu)
+	blr
+
+/*
+ * extern void abort(void)
+ *
+ * At present, this routine just applies a system reset.
+ */
+_GLOBAL(abort)
+	li	r13,0
+        mtspr   SPRN_DBCR0,r13		/* disable all debug events */
+	mfmsr	r13
+	ori	r13,r13,MSR_DE@l	/* Enable Debug Events */
+	mtmsr	r13
+        mfspr   r13,SPRN_DBCR0
+        lis	r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h
+        mtspr   SPRN_DBCR0,r13
+
+_GLOBAL(set_context)
+
+#ifdef CONFIG_BDI_SWITCH
+	/* Context switch the PTE pointer for the Abatron BDI2000.
+	 * The PGDIR is the second parameter.
+	 */
+	lis	r5, abatron_pteptrs@h
+	ori	r5, r5, abatron_pteptrs@l
+	stw	r4, 0x4(r5)
+#endif
+	mtspr	SPRN_PID,r3
+	isync			/* Force context change */
+	blr
+
+/*
+ * We put a few things here that have to be page-aligned. This stuff
+ * goes at the beginning of the data segment, which is page-aligned.
+ */
+	.data
+_GLOBAL(sdata)
+_GLOBAL(empty_zero_page)
+	.space	4096
+_GLOBAL(swapper_pg_dir)
+	.space	4096
+
+	.section .bss
+/* Stack for handling critical exceptions from kernel mode */
+critical_stack_bottom:
+	.space 4096
+critical_stack_top:
+	.previous
+
+/* Stack for handling machine check exceptions from kernel mode */
+mcheck_stack_bottom:
+	.space 4096
+mcheck_stack_top:
+	.previous
+
+/*
+ * This area is used for temporarily saving registers during the
+ * critical and machine check exception prologs. It must always
+ * follow the page aligned allocations, so it starts on a page
+ * boundary, ensuring that all crit_save areas are in a single
+ * page.
+ */
+
+/* crit_save */
+_GLOBAL(crit_save)
+	.space  4
+_GLOBAL(crit_r10)
+	.space	4
+_GLOBAL(crit_r11)
+	.space	4
+_GLOBAL(crit_sprg0)
+	.space	4
+_GLOBAL(crit_sprg1)
+	.space	4
+_GLOBAL(crit_sprg4)
+	.space	4
+_GLOBAL(crit_sprg5)
+	.space	4
+_GLOBAL(crit_sprg7)
+	.space	4
+_GLOBAL(crit_pid)
+	.space	4
+_GLOBAL(crit_srr0)
+	.space	4
+_GLOBAL(crit_srr1)
+	.space	4
+
+/* mcheck_save */
+_GLOBAL(mcheck_save)
+	.space  4
+_GLOBAL(mcheck_r10)
+	.space	4
+_GLOBAL(mcheck_r11)
+	.space	4
+_GLOBAL(mcheck_sprg0)
+	.space	4
+_GLOBAL(mcheck_sprg1)
+	.space	4
+_GLOBAL(mcheck_sprg4)
+	.space	4
+_GLOBAL(mcheck_sprg5)
+	.space	4
+_GLOBAL(mcheck_sprg7)
+	.space	4
+_GLOBAL(mcheck_pid)
+	.space	4
+_GLOBAL(mcheck_srr0)
+	.space	4
+_GLOBAL(mcheck_srr1)
+	.space	4
+_GLOBAL(mcheck_csrr0)
+	.space	4
+_GLOBAL(mcheck_csrr1)
+	.space	4
+
+/*
+ * This space gets a copy of optional info passed to us by the bootstrap
+ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+_GLOBAL(cmd_line)
+	.space	512
+
+/*
+ * Room for two PTE pointers, usually the kernel and current user pointers
+ * to their respective root page table.
+ */
+abatron_pteptrs:
+	.space	8
+
+
diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
--- a/arch/ppc/kernel/irq.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc/kernel/irq.c	2004-06-23 19:04:28 -07:00
@@ -628,7 +628,9 @@
 static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
 					unsigned long count, void *data)
 {
-	cpumask_t *mask = (cpumask_t *)data, full_count = count, err;
+	int err;
+	int full_count = count;
+	cpumask_t *mask = (cpumask_t *)data;
 	cpumask_t new_value;
 
 	err = cpumask_parse(buffer, count, new_value);
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc/kernel/misc.S	2004-06-23 19:04:28 -07:00
@@ -253,6 +253,24 @@
 	mtmsr	r7
 	blr
 
+_GLOBAL(low_choose_7447a_dfs)
+	/* Clear MSR:EE */
+	mfmsr	r7
+	rlwinm	r0,r7,0,17,15
+	mtmsr	r0
+	
+	/* Calc new HID1 value */
+	mfspr	r4,SPRN_HID1
+	insrwi	r4,r3,1,9	/* insert parameter into bit 9 */
+	sync
+	mtspr	SPRN_HID1,r4
+	sync
+	isync
+
+	/* Return */
+	mtmsr	r7
+	blr
+
 #endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */
 
 /* void local_save_flags_ptr(unsigned long *flags) */
@@ -419,7 +437,24 @@
 	ble	1b
 
 	isync
-#else /* !(CONFIG_40x || CONFIG_44x) */
+#elif defined(CONFIG_FSL_BOOKE)
+	/* Invalidate all entries in TLB0 */
+	li	r3, 0x04
+	tlbivax	0,3
+	/* Invalidate all entries in TLB1 */
+	li	r3, 0x0c
+	tlbivax	0,3
+	/* Invalidate all entries in TLB2 */
+	li	r3, 0x14
+	tlbivax	0,3
+	/* Invalidate all entries in TLB3 */
+	li	r3, 0x1c
+	tlbivax	0,3
+	msync
+#ifdef CONFIG_SMP
+	tlbsync
+#endif /* CONFIG_SMP */
+#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
 #if defined(CONFIG_SMP)
 	rlwinm	r8,r1,0,0,18
 	lwz	r8,TI_CPU(r8)
@@ -487,7 +522,20 @@
 	tlbwe	r3, r3, PPC44x_TLB_PAGEID
 	isync
 10:
-#else /* !(CONFIG_40x || CONFIG_44x) */
+#elif defined(CONFIG_FSL_BOOKE)
+	rlwinm	r4, r3, 0, 0, 19
+	ori	r5, r4, 0x08	/* TLBSEL = 1 */
+	ori	r6, r4, 0x10	/* TLBSEL = 2 */
+	ori	r7, r4, 0x18	/* TLBSEL = 3 */
+	tlbivax	0, r4
+	tlbivax	0, r5
+	tlbivax	0, r6
+	tlbivax	0, r7
+	msync
+#if defined(CONFIG_SMP)
+	tlbsync
+#endif /* CONFIG_SMP */
+#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
 #if defined(CONFIG_SMP)
 	rlwinm	r8,r1,0,0,18
 	lwz	r8,TI_CPU(r8)
@@ -544,6 +592,10 @@
 	lis	r3, KERNELBASE@h
 	iccci	0,r3
 #endif
+#elif CONFIG_FSL_BOOKE
+	mfspr	r3,SPRN_L1CSR1
+	ori	r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
+	mtspr	SPRN_L1CSR1,r3
 #else
 	mfspr	r3,PVR
 	rlwinm	r3,r3,16,16,31
@@ -1047,7 +1099,7 @@
  * and exceptions as if the cpu had performed the load or store.
  */
 
-#if defined(CONFIG_4xx)
+#if defined(CONFIG_4xx) || defined(CONFIG_E500)
 _GLOBAL(cvt_fd)
 	lfs	0,0(r3)
 	stfd	0,0(r4)
diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc/kernel/ppc_ksyms.c	2004-06-23 19:04:28 -07:00
@@ -199,6 +199,10 @@
 EXPORT_SYMBOL(last_task_used_altivec);
 EXPORT_SYMBOL(giveup_altivec);
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+EXPORT_SYMBOL(last_task_used_spe);
+EXPORT_SYMBOL(giveup_spe);
+#endif /* CONFIG_SPE */
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(smp_call_function);
 EXPORT_SYMBOL(smp_hw_index);
@@ -324,7 +328,7 @@
 EXPORT_SYMBOL(cpm_install_handler);
 EXPORT_SYMBOL(cpm_free_handler);
 #endif /* CONFIG_8xx */
-#if defined(CONFIG_8xx) || defined(CONFIG_40x)
+#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx)
 EXPORT_SYMBOL(__res);
 #endif
 #if defined(CONFIG_8xx)
diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
--- a/arch/ppc/kernel/process.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc/kernel/process.c	2004-06-23 19:04:27 -07:00
@@ -35,6 +35,7 @@
 #include <linux/init_task.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
+#include <linux/mqueue.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -49,6 +50,7 @@
 
 struct task_struct *last_task_used_math = NULL;
 struct task_struct *last_task_used_altivec = NULL;
+struct task_struct *last_task_used_spe = NULL;
 
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
@@ -177,6 +179,34 @@
 EXPORT_SYMBOL(enable_kernel_altivec);
 #endif /* CONFIG_ALTIVEC */
 
+#ifdef CONFIG_SPE
+int
+dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
+{
+	if (regs->msr & MSR_SPE)
+		giveup_spe(current);
+	/* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */
+	memcpy(evrregs, &current->thread.evr[0], sizeof(u32) * 35);
+	return 1;
+}
+
+void
+enable_kernel_spe(void)
+{
+	WARN_ON(preemptible());
+
+#ifdef CONFIG_SMP
+	if (current->thread.regs && (current->thread.regs->msr & MSR_SPE))
+		giveup_spe(current);
+	else
+		giveup_spe(NULL);	/* just enable SPE for kernel - force */
+#else
+	giveup_spe(last_task_used_spe);
+#endif /* __SMP __ */
+}
+EXPORT_SYMBOL(enable_kernel_spe);
+#endif /* CONFIG_SPE */
+
 void
 enable_kernel_fp(void)
 {
@@ -244,6 +274,17 @@
 	if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)))
 		giveup_altivec(prev);
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+	/*
+	 * If the previous thread used spe in the last quantum
+	 * (thus changing spe regs) then save them.
+	 *
+	 * On SMP we always save/restore spe regs just to avoid the
+	 * complexity of changing processors.
+	 */
+	if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE)))
+		giveup_spe(prev);
+#endif /* CONFIG_SPE */
 #endif /* CONFIG_SMP */
 
 	/* Avoid the trap.  On smp this this never happens since
@@ -251,6 +292,13 @@
 	 */
 	if (new->thread.regs && last_task_used_altivec == new)
 		new->thread.regs->msr |= MSR_VEC;
+#ifdef CONFIG_SPE
+	/* Avoid the trap.  On smp this this never happens since
+	 * we don't set last_task_used_spe
+	 */
+	if (new->thread.regs && last_task_used_spe == new)
+		new->thread.regs->msr |= MSR_SPE;
+#endif /* CONFIG_SPE */
 	new_thread = &new->thread;
 	old_thread = &current->thread;
 	last = _switch(old_thread, new_thread);
@@ -354,6 +402,10 @@
 	if (regs->msr & MSR_VEC)
 		giveup_altivec(current);
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+	if (regs->msr & MSR_SPE)
+		giveup_spe(current);
+#endif /* CONFIG_SPE */
 	preempt_enable();
 }
 
@@ -438,18 +490,45 @@
 	current->thread.vrsave = 0;
 	current->thread.used_vr = 0;
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+	memset(current->thread.evr, 0, sizeof(current->thread.evr));
+	current->thread.acc = 0;
+	current->thread.spefscr = 0;
+	current->thread.used_spe = 0;
+#endif /* CONFIG_SPE */
 }
 
+#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \
+		| PR_FP_EXC_RES | PR_FP_EXC_INV)
+
 int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
 {
 	struct pt_regs *regs = tsk->thread.regs;
 
-	if (val > PR_FP_EXC_PRECISE)
+	/* This is a bit hairy.  If we are an SPE enabled  processor
+	 * (have embedded fp) we store the IEEE exception enable flags in
+	 * fpexc_mode.  fpexc_mode is also used for setting FP exception
+	 * mode (asyn, precise, disabled) for 'Classic' FP. */
+	if (val & PR_FP_EXC_SW_ENABLE) {
+#ifdef CONFIG_SPE
+		tsk->thread.fpexc_mode = val &
+			(PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT);
+#else
 		return -EINVAL;
-	tsk->thread.fpexc_mode = __pack_fe01(val);
-	if (regs != NULL && (regs->msr & MSR_FP) != 0)
-		regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))
-			| tsk->thread.fpexc_mode;
+#endif
+	} else {
+		/* on a CONFIG_SPE this does not hurt us.  The bits that
+		 * __pack_fe01 use do not overlap with bits used for
+		 * PR_FP_EXC_SW_ENABLE.  Additionally, the MSR[FE0,FE1] bits
+		 * on CONFIG_SPE implementations are reserved so writing to
+		 * them does not change anything */
+		if (val > PR_FP_EXC_PRECISE)
+			return -EINVAL;
+		tsk->thread.fpexc_mode = __pack_fe01(val);
+		if (regs != NULL && (regs->msr & MSR_FP) != 0)
+			regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))
+				| tsk->thread.fpexc_mode;
+	}
 	return 0;
 }
 
@@ -457,7 +536,14 @@
 {
 	unsigned int val;
 
-	val = __unpack_fe01(tsk->thread.fpexc_mode);
+	if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)
+#ifdef CONFIG_SPE
+		val = tsk->thread.fpexc_mode;
+#else
+		return -EINVAL;
+#endif
+	else
+		val = __unpack_fe01(tsk->thread.fpexc_mode);
 	return put_user(val, (unsigned int *) adr);
 }
 
@@ -506,6 +592,10 @@
 	if (regs->msr & MSR_VEC)
 		giveup_altivec(current);
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+	if (regs->msr & MSR_SPE)
+		giveup_spe(current);
+#endif /* CONFIG_SPE */
 	preempt_enable();
 	error = do_execve(filename, (char __user *__user *) a1,
 			  (char __user *__user *) a2, regs);
diff -Nru a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
--- a/arch/ppc/kernel/ptrace.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ppc/kernel/ptrace.c	2004-06-23 19:04:26 -07:00
@@ -35,7 +35,7 @@
 /*
  * Set of msr bits that gdb can change on behalf of a process.
  */
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 #define MSR_DEBUGCHANGE	0
 #else
 #define MSR_DEBUGCHANGE	(MSR_SE | MSR_BE)
@@ -131,13 +131,77 @@
 }
 #endif
 
+#ifdef CONFIG_SPE
+
+/*
+ * For get_evrregs/set_evrregs functions 'data' has the following layout:
+ *
+ * struct {
+ *   u32 evr[32];
+ *   u64 acc;
+ *   u32 spefscr;
+ * }
+ */
+
+/*
+ * Get contents of SPE register state in task TASK.
+ */
+static inline int get_evrregs(unsigned long *data, struct task_struct *task)
+{
+	int i;
+
+	if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
+		return -EFAULT;
+
+	/* copy SPEFSCR */
+	if (__put_user(task->thread.spefscr, &data[34]))
+		return -EFAULT;
+
+	/* copy SPE registers EVR[0] .. EVR[31] */
+	for (i = 0; i < 32; i++, data++)
+		if (__put_user(task->thread.evr[i], data))
+			return -EFAULT;
+
+	/* copy ACC */
+	if (__put_user64(task->thread.acc, (unsigned long long *)data))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Write contents of SPE register state into task TASK.
+ */
+static inline int set_evrregs(struct task_struct *task, unsigned long *data)
+{
+	int i;
+
+	if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
+		return -EFAULT;
+
+	/* copy SPEFSCR */
+	if (__get_user(task->thread.spefscr, &data[34]))
+		return -EFAULT;
+
+	/* copy SPE registers EVR[0] .. EVR[31] */
+	for (i = 0; i < 32; i++, data++)
+		if (__get_user(task->thread.evr[i], data))
+			return -EFAULT;
+	/* copy ACC */
+	if (__get_user64(task->thread.acc, (unsigned long long*)data))
+		return -EFAULT;
+
+	return 0;
+}
+#endif /* CONFIG_SPE */
+
 static inline void
 set_single_step(struct task_struct *task)
 {
 	struct pt_regs *regs = task->thread.regs;
 
 	if (regs != NULL) {
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 		task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
 		/* MSR.DE should already be set */
 #else
@@ -152,7 +216,7 @@
 	struct pt_regs *regs = task->thread.regs;
 
 	if (regs != NULL) {
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 		task->thread.dbcr0 = 0;
 #else
 		regs->msr &= ~MSR_SE;
@@ -358,6 +422,23 @@
 			giveup_altivec(child);
 		preempt_enable();
 		ret = set_vrregs(child, (unsigned long *)data);
+		break;
+#endif
+#ifdef CONFIG_SPE
+	case PTRACE_GETEVRREGS:
+		/* Get the child spe register state. */
+		if (child->thread.regs->msr & MSR_SPE)
+			giveup_spe(child);
+		ret = get_evrregs((unsigned long *)data, child);
+		break;
+
+	case PTRACE_SETEVRREGS:
+		/* Set the child spe register state. */
+		/* this is to clear the MSR_SPE bit to force a reload
+		 * of register state from memory */
+		if (child->thread.regs->msr & MSR_SPE)
+			giveup_spe(child);
+		ret = set_evrregs(child, (unsigned long *)data);
 		break;
 #endif
 
diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
--- a/arch/ppc/kernel/signal.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc/kernel/signal.c	2004-06-23 19:04:28 -07:00
@@ -183,8 +183,8 @@
 
 /*
  * Save the current user registers on the user stack.
- * We only save the altivec registers if the process has used
- * altivec instructions at some point.
+ * We only save the altivec/spe registers if the process has used
+ * altivec/spe instructions at some point.
  */
 static int
 save_user_regs(struct pt_regs *regs, struct mcontext *frame, int sigret)
@@ -198,6 +198,10 @@
 	if (current->thread.used_vr && (regs->msr & MSR_VEC))
 		giveup_altivec(current);
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+	if (current->thread.used_spe && (regs->msr & MSR_SPE))
+		giveup_spe(current);
+#endif /* CONFIG_ALTIVEC */
 	preempt_enable();
 
 	if (__copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE)
@@ -229,6 +233,24 @@
 		return 1;
 #endif /* CONFIG_ALTIVEC */
 
+#ifdef CONFIG_SPE
+	/* save spe registers */
+	if (current->thread.used_spe) {
+		if (__copy_to_user(&frame->mc_vregs, current->thread.evr,
+				   ELF_NEVRREG * sizeof(u32)))
+			return 1;
+		/* set MSR_SPE in the saved MSR value to indicate that
+		   frame->mc_vregs contains valid data */
+		if (__put_user(regs->msr | MSR_SPE, &frame->mc_gregs[PT_MSR]))
+			return 1;
+	}
+	/* else assert((regs->msr & MSR_SPE) == 0) */
+
+	/* We always copy to/from spefscr */
+	if (__put_user(current->thread.spefscr, (u32 *)&frame->mc_vregs + ELF_NEVRREG))
+		return 1;
+#endif /* CONFIG_SPE */
+
 	if (sigret) {
 		/* Set up the sigreturn trampoline: li r0,sigret; sc */
 		if (__put_user(0x38000000UL + sigret, &frame->tramp[0])
@@ -249,7 +271,7 @@
 restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig)
 {
 	unsigned long save_r2;
-#ifdef CONFIG_ALTIVEC
+#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
 	unsigned long msr;
 #endif
 
@@ -289,6 +311,23 @@
 	if (__get_user(current->thread.vrsave, (u32 *)&sr->mc_vregs[32]))
 		return 1;
 #endif /* CONFIG_ALTIVEC */
+
+#ifdef CONFIG_SPE
+	/* force the process to reload the spe registers from
+	   current->thread when it next does spe instructions */
+	regs->msr &= ~MSR_SPE;
+	if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) {
+		/* restore spe registers from the stack */
+		if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
+				     sizeof(sr->mc_vregs)))
+			return 1;
+	} else if (current->thread.used_spe)
+		memset(&current->thread.evr, 0, ELF_NEVRREG * sizeof(u32));
+
+	/* Always get SPEFSCR back */
+	if (__get_user(current->thread.spefscr, (u32 *)&sr->mc_vregs + ELF_NEVRREG))
+		return 1;
+#endif /* CONFIG_SPE */
 
 	return 0;
 }
diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
--- a/arch/ppc/kernel/time.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc/kernel/time.c	2004-06-23 19:04:28 -07:00
@@ -56,6 +56,7 @@
 #include <linux/mc146818rtc.h>
 #include <linux/time.h>
 #include <linux/init.h>
+#include <linux/profile.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -107,17 +108,23 @@
 	return delta;
 }
 
-extern unsigned long prof_cpu_mask;
-extern unsigned int * prof_buffer;
-extern unsigned long prof_len;
-extern unsigned long prof_shift;
 extern char _stext;
 
-static inline void ppc_do_profile (unsigned long nip)
+static inline void ppc_do_profile (struct pt_regs *regs)
 {
+	unsigned long nip;
+	extern unsigned long prof_cpu_mask;
+
+	profile_hook(regs);
+
+	if (user_mode(regs))
+		return;
+
 	if (!prof_buffer)
 		return;
 
+	nip = instruction_pointer(regs);
+
 	/*
 	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
 	 * (default is all CPUs.)
@@ -156,8 +163,9 @@
 
 	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) {
 		jiffy_stamp += tb_ticks_per_jiffy;
-		if (!user_mode(regs))
-			ppc_do_profile(instruction_pointer(regs));
+		
+		ppc_do_profile(regs);
+
 	  	if (smp_processor_id())
 			continue;
 
diff -Nru a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
--- a/arch/ppc/kernel/traps.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc/kernel/traps.c	2004-06-23 19:04:25 -07:00
@@ -30,6 +30,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/prctl.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -102,8 +103,7 @@
 	do_exit(err);
 }
 
-void
-_exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
+void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
 {
 	siginfo_t info;
 
@@ -171,6 +171,11 @@
 /* On 4xx, the reason for the machine check or program exception
    is in the ESR. */
 #define get_reason(regs)	((regs)->dsisr)
+#ifndef CONFIG_E500
+#define get_mc_reason(regs)	((regs)->dsisr)
+#else
+#define get_mc_reason(regs)	(mfspr(SPRN_MCSR))
+#endif
 #define REASON_FP		0
 #define REASON_ILLEGAL		ESR_PIL
 #define REASON_PRIVILEGED	ESR_PPR
@@ -184,6 +189,7 @@
 /* On non-4xx, the reason for the machine check or program
    exception is in the MSR. */
 #define get_reason(regs)	((regs)->msr)
+#define get_mc_reason(regs)	((regs)->msr)
 #define REASON_FP		0x100000
 #define REASON_ILLEGAL		0x80000
 #define REASON_PRIVILEGED	0x40000
@@ -193,10 +199,9 @@
 #define clear_single_step(regs)	((regs)->msr &= ~MSR_SE)
 #endif
 
-void
-MachineCheckException(struct pt_regs *regs)
+void MachineCheckException(struct pt_regs *regs)
 {
-	unsigned long reason = get_reason(regs);
+	unsigned long reason = get_mc_reason(regs);
 
 	if (user_mode(regs)) {
 		regs->msr |= MSR_RI;
@@ -256,7 +261,37 @@
 		/* Clear MCSR */
 		mtspr(SPRN_MCSR, mcsr);
 	}
-#else /* !CONFIG_4xx */
+#elif defined (CONFIG_E500)
+	printk("Machine check in kernel mode.\n");
+	printk("Caused by (from MCSR=%lx): ", reason);
+
+	if (reason & MCSR_MCP)
+		printk("Machine Check Signal\n");
+	if (reason & MCSR_ICPERR)
+		printk("Instruction Cache Parity Error\n");
+	if (reason & MCSR_DCP_PERR)
+		printk("Data Cache Push Parity Error\n");
+	if (reason & MCSR_DCPERR)
+		printk("Data Cache Parity Error\n");
+	if (reason & MCSR_GL_CI)
+		printk("Guarded Load or Cache-Inhibited stwcx.\n");
+	if (reason & MCSR_BUS_IAERR)
+		printk("Bus - Instruction Address Error\n");
+	if (reason & MCSR_BUS_RAERR)
+		printk("Bus - Read Address Error\n");
+	if (reason & MCSR_BUS_WAERR)
+		printk("Bus - Write Address Error\n");
+	if (reason & MCSR_BUS_IBERR)
+		printk("Bus - Instruction Data Error\n");
+	if (reason & MCSR_BUS_RBERR)
+		printk("Bus - Read Data Bus Error\n");
+	if (reason & MCSR_BUS_WBERR)
+		printk("Bus - Read Data Bus Error\n");
+	if (reason & MCSR_BUS_IPERR)
+		printk("Bus - Instruction Parity Error\n");
+	if (reason & MCSR_BUS_RPERR)
+		printk("Bus - Read Parity Error\n");
+#else /* !CONFIG_4xx && !CONFIG_E500 */
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from SRR1=%lx): ", reason);
 	switch (reason & 0x601F0000) {
@@ -292,8 +327,7 @@
 	die("machine check", regs, SIGBUS);
 }
 
-void
-SMIException(struct pt_regs *regs)
+void SMIException(struct pt_regs *regs)
 {
 	debugger(regs);
 #if !(defined(CONFIG_XMON) || defined(CONFIG_KGDB))
@@ -302,24 +336,21 @@
 #endif
 }
 
-void
-UnknownException(struct pt_regs *regs)
+void UnknownException(struct pt_regs *regs)
 {
 	printk("Bad trap at PC: %lx, MSR: %lx, vector=%lx    %s\n",
 	       regs->nip, regs->msr, regs->trap, print_tainted());
 	_exception(SIGTRAP, regs, 0, 0);
 }
 
-void
-InstructionBreakpoint(struct pt_regs *regs)
+void InstructionBreakpoint(struct pt_regs *regs)
 {
 	if (debugger_iabr_match(regs))
 		return;
 	_exception(SIGTRAP, regs, TRAP_BRKPT, 0);
 }
 
-void
-RunModeException(struct pt_regs *regs)
+void RunModeException(struct pt_regs *regs)
 {
 	_exception(SIGTRAP, regs, 0, 0);
 }
@@ -337,8 +368,7 @@
 #define INST_MFSPR_PVR		0x7c1f42a6
 #define INST_MFSPR_PVR_MASK	0xfc1fffff
 
-static int
-emulate_instruction(struct pt_regs *regs)
+static int emulate_instruction(struct pt_regs *regs)
 {
 	u32 instword;
 	u32 rd;
@@ -401,8 +431,7 @@
 	return module_find_bug(bugaddr);
 }
 
-int
-check_bug_trap(struct pt_regs *regs)
+int check_bug_trap(struct pt_regs *regs)
 {
 	struct bug_entry *bug;
 	unsigned long addr;
@@ -439,8 +468,7 @@
 	return 0;
 }
 
-void
-ProgramCheckException(struct pt_regs *regs)
+void ProgramCheckException(struct pt_regs *regs)
 {
 	unsigned int reason = get_reason(regs);
 	extern int do_mathemu(struct pt_regs *regs);
@@ -513,8 +541,7 @@
 	_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 }
 
-void
-SingleStepException(struct pt_regs *regs)
+void SingleStepException(struct pt_regs *regs)
 {
 	regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
 	if (debugger_sstep(regs))
@@ -522,8 +549,7 @@
 	_exception(SIGTRAP, regs, TRAP_TRACE, 0);
 }
 
-void
-AlignmentException(struct pt_regs *regs)
+void AlignmentException(struct pt_regs *regs)
 {
 	int fixed;
 
@@ -543,8 +569,7 @@
 	_exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
 }
 
-void
-StackOverflow(struct pt_regs *regs)
+void StackOverflow(struct pt_regs *regs)
 {
 	printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n",
 	       current, regs->gpr[1]);
@@ -561,8 +586,7 @@
 	die("nonrecoverable exception", regs, SIGKILL);
 }
 
-void
-trace_syscall(struct pt_regs *regs)
+void trace_syscall(struct pt_regs *regs)
 {
 	printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld    %s\n",
 	       current, current->pid, regs->nip, regs->link, regs->gpr[0],
@@ -570,8 +594,7 @@
 }
 
 #ifdef CONFIG_8xx
-void
-SoftwareEmulation(struct pt_regs *regs)
+void SoftwareEmulation(struct pt_regs *regs)
 {
 	extern int do_mathemu(struct pt_regs *);
 	extern int Soft_emulate_8xx(struct pt_regs *);
@@ -623,8 +646,7 @@
 #endif /* CONFIG_4xx || CONFIG_BOOKE */
 
 #if !defined(CONFIG_TAU_INT)
-void
-TAUException(struct pt_regs *regs)
+void TAUException(struct pt_regs *regs)
 {
 	printk("TAU trap at PC: %lx, MSR: %lx, vector=%lx    %s\n",
 	       regs->nip, regs->msr, regs->trap, print_tainted());
@@ -646,14 +668,13 @@
 	/* The kernel has executed an altivec instruction without
 	   first enabling altivec.  Whinge but let it do it. */
 	if (++kernel_altivec_count < 10)
-		printk(KERN_ERR "AltiVec used in kernel (task=%p, pc=%x)\n",
+		printk(KERN_ERR "AltiVec used in kernel (task=%p, pc=%lx)\n",
 		       current, regs->nip);
 	regs->msr |= MSR_VEC;
 }
 
 #ifdef CONFIG_ALTIVEC
-void
-AltivecAssistException(struct pt_regs *regs)
+void AltivecAssistException(struct pt_regs *regs)
 {
 	int err;
 
@@ -682,6 +703,55 @@
 }
 #endif /* CONFIG_ALTIVEC */
 
+#ifdef CONFIG_FSL_BOOKE
+void CacheLockingException(struct pt_regs *regs, unsigned long address,
+			   unsigned long error_code)
+{
+	/* We treat cache locking instructions from the user
+	 * as priv ops, in the future we could try to do
+	 * something smarter
+	 */
+	if (error_code & (ESR_DLK|ESR_ILK))
+		_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+	return;
+}
+#endif /* CONFIG_FSL_BOOKE */
+
+#ifdef CONFIG_SPE
+void SPEFloatingPointException(struct pt_regs *regs)
+{
+	unsigned long spefscr;
+	int fpexc_mode;
+	int code = 0;
+
+	spefscr = current->thread.spefscr;
+	fpexc_mode = current->thread.fpexc_mode;
+
+	/* Hardware does not neccessarily set sticky
+	 * underflow/overflow/invalid flags */
+	if ((spefscr & SPEFSCR_FOVF) && (fpexc_mode & PR_FP_EXC_OVF)) {
+		code = FPE_FLTOVF;
+		spefscr |= SPEFSCR_FOVFS;
+	}
+	else if ((spefscr & SPEFSCR_FUNF) && (fpexc_mode & PR_FP_EXC_UND)) {
+		code = FPE_FLTUND;
+		spefscr |= SPEFSCR_FUNFS;
+	}
+	else if ((spefscr & SPEFSCR_FDBZ) && (fpexc_mode & PR_FP_EXC_DIV))
+		code = FPE_FLTDIV;
+	else if ((spefscr & SPEFSCR_FINV) && (fpexc_mode & PR_FP_EXC_INV)) {
+		code = FPE_FLTINV;
+		spefscr |= SPEFSCR_FINVS;
+	}
+	else if ((spefscr & (SPEFSCR_FG | SPEFSCR_FX)) && (fpexc_mode & PR_FP_EXC_RES))
+		code = FPE_FLTRES;
+
+	current->thread.spefscr = spefscr;
+
+	_exception(SIGFPE, regs, code, regs->nip);
+	return;
+}
+#endif
 
 void __init trap_init(void)
 {
diff -Nru a/arch/ppc/kernel/vecemu.c b/arch/ppc/kernel/vecemu.c
--- a/arch/ppc/kernel/vecemu.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc/kernel/vecemu.c	2004-06-23 19:04:25 -07:00
@@ -256,8 +256,7 @@
 	return (x + half) & ~(0x7fffff >> exp);
 }
 
-int
-emulate_altivec(struct pt_regs *regs)
+int emulate_altivec(struct pt_regs *regs)
 {
 	unsigned int instr, i;
 	unsigned int va, vb, vc, vd;
diff -Nru a/arch/ppc/mm/Makefile b/arch/ppc/mm/Makefile
--- a/arch/ppc/mm/Makefile	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc/mm/Makefile	2004-06-23 19:04:28 -07:00
@@ -12,3 +12,4 @@
 obj-$(CONFIG_PPC_STD_MMU)	+= hashtable.o ppc_mmu.o tlb.o
 obj-$(CONFIG_40x)		+= 4xx_mmu.o
 obj-$(CONFIG_44x)		+= 44x_mmu.o
+obj-$(CONFIG_FSL_BOOKE)		+= fsl_booke_mmu.o
diff -Nru a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
--- a/arch/ppc/mm/fault.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ppc/mm/fault.c	2004-06-23 19:04:26 -07:00
@@ -99,7 +99,7 @@
 	struct mm_struct *mm = current->mm;
 	siginfo_t info;
 	int code = SEGV_MAPERR;
-#if defined(CONFIG_4xx)
+#if defined(CONFIG_4xx) || defined (CONFIG_BOOKE)
 	int is_write = error_code & ESR_DST;
 #else
 	int is_write = 0;
@@ -114,20 +114,20 @@
 		error_code &= 0x48200000;
 	else
 		is_write = error_code & 0x02000000;
-#endif /* CONFIG_4xx */
+#endif /* CONFIG_4xx || CONFIG_BOOKE */
 
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 	if (debugger_fault_handler && TRAP(regs) == 0x300) {
 		debugger_fault_handler(regs);
 		return 0;
 	}
-#if !defined(CONFIG_4xx)
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
 	if (error_code & 0x00400000) {
 		/* DABR match */
 		if (debugger_dabr_match(regs))
 			return 0;
 	}
-#endif /* !CONFIG_4xx */
+#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
 #endif /* CONFIG_XMON || CONFIG_KGDB */
 
 	if (in_atomic() || mm == NULL)
@@ -200,8 +200,8 @@
 	if (is_write) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
-#if defined(CONFIG_4xx)
-	/* an exec  - 4xx allows for per-page execute permission */
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+	/* an exec  - 4xx/Book-E allows for per-page execute permission */
 	} else if (TRAP(regs) == 0x400) {
 		pte_t *ptep;
 
@@ -214,7 +214,7 @@
 			goto bad_area;
 #endif
 
-		/* Since 4xx supports per-page execute permission,
+		/* Since 4xx/Book-E supports per-page execute permission,
 		 * we lazily flush dcache to icache. */
 		ptep = NULL;
 		if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
diff -Nru a/arch/ppc/mm/fsl_booke_mmu.c b/arch/ppc/mm/fsl_booke_mmu.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/mm/fsl_booke_mmu.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,236 @@
+/*
+ * Modifications by Kumar Gala (kumar.gala@freescale.com) to support
+ * E500 Book E processors.
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * This file contains the routines for initializing the MMU
+ * on the 4xx series of chips.
+ *  -- paulus
+ *
+ *  Derived from arch/ppc/mm/init.c:
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ *    Copyright (C) 1996 Paul Mackerras
+ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ *  Derived from "arch/i386/mm/init.c"
+ *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the 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/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+
+#include <asm/pgalloc.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/setup.h>
+
+extern void loadcam_entry(unsigned int index);
+unsigned int tlbcam_index;
+unsigned int num_tlbcam_entries;
+static unsigned long __cam0, __cam1, __cam2;
+extern unsigned long total_lowmem;
+extern unsigned long __max_low_memory;
+#define MAX_LOW_MEM	CONFIG_LOWMEM_SIZE
+
+struct tlbcam {
+   	u32	MAS0;
+	u32	MAS1;
+	u32	MAS2;
+	u32	MAS3;
+	u32	MAS7;
+} TLBCAM[NUM_TLBCAMS];
+
+struct tlbcamrange {
+   	unsigned long start;
+	unsigned long limit;
+	phys_addr_t phys;
+} tlbcam_addrs[NUM_TLBCAMS];
+
+extern unsigned int tlbcam_index;
+
+/*
+ * Return PA for this VA if it is mapped by a CAM, or 0
+ */
+unsigned long v_mapped_by_tlbcam(unsigned long va)
+{
+	int b;
+	for (b = 0; b < tlbcam_index; ++b)
+		if (va >= tlbcam_addrs[b].start && va < tlbcam_addrs[b].limit)
+			return tlbcam_addrs[b].phys + (va - tlbcam_addrs[b].start);
+	return 0;
+}
+
+/*
+ * Return VA for a given PA or 0 if not mapped
+ */
+unsigned long p_mapped_by_tlbcam(unsigned long pa)
+{
+	int b;
+	for (b = 0; b < tlbcam_index; ++b)
+		if (pa >= tlbcam_addrs[b].phys
+	    	    && pa < (tlbcam_addrs[b].limit-tlbcam_addrs[b].start)
+		              +tlbcam_addrs[b].phys)
+			return tlbcam_addrs[b].start+(pa-tlbcam_addrs[b].phys);
+	return 0;
+}
+
+/*
+ * Set up one of the I/D BAT (block address translation) register pairs.
+ * The parameters are not checked; in particular size must be a power
+ * of 4 between 4k and 256M.
+ */
+void settlbcam(int index, unsigned long virt, phys_addr_t phys,
+		unsigned int size, int flags, unsigned int pid)
+{
+	unsigned int tsize, lz;
+
+	asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size));
+	tsize = (21 - lz) / 2;
+
+#ifdef CONFIG_SMP
+	if ((flags & _PAGE_NO_CACHE) == 0)
+		flags |= _PAGE_COHERENT;
+#endif
+
+	TLBCAM[index].MAS0 = MAS0_TLBSEL | (index << 16);
+	TLBCAM[index].MAS1 = MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(tsize) | ((pid << 16) & MAS1_TID);
+	TLBCAM[index].MAS2 = virt & PAGE_MASK;
+
+	TLBCAM[index].MAS2 |= (flags & _PAGE_WRITETHRU) ? MAS2_W : 0;
+	TLBCAM[index].MAS2 |= (flags & _PAGE_NO_CACHE) ? MAS2_I : 0;
+	TLBCAM[index].MAS2 |= (flags & _PAGE_COHERENT) ? MAS2_M : 0;
+	TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0;
+	TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0;
+
+	TLBCAM[index].MAS3 = (phys & PAGE_MASK) | MAS3_SX | MAS3_SR;
+	TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0);
+
+#ifndef CONFIG_KGDB /* want user access for breakpoints */
+	if (flags & _PAGE_USER) {
+	   TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
+	   TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
+	}
+#else
+	TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
+	TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
+#endif
+
+	tlbcam_addrs[index].start = virt;
+	tlbcam_addrs[index].limit = virt + size - 1;
+	tlbcam_addrs[index].phys = phys;
+
+	loadcam_entry(index);
+}
+
+void invalidate_tlbcam_entry(int index)
+{
+	TLBCAM[index].MAS0 = MAS0_TLBSEL | (index << 16);
+	TLBCAM[index].MAS1 = ~MAS1_VALID;
+
+	loadcam_entry(index);
+}
+
+void __init cam_mapin_ram(unsigned long cam0, unsigned long cam1,
+		unsigned long cam2)
+{
+	settlbcam(0, KERNELBASE, PPC_MEMSTART, cam0, _PAGE_KERNEL, 0);
+	tlbcam_index++;
+	if (cam1) {
+		tlbcam_index++;
+		settlbcam(1, KERNELBASE+cam0, PPC_MEMSTART+cam0, cam1, _PAGE_KERNEL, 0);
+	}
+	if (cam2) {
+		tlbcam_index++;
+		settlbcam(2, KERNELBASE+cam0+cam1, PPC_MEMSTART+cam0+cam1, cam2, _PAGE_KERNEL, 0);
+	}
+}
+
+/*
+ * MMU_init_hw does the chip-specific initialization of the MMU hardware.
+ */
+void __init MMU_init_hw(void)
+{
+	flush_instruction_cache();
+}
+
+unsigned long __init mmu_mapin_ram(void)
+{
+	cam_mapin_ram(__cam0, __cam1, __cam2);
+
+	return __cam0 + __cam1 + __cam2;
+}
+
+
+void __init
+adjust_total_lowmem(void)
+{
+	unsigned long max_low_mem = MAX_LOW_MEM;
+	unsigned long cam_max = 0x10000000;
+	unsigned long ram;
+
+	/* adjust CAM size to max_low_mem */
+	if (max_low_mem < cam_max)
+		cam_max = max_low_mem;
+
+	/* adjust lowmem size to max_low_mem */
+	if (max_low_mem < total_lowmem)
+		ram = max_low_mem;
+	else
+		ram = total_lowmem;
+
+	/* Calculate CAM values */
+	__cam0 = 1UL << 2 * (__ilog2(ram) / 2);
+	if (__cam0 > cam_max)
+		__cam0 = cam_max;
+	ram -= __cam0;
+	if (ram) {
+		__cam1 = 1UL << 2 * (__ilog2(ram) / 2);
+		if (__cam1 > cam_max)
+			__cam1 = cam_max;
+		ram -= __cam1;
+	}
+	if (ram) {
+		__cam2 = 1UL << 2 * (__ilog2(ram) / 2);
+		if (__cam2 > cam_max)
+			__cam2 = cam_max;
+		ram -= __cam2;
+	}
+
+	printk(KERN_INFO "Memory CAM mapping: CAM0=%ldMb, CAM1=%ldMb,"
+			" CAM2=%ldMb residual: %ldMb\n",
+			__cam0 >> 20, __cam1 >> 20, __cam2 >> 20,
+			(total_lowmem - __cam0 - __cam1 - __cam2) >> 20);
+	__max_low_memory = max_low_mem = __cam0 + __cam1 + __cam2;
+}
diff -Nru a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
--- a/arch/ppc/mm/init.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ppc/mm/init.c	2004-06-23 19:04:26 -07:00
@@ -253,6 +253,12 @@
 	if (__max_memory && total_memory > __max_memory)
 		total_memory = __max_memory;
 	total_lowmem = total_memory;
+#ifdef CONFIG_FSL_BOOKE
+	/* Freescale Book-E parts expect lowmem to be mapped by fixed TLB
+	 * entries, so we need to adjust lowmem to match the amount we can map
+	 * in the fixed entries */
+	adjust_total_lowmem();
+#endif /* CONFIG_FSL_BOOKE */
 	if (total_lowmem > __max_low_memory) {
 		total_lowmem = __max_low_memory;
 #ifndef CONFIG_HIGHMEM
diff -Nru a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
--- a/arch/ppc/mm/mmu_decl.h	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc/mm/mmu_decl.h	2004-06-23 19:04:27 -07:00
@@ -27,6 +27,9 @@
 extern void setbat(int index, unsigned long virt, unsigned long phys,
 		   unsigned int size, int flags);
 extern void reserve_phys_mem(unsigned long start, unsigned long size);
+extern void settlbcam(int index, unsigned long virt, phys_addr_t phys,
+		      unsigned int size, int flags, unsigned int pid);
+extern void invalidate_tlbcam_entry(int index);
 
 extern int __map_without_bats;
 extern unsigned long ioremap_base;
@@ -52,6 +55,12 @@
 #define flush_HPTE(X, va, pg)	_tlbie(va)
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(void);
+
+#elif defined(CONFIG_FSL_BOOKE)
+#define flush_HPTE(X, va, pg)	_tlbie(va)
+extern void MMU_init_hw(void);
+extern unsigned long mmu_mapin_ram(void);
+extern void adjust_total_lowmem(void);
 
 #else
 /* anything except 4xx or 8xx */
diff -Nru a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
--- a/arch/ppc/mm/pgtable.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc/mm/pgtable.c	2004-06-23 19:04:25 -07:00
@@ -42,6 +42,10 @@
 #define HAVE_BATS	1
 #endif
 
+#if defined(CONFIG_FSL_BOOKE)
+#define HAVE_TLBCAM	1
+#endif
+
 extern char etext[], _stext[];
 
 #ifdef CONFIG_SMP
@@ -59,6 +63,16 @@
 #define p_mapped_by_bats(x)	(0UL)
 #endif /* HAVE_BATS */
 
+#ifdef HAVE_TLBCAM
+extern unsigned int tlbcam_index;
+extern unsigned int num_tlbcam_entries;
+extern unsigned long v_mapped_by_tlbcam(unsigned long va);
+extern unsigned long p_mapped_by_tlbcam(unsigned long pa);
+#else /* !HAVE_TLBCAM */
+#define v_mapped_by_tlbcam(x)	(0UL)
+#define p_mapped_by_tlbcam(x)	(0UL)
+#endif /* HAVE_TLBCAM */
+
 #ifdef CONFIG_44x
 /* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */
 #define PGDIR_ORDER	1
@@ -210,6 +224,9 @@
 	if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
 		goto out;
 
+	if ((v = p_mapped_by_tlbcam(p)))
+		goto out;
+
 	if (mem_init_done) {
 		struct vm_struct *area;
 		area = get_vm_area(size, VM_IOREMAP);
@@ -300,6 +317,9 @@
 /* is x a power of 2? */
 #define is_power_of_2(x)	((x) != 0 && (((x) & ((x) - 1)) == 0))
 
+/* is x a power of 4? */
+#define is_power_of_4(x)	((x) != 0 && (((x) & (x-1)) == 0) && (ffs(x) & 1))
+
 /*
  * Set up a mapping for a block of I/O.
  * virt, phys, size must all be page-aligned.
@@ -324,6 +344,18 @@
 		return;
 	}
 #endif /* HAVE_BATS */
+
+#ifdef HAVE_TLBCAM
+	/*
+	 * Use a CAM for this if possible...
+	 */
+	if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
+	    && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
+		settlbcam(tlbcam_index, virt, phys, size, flags, 0);
+		++tlbcam_index;
+		return;
+	}
+#endif /* HAVE_TLBCAM */
 
 	/* No BATs available, put it in the page tables. */
 	for (i = 0; i < size; i += PAGE_SIZE)
diff -Nru a/arch/ppc/oprofile/Kconfig b/arch/ppc/oprofile/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/oprofile/Kconfig	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+	depends on EXPERIMENTAL
+
+config PROFILING
+	bool "Profiling support (EXPERIMENTAL)"
+	help
+	  Say Y here to enable the extended profiling support mechanisms used
+	  by profilers such as OProfile.
+
+
+config OPROFILE
+	tristate "OProfile system profiling (EXPERIMENTAL)"
+	depends on PROFILING
+	help
+	  OProfile is a profiling system capable of profiling the
+	  whole system, include the kernel, kernel modules, libraries,
+	  and applications.
+
+	  If unsure, say N.
+
+endmenu
+
diff -Nru a/arch/ppc/oprofile/Makefile b/arch/ppc/oprofile/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/oprofile/Makefile	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,9 @@
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
+		oprof.o cpu_buffer.o buffer_sync.o \
+		event_buffer.o oprofile_files.o \
+		oprofilefs.o oprofile_stats.o \
+		timer_int.o )
+
+oprofile-y := $(DRIVER_OBJS) init.o
diff -Nru a/arch/ppc/oprofile/init.c b/arch/ppc/oprofile/init.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/oprofile/init.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,23 @@
+/**
+ * @file init.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+int __init oprofile_arch_init(struct oprofile_operations ** ops)
+{
+	return -ENODEV;
+}
+
+
+void oprofile_arch_exit(void)
+{
+}
diff -Nru a/arch/ppc/platforms/85xx/Kconfig b/arch/ppc/platforms/85xx/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/85xx/Kconfig	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,44 @@
+config 85xx
+	bool
+	depends on E500
+	default y
+
+config PPC_INDIRECT_PCI_BE
+	bool
+	depends on 85xx
+	default y
+
+menu "Freescale 85xx options"
+	depends on E500
+
+choice
+	prompt "Machine Type"
+	depends on 85xx
+	default MPC8540_ADS
+
+config MPC8540_ADS
+	bool "MPC8540ADS"
+	help
+	  This option enables support for the MPC 8540 ADS evaluation board.
+
+endchoice
+
+# It's often necessary to know the specific 85xx processor type.
+# Fortunately, it is implied (so far) from the board type, so we
+# don't need to ask more redundant questions.
+config MPC8540
+	bool
+	depends on MPC8540_ADS
+	default y
+
+config FSL_OCP
+	bool
+	depends on 85xx
+	default y
+
+config PPC_GEN550
+	bool
+	depends on MPC8540
+	default y
+
+endmenu
diff -Nru a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/85xx/Makefile	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,7 @@
+#
+# Makefile for the PowerPC 85xx linux kernel.
+#
+
+obj-$(CONFIG_MPC8540_ADS)	+= mpc85xx_ads_common.o mpc8540_ads.o
+
+obj-$(CONFIG_MPC8540)		+= mpc8540.o
diff -Nru a/arch/ppc/platforms/85xx/mpc8540.c b/arch/ppc/platforms/85xx/mpc8540.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/85xx/mpc8540.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,97 @@
+/*
+ * arch/ppc/platforms/85xx/mpc8540.c
+ *
+ * MPC8540 I/O descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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 <asm/mpc85xx.h>
+#include <asm/ocp.h>
+
+/* These should be defined in platform code */
+extern struct ocp_gfar_data mpc85xx_tsec1_def;
+extern struct ocp_gfar_data mpc85xx_tsec2_def;
+extern struct ocp_gfar_data mpc85xx_fec_def;
+extern struct ocp_mpc_i2c_data mpc85xx_i2c1_def;
+
+/* We use offsets for paddr since we do not know at compile time
+ * what CCSRBAR is, platform code should fix this up in
+ * setup_arch
+ *
+ * Only the first IRQ is given even if a device has
+ * multiple lines associated with ita
+ */
+struct ocp_def core_ocp[] = {
+        { .vendor       = OCP_VENDOR_FREESCALE,
+          .function     = OCP_FUNC_IIC,
+          .index        = 0,
+          .paddr        = MPC85xx_IIC1_OFFSET,
+          .irq          = MPC85xx_IRQ_IIC1,
+          .pm           = OCP_CPM_NA,
+          .additions    = &mpc85xx_i2c1_def,
+        },
+        { .vendor       = OCP_VENDOR_FREESCALE,
+          .function     = OCP_FUNC_16550,
+          .index        = 0,
+          .paddr        = MPC85xx_UART0_OFFSET,
+          .irq          = MPC85xx_IRQ_DUART,
+          .pm           = OCP_CPM_NA,
+        },
+        { .vendor       = OCP_VENDOR_FREESCALE,
+          .function     = OCP_FUNC_16550,
+          .index        = 1,
+          .paddr        = MPC85xx_UART1_OFFSET,
+          .irq          = MPC85xx_IRQ_DUART,
+          .pm           = OCP_CPM_NA,
+        },
+        { .vendor       = OCP_VENDOR_FREESCALE,
+          .function     = OCP_FUNC_GFAR,
+          .index        = 0,
+          .paddr        = MPC85xx_ENET1_OFFSET,
+          .irq          = MPC85xx_IRQ_TSEC1_TX,
+          .pm           = OCP_CPM_NA,
+          .additions    = &mpc85xx_tsec1_def,
+        },
+        { .vendor       = OCP_VENDOR_FREESCALE,
+          .function     = OCP_FUNC_GFAR,
+          .index        = 1,
+          .paddr        = MPC85xx_ENET2_OFFSET,
+          .irq          = MPC85xx_IRQ_TSEC2_TX,
+          .pm           = OCP_CPM_NA,
+          .additions    = &mpc85xx_tsec2_def,
+        },
+        { .vendor       = OCP_VENDOR_FREESCALE,
+          .function     = OCP_FUNC_GFAR,
+          .index        = 2,
+          .paddr        = MPC85xx_ENET3_OFFSET,
+          .irq          = MPC85xx_IRQ_FEC,
+          .pm           = OCP_CPM_NA,
+          .additions    = &mpc85xx_fec_def,
+        },
+        { .vendor       = OCP_VENDOR_FREESCALE,
+          .function     = OCP_FUNC_DMA,
+          .index        = 0,
+          .paddr        = MPC85xx_DMA_OFFSET,
+          .irq          = MPC85xx_IRQ_DMA0,
+          .pm           = OCP_CPM_NA,
+        },
+        { .vendor       = OCP_VENDOR_FREESCALE,
+          .function     = OCP_FUNC_PERFMON,
+          .index        = 0,
+          .paddr        = MPC85xx_PERFMON_OFFSET,
+          .irq          = MPC85xx_IRQ_PERFMON,
+          .pm           = OCP_CPM_NA,
+        },
+        { .vendor       = OCP_VENDOR_INVALID
+        }
+};
diff -Nru a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,238 @@
+/*
+ * arch/ppc/platforms/85xx/mpc8540_ads.c
+ *
+ * MPC8540ADS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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/module.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/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/kgdb.h>
+#include <asm/ocp.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_setup.h>
+
+struct ocp_gfar_data mpc85xx_tsec1_def = {
+	.interruptTransmit = MPC85xx_IRQ_TSEC1_TX,
+	.interruptError = MPC85xx_IRQ_TSEC1_ERROR,
+	.interruptReceive = MPC85xx_IRQ_TSEC1_RX,
+	.interruptPHY = MPC85xx_IRQ_EXT5,
+	.flags = (GFAR_HAS_GIGABIT | GFAR_HAS_MULTI_INTR
+			| GFAR_HAS_RMON
+			| GFAR_HAS_PHY_INTR | GFAR_HAS_COALESCE),
+	.phyid = 0,
+	.phyregidx = 0,
+};
+
+struct ocp_gfar_data mpc85xx_tsec2_def = {
+	.interruptTransmit = MPC85xx_IRQ_TSEC2_TX,
+	.interruptError = MPC85xx_IRQ_TSEC2_ERROR,
+	.interruptReceive = MPC85xx_IRQ_TSEC2_RX,
+	.interruptPHY = MPC85xx_IRQ_EXT5,
+	.flags = (GFAR_HAS_GIGABIT | GFAR_HAS_MULTI_INTR
+			| GFAR_HAS_RMON
+			| GFAR_HAS_PHY_INTR | GFAR_HAS_COALESCE),
+	.phyid = 1,
+	.phyregidx = 0,
+};
+
+struct ocp_gfar_data mpc85xx_fec_def = {
+	.interruptTransmit = MPC85xx_IRQ_FEC,
+	.interruptError = MPC85xx_IRQ_FEC,
+	.interruptReceive = MPC85xx_IRQ_FEC,
+	.interruptPHY = MPC85xx_IRQ_EXT5,
+	.flags = 0,
+	.phyid = 3,
+	.phyregidx = 0,
+};
+
+struct ocp_fs_i2c_data mpc85xx_i2c1_def = {
+	.flags = FS_I2C_SEPARATE_DFSRR,
+};
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc8540ads_setup_arch(void)
+{
+	struct ocp_def *def;
+	struct ocp_gfar_data *einfo;
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc8540ads_setup_arch()", 0);
+
+	/* 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();
+#endif
+
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+#ifdef CONFIG_SERIAL_8250
+	mpc85xx_early_serial_map();
+#endif
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	/* Invalidate the entry we stole earlier the serial ports
+	 * should be properly mapped */
+	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+#endif
+
+	def = ocp_get_one_device(OCP_VENDOR_FREESCALE, OCP_FUNC_GFAR, 0);
+	if (def) {
+		einfo = (struct ocp_gfar_data *) def->additions;
+		memcpy(einfo->mac_addr, binfo->bi_enetaddr, 6);
+	}
+
+	def = ocp_get_one_device(OCP_VENDOR_FREESCALE, OCP_FUNC_GFAR, 1);
+	if (def) {
+		einfo = (struct ocp_gfar_data *) def->additions;
+		memcpy(einfo->mac_addr, binfo->bi_enet1addr, 6);
+	}
+
+	def = ocp_get_one_device(OCP_VENDOR_FREESCALE, OCP_FUNC_GFAR, 2);
+	if (def) {
+		einfo = (struct ocp_gfar_data *) def->additions;
+		memcpy(einfo->mac_addr, binfo->bi_enet2addr, 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
+
+	ocp_for_each_device(mpc85xx_update_paddr_ocp, &(binfo->bi_immr_base));
+}
+
+/* ************************************************************************ */
+void __init
+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());
+
+	/*
+	 * 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;
+
+		/* 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);
+	}
+#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));
+	}
+
+	/* setup the PowerPC module struct */
+	ppc_md.setup_arch = mpc8540ads_setup_arch;
+	ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
+
+	ppc_md.init_IRQ = mpc85xx_ads_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;
+
+#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("mpc8540ads_init(): exit", 0);
+
+	return;
+}
diff -Nru a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,30 @@
+/*
+ * arch/ppc/platforms/85xx/mpc8540_ads.h
+ *
+ * MPC8540ADS board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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_MPC8540ADS_H__
+#define __MACH_MPC8540ADS_H__
+
+#include <linux/config.h>
+#include <linux/serial.h>
+#include <linux/initrd.h>
+#include <syslib/ppc85xx_setup.h>
+#include <platforms/85xx/mpc85xx_ads_common.h>
+
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+
+#endif /* __MACH_MPC8540ADS_H__ */
diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,237 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_ads_common.c
+ *
+ * MPC85xx ADS board common routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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/serial.h>
+#include <linux/module.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/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/ocp.h>
+
+#include <mm/mmu_decl.h>
+
+#include <platforms/85xx/mpc85xx_ads_common.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)];
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+
+static u_char mpc85xx_ads_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 */
+	0x0,						/* External  0: */
+#if defined(CONFIG_PCI)
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 1: PCI slot 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 2: PCI slot 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 3: PCI slot 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 4: PCI slot 3 */
+#else
+	0x0,				/* External  1: */
+	0x0,				/* External  2: */
+	0x0,				/* External  3: */
+	0x0,				/* External  4: */
+#endif
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 5: PHY */
+	0x0,				/* External  6: */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 7: PHY */
+	0x0,				/* External  8: */
+	0x0,				/* External  9: */
+	0x0,				/* External 10: */
+	0x0,				/* External 11: */
+};
+
+/* ************************************************************************ */
+int
+mpc85xx_ads_show_cpuinfo(struct seq_file *m)
+{
+	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;
+
+	pvid = mfspr(PVR);
+	svid = mfspr(SVR);
+
+	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, "bus freq\t: %u.%.6u MHz\n", freq / 1000000,
+		   freq % 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", memsize / (1024 * 1024));
+
+	return 0;
+}
+
+void __init
+mpc85xx_ads_init_IRQ(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	/* 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_ads_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof (mpc85xx_ads_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);
+
+	return;
+}
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+
+int
+mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     * This is little evil, but works around the fact
+	     * that revA boards have IDSEL starting at 18
+	     * and others boards (older) start at 12
+	     *
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *       A      B      C      D
+	     */
+	{
+		{PIRQA, PIRQB, PIRQC, PIRQD},	/* IDSEL 2 */
+		{PIRQD, PIRQA, PIRQB, PIRQC},
+		{PIRQC, PIRQD, PIRQA, PIRQB},
+		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 5 */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{PIRQA, PIRQB, PIRQC, PIRQD},	/* IDSEL 12 */
+		{PIRQD, PIRQA, PIRQB, PIRQC},
+		{PIRQC, PIRQD, PIRQA, PIRQB},
+		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 15 */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{PIRQA, PIRQB, PIRQC, PIRQD},	/* IDSEL 18 */
+		{PIRQD, PIRQA, PIRQB, PIRQC},
+		{PIRQC, PIRQD, PIRQA, PIRQB},
+		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 21 */
+	};
+
+	const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int
+mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+
+#endif /* CONFIG_PCI */
diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,50 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_ads_common.h
+ *
+ * MPC85XX ADS common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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_MPC85XX_ADS_H__
+#define __MACH_MPC85XX_ADS_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <asm/ppcboot.h>
+
+#define BOARD_CCSRBAR		((uint)0xe0000000)
+#define BCSR_ADDR		((uint)0xf8000000)
+#define BCSR_SIZE		((uint)(32 * 1024))
+
+extern int mpc85xx_ads_show_cpuinfo(struct seq_file *m);
+extern void mpc85xx_ads_init_IRQ(void) __init;
+extern void mpc85xx_ads_map_io(void) __init;
+
+/* PCI interrupt controller */
+#define PIRQA		MPC85xx_IRQ_EXT1
+#define PIRQB		MPC85xx_IRQ_EXT2
+#define PIRQC		MPC85xx_IRQ_EXT3
+#define PIRQD		MPC85xx_IRQ_EXT4
+
+#define MPC85XX_PCI1_LOWER_IO	0x00000000
+#define MPC85XX_PCI1_UPPER_IO	0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM	0x80000000
+#define MPC85XX_PCI1_UPPER_MEM	0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE	0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET	0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE	0x01000000
+
+#endif				/* __MACH_MPC85XX_ADS_H__ */
diff -Nru a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
--- a/arch/ppc/platforms/pmac_cpufreq.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc/platforms/pmac_cpufreq.c	2004-06-23 19:04:27 -07:00
@@ -1,7 +1,8 @@
 /*
  *  arch/ppc/platforms/pmac_cpufreq.c
  *
- *  Copyright (C) 2002 - 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *  Copyright (C) 2002 - 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *  Copyright (C) 2004        John Steele Scott <toojays@toojays.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,6 +48,7 @@
 #warning "WARNING, CPUFREQ not recommended on SMP kernels"
 #endif
 
+extern void low_choose_7447a_dfs(int dfs);
 extern void low_choose_750fx_pll(int pll);
 extern void low_sleep_handler(void);
 extern void openpic_suspend(struct sys_device *sysdev, u32 state);
@@ -54,18 +56,27 @@
 extern void enable_kernel_altivec(void);
 extern void enable_kernel_fp(void);
 
+/*
+ * Currently, PowerMac cpufreq supports only high & low frequencies
+ * that are set by the firmware
+ */
 static unsigned int low_freq;
 static unsigned int hi_freq;
 static unsigned int cur_freq;
 
-/* Clean that up some day ... use a func ptr or at least an enum... */
-static int cpufreq_uses_pmu;
-static int cpufreq_uses_gpios;
+/*
+ * Different models uses different mecanisms to switch the frequency
+ */
+static int (*set_speed_proc)(int low_speed);
 
+/*
+ * Some definitions used by the various speedprocs
+ */
 static u32 voltage_gpio;
 static u32 frequency_gpio;
 static u32 slew_done_gpio;
 
+
 #define PMAC_CPU_LOW_SPEED	1
 #define PMAC_CPU_HIGH_SPEED	0
 
@@ -123,9 +134,39 @@
 	return 0;
 }
 
+/* Switch CPU speed using DFS */
+static int __pmac dfs_set_cpu_speed(int low_speed)
+{
+	if (low_speed == 0) {
+		/* ramping up, set voltage first */
+		pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ/1000);
+	} else {
+		/* ramping down, enable aack delay first */
+		pmac_call_feature(PMAC_FTR_AACK_DELAY_ENABLE, NULL, 1, 0);
+	}
+
+	/* set frequency */
+	low_choose_7447a_dfs(low_speed);
+
+	if (low_speed == 1) {
+		/* ramping down, set voltage last */
+		pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ/1000);
+	} else {
+		/* ramping up, disable aack delay last */
+		pmac_call_feature(PMAC_FTR_AACK_DELAY_ENABLE, NULL, 0, 0);
+	}
+
+	return 0;
+}
+
+
 /* Switch CPU speed using slewing GPIOs
  */
-static int __pmac gpios_set_cpu_speed(unsigned int low_speed)
+static int __pmac gpios_set_cpu_speed(int low_speed)
 {
 	int gpio;
 
@@ -138,7 +179,8 @@
 	}
 
 	/* Set frequency */
-	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, low_speed ? 0x04 : 0x05);
+	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio,
+			  low_speed ? 0x04 : 0x05);
 	udelay(200);
 	do {
 		set_current_state(TASK_UNINTERRUPTIBLE);
@@ -163,7 +205,7 @@
 
 /* Switch CPU speed under PMU control
  */
-static int __pmac pmu_set_cpu_speed(unsigned int low_speed)
+static int __pmac pmu_set_cpu_speed(int low_speed)
 {
 	struct adb_request req;
 	unsigned long save_l2cr;
@@ -269,12 +311,7 @@
 		return 0;
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	if (cpufreq_uses_pmu)
-		rc = pmu_set_cpu_speed(speed_mode);
-	else if (cpufreq_uses_gpios)
-		rc = gpios_set_cpu_speed(speed_mode);
-	else
-		rc = cpu_750fx_cpu_speed(speed_mode);
+	set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED);
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 	cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
 
@@ -338,20 +375,137 @@
 };
 
 
+static int __pmac pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
+{
+	struct device_node *volt_gpio_np = of_find_node_by_name(NULL,
+								"voltage-gpio");
+	struct device_node *freq_gpio_np = of_find_node_by_name(NULL,
+								"frequency-gpio");
+	struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL,
+								     "slewing-done");
+	u32 *value;
+
+	/*
+	 * Check to see if it's GPIO driven or PMU only
+	 *
+	 * The way we extract the GPIO address is slightly hackish, but it
+	 * works well enough for now. We need to abstract the whole GPIO
+	 * stuff sooner or later anyway
+	 */
+
+	if (volt_gpio_np)
+		voltage_gpio = read_gpio(volt_gpio_np);
+	if (freq_gpio_np)
+		frequency_gpio = read_gpio(freq_gpio_np);
+	if (slew_done_gpio_np)
+		slew_done_gpio = read_gpio(slew_done_gpio_np);
+
+	/* If we use the frequency GPIOs, calculate the min/max speeds based
+	 * on the bus frequencies
+	 */
+	if (frequency_gpio && slew_done_gpio) {
+		int lenp, rc;
+		u32 *freqs, *ratio;
+
+		freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp);
+		lenp /= sizeof(u32);
+		if (freqs == NULL || lenp != 2) {
+			printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");
+			return 1;
+		}
+		ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL);
+		if (ratio == NULL) {
+			printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");
+			return 1;
+		}
+
+		/* Get the min/max bus frequencies */
+		low_freq = min(freqs[0], freqs[1]);
+		hi_freq = max(freqs[0], freqs[1]);
+
+		/* Grrrr.. It _seems_ that the device-tree is lying on the low bus
+		 * frequency, it claims it to be around 84Mhz on some models while
+		 * it appears to be approx. 101Mhz on all. Let's hack around here...
+		 * fortunately, we don't need to be too precise
+		 */
+		if (low_freq < 98000000)
+			low_freq = 101000000;
+			
+		/* Convert those to CPU core clocks */
+		low_freq = (low_freq * (*ratio)) / 2000;
+		hi_freq = (hi_freq * (*ratio)) / 2000;
+
+		/* Now we get the frequencies, we read the GPIO to see what is out current
+		 * speed
+		 */
+		rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
+		cur_freq = (rc & 0x01) ? hi_freq : low_freq;
+
+		set_speed_proc = gpios_set_cpu_speed;
+		return 1;
+	}
+
+	/* If we use the PMU, look for the min & max frequencies in the
+	 * device-tree
+	 */
+	value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL);
+	if (!value)
+		return 1;
+	low_freq = (*value) / 1000;
+	/* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree
+	 * here */
+	if (low_freq < 100000)
+		low_freq *= 10;
+
+	value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL);
+	if (!value)
+		return 1;
+	hi_freq = (*value) / 1000;
+	set_speed_proc = pmu_set_cpu_speed;
+
+	return 0;
+}
+
+static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode)
+{
+	struct device_node *volt_gpio_np;
+
+	/* OF only reports the high frequency */
+	hi_freq = cur_freq;
+	low_freq = cur_freq/2;
+	if (mfspr(HID1) & HID1_DFS)
+		cur_freq = low_freq;
+	else
+		cur_freq = hi_freq;
+
+	volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
+	if (!volt_gpio_np){
+		printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");
+		return 1;
+	}
+
+	u32 *reg = (u32 *)get_property(volt_gpio_np, "reg", NULL);
+	voltage_gpio = *reg;
+	set_speed_proc = dfs_set_cpu_speed;
+
+	return 0;
+}
+
 /* Currently, we support the following machines:
  *
  *  - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz)
  *  - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)
+ *  - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)
  *  - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
  *  - iBook2 500 (PMU based, 400Mhz & 500Mhz)
  *  - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
- *  - Recent MacRISC3 machines
+ *  - Recent MacRISC3 laptops
+ *  - iBook G4s and PowerBook G4s with 7447A CPUs
  */
 static int __init pmac_cpufreq_setup(void)
 {
 	struct device_node	*cpunode;
 	u32			*value;
-	int			has_freq_ctl = 0;
 
 	if (strstr(cmd_line, "nocpufreq"))
 		return 0;
@@ -367,113 +521,36 @@
 		goto out;
 	cur_freq = (*value) / 1000;
 
-	/* Check for newer machines */
-	if (machine_is_compatible("PowerBook3,4") ||
-	    machine_is_compatible("PowerBook3,5") ||
-	    machine_is_compatible("MacRISC3")) {
-		struct device_node *volt_gpio_np = of_find_node_by_name(NULL, "voltage-gpio");
-		struct device_node *freq_gpio_np = of_find_node_by_name(NULL, "frequency-gpio");
-		struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, "slewing-done");
-
-		/*
-		 * Check to see if it's GPIO driven or PMU only
-		 *
-		 * The way we extract the GPIO address is slightly hackish, but it
-		 * works well enough for now. We need to abstract the whole GPIO
-		 * stuff sooner or later anyway
-		 */
-
-		if (volt_gpio_np)
-			voltage_gpio = read_gpio(volt_gpio_np);
-		if (freq_gpio_np)
-			frequency_gpio = read_gpio(freq_gpio_np);
-		if (slew_done_gpio_np)
-			slew_done_gpio = read_gpio(slew_done_gpio_np);
-
-		/* If we use the frequency GPIOs, calculate the min/max speeds based
-		 * on the bus frequencies
-		 */
-		if (frequency_gpio && slew_done_gpio) {
-			int lenp, rc;
-			u32 *freqs, *ratio;
-
-			freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp);
-			lenp /= sizeof(u32);
-			if (freqs == NULL || lenp != 2) {
-				printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");
-				goto out;
-			}
-			ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL);
-			if (ratio == NULL) {
-				printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");
-				goto out;
-			}
-
-			/* Get the min/max bus frequencies */
-			low_freq = min(freqs[0], freqs[1]);
-			hi_freq = max(freqs[0], freqs[1]);
-
-			/* Grrrr.. It _seems_ that the device-tree is lying on the low bus
-			 * frequency, it claims it to be around 84Mhz on some models while
-			 * it appears to be approx. 101Mhz on all. Let's hack around here...
-			 * fortunately, we don't need to be too precise
-			 */
-			if (low_freq < 98000000)
-				low_freq = 101000000;
-			
-			/* Convert those to CPU core clocks */
-			low_freq = (low_freq * (*ratio)) / 2000;
-			hi_freq = (hi_freq * (*ratio)) / 2000;
-
-			/* Now we get the frequencies, we read the GPIO to see what is out current
-			 * speed
-			 */
-			rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
-			cur_freq = (rc & 0x01) ? hi_freq : low_freq;
-
-			has_freq_ctl = 1;
-			cpufreq_uses_gpios = 1;
-			goto out;
-		}
-
-		/* If we use the PMU, look for the min & max frequencies in the
-		 * device-tree
-		 */
-		value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL);
-		if (!value)
-			goto out;
-		low_freq = (*value) / 1000;
-		/* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree
-		 * here */
-		if (low_freq < 100000)
-			low_freq *= 10;
-
-		value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL);
-		if (!value)
-			goto out;
-		hi_freq = (*value) / 1000;
-		has_freq_ctl = 1;
-		cpufreq_uses_pmu = 1;
-	}
+	/*  Check for 7447A based iBook G4 or PowerBook */
+	if (machine_is_compatible("PowerBook6,5") ||
+	    machine_is_compatible("PowerBook6,4") ||
+	    machine_is_compatible("PowerBook5,5") ||
+	    machine_is_compatible("PowerBook5,4")) {
+		pmac_cpufreq_init_7447A(cpunode);
+	/* Check for other MacRISC3 machines */
+	} else if (machine_is_compatible("PowerBook3,4") ||
+		   machine_is_compatible("PowerBook3,5") ||
+		   machine_is_compatible("MacRISC3")) {
+		pmac_cpufreq_init_MacRISC3(cpunode);
 	/* Else check for iBook2 500 */
-	else if (machine_is_compatible("PowerBook4,1")) {
+	} else if (machine_is_compatible("PowerBook4,1")) {
 		/* We only know about 500Mhz model */
 		if (cur_freq < 450000 || cur_freq > 550000)
 			goto out;
 		hi_freq = cur_freq;
 		low_freq = 400000;
-		has_freq_ctl = 1;
-		cpufreq_uses_pmu = 1;
+		set_speed_proc = pmu_set_cpu_speed;
 	}
-	/* Else check for TiPb 500 */
+	/* Else check for TiPb 400 & 500 */
 	else if (machine_is_compatible("PowerBook3,2")) {
-		/* We only know about 500Mhz model */
-		if (cur_freq < 450000 || cur_freq > 550000)
+		/* We only know about the 400 MHz and the 500Mhz model
+		 * they both have 300 MHz as low frequency
+		 */
+		if (cur_freq < 350000 || cur_freq > 550000)
 			goto out;
 		hi_freq = cur_freq;
 		low_freq = 300000;
-		has_freq_ctl = 1;
-		cpufreq_uses_pmu = 1;
+		set_speed_proc = pmu_set_cpu_speed;
 	}
 	/* Else check for 750FX */
 	else if (PVR_VER(mfspr(PVR)) == 0x7000) {
@@ -483,21 +560,19 @@
 		value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL);
 		if (!value)
 			goto out;
-		low_freq = (*value) / 1000;
-		cpufreq_uses_pmu = 0;
-		has_freq_ctl = 1;
+		low_freq = (*value) / 1000;		
+		set_speed_proc = cpu_750fx_cpu_speed;
 	}
 out:
-	if (!has_freq_ctl)
+	if (set_speed_proc == NULL)
 		return -ENODEV;
 
 	pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq;
 	pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq;
 
 	printk(KERN_INFO "Registering PowerMac CPU frequency driver\n");
-	printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz, switch method: %s\n",
-	       low_freq/1000, hi_freq/1000, cur_freq/1000,
-	       cpufreq_uses_pmu ? "PMU" : (cpufreq_uses_gpios ? "GPIOs" : "CPU"));
+	printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",
+	       low_freq/1000, hi_freq/1000, cur_freq/1000);
 
 	return cpufreq_register_driver(&pmac_cpufreq_driver);
 }
diff -Nru a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
--- a/arch/ppc/platforms/pmac_feature.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc/platforms/pmac_feature.c	2004-06-23 19:04:28 -07:00
@@ -1282,6 +1282,25 @@
 	return 0;
 }
 
+static long __pmac
+intrepid_aack_delay_enable(struct device_node* node, long param, long value)
+{
+	unsigned long flags;
+
+    	if (uninorth_rev < 0xd2)
+		return -ENODEV;
+
+	LOCK(flags);
+	if (param)
+		UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
+	else
+		UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
+	UNLOCK(flags);
+
+    	return 0;
+}
+
+
 #endif /* CONFIG_POWER4 */
 
 static long __pmac
@@ -1914,6 +1933,7 @@
 	{ PMAC_FTR_SLEEP_STATE,		core99_sleep_state },
 	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
 	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
+	{ PMAC_FTR_AACK_DELAY_ENABLE,	intrepid_aack_delay_enable },
 	{ 0, NULL }
 };
 
@@ -2116,6 +2136,14 @@
 		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
 		PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
 	},
+	{	"PowerBook5,4",			"PowerBook G4 15\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook5,5",			"PowerBook G4 17\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
 	{	"PowerBook6,1",			"PowerBook G4 12\"",
 		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
 		PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
@@ -2125,6 +2153,10 @@
 		PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
 	},
 	{	"PowerBook6,3",			"iBook G4",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook6,4",			"PowerBook G4 12\"",
 		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
 		PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
 	},
diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
--- a/arch/ppc/syslib/Makefile	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc/syslib/Makefile	2004-06-23 19:04:25 -07:00
@@ -8,6 +8,9 @@
 ifdef CONFIG_4xx
 EXTRA_AFLAGS		:= -Wa,-m405
 endif
+ifdef CONFIG_E500
+EXTRA_AFLAGS		:= -Wa,-me500
+endif
 
 CFLAGS_prom_init.o      += -fPIC
 CFLAGS_btext.o          += -fPIC
@@ -75,3 +78,7 @@
 obj-$(CONFIG_MPC10X_BRIDGE)     += mpc10x_common.o indirect_pci.o
 obj-$(CONFIG_40x)		+= dcr.o
 obj-$(CONFIG_BOOKE)		+= dcr.o
+obj-$(CONFIG_85xx)		+= open_pic.o ppc85xx_common.o ppc85xx_setup.o
+ifeq ($(CONFIG_85xx),y)
+obj-$(CONFIG_PCI)		+= indirect_pci.o pci_auto.o
+endif
diff -Nru a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
--- a/arch/ppc/syslib/open_pic.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc/syslib/open_pic.c	2004-06-23 19:04:27 -07:00
@@ -28,7 +28,7 @@
 
 #include "open_pic_defs.h"
 
-#ifdef CONFIG_PRPMC800
+#if defined(CONFIG_PRPMC800) || defined(CONFIG_85xx)
 #define OPENPIC_BIG_ENDIAN
 #endif
 
diff -Nru a/arch/ppc/syslib/ppc85xx_common.c b/arch/ppc/syslib/ppc85xx_common.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/ppc85xx_common.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,46 @@
+/*
+ * arch/ppc/syslib/ppc85xx_common.c
+ *
+ * MPC85xx support routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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 <asm/mpc85xx.h>
+#include <asm/mmu.h>
+#include <asm/ocp.h>
+
+/* ************************************************************************ */
+/* Return the value of CCSRBAR for the current board */
+
+phys_addr_t
+get_ccsrbar(void)
+{
+        return BOARD_CCSRBAR;
+}
+
+/* ************************************************************************ */
+/* Update the 85xx OCP tables paddr field */
+void
+mpc85xx_update_paddr_ocp(struct ocp_device *dev, void *arg)
+{
+	phys_addr_t ccsrbar;
+	if (arg) {
+		ccsrbar = *(phys_addr_t *)arg;
+		dev->def->paddr += ccsrbar;
+	}
+}
+
+EXPORT_SYMBOL(get_ccsrbar);
diff -Nru a/arch/ppc/syslib/ppc85xx_common.h b/arch/ppc/syslib/ppc85xx_common.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/ppc85xx_common.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,29 @@
+/*
+ * arch/ppc/syslib/ppc85xx_common.h
+ *
+ * MPC85xx support routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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_PPC85XX_COMMON_H
+#define __PPC_SYSLIB_PPC85XX_COMMON_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ocp.h>
+
+/* Provide access to ccsrbar for any modules, etc */
+phys_addr_t get_ccsrbar(void);
+
+/* Update the 85xx OCP tables paddr field */
+void mpc85xx_update_paddr_ocp(struct ocp_device *dev, void *ccsrbar);
+
+#endif /* __PPC_SYSLIB_PPC85XX_COMMON_H */
diff -Nru a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/ppc85xx_setup.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,341 @@
+/*
+ * arch/ppc/syslib/ppc85xx_setup.c
+ *
+ * MPC85XX common board code
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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 <asm/prom.h>
+#include <asm/time.h>
+#include <asm/mpc85xx.h>
+#include <asm/immap_85xx.h>
+#include <asm/mmu.h>
+#include <asm/ocp.h>
+#include <asm/kgdb.h>
+
+/* Return the amount of memory */
+unsigned long __init
+mpc85xx_find_end_of_memory(void)
+{
+        bd_t *binfo;
+
+        binfo = (bd_t *) __res;
+
+        return binfo->bi_memsize;
+}
+
+/* The decrementer counts at the system (internal) clock freq divided by 8 */
+void __init
+mpc85xx_calibrate_decr(void)
+{
+        bd_t *binfo = (bd_t *) __res;
+        unsigned int freq, divisor;
+
+        /* get the core frequency */
+        freq = binfo->bi_busfreq;
+
+        /* The timebase is updated every 8 bus clocks, HID0[SEL_TBCLK] = 0 */
+        divisor = 8;
+        tb_ticks_per_jiffy = freq / divisor / HZ;
+        tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+
+	/* Set the time base to zero */
+	mtspr(SPRN_TBWL, 0);
+	mtspr(SPRN_TBWU, 0);
+
+	/* Clear any pending timer interrupts */
+	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+	/* Enable decrementer interrupt */
+	mtspr(SPRN_TCR, TCR_DIE);
+}
+
+#ifdef CONFIG_SERIAL_8250
+void __init
+mpc85xx_early_serial_map(void)
+{
+	struct uart_port serial_req;
+	bd_t *binfo = (bd_t *) __res;
+	phys_addr_t duart_paddr = binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
+
+	/* Setup serial port access */
+	memset(&serial_req, 0, sizeof (serial_req));
+	serial_req.uartclk = binfo->bi_busfreq;
+	serial_req.line = 0;
+	serial_req.irq = MPC85xx_IRQ_DUART;
+	serial_req.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.membase = ioremap(duart_paddr, MPC85xx_UART0_SIZE);
+	serial_req.mapbase = duart_paddr;
+	serial_req.regshift = 0;
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	gen550_init(0, &serial_req);
+#endif
+
+	if (early_serial_setup(&serial_req) != 0)
+		printk("Early serial init of port 0 failed\n");
+
+	/* Assume early_serial_setup() doesn't modify serial_req */
+	duart_paddr = binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
+	serial_req.line = 1;
+	serial_req.mapbase = duart_paddr;
+	serial_req.membase = ioremap(duart_paddr, MPC85xx_UART1_SIZE);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	gen550_init(1, &serial_req);
+#endif
+
+	if (early_serial_setup(&serial_req) != 0)
+		printk("Early serial init of port 1 failed\n");
+}
+#endif
+
+void
+mpc85xx_restart(char *cmd)
+{
+	local_irq_disable();
+	abort();
+}
+
+void
+mpc85xx_power_off(void)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+void
+mpc85xx_halt(void)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+#ifdef CONFIG_PCI
+static void __init
+mpc85xx_setup_pci1(struct pci_controller *hose)
+{
+	volatile struct ccsr_pci *pci;
+	volatile struct ccsr_guts *guts;
+	unsigned short temps;
+	bd_t *binfo = (bd_t *) __res;
+
+	pci = ioremap(binfo->bi_immr_base + MPC85xx_PCI1_OFFSET,
+		    MPC85xx_PCI1_SIZE);
+
+	guts = ioremap(binfo->bi_immr_base + MPC85xx_GUTS_OFFSET,
+		    MPC85xx_GUTS_SIZE);
+
+	early_read_config_word(hose, 0, 0, PCI_COMMAND, &temps);
+	temps |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	early_write_config_word(hose, 0, 0, PCI_COMMAND, temps);
+
+#define PORDEVSR_PCI	(0x00800000)	/* PCI Mode */
+	if (guts->pordevsr & PORDEVSR_PCI) {
+ 		early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
+ 	} else {
+		/* PCI-X init */
+		temps = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ
+			| PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
+		early_write_config_word(hose, 0, 0, PCIX_COMMAND, temps);
+	}
+
+	/* Disable all windows (except powar0 since its ignored) */
+	pci->powar1 = 0;
+	pci->powar2 = 0;
+	pci->powar3 = 0;
+	pci->powar4 = 0;
+	pci->piwar1 = 0;
+	pci->piwar2 = 0;
+	pci->piwar3 = 0;
+
+	/* Setup 512M Phys:PCI 1:1 outbound mem window @ 0x80000000 */
+	pci->potar1 = (MPC85XX_PCI1_LOWER_MEM >> 12) & 0x000fffff;
+	pci->potear1 = 0x00000000;
+	pci->powbar1 = (MPC85XX_PCI1_LOWER_MEM >> 12) & 0x000fffff;
+	pci->powar1 = 0x8004401c;	/* Enable, Mem R/W, 512M */
+
+	/* Setup 16M outboud IO windows @ 0xe2000000 */
+	pci->potar2 = 0x00000000;
+	pci->potear2 = 0x00000000;
+	pci->powbar2 = (MPC85XX_PCI1_IO_BASE >> 12) & 0x000fffff;
+	pci->powar2 = 0x80088017;	/* Enable, IO R/W, 16M */
+
+	/* Setup 2G inbound Memory Window @ 0 */
+	pci->pitar1 = 0x00000000;
+	pci->piwbar1 = 0x00000000;
+	pci->piwar1 = 0xa0f5501e;	/* Enable, Prefetch, Local
+					   Mem, Snoop R/W, 2G */
+}
+
+
+extern int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin);
+extern int mpc85xx_exclude_device(u_char bus, u_char devfn);
+
+#if CONFIG_85xx_PCI2
+static void __init
+mpc85xx_setup_pci2(struct pci_controller *hose)
+{
+	volatile struct ccsr_pci *pci;
+	unsigned short temps;
+	bd_t *binfo = (bd_t *) __res;
+
+	pci = ioremap(binfo->bi_immr_base + MPC85xx_PCI2_OFFSET,
+		    MPC85xx_PCI2_SIZE);
+
+	early_read_config_word(hose, 0, 0, PCI_COMMAND, &temps);
+	temps |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	early_write_config_word(hose, 0, 0, PCI_COMMAND, temps);
+	early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
+
+	/* Disable all windows (except powar0 since its ignored) */
+	pci->powar1 = 0;
+	pci->powar2 = 0;
+	pci->powar3 = 0;
+	pci->powar4 = 0;
+	pci->piwar1 = 0;
+	pci->piwar2 = 0;
+	pci->piwar3 = 0;
+
+	/* Setup 512M Phys:PCI 1:1 outbound mem window @ 0xa0000000 */
+	pci->potar1 = (MPC85XX_PCI2_LOWER_MEM >> 12) & 0x000fffff;
+	pci->potear1 = 0x00000000;
+	pci->powbar1 = (MPC85XX_PCI2_LOWER_MEM >> 12) & 0x000fffff;
+	pci->powar1 = 0x8004401c;	/* Enable, Mem R/W, 512M */
+
+	/* Setup 16M outboud IO windows @ 0xe3000000 */
+	pci->potar2 = 0x00000000;
+	pci->potear2 = 0x00000000;
+	pci->powbar2 = (MPC85XX_PCI2_IO_BASE >> 12) & 0x000fffff;
+	pci->powar2 = 0x80088017;	/* Enable, IO R/W, 16M */
+
+	/* Setup 2G inbound Memory Window @ 0 */
+	pci->pitar1 = 0x00000000;
+	pci->piwbar1 = 0x00000000;
+	pci->piwar1 = 0xa0f5501e;	/* Enable, Prefetch, Local
+					   Mem, Snoop R/W, 2G */
+}
+#endif /* CONFIG_85xx_PCI2 */
+
+void __init
+mpc85xx_setup_hose(void)
+{
+	struct pci_controller *hose_a;
+#ifdef CONFIG_85xx_PCI2
+	struct pci_controller *hose_b;
+#endif
+	bd_t *binfo = (bd_t *) __res;
+
+	hose_a = pcibios_alloc_controller();
+
+	if (!hose_a)
+		return;
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mpc85xx_map_irq;
+
+	hose_a->first_busno = 0;
+	hose_a->bus_offset = 0;
+	hose_a->last_busno = 0xff;
+
+	setup_indirect_pci(hose_a, binfo->bi_immr_base + PCI1_CFG_ADDR_OFFSET,
+			   binfo->bi_immr_base + PCI1_CFG_DATA_OFFSET);
+	hose_a->set_cfg_type = 1;
+
+	mpc85xx_setup_pci1(hose_a);
+
+	hose_a->pci_mem_offset = MPC85XX_PCI1_MEM_OFFSET;
+	hose_a->mem_space.start = MPC85XX_PCI1_LOWER_MEM;
+	hose_a->mem_space.end = MPC85XX_PCI1_UPPER_MEM;
+
+	hose_a->io_space.start = MPC85XX_PCI1_LOWER_IO;
+	hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO;
+	hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE;
+#if CONFIG_85xx_PCI2
+	isa_io_base =
+		(unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
+					MPC85XX_PCI1_IO_SIZE +
+					MPC85XX_PCI2_IO_SIZE);
+#else
+	isa_io_base =
+		(unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
+					MPC85XX_PCI1_IO_SIZE);
+#endif
+	hose_a->io_base_virt = (void *) isa_io_base;
+
+	/* setup resources */
+	pci_init_resource(&hose_a->mem_resources[0],
+			MPC85XX_PCI1_LOWER_MEM,
+			MPC85XX_PCI1_UPPER_MEM,
+			IORESOURCE_MEM, "PCI1 host bridge");
+
+	pci_init_resource(&hose_a->io_resource,
+			MPC85XX_PCI1_LOWER_IO,
+			MPC85XX_PCI1_UPPER_IO,
+			IORESOURCE_IO, "PCI1 host bridge");
+
+	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
+
+	hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+
+#if CONFIG_85xx_PCI2
+	hose_b = pcibios_alloc_controller();
+
+	if (!hose_b)
+		return;
+
+	hose_b->bus_offset = hose_a->last_busno + 1;
+	hose_b->first_busno = hose_a->last_busno + 1;
+	hose_b->last_busno = 0xff;
+
+	setup_indirect_pci(hose_b, binfo->bi_immr_base + PCI2_CFG_ADDR_OFFSET,
+			   binfo->bi_immr_base + PCI2_CFG_DATA_OFFSET);
+	hose_b->set_cfg_type = 1;
+
+	mpc85xx_setup_pci2(hose_b);
+
+	hose_b->pci_mem_offset = MPC85XX_PCI2_MEM_OFFSET;
+	hose_b->mem_space.start = MPC85XX_PCI2_LOWER_MEM;
+	hose_b->mem_space.end = MPC85XX_PCI2_UPPER_MEM;
+
+	hose_b->io_space.start = MPC85XX_PCI2_LOWER_IO;
+	hose_b->io_space.end = MPC85XX_PCI2_UPPER_IO;
+	hose_b->io_base_phys = MPC85XX_PCI2_IO_BASE;
+	hose_b->io_base_virt = (void *) isa_io_base + MPC85XX_PCI1_IO_SIZE;
+
+	/* setup resources */
+	pci_init_resource(&hose_b->mem_resources[0],
+			MPC85XX_PCI2_LOWER_MEM,
+			MPC85XX_PCI2_UPPER_MEM,
+			IORESOURCE_MEM, "PCI2 host bridge");
+
+	pci_init_resource(&hose_b->io_resource,
+			MPC85XX_PCI2_LOWER_IO,
+			MPC85XX_PCI2_UPPER_IO,
+			IORESOURCE_IO, "PCI2 host bridge");
+
+	hose_b->last_busno = pciauto_bus_scan(hose_b, hose_b->first_busno);
+#endif
+	return;
+}
+#endif /* CONFIG_PCI */
+
+
diff -Nru a/arch/ppc/syslib/ppc85xx_setup.h b/arch/ppc/syslib/ppc85xx_setup.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/ppc85xx_setup.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,67 @@
+/*
+ * arch/ppc/syslib/ppc85xx_setup.h
+ *
+ * MPC85XX common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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_PPC85XX_SETUP_H
+#define __PPC_SYSLIB_PPC85XX_SETUP_H
+
+#include <linux/config.h>
+#include <linux/serial.h>
+#include <linux/init.h>
+#include <asm/ppcboot.h>
+
+extern unsigned long mpc85xx_find_end_of_memory(void) __init;
+extern void mpc85xx_calibrate_decr(void) __init;
+extern void mpc85xx_early_serial_map(void) __init;
+extern void mpc85xx_restart(char *cmd);
+extern void mpc85xx_power_off(void);
+extern void mpc85xx_halt(void);
+extern void mpc85xx_setup_hose(void) __init;
+
+/* PCI config */
+#define PCI1_CFG_ADDR_OFFSET	(0x8000)
+#define PCI1_CFG_DATA_OFFSET	(0x8004)
+
+#define PCI2_CFG_ADDR_OFFSET	(0x9000)
+#define PCI2_CFG_DATA_OFFSET	(0x9004)
+
+/* Additional register for PCI-X configuration */
+#define PCIX_NEXT_CAP	0x60
+#define PCIX_CAP_ID	0x61
+#define PCIX_COMMAND	0x62
+#define PCIX_STATUS	0x64
+
+/* Serial Config */
+#define MPC85XX_0_SERIAL                (CCSRBAR + 0x4500)
+#define MPC85XX_1_SERIAL                (CCSRBAR + 0x4600)
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  2
+#endif
+
+#define BASE_BAUD 0
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, num, MPC85xx_IRQ_DUART,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (u8 *)MPC85XX_##num##_SERIAL,	\
+		io_type: SERIAL_IO_MEM},
+
+/* Offset of CPM register space */
+#define CPM_MAP_ADDR	(CCSRBAR + MPC85xx_CPM_OFFSET)
+
+#endif /* __PPC_SYSLIB_PPC85XX_SETUP_H */
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/Kconfig	2004-06-23 19:04:27 -07:00
@@ -198,7 +198,6 @@
 
 config PREEMPT
 	bool "Preemptible Kernel"
-	depends on BROKEN
 	help
 	  This option reduces the latency of the kernel when reacting to
 	  real-time or interactive events by allowing a low priority process to
diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
--- a/arch/ppc64/kernel/Makefile	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc64/kernel/Makefile	2004-06-23 19:04:28 -07:00
@@ -56,4 +56,6 @@
 obj-$(CONFIG_PPC_PMAC)		+= pmac_smp.o smp-tbsync.o
 endif
 
+obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
+
 CFLAGS_ioctl32.o += -Ifs/
diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c
--- a/arch/ppc64/kernel/align.c	2004-06-23 19:04:29 -07:00
+++ b/arch/ppc64/kernel/align.c	2004-06-23 19:04:29 -07:00
@@ -22,8 +22,6 @@
 #include <asm/cache.h>
 #include <asm/cputable.h>
 
-void disable_kernel_fp(void); /* asm function from head.S */
-
 struct aligninfo {
 	unsigned char len;
 	unsigned char flags;
@@ -280,8 +278,11 @@
 	}
 
 	/* Force the fprs into the save area so we can reference them */
-	if ((flags & F) && (regs->msr & MSR_FP))
-		giveup_fpu(current);
+	if (flags & F) {
+		if (!user_mode(regs))
+			return 0;
+		flush_fp_to_thread(current);
+	}
 	
 	/* If we are loading, get the data from user space */
 	if (flags & LD) {
@@ -310,9 +311,11 @@
 		if (flags & F) {
 			if (nb == 4) {
 				/* Doing stfs, have to convert to single */
+				preempt_disable();
 				enable_kernel_fp();
 				cvt_df(&current->thread.fpr[reg], (float *)&data.v[4], &current->thread.fpscr);
 				disable_kernel_fp();
+				preempt_enable();
 			}
 			else
 				data.dd = current->thread.fpr[reg];
@@ -344,9 +347,11 @@
 		if (flags & F) {
 			if (nb == 4) {
 				/* Doing lfs, have to convert to double */
+				preempt_disable();
 				enable_kernel_fp();
 				cvt_fd((float *)&data.v[4], &current->thread.fpr[reg], &current->thread.fpscr);
 				disable_kernel_fp();
+				preempt_enable();
 			}
 			else
 				current->thread.fpr[reg] = data.dd;
diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
--- a/arch/ppc64/kernel/asm-offsets.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/kernel/asm-offsets.c	2004-06-23 19:04:27 -07:00
@@ -48,6 +48,8 @@
 	DEFINE(THREAD_SHIFT, THREAD_SHIFT);
 	DEFINE(THREAD_SIZE, THREAD_SIZE);
 	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+	DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror));
 
 	/* task_struct->thread */
 	DEFINE(THREAD, offsetof(struct task_struct, thread));
@@ -99,7 +101,10 @@
 	DEFINE(PACALPPACA, offsetof(struct paca_struct, xLpPaca));
         DEFINE(LPPACA, offsetof(struct paca_struct, xLpPaca));
         DEFINE(PACAREGSAV, offsetof(struct paca_struct, xRegSav));
-        DEFINE(PACAEXC, offsetof(struct paca_struct, exception_stack));
+        DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
+        DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
+        DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
+        DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi));
         DEFINE(PACAGUARD, offsetof(struct paca_struct, guard));
         DEFINE(LPPACASRR0, offsetof(struct ItLpPaca, xSavedSrr0));
         DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1));
@@ -136,6 +141,10 @@
 	DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
 	DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
 	DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
+	DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
+	DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
+	DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
+	DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
 	DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
 	DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
 	DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
@@ -154,7 +163,7 @@
 	DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
 	DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3));
 	DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
-	DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
+	DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
 	DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe));
 
 	/* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */
diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
--- a/arch/ppc64/kernel/entry.S	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc64/kernel/entry.S	2004-06-23 19:04:25 -07:00
@@ -35,15 +35,9 @@
 #define DO_SOFT_DISABLE
 #endif
 
-#undef SHOW_SYSCALLS
-#undef SHOW_SYSCALLS_TASK
-
-#ifdef SHOW_SYSCALLS_TASK
-	.data
-show_syscalls_task:
-	.long	-1
-#endif
-
+/*
+ * System calls.
+ */
 	.section	".toc","aw"
 .SYS_CALL_TABLE:
 	.tc .sys_call_table[TC],.sys_call_table
@@ -51,107 +45,175 @@
 .SYS_CALL_TABLE32:
 	.tc .sys_call_table32[TC],.sys_call_table32
 
+/* This value is used to mark exception frames on the stack. */
+exception_marker:
+	.tc	ID_72656773_68657265[TC],0x7265677368657265
+
 	.section	".text"
-	.align 3
+	.align 7
 
-/*
- * Handle a system call.
- */
-_GLOBAL(DoSyscall)
+#undef SHOW_SYSCALLS
+
+	.globl SystemCall_common
+SystemCall_common:
+	andi.	r10,r12,MSR_PR
+	mr	r10,r1
+	addi	r1,r1,-INT_FRAME_SIZE
+	beq-	1f
+	ld	r1,PACAKSAVE(r13)
+1:	std	r10,0(r1)
+	std	r11,_NIP(r1)
+	std	r12,_MSR(r1)
+	std	r0,GPR0(r1)
+	std	r10,GPR1(r1)
+	std	r2,GPR2(r1)
+	std	r3,GPR3(r1)
+	std	r4,GPR4(r1)
+	std	r5,GPR5(r1)
+	std	r6,GPR6(r1)
+	std	r7,GPR7(r1)
+	std	r8,GPR8(r1)
+	li	r11,0
+	std	r11,GPR9(r1)
+	std	r11,GPR10(r1)
+	std	r11,GPR11(r1)
+	std	r11,GPR12(r1)
+	std	r9,GPR13(r1)
+	crclr	so
+	mfcr	r9
+	mflr	r10
+	li	r11,0xc01
+	std	r9,_CCR(r1)
+	std	r10,_LINK(r1)
+	std	r11,_TRAP(r1)
+	mfxer	r9
+	mfctr	r10
+	std	r9,_XER(r1)
+	std	r10,_CTR(r1)
 	std	r3,ORIG_GPR3(r1)
-	ld	r11,_CCR(r1)	/* Clear SO bit in CR */
-	lis	r10,0x1000
-	andc	r11,r11,r10
-	std	r11,_CCR(r1)
+	ld	r2,PACATOC(r13)
+	addi	r9,r1,STACK_FRAME_OVERHEAD
+	ld	r11,exception_marker@toc(r2)
+	std	r11,-16(r9)		/* "regshere" marker */
+#ifdef CONFIG_PPC_ISERIES
+	/* Hack for handling interrupts when soft-enabling on iSeries */
+	cmpdi	cr1,r0,0x5555		/* syscall 0x5555 */
+	andi.	r10,r12,MSR_PR		/* from kernel */
+	crand	4*cr0+eq,4*cr1+eq,4*cr0+eq
+	beq	HardwareInterrupt_entry
+	lbz	r10,PACAPROCENABLED(r13)
+	std	r10,SOFTE(r1)
+#endif
+	mfmsr	r11
+	ori	r11,r11,MSR_EE
+	mtmsrd	r11,1
+
 #ifdef SHOW_SYSCALLS
-#ifdef SHOW_SYSCALLS_TASK
-	LOADBASE(r31,show_syscalls_task)
-	ld	r31,show_syscalls_task@l(r31)
-	ld	r10,PACACURRENT(r13)
-	cmp	0,r10,r31
-	bne	1f
+	bl	.do_show_syscall
+	REST_GPR(0,r1)
+	REST_4GPRS(3,r1)
+	REST_2GPRS(7,r1)
+	addi	r9,r1,STACK_FRAME_OVERHEAD
 #endif
-	LOADADDR(r3,7f)
-	ld	r4,GPR0(r1)
-	ld	r5,GPR3(r1)
-	ld	r6,GPR4(r1)
-	ld	r7,GPR5(r1)
-	ld	r8,GPR6(r1)
-	ld	r9,GPR7(r1)
-	bl	.printk
-	LOADADDR(r3,77f)
-	ld	r4,GPR8(r1)
-	ld	r5,GPR9(r1)
-	ld	r6, PACACURRENT(r13)
-	bl	.printk
-	ld	r0,GPR0(r1)
-	ld	r3,GPR3(r1)
-	ld	r4,GPR4(r1)
-	ld	r5,GPR5(r1)
-	ld	r6,GPR6(r1)
-	ld	r7,GPR7(r1)
-	ld	r8,GPR8(r1)
-1:
-#endif /* SHOW_SYSCALLS */
-	clrrdi	r10,r1,THREAD_SHIFT
-	ld	r10,TI_FLAGS(r10)
+	clrrdi	r11,r1,THREAD_SHIFT
+	li	r12,0
+	ld	r10,TI_FLAGS(r11)
+	stb	r12,TI_SC_NOERR(r11)
 	andi.	r11,r10,_TIF_SYSCALL_T_OR_A
-	bne-	50f
+	bne-	syscall_dotrace
+syscall_dotrace_cont:
 	cmpli	0,r0,NR_syscalls
-	bge-	66f
+	bge-	syscall_enosys
+
+system_call:			/* label this so stack traces look sane */
 /*
  * Need to vector to 32 Bit or default sys_call_table here,
  * based on caller's run-mode / personality.
  */
-	andi.	r11,r10,_TIF_32BIT
+	ld	r11,.SYS_CALL_TABLE@toc(2)
+	andi.	r10,r10,_TIF_32BIT
 	beq-	15f
-	ld	r10,.SYS_CALL_TABLE32@toc(2)
-/*
- * We now zero extend all six arguments (r3 - r8), the compatibility
- * layer assumes this.
- */
+	ld	r11,.SYS_CALL_TABLE32@toc(2)
 	clrldi	r3,r3,32
 	clrldi	r4,r4,32
 	clrldi	r5,r5,32
 	clrldi	r6,r6,32
 	clrldi	r7,r7,32
 	clrldi	r8,r8,32
-	b	17f
 15:
-	ld	r10,.SYS_CALL_TABLE@toc(2)
-17:	slwi	r0,r0,3
-	ldx	r10,r10,r0	/* Fetch system call handler [ptr] */
+	slwi	r0,r0,3
+	ldx	r10,r11,r0	/* Fetch system call handler [ptr] */
 	mtlr	r10
-	addi	r9,r1,STACK_FRAME_OVERHEAD
 	blrl			/* Call handler */
-_GLOBAL(ret_from_syscall_1)
-	std	r3,RESULT(r1)	/* Save result */
+
+syscall_exit:
 #ifdef SHOW_SYSCALLS
-#ifdef SHOW_SYSCALLS_TASK
-	ld	r10, PACACURRENT(13)
-	cmp	0,r10,r31
-	bne	91f
-#endif
-	mr	r4,r3
-	LOADADDR(r3,79f)
-	bl	.printk
-	ld	r3,RESULT(r1)
-91:
+	std	r3,GPR3(r1)
+	bl	.do_show_syscall_exit
+	ld	r3,GPR3(r1)
 #endif
+	std	r3,RESULT(r1)
+	ld	r5,_CCR(r1)
 	li	r10,-_LAST_ERRNO
-	cmpld	0,r3,r10
-	blt	30f
+	cmpld	r3,r10
+	clrrdi	r12,r1,THREAD_SHIFT
+	bge-	syscall_error
+syscall_error_cont:
+
+	/* check for syscall tracing or audit */
+	ld	r9,TI_FLAGS(r12)
+	andi.	r0,r9,_TIF_SYSCALL_T_OR_A
+	bne-	syscall_exit_trace
+syscall_exit_trace_cont:
+
+	/* disable interrupts so current_thread_info()->flags can't change,
+	   and so that we don't get interrupted after loading SRR0/1. */
+	ld	r8,_MSR(r1)
+	andi.	r10,r8,MSR_RI
+	beq-	unrecov_restore
+	mfmsr	r10
+	rldicl	r10,r10,48,1
+	rotldi	r10,r10,16
+	mtmsrd	r10,1
+	ld	r9,TI_FLAGS(r12)
+	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+	bne-	syscall_exit_work
+	ld	r7,_NIP(r1)
+	stdcx.	r0,0,r1			/* to clear the reservation */
+	andi.	r6,r8,MSR_PR
+	ld	r4,_LINK(r1)
+	beq	1f			/* only restore r13 if */
+	ld	r13,GPR13(r1)		/* returning to usermode */
+1:	ld	r2,GPR2(r1)
+	ld	r1,GPR1(r1)
+	li	r12,MSR_RI
+	andc	r10,r10,r12
+	mtmsrd	r10,1			/* clear MSR.RI */
+	mtlr	r4
+	mtcr	r5
+	mtspr	SRR0,r7
+	mtspr	SRR1,r8
+	rfid
+
+syscall_enosys:
+	li	r3,-ENOSYS
+	std	r3,RESULT(r1)
+	clrrdi	r12,r1,THREAD_SHIFT
+	ld	r5,_CCR(r1)
+
+syscall_error:
+	lbz	r11,TI_SC_NOERR(r12)
+	cmpi	0,r11,0
+	bne-	syscall_error_cont
 	neg	r3,r3
-22:	ld	r10,_CCR(r1)	/* Set SO bit in CR */
-	oris	r10,r10,0x1000
-	std	r10,_CCR(r1)
-30:	std	r3,GPR3(r1)	/* Update return value */
-	b	.ret_from_except
-66:	li	r3,ENOSYS
-	b	22b
+	oris	r5,r5,0x1000	/* Set SO bit in CR */
+	std	r5,_CCR(r1)
+	b	syscall_error_cont
         
 /* Traced system call support */
-50:	addi	r3,r1,STACK_FRAME_OVERHEAD
+syscall_dotrace:
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.do_syscall_trace_enter
 	ld	r0,GPR0(r1)	/* Restore original registers */
 	ld	r3,GPR3(r1)
@@ -160,65 +222,82 @@
 	ld	r6,GPR6(r1)
 	ld	r7,GPR7(r1)
 	ld	r8,GPR8(r1)
-	/* XXX check this - Anton */
-	ld	r9,GPR9(r1)
-	cmpli	0,r0,NR_syscalls
-	bge-	66f
-/*
- * Need to vector to 32 Bit or default sys_call_table here,
- * based on caller's run-mode / personality.
- */
+	addi	r9,r1,STACK_FRAME_OVERHEAD
 	clrrdi	r10,r1,THREAD_SHIFT
 	ld	r10,TI_FLAGS(r10)
-	andi.	r11,r10,_TIF_32BIT
-	beq-	55f
-	ld	r10,.SYS_CALL_TABLE32@toc(2)
+	b	syscall_dotrace_cont
+
+syscall_exit_trace:
+	std	r3,GPR3(r1)
+	bl	.save_nvgprs
+	bl	.do_syscall_trace_leave
+	REST_NVGPRS(r1)
+	ld	r3,GPR3(r1)
+	ld	r5,_CCR(r1)
+	clrrdi	r12,r1,THREAD_SHIFT
+	b	syscall_exit_trace_cont
+
+/* Stuff to do on exit from a system call. */
+syscall_exit_work:
+	std	r3,GPR3(r1)
+	std	r5,_CCR(r1)
+	b	.ret_from_except_lite
+
+/* Save non-volatile GPRs, if not already saved. */
+_GLOBAL(save_nvgprs)
+	ld	r11,_TRAP(r1)
+	andi.	r0,r11,1
+	beqlr-
+	SAVE_NVGPRS(r1)
+	clrrdi	r0,r11,1
+	std	r0,_TRAP(r1)
+	blr
+
 /*
- * We now zero extend all six arguments (r3 - r8), the compatibility
- * layer assumes this.
+ * The sigsuspend and rt_sigsuspend system calls can call do_signal
+ * and thus put the process into the stopped state where we might
+ * want to examine its user state with ptrace.  Therefore we need
+ * to save all the nonvolatile registers (r14 - r31) before calling
+ * the C code.  Similarly, fork, vfork and clone need the full
+ * register state on the stack so that it can be copied to the child.
  */
-	clrldi	r3,r3,32
-	clrldi	r4,r4,32
-	clrldi	r5,r5,32
-	clrldi	r6,r6,32
-	clrldi	r7,r7,32
-	clrldi	r8,r8,32
-	b	57f
-55:
-	ld	r10,.SYS_CALL_TABLE@toc(2)
-57:
-	slwi	r0,r0,3
-	ldx	r10,r10,r0	/* Fetch system call handler [ptr] */
-	mtlr	r10
-	addi	r9,r1,STACK_FRAME_OVERHEAD
-	blrl			/* Call handler */
-_GLOBAL(ret_from_syscall_2)
-	std	r3,RESULT(r1)	/* Save result */	
-	li	r10,-_LAST_ERRNO
-	cmpld	0,r3,r10
-	blt	60f
-	neg	r3,r3
-57:	ld	r10,_CCR(r1)	/* Set SO bit in CR */
-	oris	r10,r10,0x1000
-	std	r10,_CCR(r1)
-60:	std	r3,GPR3(r1)	/* Update return value */
-	bl	.do_syscall_trace_leave
-	b	.ret_from_except
-66:	li	r3,ENOSYS
-	b	57b
-#ifdef SHOW_SYSCALLS
-7:	.string	"syscall %d(%x, %x, %x, %x, %x, "
-77:	.string	"%x, %x), current=%p\n"
-79:	.string	" -> %x\n"
-	.align	2,0
-#endif
+_GLOBAL(ppc32_sigsuspend)
+	bl	.save_nvgprs
+	bl	.sys32_sigsuspend
+	b	syscall_exit
+
+_GLOBAL(ppc64_rt_sigsuspend)
+	bl	.save_nvgprs
+	bl	.sys_rt_sigsuspend
+	b	syscall_exit
+
+_GLOBAL(ppc32_rt_sigsuspend)
+	bl	.save_nvgprs
+	bl	.sys32_rt_sigsuspend
+	b	syscall_exit
+
+_GLOBAL(ppc_fork)
+	bl	.save_nvgprs
+	bl	.sys_fork
+	b	syscall_exit
+
+_GLOBAL(ppc_vfork)
+	bl	.save_nvgprs
+	bl	.sys_vfork
+	b	syscall_exit
+
+_GLOBAL(ppc_clone)
+	bl	.save_nvgprs
+	bl	.sys_clone
+	b	syscall_exit
 
-	
 _GLOBAL(ppc32_swapcontext)
+	bl	.save_nvgprs
 	bl	.sys32_swapcontext
 	b	80f
 	
 _GLOBAL(ppc64_swapcontext)
+	bl	.save_nvgprs
 	bl	.sys_swapcontext
 	b	80f
 
@@ -233,17 +312,20 @@
 _GLOBAL(ppc64_rt_sigreturn)
 	bl	.sys_rt_sigreturn
 
-80:	clrrdi	r4,r1,THREAD_SHIFT
+80:	cmpdi	0,r3,0
+	blt	syscall_exit
+	clrrdi	r4,r1,THREAD_SHIFT
 	ld	r4,TI_FLAGS(r4)
 	andi.	r4,r4,_TIF_SYSCALL_T_OR_A
-	bne-	81f
-	cmpi	0,r3,0
-	bge	.ret_from_except
-	b	.ret_from_syscall_1
-81:	cmpi	0,r3,0
-	blt	.ret_from_syscall_2
+	beq+	81f
 	bl	.do_syscall_trace_leave
-	b	.ret_from_except
+81:	b	.ret_from_except
+
+_GLOBAL(ret_from_fork)
+	bl	.schedule_tail
+	REST_NVGPRS(r1)
+	li	r3,0
+	b	syscall_exit
 
 /*
  * This routine switches between two different tasks.  The process
@@ -263,6 +345,7 @@
  * The code which creates the new task context is in 'copy_thread'
  * in arch/ppc64/kernel/process.c
  */
+	.align	7
 _GLOBAL(_switch)
 	mflr	r0
 	std	r0,16(r1)
@@ -315,7 +398,10 @@
 2:
 END_FTR_SECTION_IFSET(CPU_FTR_SLB)
 	clrrdi	r7,r8,THREAD_SHIFT	/* base of new stack */
-	addi	r7,r7,THREAD_SIZE-INT_FRAME_SIZE
+	/* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE
+	   because we don't need to leave the 288-byte ABI gap at the
+	   top of the kernel stack. */
+	addi	r7,r7,THREAD_SIZE-SWITCH_FRAME_SIZE
 
 	mr	r1,r8		/* start using new stack pointer */
 	std	r7,PACAKSAVE(r13)
@@ -350,60 +436,56 @@
 	addi	r1,r1,SWITCH_FRAME_SIZE
 	blr
 
-_GLOBAL(ret_from_fork)
-	bl	.schedule_tail
-	clrrdi	r4,r1,THREAD_SHIFT
-	ld	r4,TI_FLAGS(r4)
-	andi.	r4,r4,_TIF_SYSCALL_T_OR_A
-	beq+	.ret_from_except
-	bl	.do_syscall_trace_leave
-	b	.ret_from_except
-
+	.align	7
 _GLOBAL(ret_from_except)
+	ld	r11,_TRAP(r1)
+	andi.	r0,r11,1
+	bne	.ret_from_except_lite
+	REST_NVGPRS(r1)
+
+_GLOBAL(ret_from_except_lite)
 	/*
 	 * Disable interrupts so that current_thread_info()->flags
 	 * can't change between when we test it and when we return
 	 * from the interrupt.
 	 */
 	mfmsr	r10		/* Get current interrupt state */
-	li	r4,0
-	ori	r4,r4,MSR_EE
-	andc	r9,r10,r4	/* clear MSR_EE */
+	rldicl	r9,r10,48,1	/* clear MSR_EE */
+	rotldi	r9,r9,16
 	mtmsrd	r9,1		/* Update machine state */
 
+#ifdef CONFIG_PREEMPT
+	clrrdi	r9,r1,THREAD_SHIFT	/* current_thread_info() */
+	li	r0,_TIF_NEED_RESCHED	/* bits to check */
+	ld	r3,_MSR(r1)
+	ld	r4,TI_FLAGS(r9)
+	/* Move MSR_PR bit in r3 to _TIF_SIGPENDING position in r0 */
+	rlwimi	r0,r3,32+TIF_SIGPENDING-MSR_PR_LG,_TIF_SIGPENDING
+	and.	r0,r4,r0	/* check NEED_RESCHED and maybe SIGPENDING */
+	bne	do_work
+
+#else /* !CONFIG_PREEMPT */
 	ld	r3,_MSR(r1)	/* Returning to user mode? */
 	andi.	r3,r3,MSR_PR
 	beq	restore		/* if not, just restore regs and return */
 
 	/* Check current_thread_info()->flags */
-	clrrdi	r3,r1,THREAD_SHIFT
-	ld	r3,TI_FLAGS(r3)
-	andi.	r0,r3,_TIF_USER_WORK_MASK
+	clrrdi	r9,r1,THREAD_SHIFT
+	ld	r4,TI_FLAGS(r9)
+	andi.	r0,r4,_TIF_USER_WORK_MASK
 	bne	do_work
-
-	addi	r0,r1,INT_FRAME_SIZE	/* size of frame */
-	ld	r4,PACACURRENT(r13)
-	std	r0,THREAD+KSP(r4)	/* save kernel stack pointer */
-
-	/*
-	 * r13 is our per cpu area, only restore it if we are returning to
-	 * userspace
-	 */
-	REST_GPR(13,r1)
+#endif
 
 restore:
 #ifdef CONFIG_PPC_ISERIES
 	ld	r5,SOFTE(r1)
-	mfspr	r4,SPRG3		/* get paca address */
 	cmpdi	0,r5,0
 	beq	4f
 	/* Check for pending interrupts (iSeries) */
-	/* this is CHECKANYINT except that we already have the paca address */
-	ld	r3,PACALPPACA+LPPACAANYINT(r4)
+	ld	r3,PACALPPACA+LPPACAANYINT(r13)
 	cmpdi	r3,0
 	beq+	4f			/* skip do_IRQ if no interrupts */
 
-	mfspr	r13,SPRG3		/* get paca pointer back */
 	li	r3,0
 	stb	r3,PACAPROCENABLED(r13)	/* ensure we are soft-disabled */
 	mtmsrd	r10			/* hard-enable again */
@@ -411,13 +493,22 @@
 	bl	.do_IRQ
 	b	.ret_from_except		/* loop back and handle more */
 
-4:	stb	r5,PACAPROCENABLED(r4)
+4:	stb	r5,PACAPROCENABLED(r13)
 #endif
 
 	ld	r3,_MSR(r1)
-	andi.	r3,r3,MSR_RI
+	andi.	r0,r3,MSR_RI
 	beq-	unrecov_restore
 
+	andi.	r0,r3,MSR_PR
+
+	/*
+	 * r13 is our per cpu area, only restore it if we are returning to
+	 * userspace
+	 */
+	beq	1f
+	REST_GPR(13, r1)
+1:
 	ld	r3,_CTR(r1)
 	ld	r0,_LINK(r1)
 	mtctr	r3
@@ -426,8 +517,6 @@
 	mtspr	XER,r3
 
 	REST_8GPRS(5, r1)
-	REST_10GPRS(14, r1)
-	REST_8GPRS(24, r1)
 
 	stdcx.	r0,0,r1		/* to clear the reservation */
 
@@ -451,26 +540,62 @@
 	ld	r1,GPR1(r1)
 
 	rfid
+	b	.
 
-/* Note: this must change if we start using the  TIF_NOTIFY_RESUME bit */
+/* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */
 do_work:
+#ifdef CONFIG_PREEMPT
+	andi.	r0,r3,MSR_PR	/* Returning to user mode? */
+	bne	user_work
+	/* Check that preempt_count() == 0 and interrupts are enabled */
+	lwz	r8,TI_PREEMPT(r9)
+	cmpwi	cr1,r8,0
+#ifdef CONFIG_PPC_ISERIES
+	ld	r0,SOFTE(r1)
+	cmpdi	r0,0
+#else
+	andi.	r0,r3,MSR_EE
+#endif
+	crandc	eq,cr1*4+eq,eq
+	bne	restore
+	/* here we are preempting the current task */
+1:	lis	r0,PREEMPT_ACTIVE@h
+	stw	r0,TI_PREEMPT(r9)
+#ifdef CONFIG_PPC_ISERIES
+	li	r0,1
+	stb	r0,PACAPROCENABLED(r13)
+#endif
+	mtmsrd	r10,1		/* reenable interrupts */
+	bl	.schedule
+	mfmsr	r10
+	clrrdi	r9,r1,THREAD_SHIFT
+	rldicl	r10,r10,48,1	/* disable interrupts again */
+	li	r0,0
+	rotldi	r10,r10,16
+	mtmsrd	r10,1
+	ld	r4,TI_FLAGS(r9)
+	andi.	r0,r4,_TIF_NEED_RESCHED
+	bne	1b
+	stw	r0,TI_PREEMPT(r9)
+	b	restore
+
+user_work:
+#endif
 	/* Enable interrupts */
 	mtmsrd	r10,1
 
-	andi.	r0,r3,_TIF_NEED_RESCHED
+	andi.	r0,r4,_TIF_NEED_RESCHED
 	beq	1f
 	bl	.schedule
-	b	.ret_from_except
+	b	.ret_from_except_lite
 
-1:	andi.	r0,r3,_TIF_SIGPENDING
-	beq	.ret_from_except
+1:	bl	.save_nvgprs
 	li	r3,0
 	addi	r4,r1,STACK_FRAME_OVERHEAD
 	bl	.do_signal
 	b	.ret_from_except
 
 unrecov_restore:
-	mfspr   r13,SPRG3
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.unrecoverable_exception
 	b	unrecov_restore
@@ -488,7 +613,7 @@
 	mflr	r0
 	std	r0,16(r1)
         stdu	r1,-RTAS_FRAME_SIZE(r1)	/* Save SP and create stack space. */
-	
+
 	/* Because RTAS is running in 32b mode, it clobbers the high order half
 	 * of all registers that it saves.  We therefore save those registers
 	 * RTAS might touch to the stack.  (r0, r3-r13 are caller saved)
diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
--- a/arch/ppc64/kernel/head.S	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/kernel/head.S	2004-06-23 19:04:27 -07:00
@@ -40,15 +40,6 @@
 #define DO_SOFT_DISABLE
 #endif
 
-/* copy saved SOFTE bit or EE bit from saved MSR depending
- * if we are doing soft-disable or not
- */
-#ifdef DO_SOFT_DISABLE
-#define DO_COPY_EE()	ld	r20,SOFTE(r1)
-#else
-#define DO_COPY_EE()	rldicl	r20,r23,49,63
-#endif
-
 /*
  * hcall interface to pSeries LPAR
  */
@@ -177,11 +168,18 @@
 #endif
 #endif
 
+/* This value is used to mark exception frames on the stack. */
+	.section ".toc","aw"
+exception_marker:
+	.tc	ID_72656773_68657265[TC],0x7265677368657265
+	.text
+
 /*
  * The following macros define the code that appears as
  * the prologue to each of the exception handlers.  They
  * are split into two parts to allow a single kernel binary
- * to be used for pSeries, and iSeries.
+ * to be used for pSeries and iSeries.
+ * LOL.  One day... - paulus
  */
 
 /*
@@ -194,81 +192,55 @@
  * This is the start of the interrupt handlers for pSeries
  * This code runs with relocation off.
  */
-#define EX_SRR0		0
-#define EX_SRR1		8
-#define EX_R20		16
-#define EX_R21		24
-#define EX_R22		32
-#define EX_R23		40
+#define EX_R9		0
+#define EX_R10		8
+#define EX_R11		16
+#define EX_R12		24
+#define EX_R13		32
+#define EX_SRR0		40
 #define EX_DAR		48
 #define EX_DSISR	56
 #define EX_CCR   	60
-#define EX_TRAP   	60
 
-#define EXCEPTION_PROLOG_PSERIES(n,label)                                \
-	mtspr   SPRG2,r20;              /* use SPRG2 as scratch reg   */ \
-	mtspr   SPRG1,r21;              /* save r21                   */ \
-	mfspr   r20,SPRG3;              /* get paca virt addr         */ \
-	ld      r21,PACAEXCSP(r20);     /* get exception stack ptr    */ \
-	addi    r21,r21,EXC_FRAME_SIZE; /* make exception frame       */ \
-	std	r22,EX_R22(r21);	/* Save r22 in exc. frame     */ \
-	li	r22,n;                  /* Save the ex # in exc. frame*/ \
-	stw	r22,EX_TRAP(r21);	/*                            */ \
-	std	r23,EX_R23(r21);	/* Save r23 in exc. frame     */ \
-	mfspr   r22,SRR0;               /* EA of interrupted instr    */ \
-	std	r22,EX_SRR0(r21);	/* Save SRR0 in exc. frame    */ \
-	mfspr   r23,SRR1;               /* machine state at interrupt */ \
-	std	r23,EX_SRR1(r21);	/* Save SRR1 in exc. frame    */ \
-                                                                         \
-	mfspr   r23,DAR;                /* Save DAR in exc. frame      */ \
-	std	r23,EX_DAR(r21);	                                  \
-	mfspr	r23,DSISR;		/* Save DSISR in exc. frame    */ \
-	stw	r23,EX_DSISR(r21);	                                  \
-	mfspr	r23,SPRG2;		/* Save r20 in exc. frame      */ \
-	std	r23,EX_R20(r21);	                                  \
-                                                                         \
-	clrrdi  r22,r20,60;             /* Get 0xc part of the vaddr  */ \
-	ori	r22,r22,(label)@l;      /* add in the vaddr offset    */ \
-		                        /*   assumes *_common < 16b   */ \
-	mfmsr   r23;                                                     \
-	rotldi  r23,r23,4;                                               \
-	ori     r23,r23,0x32B;          /* Set IR, DR, RI, SF, ISF, HV*/ \
-	rotldi  r23,r23,60;             /* for generic handlers       */ \
-	mtspr   SRR0,r22;                                                \
-	mtspr   SRR1,r23;                                                \
-	mfcr    r23;                    /* save CR in r23             */ \
+#define EXCEPTION_PROLOG_PSERIES(area, label)				\
+	mfspr	r13,SPRG3;		/* get paca address into r13 */	\
+	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\
+	std	r10,area+EX_R10(r13);					\
+	std	r11,area+EX_R11(r13);					\
+	std	r12,area+EX_R12(r13);					\
+	mfspr	r9,SPRG1;						\
+	std	r9,area+EX_R13(r13);					\
+	mfcr	r9;							\
+	clrrdi	r12,r13,32;		/* get high part of &label */	\
+	mfmsr	r10;							\
+	mfspr	r11,SRR0;		/* save SRR0 */			\
+	ori	r12,r12,(label)@l;	/* virt addr of handler */	\
+	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI;				\
+	mtspr	SRR0,r12;						\
+	mfspr	r12,SRR1;		/* and SRR1 */			\
+	mtspr	SRR1,r10;						\
 	rfid
 
 /*
  * This is the start of the interrupt handlers for iSeries
  * This code runs with relocation on.
  */
-#define EXCEPTION_PROLOG_ISERIES(n)	                                      \
-	mtspr	SPRG2,r20;		    /* use SPRG2 as scratch reg    */ \
-	mtspr   SPRG1,r21;                  /* save r21                    */ \
-	mfspr	r20,SPRG3;		    /* get paca                    */ \
-	ld      r21,PACAEXCSP(r20);         /* get exception stack ptr     */ \
-	addi    r21,r21,EXC_FRAME_SIZE;     /* make exception frame        */ \
-	std	r22,EX_R22(r21);	    /* save r22 on exception frame */ \
-	li	r22,n;                      /* Save the ex # in exc. frame */ \
-	stw	r22,EX_TRAP(r21);	    /*                             */ \
-	std	r23,EX_R23(r21);	    /* Save r23 in exc. frame      */ \
-	ld      r22,LPPACA+LPPACASRR0(r20); /* Get SRR0 from ItLpPaca      */ \
-	std	r22,EX_SRR0(r21);	    /* save SRR0 in exc. frame     */ \
-	ld      r23,LPPACA+LPPACASRR1(r20); /* Get SRR1 from ItLpPaca      */ \
-	std	r23,EX_SRR1(r21);	    /* save SRR1 in exc. frame     */ \
-                                                                         \
-	mfspr   r23,DAR;                /* Save DAR in exc. frame      */ \
-	std	r23,EX_DAR(r21);	                                  \
-	mfspr	r23,DSISR;		/* Save DSISR in exc. frame    */ \
-	stw	r23,EX_DSISR(r21);	                                  \
-	mfspr	r23,SPRG2;		/* Save r20 in exc. frame      */ \
-	std	r23,EX_R20(r21);	                                  \
-                                                                         \
-	mfmsr	r22;			    /* set MSR.RI		   */ \
-	ori	r22,r22,MSR_RI;						      \
-	mtmsrd	r22,1;							      \
-	mfcr    r23;                        /* save CR in r23              */
+#define EXCEPTION_PROLOG_ISERIES_1(area)				\
+	mfspr	r13,SPRG3;		/* get paca address into r13 */	\
+	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\
+	std	r10,area+EX_R10(r13);					\
+	std	r11,area+EX_R11(r13);					\
+	std	r12,area+EX_R12(r13);					\
+	mfspr	r9,SPRG1;						\
+	std	r9,area+EX_R13(r13);					\
+	mfcr	r9
+
+#define EXCEPTION_PROLOG_ISERIES_2					\
+	mfmsr	r10;							\
+	ld	r11,LPPACA+LPPACASRR0(r13);				\
+	ld	r12,LPPACA+LPPACASRR1(r13);				\
+	ori	r10,r10,MSR_RI;						\
+	mtmsrd	r10,1
 
 /*
  * The common exception prolog is used for all except a few exceptions
@@ -276,107 +248,154 @@
  * to take another exception from the point where we first touch the
  * kernel stack onwards.
  *
- * On entry r20 points to the paca and r21 points to the exception
- * frame on entry, r23 contains the saved CR, and relocation is on.
- */
-#define EXCEPTION_PROLOG_COMMON                                           \
-	mfspr	r22,SPRG1;		/* Save r21 in exc. frame      */ \
-	std	r22,EX_R21(r21);	                                  \
-	std     r21,PACAEXCSP(r20);     /* update exception stack ptr  */ \
-	ld	r22,EX_SRR1(r21);	/* Get SRR1 from exc. frame    */ \
-	andi.   r22,r22,MSR_PR;         /* Set CR for later branch     */ \
-	mr      r22,r1;                 /* Save r1                     */ \
-	subi    r1,r1,INT_FRAME_SIZE;   /* alloc frame on kernel stack */ \
-	beq-    1f;                                                       \
-	ld      r1,PACAKSAVE(r20);      /* kernel stack to use         */ \
-1:      cmpdi	cr1,r1,0;		/* check if r1 is in userspace */ \
-	bge	cr1,bad_stack;		/* abort if it is	       */ \
-	std     r22,GPR1(r1);           /* save r1 in stackframe       */ \
-	std     r22,0(r1);              /* make stack chain pointer    */ \
-	std     r23,_CCR(r1);           /* save CR in stackframe       */ \
-	ld	r22,EX_R20(r21);	/* move r20 to stackframe      */ \
-	std	r22,GPR20(r1);		                                  \
-	ld	r23,EX_R21(r21);	/* move r21 to stackframe      */ \
-	std	r23,GPR21(r1);		                                  \
-	ld	r22,EX_R22(r21);	/* move r22 to stackframe      */ \
-	std	r22,GPR22(r1);		                                  \
-	ld	r23,EX_R23(r21);	/* move r23 to stackframe      */ \
-	std	r23,GPR23(r1);		                                  \
-	mflr    r22;                    /* save LR in stackframe       */ \
-	std     r22,_LINK(r1);                                            \
-	mfctr   r23;                    /* save CTR in stackframe      */ \
-	std     r23,_CTR(r1);                                             \
-	mfspr   r22,XER;                /* save XER in stackframe      */ \
-	std     r22,_XER(r1);                                             \
-	ld	r23,EX_DAR(r21);	/* move DAR to stackframe      */ \
-	std	r23,_DAR(r1);		                                  \
-	lwz     r22,EX_DSISR(r21);	/* move DSISR to stackframe    */ \
-	std	r22,_DSISR(r1);		                                  \
-	lbz	r22,PACAPROCENABLED(r20);                                 \
-	std	r22,SOFTE(r1);		                                  \
-	ld	r22,EX_SRR0(r21);	/* get SRR0 from exc. frame    */ \
-	ld	r23,EX_SRR1(r21);	/* get SRR1 from exc. frame    */ \
-	addi    r21,r21,-EXC_FRAME_SIZE;/* pop off exception frame     */ \
-	std     r21,PACAEXCSP(r20);                                       \
-	SAVE_GPR(0, r1);                /* save r0 in stackframe       */ \
-	SAVE_8GPRS(2, r1);              /* save r2 - r13 in stackframe */ \
-	SAVE_4GPRS(10, r1);                                               \
-	ld      r2,PACATOC(r20);	                                  \
-	mr	r13,r20
-
-/*
- * Note: code which follows this uses cr0.eq (set if from kernel),
- * r1, r22 (SRR0), and r23 (SRR1).
- */
+ * On entry r13 points to the paca, r9-r13 are saved in the paca,
+ * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and
+ * SRR1, and relocation is on.
+ */
+#define EXCEPTION_PROLOG_COMMON(n, area)				   \
+	andi.	r10,r12,MSR_PR;		/* See if coming from user	*/ \
+	mr	r10,r1;			/* Save r1			*/ \
+	subi    r1,r1,INT_FRAME_SIZE;   /* alloc frame on kernel stack  */ \
+	beq-    1f;                                                        \
+	ld	r1,PACAKSAVE(r13);	/* kernel stack to use		*/ \
+1:      cmpdi	cr1,r1,0;		/* check if r1 is in userspace  */ \
+	bge-	cr1,bad_stack;		/* abort if it is		*/ \
+	std	r9,_CCR(r1);		/* save CR in stackframe	*/ \
+	std	r11,_NIP(r1);		/* save SRR0 in stackframe	*/ \
+	std	r12,_MSR(r1);		/* save SRR1 in stackframe	*/ \
+	std	r10,0(r1);		/* make stack chain pointer	*/ \
+	std	r0,GPR0(r1);		/* save r0 in stackframe	*/ \
+	std	r10,GPR1(r1);		/* save r1 in stackframe	*/ \
+	std	r2,GPR2(r1);		/* save r2 in stackframe	*/ \
+	SAVE_4GPRS(3, r1);		/* save r3 - r6 in stackframe	*/ \
+	SAVE_2GPRS(7, r1);		/* save r7, r8 in stackframe	*/ \
+	ld	r9,area+EX_R9(r13);	/* move r9, r10 to stackframe	*/ \
+	ld	r10,area+EX_R10(r13);					   \
+	std	r9,GPR9(r1);						   \
+	std	r10,GPR10(r1);						   \
+	ld	r9,area+EX_R11(r13);	/* move r11 - r13 to stackframe	*/ \
+	ld	r10,area+EX_R12(r13);					   \
+	ld	r11,area+EX_R13(r13);					   \
+	std	r9,GPR11(r1);						   \
+	std	r10,GPR12(r1);						   \
+	std	r11,GPR13(r1);						   \
+	ld	r2,PACATOC(r13);	/* get kernel TOC into r2	*/ \
+	mflr	r9;			/* save LR in stackframe	*/ \
+	std	r9,_LINK(r1);						   \
+	mfctr	r10;			/* save CTR in stackframe	*/ \
+	std	r10,_CTR(r1);						   \
+	mfspr	r11,XER;		/* save XER in stackframe	*/ \
+	std	r11,_XER(r1);						   \
+	li	r9,(n)+1;						   \
+	std	r9,_TRAP(r1);		/* set trap number		*/ \
+	li	r10,0;							   \
+	ld	r11,exception_marker@toc(r2);				   \
+	std	r10,RESULT(r1);		/* clear regs->result		*/ \
+	std	r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame	*/
 
 /*
  * Exception vectors.
  */
-#define STD_EXCEPTION_PSERIES(n, label )	\
-	. = n;					\
-	.globl label##_Pseries;			\
-label##_Pseries:				\
-	EXCEPTION_PROLOG_PSERIES( n, label##_common )
-
-#define STD_EXCEPTION_ISERIES( n, label )	\
-	.globl label##_Iseries;			\
-label##_Iseries:				\
-	EXCEPTION_PROLOG_ISERIES( n );          \
+#define STD_EXCEPTION_PSERIES(n, label )		\
+	. = n;						\
+	.globl label##_Pseries;				\
+label##_Pseries:					\
+	mtspr	SPRG1,r13;		/* save r13 */	\
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
+
+#define STD_EXCEPTION_ISERIES(n, label, area)		\
+	.globl label##_Iseries;				\
+label##_Iseries:					\
+	mtspr	SPRG1,r13;		/* save r13 */	\
+	EXCEPTION_PROLOG_ISERIES_1(area);		\
+	EXCEPTION_PROLOG_ISERIES_2;			\
 	b	label##_common
 
-#define MASKABLE_EXCEPTION_ISERIES( n, label )	\
-	.globl label##_Iseries;			\
-label##_Iseries:				\
-	EXCEPTION_PROLOG_ISERIES( n );		\
-	lbz	r22,PACAPROFENABLED(r20);	\
-	cmpi	0,r22,0;			\
-	bne-	label##_Iseries_profile;	\
-label##_Iseries_prof_ret:			\
-	lbz	r22,PACAPROCENABLED(r20);	\
-	cmpi	0,r22,0;			\
-	beq-	label##_Iseries_masked;		\
-	b	label##_common;			\
-label##_Iseries_profile:			\
-	std	r24,48(r21);			\
-	std	r25,56(r21);			\
-	mflr	r24;				\
-	bl	do_profile;			\
-	mtlr	r24;				\
-	ld	r24,48(r21);			\
-	ld	r25,56(r21);			\
+#define MASKABLE_EXCEPTION_ISERIES( n, label )				\
+	.globl label##_Iseries;						\
+label##_Iseries:							\
+	mtspr	SPRG1,r13;		/* save r13 */			\
+	EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN);				\
+	lbz	r10,PACAPROFENABLED(r13);				\
+	cmpwi	r10,0;							\
+	bne-	label##_Iseries_profile;				\
+label##_Iseries_prof_ret:						\
+	lbz	r10,PACAPROCENABLED(r13);				\
+	cmpwi	0,r10,0;						\
+	beq-	label##_Iseries_masked;					\
+	EXCEPTION_PROLOG_ISERIES_2;					\
+	b	label##_common;						\
+label##_Iseries_profile:						\
+	ld	r12,LPPACA+LPPACASRR1(r13);				\
+	andi.	r12,r12,MSR_PR;		/* Test if in kernel */		\
+	bne	label##_Iseries_prof_ret;				\
+	ld	r11,LPPACA+LPPACASRR0(r13);				\
+	ld	r12,PACAPROFSTEXT(r13);	/* _stext */			\
+	subf	r11,r12,r11;		/* offset into kernel */	\
+	lwz	r12,PACAPROFSHIFT(r13);					\
+	srd	r11,r11,r12;						\
+	lwz	r12,PACAPROFLEN(r13);	/* profile table length - 1 */	\
+	cmpd	r11,r12;		/* off end? */			\
+	ble	1f;							\
+	mr	r11,r12;		/* force into last entry */	\
+1:	sldi	r11,r11,2;		/* convert to offset */		\
+	ld	r12,PACAPROFBUFFER(r13);/* profile buffer */		\
+	add	r12,r12,r11;						\
+2:	lwarx	r11,0,r12;		/* atomically increment */	\
+	addi	r11,r11,1;						\
+	stwcx.	r11,0,r12;						\
+	bne-	2b;							\
 	b	label##_Iseries_prof_ret
 
+#ifdef DO_SOFT_DISABLE
+#define DISABLE_INTS				\
+	lbz	r10,PACAPROCENABLED(r13);	\
+	li	r11,0;				\
+	std	r10,SOFTE(r1);			\
+	mfmsr	r10;				\
+	stb	r11,PACAPROCENABLED(r13);	\
+	ori	r10,r10,MSR_EE;			\
+	mtmsrd	r10,1
+
+#define ENABLE_INTS				\
+	lbz	r10,PACAPROCENABLED(r13);	\
+	mfmsr	r11;				\
+	std	r10,SOFTE(r1);			\
+	ori	r11,r11,MSR_EE;			\
+	mtmsrd	r11,1
+
+#else	/* hard enable/disable interrupts */
+#define DISABLE_INTS
+
+#define ENABLE_INTS				\
+	ld	r12,_MSR(r1);			\
+	mfmsr	r11;				\
+	rlwimi	r11,r12,0,MSR_EE;		\
+	mtmsrd	r11,1
+
+#endif
+
 #define STD_EXCEPTION_COMMON( trap, label, hdlr )	\
-	.globl label##_common;			\
-label##_common:					\
-	EXCEPTION_PROLOG_COMMON;		\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;	\
-	li	r20,0;				\
-	li	r6,trap;			\
-	bl      .save_remaining_regs;           \
-	bl      hdlr;                           \
+	.align	7;					\
+	.globl label##_common;				\
+label##_common:						\
+	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);	\
+	DISABLE_INTS;					\
+	bl	.save_nvgprs;				\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;		\
+	bl      hdlr;					\
 	b       .ret_from_except
 
+#define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr)	\
+	.align	7;					\
+	.globl label##_common;				\
+label##_common:						\
+	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);	\
+	DISABLE_INTS;					\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;		\
+	bl	hdlr;					\
+	b	.ret_from_except_lite
+
 /*
  * Start of pSeries system interrupt routines
  */
@@ -385,9 +404,45 @@
 __start_interrupts:
 
 	STD_EXCEPTION_PSERIES( 0x100, SystemReset )
-	STD_EXCEPTION_PSERIES( 0x200, MachineCheck )
-	STD_EXCEPTION_PSERIES( 0x300, DataAccess )
-	STD_EXCEPTION_PSERIES( 0x380, DataAccessSLB )
+
+	. = 0x200
+	.globl MachineCheck_Pseries
+_MachineCheckPseries:
+	mtspr	SPRG1,r13		/* save r13 */
+	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common)
+
+	. = 0x300
+	.globl DataAccess_Pseries
+DataAccess_Pseries:
+	mtspr	SPRG1,r13
+BEGIN_FTR_SECTION
+	mtspr	SPRG2,r12
+	mfspr	r13,DAR
+	mfspr	r12,DSISR
+	srdi	r13,r13,60
+	rlwimi	r13,r12,16,0x20
+	mfcr	r12
+	cmpwi	r13,0x2c
+	beq	.do_stab_bolted_Pseries
+	mtcrf	0x80,r12
+	mfspr	r12,SPRG2
+END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, DataAccess_common)
+
+	. = 0x380
+	.globl DataAccessSLB_Pseries
+DataAccessSLB_Pseries:
+	mtspr	SPRG1,r13
+	mtspr	SPRG2,r12
+	mfspr	r13,DAR
+	mfcr	r12
+	srdi	r13,r13,60
+	cmpdi	r13,0xc
+	beq	.do_slb_bolted_Pseries
+	mtcrf	0x80,r12
+	mfspr	r12,SPRG2
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, DataAccessSLB_common)
+
 	STD_EXCEPTION_PSERIES( 0x400, InstructionAccess )
 	STD_EXCEPTION_PSERIES( 0x480, InstructionAccessSLB )
 	STD_EXCEPTION_PSERIES( 0x500, HardwareInterrupt )
@@ -397,7 +452,23 @@
 	STD_EXCEPTION_PSERIES( 0x900, Decrementer )
 	STD_EXCEPTION_PSERIES( 0xa00, Trap_0a )
 	STD_EXCEPTION_PSERIES( 0xb00, Trap_0b )
-	STD_EXCEPTION_PSERIES( 0xc00, SystemCall )
+
+	. = 0xc00
+	.globl	SystemCall_Pseries
+SystemCall_Pseries:
+	mr	r9,r13
+	mfmsr	r10
+	mfspr	r13,SPRG3
+	mfspr	r11,SRR0
+	clrrdi	r12,r13,32
+	oris	r12,r12,SystemCall_common@h
+	ori	r12,r12,SystemCall_common@l
+	mtspr	SRR0,r12
+	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI
+	mfspr	r12,SRR1
+	mtspr	SRR1,r10
+	rfid
+
 	STD_EXCEPTION_PSERIES( 0xd00, SingleStep )
 	STD_EXCEPTION_PSERIES( 0xe00, Trap_0e )
 
@@ -407,25 +478,26 @@
 	 * trickery is thus necessary
 	 */
 	. = 0xf00
-	b	.PerformanceMonitor_Pseries
-	. = 0xf20
-	b	.AltivecUnavailable_Pseries
+	b	PerformanceMonitor_Pseries
+
+	STD_EXCEPTION_PSERIES(0xf20, AltivecUnavailable)
 
 	STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint )
 	STD_EXCEPTION_PSERIES( 0x1700, AltivecAssist )
 
-	/* Here are the "moved" performance monitor and
-	 * altivec unavailable exceptions
-	 */
-	. = 0x3000
-	.globl PerformanceMonitor_Pseries;
-.PerformanceMonitor_Pseries:
-	EXCEPTION_PROLOG_PSERIES(0xf00, PerformanceMonitor_common)
+	/* moved from 0xf00 */
+	STD_EXCEPTION_PSERIES(0x3000, PerformanceMonitor)
 	
 	. = 0x3100
-	.globl AltivecUnavailable_Pseries;
-.AltivecUnavailable_Pseries:
-	EXCEPTION_PROLOG_PSERIES(0xf20, AltivecUnavailable_common)
+_GLOBAL(do_stab_bolted_Pseries)
+	mtcrf	0x80,r12
+	mfspr	r12,SPRG2
+	EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
+
+_GLOBAL(do_slb_bolted_Pseries)
+	mtcrf	0x80,r12
+	mfspr	r12,SPRG2
+	EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_slb_bolted)
 	
 		
 	/* Space for the naca.  Architected to be located at real address
@@ -484,31 +556,82 @@
 
 /***  ISeries-LPAR interrupt handlers ***/
 
-	STD_EXCEPTION_ISERIES( 0x200, MachineCheck )
-	STD_EXCEPTION_ISERIES( 0x300, DataAccess )
-	STD_EXCEPTION_ISERIES( 0x380, DataAccessSLB )
-	STD_EXCEPTION_ISERIES( 0x400, InstructionAccess )
-	STD_EXCEPTION_ISERIES( 0x480, InstructionAccessSLB )
-	MASKABLE_EXCEPTION_ISERIES( 0x500, HardwareInterrupt )
-	STD_EXCEPTION_ISERIES( 0x600, Alignment )
-	STD_EXCEPTION_ISERIES( 0x700, ProgramCheck )
-	STD_EXCEPTION_ISERIES( 0x800, FPUnavailable )
-	MASKABLE_EXCEPTION_ISERIES( 0x900, Decrementer )
-	STD_EXCEPTION_ISERIES( 0xa00, Trap_0a )
-	STD_EXCEPTION_ISERIES( 0xb00, Trap_0b )
-	STD_EXCEPTION_ISERIES( 0xc00, SystemCall )
-	STD_EXCEPTION_ISERIES( 0xd00, SingleStep )
-	STD_EXCEPTION_ISERIES( 0xe00, Trap_0e )
-	STD_EXCEPTION_ISERIES( 0xf00, PerformanceMonitor )
+	STD_EXCEPTION_ISERIES(0x200, MachineCheck, PACA_EXMC)
+
+	.globl DataAccess_Iseries
+DataAccess_Iseries:
+	mtspr	SPRG1,r13
+BEGIN_FTR_SECTION
+	mtspr	SPRG2,r12
+	mfspr	r13,DAR
+	mfspr	r12,DSISR
+	srdi	r13,r13,60
+	rlwimi	r13,r12,16,0x20
+	mfcr	r12
+	cmpwi	r13,0x2c
+	beq	.do_stab_bolted_Iseries
+	mtcrf	0x80,r12
+	mfspr	r12,SPRG2
+END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+	EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN)
+	EXCEPTION_PROLOG_ISERIES_2
+	b	DataAccess_common
+
+.do_stab_bolted_Iseries:
+	mtcrf	0x80,r12
+	mfspr	r12,SPRG2
+	EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
+	EXCEPTION_PROLOG_ISERIES_2
+	b	.do_stab_bolted
+
+	.globl	DataAccessSLB_Iseries
+DataAccessSLB_Iseries:
+	mtspr	SPRG1,r13		/* save r13 */
+	mtspr	SPRG2,r12
+	mfspr	r13,DAR
+	mfcr	r12
+	srdi	r13,r13,60
+	cmpdi	r13,0xc
+	beq	.do_slb_bolted_Iseries
+	mtcrf	0x80,r12
+	mfspr	r12,SPRG2
+	EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN)
+	EXCEPTION_PROLOG_ISERIES_2
+	b	DataAccessSLB_common
+
+.do_slb_bolted_Iseries:
+	mtcrf	0x80,r12
+	mfspr	r12,SPRG2
+	EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
+	EXCEPTION_PROLOG_ISERIES_2
+	b	.do_slb_bolted
+
+	STD_EXCEPTION_ISERIES(0x400, InstructionAccess, PACA_EXGEN)
+	STD_EXCEPTION_ISERIES(0x480, InstructionAccessSLB, PACA_EXGEN)
+	MASKABLE_EXCEPTION_ISERIES(0x500, HardwareInterrupt)
+	STD_EXCEPTION_ISERIES(0x600, Alignment, PACA_EXGEN)
+	STD_EXCEPTION_ISERIES(0x700, ProgramCheck, PACA_EXGEN)
+	STD_EXCEPTION_ISERIES(0x800, FPUnavailable, PACA_EXGEN)
+	MASKABLE_EXCEPTION_ISERIES(0x900, Decrementer)
+	STD_EXCEPTION_ISERIES(0xa00, Trap_0a, PACA_EXGEN)
+	STD_EXCEPTION_ISERIES(0xb00, Trap_0b, PACA_EXGEN)
+
+	.globl	SystemCall_Iseries
+SystemCall_Iseries:
+	mr	r9,r13
+	mfspr	r13,SPRG3
+	EXCEPTION_PROLOG_ISERIES_2
+	b	SystemCall_common
+
+	STD_EXCEPTION_ISERIES( 0xd00, SingleStep, PACA_EXGEN)
+	STD_EXCEPTION_ISERIES( 0xe00, Trap_0e, PACA_EXGEN)
+	STD_EXCEPTION_ISERIES( 0xf00, PerformanceMonitor, PACA_EXGEN)
 
 	.globl SystemReset_Iseries
 SystemReset_Iseries:
 	mfspr	r13,SPRG3		/* Get paca address */
-	mfmsr	r24
-	ori	r24,r24,MSR_RI
-	mtmsrd	r24			/* RI on */
 	lhz	r24,PACAPACAINDEX(r13)	/* Get processor # */
-	cmpi	0,r24,0			/* Are we processor 0? */
+	cmpwi	0,r24,0			/* Are we processor 0? */
 	beq	.__start_initialization_iSeries	/* Start up the first processor */
 	mfspr	r4,CTRLF
 	li	r5,RUNLATCH		/* Turn off the run light */
@@ -527,7 +650,7 @@
 	addi	r1,r3,THREAD_SIZE
 	subi	r1,r1,STACK_FRAME_OVERHEAD
 
-	cmpi	0,r23,0
+	cmpwi	0,r23,0
 	beq	iseries_secondary_smp_loop	/* Loop until told to go */
 #ifdef SECONDARY_PROCESSORS
 	bne	.__secondary_start		/* Loop until told to go */
@@ -552,28 +675,29 @@
 	b	1b			/* If SMP not configured, secondaries
 					 * loop forever */
 
-	.globl HardwareInterrupt_Iseries_masked
-HardwareInterrupt_Iseries_masked:
-	b	maskable_exception_exit
-
 	.globl Decrementer_Iseries_masked
 Decrementer_Iseries_masked:
-	li	r22,1
-	stb	r22,PACALPPACA+LPPACADECRINT(r20)
-	lwz	r22,PACADEFAULTDECR(r20)
-	mtspr	DEC,r22
-maskable_exception_exit:
-	mtcrf	0xff,r23		/* Restore regs and free exception frame */
-	ld	r22,EX_SRR0(r21)
-	ld	r23,EX_SRR1(r21)
-	mtspr	SRR0,r22
-	mtspr	SRR1,r23
-	ld	r22,EX_R22(r21)
-	ld	r23,EX_R23(r21)
-	mfspr	r21,SPRG1
-	mfspr	r20,SPRG2
+	li	r11,1
+	stb	r11,PACALPPACA+LPPACADECRINT(r13)
+	lwz	r12,PACADEFAULTDECR(r13)
+	mtspr	DEC,r12
+	/* fall through */
+
+	.globl HardwareInterrupt_Iseries_masked
+HardwareInterrupt_Iseries_masked:
+	mtcrf	0x80,r9		/* Restore regs */
+	ld	r11,LPPACA+LPPACASRR0(r13)
+	ld	r12,LPPACA+LPPACASRR1(r13)
+	mtspr	SRR0,r11
+	mtspr	SRR1,r12
+	ld	r9,PACA_EXGEN+EX_R9(r13)
+	ld	r10,PACA_EXGEN+EX_R10(r13)
+	ld	r11,PACA_EXGEN+EX_R11(r13)
+	ld	r12,PACA_EXGEN+EX_R12(r13)
+	ld	r13,PACA_EXGEN+EX_R13(r13)
 	rfid
 #endif
+
 /*
  * Data area reserved for FWNMI option.
  */
@@ -587,10 +711,12 @@
 	. = 0x8000
 	.globl SystemReset_FWNMI
 SystemReset_FWNMI:
-	EXCEPTION_PROLOG_PSERIES(0x100, SystemReset_common)
+	mtspr	SPRG1,r13		/* save r13 */
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, SystemReset_common)
 	.globl MachineCheck_FWNMI
 MachineCheck_FWNMI:
-	EXCEPTION_PROLOG_PSERIES(0x200, MachineCheck_common)
+	mtspr	SPRG1,r13		/* save r13 */
+	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common)
 
 	/*
 	 * Space for the initial segment table
@@ -609,8 +735,22 @@
 /*** Common interrupt handlers ***/
 
 	STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException )
-	STD_EXCEPTION_COMMON( 0x200, MachineCheck, .MachineCheckException )
-	STD_EXCEPTION_COMMON( 0x900, Decrementer, .timer_interrupt )
+
+	/*
+	 * Machine check is different because we use a different
+	 * save area: PACA_EXMC instead of PACA_EXGEN.
+	 */
+	.align	7
+	.globl MachineCheck_common
+MachineCheck_common:
+	EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
+	DISABLE_INTS
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.MachineCheckException
+	b	.ret_from_except
+
+	STD_EXCEPTION_COMMON_LITE(0x900, Decrementer, .timer_interrupt)
 	STD_EXCEPTION_COMMON( 0xa00, Trap_0a, .UnknownException )
 	STD_EXCEPTION_COMMON( 0xb00, Trap_0b, .UnknownException )
 	STD_EXCEPTION_COMMON( 0xd00, SingleStep, .SingleStepException )
@@ -624,65 +764,56 @@
 #endif
 
 /*
- * Here the exception frame is filled out and we have detected that
- * the kernel stack pointer is bad.  R23 contains the saved CR, r20
- * points to the paca, r21 points to the exception frame, and r22
- * contains the (bad) kernel stack pointer.
+ * Here we have detected that the kernel stack pointer is bad.
+ * R9 contains the saved CR, r13 points to the paca,
+ * r10 contains the (bad) kernel stack pointer,
+ * r11 and r12 contain the saved SRR0 and SRR1.
  * We switch to using the paca guard page as an emergency stack,
- * save the registers on there, and call kernel_bad_stack(),
- * which panics.
+ * save the registers there, and call kernel_bad_stack(), which panics.
  */
 bad_stack:
-	addi	r1,r20,8192-64-INT_FRAME_SIZE
-	std	r22,GPR1(r1)
-	std	r23,_CCR(r1)
-	ld	r22,EX_R20(r21)
-	std	r22,GPR20(r1)
-	ld	r23,EX_R21(r21)
-	std	r23,GPR21(r1)
-	ld	r22,EX_R22(r21)
-	std	r22,GPR22(r1)
-	ld	r23,EX_R23(r21)
-	std	r23,GPR23(r1)
-	ld	r23,EX_DAR(r21)
-	std	r23,_DAR(r1)
-	lwz     r22,EX_DSISR(r21)
-	std	r22,_DSISR(r1)
-	lwz	r23,EX_TRAP(r21)
-	std	r23,TRAP(r1)
-	ld	r22,EX_SRR0(r21)
-	ld	r23,EX_SRR1(r21)
-	std	r22,_NIP(r1)
-	std	r23,_MSR(r1)
-	addi	r21,r21,-EXC_FRAME_SIZE
-	std	r21,PACAEXCSP(r20)
-	mflr	r22
-	std	r22,_LINK(r1)
-	mfctr	r23
-	std	r23,_CTR(r1)
-	mfspr	r22,XER
-	std	r22,_XER(r1)
+	addi	r1,r13,8192-64-INT_FRAME_SIZE
+	std	r9,_CCR(r1)
+	std	r10,GPR1(r1)
+	std	r11,_NIP(r1)
+	std	r12,_MSR(r1)
+	mfspr	r11,DAR
+	mfspr	r12,DSISR
+	std	r11,_DAR(r1)
+	std	r12,_DSISR(r1)
+	mflr	r10
+	mfctr	r11
+	mfxer	r12
+	std	r10,_LINK(r1)
+	std	r11,_CTR(r1)
+	std	r12,_XER(r1)
 	SAVE_GPR(0, r1)
-	SAVE_10GPRS(2, r1)
-	SAVE_8GPRS(12, r1)
-	SAVE_8GPRS(24, r1)
-	addi	r21,r1,INT_FRAME_SIZE
-	std	r21,0(r1)
-	li	r22,0
-	std	r22,0(r21)
-	ld	r2,PACATOC(r20)
-	mr	r13,r20
+	SAVE_GPR(2,r1)
+	SAVE_4GPRS(3,r1)
+	SAVE_2GPRS(7,r1)
+	SAVE_10GPRS(12,r1)
+	SAVE_10GPRS(22,r1)
+	addi	r11,r1,INT_FRAME_SIZE
+	std	r11,0(r1)
+	li	r12,0
+	std	r12,0(r11)
+	ld	r2,PACATOC(r13)
 1:	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.kernel_bad_stack
 	b	1b
 
 /*
- * Return from an exception which is handled without calling
- * save_remaining_regs.  The caller is assumed to have done
- * EXCEPTION_PROLOG_COMMON.
+ * Return from an exception with minimal checks.
+ * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
+ * If interrupts have been enabled, or anything has been
+ * done that might have changed the scheduling status of
+ * any task or sent any task a signal, you should use
+ * ret_from_except or ret_from_except_lite instead of this.
  */
 fast_exception_return:
-	andi.	r3,r23,MSR_RI		/* check if RI is set */
+	ld	r12,_MSR(r1)
+	ld	r11,_NIP(r1)
+	andi.	r3,r12,MSR_RI		/* check if RI is set */
 	beq-	unrecov_fer
 	ld      r3,_CCR(r1)
 	ld      r4,_LINK(r1)
@@ -691,244 +822,178 @@
 	mtcr    r3
 	mtlr    r4
 	mtctr   r5
-	mtspr   XER,r6
+	mtxer	r6
 	REST_GPR(0, r1)
 	REST_8GPRS(2, r1)
-	REST_4GPRS(10, r1)
 
-	mfmsr	r20
-	li	r21, MSR_RI
-	andc	r20,r20,r21
-	mtmsrd	r20,1
-
-	mtspr   SRR1,r23
-	mtspr   SRR0,r22
-	REST_4GPRS(20, r1)
+	mfmsr	r10
+	clrrdi	r10,r10,2		/* clear RI (LE is 0 already) */
+	mtmsrd	r10,1
+
+	mtspr	SRR1,r12
+	mtspr	SRR0,r11
+	REST_4GPRS(10, r1)
 	ld      r1,GPR1(r1)
 	rfid
 
 unrecov_fer:
-	li	r6,0x4000
-	li	r20,0
-	bl	.save_remaining_regs
+	bl	.save_nvgprs
 1:	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.unrecoverable_exception
 	b	1b
 
 /*
- * Here r20 points to the PACA, r21 to the exception frame,
- * r23 contains the saved CR.
- * r20 - r23, SRR0 and SRR1 are saved in the exception frame.
+ * Here r13 points to the paca, r9 contains the saved CR,
+ * SRR0 and SRR1 are saved in r11 and r12,
+ * r9 - r13 are saved in paca->exgen.
  */
+	.align	7
 	.globl DataAccess_common
 DataAccess_common:
-BEGIN_FTR_SECTION
-	mfspr   r22,DAR
-	srdi    r22,r22,60
-	cmpi    0,r22,0xc
-
-	/* Segment fault on a bolted segment. Go off and map that segment. */
-	beq-	.do_stab_bolted
-END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
-stab_bolted_user_return:
-	EXCEPTION_PROLOG_COMMON
-	ld      r3,_DSISR(r1)
-	andis.	r0,r3,0xa450		/* weird error? */
-	bne	1f			/* if not, try to put a PTE */
-	andis.	r0,r3,0x0020		/* Is it a page table fault? */
-	rlwinm	r4,r3,32-23,29,29	/* DSISR_STORE -> _PAGE_RW */
-	ld      r3,_DAR(r1)             /* into the hash table */
-
-BEGIN_FTR_SECTION
-	beq+	2f			/* If so handle it */
-	li	r4,0x300                /* Trap number */
-	bl	.do_stab_SI
-	b	1f
-END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
-
-2:	li	r5,0x300
-	bl	.do_hash_page_DSI 	/* Try to handle as hpte fault */
-1:
-	ld      r4,_DAR(r1)
-	ld      r5,_DSISR(r1)
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	DO_COPY_EE()
-	li	r6,0x300
-	bl      .save_remaining_regs
-	bl      .do_page_fault
-	b       .ret_from_except
+	mfspr	r10,DAR
+	std	r10,PACA_EXGEN+EX_DAR(r13)
+	mfspr	r10,DSISR
+	stw	r10,PACA_EXGEN+EX_DSISR(r13)
+	EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
+	ld	r3,PACA_EXGEN+EX_DAR(r13)
+	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
+	li	r5,0x300
+	b	.do_hash_page	 	/* Try to handle as hpte fault */
 
+	.align	7
 	.globl DataAccessSLB_common
 DataAccessSLB_common:
-	mfspr   r22,DAR
-	srdi    r22,r22,60
-	cmpi    0,r22,0xc
-
-	/* Segment fault on a bolted segment. Go off and map that segment. */
-	beq     .do_slb_bolted
-
-	EXCEPTION_PROLOG_COMMON
-	ld      r3,_DAR(r1)
-	li      r4,0x380                /* Exception vector  */
+	mfspr	r10,DAR
+	std	r10,PACA_EXGEN+EX_DAR(r13)
+	EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN)
+	ld	r3,PACA_EXGEN+EX_DAR(r13)
+	std	r3,_DAR(r1)
 	bl	.slb_allocate
-	or.	r3,r3,r3		/* Check return code */
+	cmpdi	r3,0			/* Check return code */
 	beq     fast_exception_return   /* Return if we succeeded */
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	DO_COPY_EE()
-	ld      r4,_DAR(r1)
-	li	r6,0x380
 	li	r5,0
-	bl      .save_remaining_regs
-	bl      .do_page_fault
-	b       .ret_from_except
+	std	r5,_DSISR(r1)
+	b	.handle_page_fault
 
+	.align	7
 	.globl InstructionAccess_common
 InstructionAccess_common:
-	EXCEPTION_PROLOG_COMMON
-
-BEGIN_FTR_SECTION
-	andis.	r0,r23,0x0020		/* no ste found? */
-	beq+	2f
-	mr	r3,r22			/* SRR0 at interrupt */
-	li	r4,0x400		/* Trap number       */
-	bl	.do_stab_SI
-	b	1f
-END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
-
-2:	mr	r3,r22
+	EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
+	ld	r3,_NIP(r1)
+	andis.	r4,r12,0x5820
 	li	r5,0x400
-	bl	.do_hash_page_ISI	/* Try to handle as hpte fault */
-1:
-	mr	r4,r22
-	rlwinm	r5,r23,0,4,4		/* We only care about PR in error_code */
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	DO_COPY_EE()
-	li	r6,0x400
-	bl      .save_remaining_regs
-	bl      .do_page_fault
-	b       .ret_from_except
+	b	.do_hash_page		/* Try to handle as hpte fault */
 
+	.align	7
 	.globl InstructionAccessSLB_common
 InstructionAccessSLB_common:
-	EXCEPTION_PROLOG_COMMON
-	mr      r3,r22                  /* SRR0 = NIA        */
-	li	r4,0x480                /* Exception vector  */
+	EXCEPTION_PROLOG_COMMON(0x480, PACA_EXGEN)
+	ld	r3,_NIP(r1)		/* SRR0 = NIA	*/
 	bl	.slb_allocate
 	or.	r3,r3,r3		/* Check return code */
 	beq+	fast_exception_return   /* Return if we succeeded */
 
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	DO_COPY_EE()
-	mr      r4,r22                  /* SRR0 = NIA        */
-	li	r6,0x480
+	ld	r4,_NIP(r1)
 	li	r5,0
-	bl      .save_remaining_regs
-	bl      .do_page_fault
-	b       .ret_from_except
+	std	r4,_DAR(r1)
+	std	r5,_DSISR(r1)
+	b      .handle_page_fault
 
+	.align	7
 	.globl HardwareInterrupt_common
+	.globl HardwareInterrupt_entry
 HardwareInterrupt_common:
-	EXCEPTION_PROLOG_COMMON
+	EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
 HardwareInterrupt_entry:
+	DISABLE_INTS
 	addi	r3,r1,STACK_FRAME_OVERHEAD
-	li	r20,0
-	li	r6,0x500
-	bl      .save_remaining_regs
 	bl      .do_IRQ
-	b       .ret_from_except
+	b	.ret_from_except_lite
 
+	.align	7
 	.globl Alignment_common
 Alignment_common:
-	EXCEPTION_PROLOG_COMMON
+	mfspr	r10,DAR
+	std	r10,PACA_EXGEN+EX_DAR(r13)
+	mfspr	r10,DSISR
+	stw	r10,PACA_EXGEN+EX_DSISR(r13)
+	EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN)
+	ld	r3,PACA_EXGEN+EX_DAR(r13)
+	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
+	std	r3,_DAR(r1)
+	std	r4,_DSISR(r1)
+	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
-	DO_COPY_EE()
-	li	r6,0x600
-	bl      .save_remaining_regs
+	ENABLE_INTS
 	bl      .AlignmentException
 	b       .ret_from_except
 
+	.align	7
 	.globl ProgramCheck_common
 ProgramCheck_common:
-	EXCEPTION_PROLOG_COMMON
+	EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
+	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
-	DO_COPY_EE()
-	li	r6,0x700
-	bl      .save_remaining_regs
+	ENABLE_INTS
 	bl      .ProgramCheckException
 	b       .ret_from_except
 
+	.align	7
 	.globl FPUnavailable_common
 FPUnavailable_common:
-	EXCEPTION_PROLOG_COMMON
+	EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
 	bne	.load_up_fpu		/* if from user, just load it up */
+	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
-	DO_COPY_EE()
-	li	r6,0x800
-	bl      .save_remaining_regs
+	ENABLE_INTS
 	bl      .KernelFPUnavailableException
 	BUG_OPCODE
 
+	.align	7
 	.globl AltivecUnavailable_common
 AltivecUnavailable_common:
-	EXCEPTION_PROLOG_COMMON
+	EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN)
 #ifdef CONFIG_ALTIVEC
-	bne	.load_up_altivec		/* if from user, just load it up */
+	bne	.load_up_altivec	/* if from user, just load it up */
 #endif
+	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
-	DO_COPY_EE()
-	li	r6,0xf20
-	bl      .save_remaining_regs
-#ifdef CONFIG_ALTIVEC
-	bl	.KernelAltivecUnavailableException
-#else
-	bl      .UnknownException
-#endif
-	BUG_OPCODE
+	ENABLE_INTS
+	bl	.AltivecUnavailableException
+	b	.ret_from_except
 		
-	.globl SystemCall_common
-SystemCall_common:
-	EXCEPTION_PROLOG_COMMON
-#ifdef CONFIG_PPC_ISERIES
-	cmpi	0,r0,0x5555		/* Special syscall to handle pending */
-	bne+	1f			/* interrupts */
-	andi.	r6,r23,MSR_PR		/* Only allowed from kernel */
-	beq+	HardwareInterrupt_entry
-1:
-#endif
-	DO_COPY_EE()
-	li	r6,0xC00
-	bl      .save_remaining_regs
-	bl      .DoSyscall
-	b       .ret_from_except
+/*
+ * Hash table stuff
+ */
+	.align	7
+_GLOBAL(do_hash_page)
+	std	r3,_DAR(r1)
+	std	r4,_DSISR(r1)
+
+	andis.	r0,r4,0xa450		/* weird error? */
+	bne-	.handle_page_fault	/* if not, try to insert a HPTE */
+BEGIN_FTR_SECTION
+	andis.	r0,r4,0x0020		/* Is it a segment table fault? */
+	bne-	.do_ste_alloc		/* If so handle it */
+END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
 
-_GLOBAL(do_hash_page_ISI)
-	li	r4,0
-_GLOBAL(do_hash_page_DSI)
 	/*
 	 * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
 	 * accessing a userspace segment (even from the kernel). We assume
 	 * kernel addresses always have the high bit set.
 	 */
-	rotldi	r0,r3,15		/* Move high bit into MSR_PR position */
-	orc	r0,r23,r0
-	rlwimi	r4,r0,32-13,30,30	/* Insert into _PAGE_USER */
+	rlwinm	r4,r4,32-23,29,29	/* DSISR_STORE -> _PAGE_RW */
+	rotldi	r0,r3,15		/* Move high bit into MSR_PR posn */
+	orc	r0,r12,r0		/* MSR_PR | ~high_bit */
+	rlwimi	r4,r0,32-13,30,30	/* becomes _PAGE_USER access bit */
 	ori	r4,r4,1			/* add _PAGE_PRESENT */
 
-	mflr	r21			/* Save LR in r21 */
-
-#ifdef DO_SOFT_DISABLE
 	/*
-	 * We hard enable here (but first soft disable) so that the hash_page
-	 * code can spin on the hash_table_lock with problem on a shared
-	 * processor.
+	 * On iSeries, we soft-disable interrupts here, then
+	 * hard-enable interrupts so that the hash_page code can spin on
+	 * the hash_table_lock without problems on a shared processor.
 	 */
-	li	r0,0
-	stb	r0,PACAPROCENABLED(r20)	/* Soft Disabled */
-
-	mfmsr	r0
-	ori	r0,r0,MSR_EE
-	mtmsrd	r0,1			/* Hard Enable */
-#endif
+	DISABLE_INTS
 
 	/*
 	 * r3 contains the faulting address
@@ -937,184 +1002,159 @@
 	 *
 	 * at return r3 = 0 for success
 	 */
-
 	bl	.hash_page		/* build HPTE if possible */
+	cmpdi	r3,0			/* see if hash_page succeeded */
 
 #ifdef DO_SOFT_DISABLE
 	/*
-	 * Now go back to hard disabled.
+	 * If we had interrupts soft-enabled at the point where the
+	 * DSI/ISI occurred, and an interrupt came in during hash_page,
+	 * handle it now.
+	 * We jump to ret_from_except_lite rather than fast_exception_return
+	 * because ret_from_except_lite will check for and handle pending
+	 * interrupts if necessary.
 	 */
-	mfmsr	r0
-	li	r4,0
-	ori	r4,r4,MSR_EE
-	andc	r0,r0,r4
-	mtmsrd	r0,1			/* Hard Disable */
-
-	ld	r0,SOFTE(r1)
-	cmpdi	0,r0,0			/* See if we will soft enable in */
-					/* save_remaining_regs */
-	beq	5f
-	CHECKANYINT(r4,r5)
-	bne-	HardwareInterrupt_entry	/* Convert this DSI into an External */
-					/* to process interrupts which occurred */
-					/* during hash_page */
-5:
-	stb	r0,PACAPROCENABLED(r20)	/* Restore soft enable/disable status */
+	beq	.ret_from_except_lite
+	/*
+	 * hash_page couldn't handle it, set soft interrupt enable back
+	 * to what it was before the trap.  Note that .local_irq_restore
+	 * handles any interrupts pending at this point.
+	 */
+	ld	r3,SOFTE(r1)
+	bl	.local_irq_restore
+	b	11f
+#else
+	beq+	fast_exception_return   /* Return from exception on success */
+	/* fall through */
 #endif
-	or.	r3,r3,r3		/* Check return code */
-	beq     fast_exception_return   /* Return from exception on success */
 
-	mtlr    r21                     /* restore LR */
-	blr                             /* Return to DSI or ISI on failure */
+/* Here we have a page fault that hash_page can't handle. */
+_GLOBAL(handle_page_fault)
+	ENABLE_INTS
+11:	ld	r4,_DAR(r1)
+	ld	r5,_DSISR(r1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.do_page_fault
+	cmpdi	r3,0
+	beq+	.ret_from_except_lite
+	bl	.save_nvgprs
+	mr	r5,r3
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	lwz	r4,_DAR(r1)
+	bl	.bad_page_fault
+	b	.ret_from_except
+
+	/* here we have a segment miss */
+_GLOBAL(do_ste_alloc)
+	bl	.ste_allocate		/* try to insert stab entry */
+	cmpdi	r3,0
+	beq+	fast_exception_return
+	b	.handle_page_fault
 
 /*
- * r20 points to the PACA, r21 to the exception frame,
- * r23 contains the saved CR.
- * r20 - r23, SRR0 and SRR1 are saved in the exception frame.
+ * r13 points to the PACA, r9 contains the saved CR,
+ * r11 and r12 contain the saved SRR0 and SRR1.
+ * r9 - r13 are saved in paca->exslb.
  * We assume we aren't going to take any exceptions during this procedure.
+ * We assume (DAR >> 60) == 0xc.
  */
+	.align	7
 _GLOBAL(do_stab_bolted)
-	stw	r23,EX_CCR(r21)	/* save CR in exc. frame */
+	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
+	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */
 
-	mfspr   r22,DSISR
-	andis.  r22,r22,0x0020
-	beq-	stab_bolted_user_return
+	/* Hash to the primary group */
+	ld	r10,PACASTABVIRT(r13)
+	mfspr	r11,DAR
+	srdi	r11,r11,28
+	rldimi	r10,r11,7,52	/* r10 = first ste of the group */
 
+	/* Calculate VSID */
 	/* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
-	mfspr	r21,DAR
-	rldicl	r20,r21,36,51
-	sldi	r20,r20,15
-	srdi	r21,r21,60
-	or	r20,r20,r21
+	rldic	r11,r11,15,36
+	ori	r11,r11,0xc
 
 	/* VSID_RANDOMIZER */
-	li      r21,9
-	sldi    r21,r21,32
-	oris    r21,r21,58231
-	ori     r21,r21,39831
+	li	r9,9
+	sldi	r9,r9,32
+	oris	r9,r9,58231
+	ori	r9,r9,39831
 
-	mulld   r20,r20,r21
-	clrldi  r20,r20,28      /* r20 = vsid */
-
-	mfsprg  r21,3
-	ld      r21,PACASTABVIRT(r21)
-
-	/* Hash to the primary group */
-	mfspr	r22,DAR
-	rldicl  r22,r22,36,59
-	rldicr  r22,r22,7,56
-	or      r21,r21,r22     /* r21 = first ste of the group */
+	mulld	r9,r11,r9
+	rldic	r9,r9,12,16	/* r9 = vsid << 12 */
 
 	/* Search the primary group for a free entry */
-	li      r22,0
-1:
-	ld      r23,0(r21)      /* Test valid bit of the current ste   */
-	rldicl  r23,r23,57,63
-	cmpwi   r23,0
-	bne     2f
-	li	r23,0
-	rldimi  r23,r20,12,0    /* Insert the new vsid value            */
-	std     r23,8(r21)      /* Put new entry back into the stab     */
-	eieio                  /* Order vsid update                    */
-	li	r23,0
-	mfspr	r20,DAR        /* Get the new esid                     */
-	rldicl  r20,r20,36,28  /* Permits a full 36b of ESID           */
-	rldimi  r23,r20,28,0    /* Insert the new esid value            */
-	ori     r23,r23,144      /* Turn on valid and kp                 */
-	std     r23,0(r21)      /* Put new entry back into the stab     */
-	sync                   /* Order the update                     */
-	b       3f
-2:
-	addi    r22,r22,1
-	addi    r21,r21,16
-	cmpldi  r22,7
-	ble     1b
+1:	ld	r11,0(r10)	/* Test valid bit of the current ste	*/
+	andi.	r11,r11,0x80
+	beq	2f
+	addi	r10,r10,16
+	andi.	r11,r10,0x70
+	bne	1b
 
 	/* Stick for only searching the primary group for now.          */
 	/* At least for now, we use a very simple random castout scheme */
 	/* Use the TB as a random number ;  OR in 1 to avoid entry 0    */
-	mftb    r22
-	andi.   r22,r22,7
-	ori	r22,r22,1
-	sldi	r22,r22,4
+	mftb	r11
+	rldic	r11,r11,4,57	/* r11 = (r11 << 4) & 0x70 */
+	ori	r11,r11,0x10
 
-	/* r21 currently points to and ste one past the group of interest */
+	/* r10 currently points to an ste one past the group of interest */
 	/* make it point to the randomly selected entry                   */
-	subi	r21,r21,128
-	or 	r21,r21,r22      /* r21 is the entry to invalidate        */
+	subi	r10,r10,128
+	or 	r10,r10,r11	/* r10 is the entry to invalidate	*/
 
 	isync                    /* mark the entry invalid                */
-	ld      r23,0(r21)
-	li      r22,-129
-	and     r23,r23,r22
-	std     r23,0(r21)
+	ld	r11,0(r10)
+	rldicl	r11,r11,56,1	/* clear the valid bit */
+	rotldi	r11,r11,8
+	std	r11,0(r10)
 	sync
 
-	li	r23,0
-	rldimi  r23,r20,12,0
-	std     r23,8(r21)
+	clrrdi	r11,r11,28	/* Get the esid part of the ste		*/
+	slbie	r11
+
+2:	std	r9,8(r10)	/* Store the vsid part of the ste	*/
 	eieio
 
-	ld	r22,0(r21)	/* Get the esid part of the ste         */
-	li	r23,0
-	mfspr	r20,DAR         /* Get the new esid                     */
-	rldicl  r20,r20,36,28   /* Permits a full 32b of ESID           */
-	rldimi  r23,r20,28,0    /* Insert the new esid value            */
-	ori     r23,r23,144     /* Turn on valid and kp                 */
-	std     r23,0(r21)      /* Put new entry back into the stab     */
-
-	rldicl  r22,r22,36,28
-	rldicr  r22,r22,28,35
-	slbie   r22
+	mfspr	r11,DAR		/* Get the new esid			*/
+	clrrdi	r11,r11,28	/* Permits a full 32b of ESID		*/
+	ori	r11,r11,0x90	/* Turn on valid and kp			*/
+	std	r11,0(r10)	/* Put new entry back into the stab	*/
+
 	sync
 
-3:
 	/* All done -- return from exception. */
-	mfsprg  r20,3                   /* Load the PACA pointer  */
-	ld      r21,PACAEXCSP(r20)      /* Get the exception frame pointer */
-	addi    r21,r21,EXC_FRAME_SIZE
-	lwz	r23,EX_CCR(r21)		/* get saved CR */
-
-	ld	r22,EX_SRR1(r21)
-	andi.	r22,r22,MSR_RI
-	beq-	unrecov_stab
-
-	/* note that this is almost identical to maskable_exception_exit */
-	mtcr    r23                     /* restore CR */
-
-	mfmsr	r22
-	li	r23, MSR_RI
-	andc	r22,r22,r23
-	mtmsrd	r22,1
-
-	ld	r22,EX_SRR0(r21)	/* Get SRR0 from exc. frame */
-	ld	r23,EX_SRR1(r21)	/* Get SRR1 from exc. frame */
-	mtspr	SRR0,r22
-	mtspr   SRR1,r23
-	ld	r22,EX_R22(r21)		/* restore r22 and r23 */
-	ld	r23,EX_R23(r21)
-	mfspr	r20,SPRG2
-	mfspr	r21,SPRG1
-	rfid
+	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
+	ld	r11,PACA_EXSLB+EX_SRR0(r13)	/* get saved SRR0 */
 
-unrecov_stab:
-	EXCEPTION_PROLOG_COMMON
-	li	r6,0x4100
-	li	r20,0
-	bl	.save_remaining_regs
-1:	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.unrecoverable_exception
-	b	1b
+	andi.	r10,r12,MSR_RI
+	beq-	unrecov_slb
+
+	mtcrf	0x80,r9			/* restore CR */
+
+	mfmsr	r10
+	clrrdi	r10,r10,2
+	mtmsrd	r10,1
+
+	mtspr	SRR0,r11
+	mtspr	SRR1,r12
+	ld	r9,PACA_EXSLB+EX_R9(r13)
+	ld	r10,PACA_EXSLB+EX_R10(r13)
+	ld	r11,PACA_EXSLB+EX_R11(r13)
+	ld	r12,PACA_EXSLB+EX_R12(r13)
+	ld	r13,PACA_EXSLB+EX_R13(r13)
+	rfid
 
 /*
- * r20 points to the PACA, r21 to the exception frame,
- * r23 contains the saved CR.
- * r20 - r23, SRR0 and SRR1 are saved in the exception frame.
+ * r13 points to the PACA, r9 contains the saved CR,
+ * r11 and r12 contain the saved SRR0 and SRR1.
+ * r9 - r13 are saved in paca->exslb.
  * We assume we aren't going to take any exceptions during this procedure.
  */
 /* XXX note fix masking in get_kernel_vsid to match */
 _GLOBAL(do_slb_bolted)
-	stw	r23,EX_CCR(r21)		/* save CR in exc. frame */
+	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
+	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */
 
 	/*
 	 * We take the next entry, round robin. Previously we tried
@@ -1122,15 +1162,15 @@
 	 * we dont have any LRU information to help us choose a slot.
 	 */
 
-	/* r20 = paca */
-1:	ld	r22,PACASTABRR(r20)
-	addi	r21,r22,1
-	cmpdi	r21,SLB_NUM_ENTRIES
+	/* r13 = paca */
+1:	ld	r10,PACASTABRR(r13)
+	addi	r9,r10,1
+	cmpdi	r9,SLB_NUM_ENTRIES
 	blt+	2f
-	li	r21,2			/* dont touch slot 0 or 1 */
-2:	std	r21,PACASTABRR(r20)
+	li	r9,2			/* dont touch slot 0 or 1 */
+2:	std	r9,PACASTABRR(r13)
 
-	/* r20 = paca, r22 = entry */
+	/* r13 = paca, r10 = entry */
 
 	/* 
 	 * Never cast out the segment for our kernel stack. Since we
@@ -1139,8 +1179,8 @@
 	 * which gets invalidated due to a tlbie from another cpu at a
 	 * non recoverable point (after setting srr0/1) - Anton
 	 */
-	slbmfee	r21,r22
-	srdi	r21,r21,27
+	slbmfee	r9,r10
+	srdi	r9,r9,27
 	/*
 	 * Use paca->ksave as the value of the kernel stack pointer,
 	 * because this is valid at all times.
@@ -1150,74 +1190,71 @@
 	 * switch (between updating r1 and updating paca->ksave),
 	 * we check against both r1 and paca->ksave.
 	 */
-	srdi	r23,r1,27
-	ori	r23,r23,1
-	cmpd	r23,r21
+	srdi	r11,r1,27
+	ori	r11,r11,1
+	cmpd	r11,r9
 	beq-	1b
-	ld	r23,PACAKSAVE(r20)
-	srdi	r23,r23,27
- 	ori	r23,r23,1
- 	cmpd	r23,r21
+	ld	r11,PACAKSAVE(r13)
+	srdi	r11,r11,27
+ 	ori	r11,r11,1
+ 	cmpd	r11,r9
  	beq-	1b
 
-	/* r20 = paca, r22 = entry */
+	/* r13 = paca, r10 = entry */
 
 	/* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
-	mfspr	r21,DAR
-	rldicl	r23,r21,36,51
-	sldi	r23,r23,15
-	srdi	r21,r21,60
-	or	r23,r23,r21
+	mfspr	r9,DAR
+	rldicl	r11,r9,36,51
+	sldi	r11,r11,15
+	srdi	r9,r9,60
+	or	r11,r11,r9
 
 	/* VSID_RANDOMIZER */
-	li	r21,9
-	sldi	r21,r21,32
-	oris	r21,r21,58231
-	ori	r21,r21,39831
+	li	r9,9
+	sldi	r9,r9,32
+	oris	r9,r9,58231
+	ori	r9,r9,39831
 
 	/* vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK */
-	mulld	r23,r23,r21
-	clrldi	r23,r23,28
+	mulld	r11,r11,r9
+	clrldi	r11,r11,28
 
-	/* r20 = paca, r22 = entry, r23 = vsid */
+	/* r13 = paca, r10 = entry, r11 = vsid */
 
 	/* Put together slb word1 */
-	sldi	r23,r23,12
+	sldi	r11,r11,12
 
 BEGIN_FTR_SECTION
 	/* set kp and c bits */
-	ori	r23,r23,0x480
+	ori	r11,r11,0x480
 END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE)
 BEGIN_FTR_SECTION
 	/* set kp, l and c bits */
-	ori	r23,r23,0x580
+	ori	r11,r11,0x580
 END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
 
-	/* r20 = paca, r22 = entry, r23 = slb word1 */
+	/* r13 = paca, r10 = entry, r11 = slb word1 */
 
 	/* Put together slb word0 */
-	mfspr	r21,DAR
-	rldicr	r21,r21,0,35	/* get the new esid */
-	oris	r21,r21,2048	/* set valid bit */
-	rldimi	r21,r22,0,52	/* insert entry */
+	mfspr	r9,DAR
+	clrrdi	r9,r9,28	/* get the new esid */
+	oris	r9,r9,0x800	/* set valid bit */
+	rldimi	r9,r10,0,52	/* insert entry */
 
-	/* r20 = paca, r21 = slb word0, r23 = slb word1 */
+	/* r13 = paca, r9 = slb word0, r11 = slb word1 */
 
 	/* 
 	 * No need for an isync before or after this slbmte. The exception
 	 * we enter with and the rfid we exit with are context synchronizing .
 	 */
-	slbmte	r23,r21
+	slbmte	r11,r9
 
 	/* All done -- return from exception. */
-	ld	r21,PACAEXCSP(r20)	/* Get the exception frame pointer */
-	addi	r21,r21,EXC_FRAME_SIZE
-	lwz	r23,EX_CCR(r21)		/* get saved CR */
-	/* note that this is almost identical to maskable_exception_exit */
-
-	ld	r22,EX_SRR1(r21)
-	andi.	r22,r22,MSR_RI
-	beq-	unrecov_stab
+	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
+	ld	r11,PACA_EXSLB+EX_SRR0(r13)	/* get saved SRR0 */
+
+	andi.	r10,r12,MSR_RI	/* check for unrecoverable exception */
+	beq-	unrecov_slb
 
 	/*
 	 * Until everyone updates binutils hardwire the POWER4 optimised
@@ -1226,124 +1263,32 @@
 #if 0
 	.machine	push
 	.machine	"power4"
-	mtcrf	0x80,r23
+	mtcrf	0x80,r9
 	.machine	pop
 #else
-	.long 0x7ef80120
+	.long 0x7d380120
 #endif
 
-	mfmsr	r22
-	li	r23, MSR_RI
-	andc	r22,r22,r23
-	mtmsrd	r22,1
-
-	ld	r22,EX_SRR0(r21)	/* Get SRR0 from exc. frame */
-	ld	r23,EX_SRR1(r21)	/* Get SRR1 from exc. frame */
-	mtspr	SRR0,r22
-	mtspr	SRR1,r23
-	ld	r22,EX_R22(r21)		/* restore r22 and r23 */
-	ld	r23,EX_R23(r21)
-	ld	r20,EX_R20(r21)
-	mfspr	r21,SPRG1
+	mfmsr	r10
+	clrrdi	r10,r10,2
+	mtmsrd	r10,1
+
+	mtspr	SRR0,r11
+	mtspr	SRR1,r12
+	ld	r9,PACA_EXSLB+EX_R9(r13)
+	ld	r10,PACA_EXSLB+EX_R10(r13)
+	ld	r11,PACA_EXSLB+EX_R11(r13)
+	ld	r12,PACA_EXSLB+EX_R12(r13)
+	ld	r13,PACA_EXSLB+EX_R13(r13)
 	rfid
 
-_GLOBAL(do_stab_SI)
-	mflr	r21			/* Save LR in r21 */
-
-	/*
-	 * r3 contains the faulting address
-	 * r4 contains the required access permissions
-	 *
-	 * at return r3 = 0 for success
-	 */
-
-	bl	.ste_allocate		/* build STE if possible */
-	or.	r3,r3,r3		/* Check return code */
-	beq     fast_exception_return   /* Return from exception on success */
-	mtlr    r21                     /* restore LR */
-	blr                             /* Return to DSI or ISI on failure */
-
-/*
- * This code finishes saving the registers to the exception frame.
- * Address translation is already on.
- */
-_GLOBAL(save_remaining_regs)
-	/*
-	 * Save the rest of the registers into the pt_regs structure
-	 */
-	std     r22,_NIP(r1)
-	std     r23,_MSR(r1)
-	std     r6,TRAP(r1)
-	ld      r6,GPR6(r1)
-	SAVE_2GPRS(14, r1)
-	SAVE_4GPRS(16, r1)
-	SAVE_8GPRS(24, r1)
-
-	/* Set the marker value "regshere" just before the reg values */
-	SET_REG_TO_CONST(r22, 0x7265677368657265)
-	std	r22,STACK_FRAME_OVERHEAD-16(r1)
-
-	/*
-	 * Clear the RESULT field
-	 */
-	li	r22,0
-	std	r22,RESULT(r1)
-
-	/*
-	 * Test if from user state; result will be tested later
-	 */
-	andi.	r23,r23,MSR_PR		/* Set CR for later branch */
-
-	/*
-	 * Indicate that r1 contains the kernel stack and
-	 * get the Kernel TOC pointer from the paca
-	 */
-	ld	r2,PACATOC(r13)		/* Get Kernel TOC pointer */
-
-	/*
-	 * If from user state, update THREAD.regs
-	 */
-	beq	2f			/* Modify THREAD.regs if from user */
-	addi	r23,r1,STACK_FRAME_OVERHEAD
-	ld	r22, PACACURRENT(r13)
-	std	r23,THREAD+PT_REGS(r22)
-2:
-	SET_REG_TO_CONST(r22, MSR_KERNEL)
-
-#ifdef DO_SOFT_DISABLE
-	stb	r20,PACAPROCENABLED(r13) /* possibly soft enable */
-	ori	r22,r22,MSR_EE		/* always hard enable */
-#else
-	rldimi	r22,r20,15,48		/* Insert desired EE value */
-#endif
-
-	mtmsrd  r22,1
-	blr
-
-/*
- * Kernel profiling with soft disable on iSeries
- */
-do_profile:
-	ld	r22,8(r21)		/* Get SRR1 */
-	andi.	r22,r22,MSR_PR		/* Test if in kernel */
-	bnelr				/* return if not in kernel */
-	ld	r22,0(r21)		/* Get SRR0 */
-	ld	r25,PACAPROFSTEXT(r20)	/* _stext */
-	subf	r22,r25,r22		/* offset into kernel */
-	lwz	r25,PACAPROFSHIFT(r20)
-	srd	r22,r22,r25
-	lwz	r25,PACAPROFLEN(r20)	/* length of profile table (-1) */
-	cmp	0,r22,r25		/* off end? */
-	ble	1f
-	mr	r22,r25			/* force into last entry */
-1:	sldi	r22,r22,2		/* convert to offset into buffer */
-	ld	r25,PACAPROFBUFFER(r20)	/* profile buffer */
-	add	r25,r25,r22
-2:	lwarx	r22,0,r25		/* atomically increment */
-	addi	r22,r22,1
-	stwcx.	r22,0,r25
-	bne-	2b
-	blr
+unrecov_slb:
+	EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
+	DISABLE_INTS
+	bl	.save_nvgprs
+1:	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.unrecoverable_exception
+	b	1b
 
 
 /*
@@ -1375,7 +1320,7 @@
         addi    r1,r1,0x1000
         subi    r1,r1,STACK_FRAME_OVERHEAD
 
-	cmpi	0,r23,0
+	cmpwi	0,r23,0
 #ifdef CONFIG_SMP
 #ifdef SECONDARY_PROCESSORS
 	bne	.__secondary_start
@@ -1594,9 +1539,9 @@
  *
  */
 #ifndef CONFIG_SMP
-	LOADBASE(r3,last_task_used_math)
-	ld	r4,last_task_used_math@l(r3)
-	cmpi	0,r4,0
+	ld	r3,last_task_used_math@got(r2)
+	ld	r4,0(r3)
+	cmpdi	0,r4,0
 	beq	1f
 	/* Save FP state to last_task_used_math's THREAD struct */
 	addi	r4,r4,THREAD
@@ -1606,8 +1551,8 @@
 	/* Disable FP for last_task_used_math */
 	ld	r5,PT_REGS(r4)
 	ld	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	li	r20,MSR_FP|MSR_FE0|MSR_FE1
-	andc	r4,r4,r20
+	li	r6,MSR_FP|MSR_FE0|MSR_FE1
+	andc	r4,r4,r6
 	std	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
 1:
 #endif /* CONFIG_SMP */
@@ -1615,15 +1560,16 @@
 	ld	r4,PACACURRENT(r13)
 	addi	r5,r4,THREAD		/* Get THREAD */
 	ld	r4,THREAD_FPEXC_MODE(r5)
-	ori	r23,r23,MSR_FP
-	or	r23,r23,r4
+	ori	r12,r12,MSR_FP
+	or	r12,r12,r4
+	std	r12,_MSR(r1)
 	lfd	fr0,THREAD_FPSCR(r5)
 	mtfsf	0xff,fr0
 	REST_32FPRS(0, r5)
 #ifndef CONFIG_SMP
 	/* Update last_task_used_math to 'current' */
 	subi	r4,r5,THREAD		/* Back to 'current' */
-	std	r4,last_task_used_math@l(r3)
+	std	r4,0(r3)
 #endif /* CONFIG_SMP */
 	/* restore registers and return */
 	b	fast_exception_return
@@ -1651,11 +1597,11 @@
 	ori	r5,r5,MSR_FP
 	mtmsrd	r5			/* enable use of fpu now */
 	isync
-	cmpi	0,r3,0
+	cmpdi	0,r3,0
 	beqlr-				/* if no previous owner, done */
 	addi	r3,r3,THREAD		/* want THREAD of task */
 	ld	r5,PT_REGS(r3)
-	cmpi	0,r5,0
+	cmpdi	0,r5,0
 	SAVE_32FPRS(0, r3)
 	mffs	fr0
 	stfd	fr0,THREAD_FPSCR(r3)
@@ -1667,8 +1613,8 @@
 1:
 #ifndef CONFIG_SMP
 	li	r5,0
-	LOADBASE(r4,last_task_used_math)
-	std	r5,last_task_used_math@l(r4)
+	ld	r4,last_task_used_math@got(r2)
+	std	r5,0(r4)
 #endif /* CONFIG_SMP */
 	blr
 
@@ -1699,9 +1645,9 @@
  * avoid saving all of the VREGs here...
  */
 #ifndef CONFIG_SMP
-	LOADBASE(r3,last_task_used_altivec)
-	ld	r4,last_task_used_altivec@l(r3)
-	cmpi	0,r4,0
+	ld	r3,last_task_used_altivec@got(r2)
+	ld	r4,0(r3)
+	cmpdi	0,r4,0
 	beq	1f
 	/* Save VMX state to last_task_used_altivec's THREAD struct */
 	addi	r4,r4,THREAD
@@ -1712,8 +1658,8 @@
 	/* Disable VMX for last_task_used_altivec */
 	ld	r5,PT_REGS(r4)
 	ld	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	lis	r20,MSR_VEC@h
-	andc	r4,r4,r20
+	lis	r6,MSR_VEC@h
+	andc	r4,r4,r6
 	std	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
 1:
 #endif /* CONFIG_SMP */
@@ -1723,7 +1669,7 @@
 	 * all 1's
 	 */
 	mfspr	r4,SPRN_VRSAVE
-	cmpi	0,r4,0
+	cmpdi	0,r4,0
 	bne+	1f
 	li	r4,-1
 	mtspr	SPRN_VRSAVE,r4
@@ -1731,7 +1677,8 @@
 	/* enable use of VMX after return */
 	ld	r4,PACACURRENT(r13)
 	addi	r5,r4,THREAD		/* Get THREAD */
-	oris	r23,r23,MSR_VEC@h
+	oris	r12,r12,MSR_VEC@h
+	std	r12,_MSR(r1)
 	li	r4,1
 	li	r10,THREAD_VSCR
 	stw	r4,THREAD_USED_VR(r5)
@@ -1740,7 +1687,7 @@
 #ifndef CONFIG_SMP
 	/* Update last_task_used_math to 'current' */
 	subi	r4,r5,THREAD		/* Back to 'current' */
-	std	r4,last_task_used_altivec@l(r3)
+	std	r4,0(r3)
 #endif /* CONFIG_SMP */
 	/* restore registers and return */
 	b	fast_exception_return
@@ -1768,11 +1715,11 @@
 	oris	r5,r5,MSR_VEC@h
 	mtmsrd	r5			/* enable use of VMX now */
 	isync
-	cmpi	0,r3,0
+	cmpdi	0,r3,0
 	beqlr-				/* if no previous owner, done */
 	addi	r3,r3,THREAD		/* want THREAD of task */
 	ld	r5,PT_REGS(r3)
-	cmpi	0,r5,0
+	cmpdi	0,r5,0
 	SAVE_32VRS(0,r4,r3)
 	mfvscr	vr0
 	li	r4,THREAD_VSCR
@@ -1785,8 +1732,8 @@
 1:
 #ifndef CONFIG_SMP
 	li	r5,0
-	LOADBASE(r4,last_task_used_altivec)
-	std	r5,last_task_used_altivec@l(r4)
+	ld	r4,last_task_used_altivec@got(r2)
+	std	r5,0(r4)
 #endif /* CONFIG_SMP */
 	blr
 
@@ -1885,8 +1832,9 @@
 	LOADADDR(r3,current_set)
 	sldi	r28,r24,3		/* get current_set[cpu#] */
 	ldx	r1,r3,r28
-	addi	r1,r1,THREAD_SIZE
-	subi	r1,r1,STACK_FRAME_OVERHEAD
+	addi	r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
+	li	r0,0
+	std	r0,0(r1)
 	std	r1,PACAKSAVE(r13)
 
 	ld	r3,PACASTABREAL(r13)    /* get raddr of segment table       */
@@ -1943,7 +1891,7 @@
 #endif
 
 /*
- * This subroutine clobbers r11, r12 and the LR
+ * This subroutine clobbers r11 and r12
  */
 _GLOBAL(enable_64b_mode)
 	mfmsr   r11                      /* grab the current MSR */
@@ -2144,7 +2092,6 @@
 	std	r4,PACACURRENT(r13)
 
 	std	r2,PACATOC(r13)
-	li	r5,0
 	std	r1,PACAKSAVE(r13)
 
 	/* Restore the parms passed in from the bootloader. */
diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
--- a/arch/ppc64/kernel/iSeries_setup.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc64/kernel/iSeries_setup.c	2004-06-23 19:04:28 -07:00
@@ -357,15 +357,14 @@
 	HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
 			HvLpDma_Direction_RemoteToLocal);
 
-	p = q = cmd_line + 255;
-	while (p > cmd_line) {
-		if ((*p == 0) || (*p == ' ') || (*p == '\n'))
-			--p;
-		else
+	p = cmd_line;
+	q = cmd_line + 255;
+	while( p < q ) {
+		if (!*p || *p == '\n')
 			break;
+		++p;
 	}
-	if (p < q)
-		*(p + 1) = 0;
+	*p = 0;
 
         if (strstr(cmd_line, "dprofile=")) {
                 for (q = cmd_line; (p = strstr(q, "dprofile=")) != 0; ) {
diff -Nru a/arch/ppc64/kernel/init_task.c b/arch/ppc64/kernel/init_task.c
--- a/arch/ppc64/kernel/init_task.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ppc64/kernel/init_task.c	2004-06-23 19:04:26 -07:00
@@ -4,6 +4,7 @@
 #include <linux/init.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
+#include <linux/mqueue.h>
 #include <asm/uaccess.h>
 
 static struct fs_struct init_fs = INIT_FS;
diff -Nru a/arch/ppc64/kernel/mf_proc.c b/arch/ppc64/kernel/mf_proc.c
--- a/arch/ppc64/kernel/mf_proc.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ppc64/kernel/mf_proc.c	2004-06-23 19:04:26 -07:00
@@ -25,33 +25,26 @@
 {
 	int len = count;
 	char *p;
-    
+
+	if (off) {
+		*eof = 1;
+		return 0;
+	}
+
 	len = mf_getCmdLine(page, &len, (u64)data);
    
-	p = page + len - 1;
-	while (p > page) {
-		if ((*p == 0) || (*p == ' '))
-			--p;
-		else
+	p = page;
+	while (len < (count - 1)) {
+		if (!*p || *p == '\n')
 			break;
+		p++;
+		len++;
 	}
-	if (*p != '\n') {
-		++p;
-		*p = '\n';
-	}
-	++p;
+	*p = '\n';
+	p++;
 	*p = 0;
-	len = p - page;
-    
-	len -= off;			
-	if (len < count) {		
-		*eof = 1;		
-		if (len <= 0)		
-			return 0;	
-	} else				
-		len = count;		
-	*start = page + off;		
-	return len;			
+
+	return p - page;
 }
 
 #if 0
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc64/kernel/misc.S	2004-06-23 19:04:28 -07:00
@@ -85,16 +85,17 @@
 	cmpw	0,r3,r5
 	beqlr
 	/* are we enabling interrupts? */
-	cmpi	0,r3,0
+	cmpdi	0,r3,0
 	stb	r3,PACAPROCENABLED(r13)
 	beqlr
 	/* Check pending interrupts */
 	/*   A decrementer, IPI or PMC interrupt may have occurred
 	 *   while we were in the hypervisor (which enables) */
-	CHECKANYINT(r4,r5)
+	ld	r4,PACALPPACA+LPPACAANYINT(r13)
+	cmpdi	r4,0
 	beqlr
 
-	/* 
+	/*
 	 * Handle pending interrupts in interrupt context
 	 */
 	li	r0,0x5555
@@ -608,7 +609,7 @@
 _GLOBAL(sys_call_table32)
 	.llong .sys_restart_syscall	/* 0 */
 	.llong .sys_exit
-	.llong .sys_fork
+	.llong .ppc_fork
 	.llong .sys_read
 	.llong .sys_write
 	.llong .sys32_open		/* 5 */
@@ -678,7 +679,7 @@
 	.llong .sys32_ssetmask
 	.llong .sys_setreuid	        /* 70 */
 	.llong .sys_setregid
-	.llong .sys32_sigsuspend
+	.llong .ppc32_sigsuspend
 	.llong .compat_sys_sigpending
 	.llong .sys32_sethostname
 	.llong .compat_sys_setrlimit	        /* 75 */
@@ -726,7 +727,7 @@
 	.llong .sys32_ipc
 	.llong .sys_fsync
 	.llong .ppc32_sigreturn
-	.llong .sys_clone		/* 120 */
+	.llong .ppc_clone		/* 120 */
 	.llong .sys32_setdomainname
 	.llong .ppc64_newuname
 	.llong .sys_ni_syscall		/* old modify_ldt syscall */
@@ -784,7 +785,7 @@
 	.llong .sys32_rt_sigpending     /* 175 */
 	.llong .sys32_rt_sigtimedwait
 	.llong .sys32_rt_sigqueueinfo
-	.llong .sys32_rt_sigsuspend
+	.llong .ppc32_rt_sigsuspend
 	.llong .sys32_pread64
 	.llong .sys32_pwrite64	        /* 180 */
 	.llong .sys_chown
@@ -795,7 +796,7 @@
 	.llong .sys32_sendfile
 	.llong .sys_ni_syscall		/* reserved for streams1 */
 	.llong .sys_ni_syscall		/* reserved for streams2 */
-	.llong .sys_vfork
+	.llong .ppc_vfork
 	.llong .compat_sys_getrlimit	        /* 190 */
 	.llong .sys32_readahead
 	.llong .sys32_mmap2
@@ -880,7 +881,7 @@
 _GLOBAL(sys_call_table)
 	.llong .sys_restart_syscall	/* 0 */
 	.llong .sys_exit
-	.llong .sys_fork
+	.llong .ppc_fork
 	.llong .sys_read
 	.llong .sys_write
 	.llong .sys_open		/* 5 */
@@ -998,7 +999,7 @@
 	.llong .sys_ipc
 	.llong .sys_fsync
 	.llong .sys_ni_syscall
-	.llong .sys_clone		/* 120 */
+	.llong .ppc_clone		/* 120 */
 	.llong .sys_setdomainname
 	.llong .ppc64_newuname
 	.llong .sys_ni_syscall		/* old modify_ldt syscall */
@@ -1056,7 +1057,7 @@
 	.llong .sys_rt_sigpending	/* 175 */
 	.llong .sys_rt_sigtimedwait
 	.llong .sys_rt_sigqueueinfo
-	.llong .sys_rt_sigsuspend
+	.llong .ppc64_rt_sigsuspend
 	.llong .sys_pread64
 	.llong .sys_pwrite64	        /* 180 */
 	.llong .sys_chown
@@ -1067,7 +1068,7 @@
 	.llong .sys_sendfile64
 	.llong .sys_ni_syscall		/* reserved for streams1 */
 	.llong .sys_ni_syscall		/* reserved for streams2 */
-	.llong .sys_vfork
+	.llong .ppc_vfork
 	.llong .sys_getrlimit	        /* 190 */
 	.llong .sys_readahead
 	.llong .sys_ni_syscall		/* 32bit only mmap2 */
diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
--- a/arch/ppc64/kernel/pacaData.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc64/kernel/pacaData.c	2004-06-23 19:04:28 -07:00
@@ -62,8 +62,6 @@
 		.xDesc = 0xd397d9e2,	/* "LpRS" */			    \
 		.xSize = sizeof(struct ItLpRegSave)			    \
 	},								    \
-	.exception_sp =							    \
-		(&paca[number].exception_stack[0]) - EXC_FRAME_SIZE,	    \
 }
 
 struct paca_struct paca[] __page_aligned = {
diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
--- a/arch/ppc64/kernel/ppc_ksyms.c	2004-06-23 19:04:26 -07:00
+++ b/arch/ppc64/kernel/ppc_ksyms.c	2004-06-23 19:04:26 -07:00
@@ -50,7 +50,6 @@
 int abs(int);
 
 EXPORT_SYMBOL(do_signal);
-EXPORT_SYMBOL(sys_ioctl);
 
 EXPORT_SYMBOL(isa_io_base);
 EXPORT_SYMBOL(pci_io_base);
diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
--- a/arch/ppc64/kernel/process.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/kernel/process.c	2004-06-23 19:04:27 -07:00
@@ -65,8 +65,43 @@
 	.page_table_lock = SPIN_LOCK_UNLOCKED,
 };
 
+/*
+ * Make sure the floating-point register state in the
+ * the thread_struct is up to date for task tsk.
+ */
+void flush_fp_to_thread(struct task_struct *tsk)
+{
+	if (tsk->thread.regs) {
+		/*
+		 * We need to disable preemption here because if we didn't,
+		 * another process could get scheduled after the regs->msr
+		 * test but before we have finished saving the FP registers
+		 * to the thread_struct.  That process could take over the
+		 * FPU, and then when we get scheduled again we would store
+		 * bogus values for the remaining FP registers.
+		 */
+		preempt_disable();
+		if (tsk->thread.regs->msr & MSR_FP) {
+#ifdef CONFIG_SMP
+			/*
+			 * This should only ever be called for current or
+			 * for a stopped child process.  Since we save away
+			 * the FP register state on context switch on SMP,
+			 * there is something wrong if a stopped child appears
+			 * to still have its FP state in the CPU registers.
+			 */
+			BUG_ON(tsk != current);
+#endif
+			giveup_fpu(current);
+		}
+		preempt_enable();
+	}
+}
+
 void enable_kernel_fp(void)
 {
+	WARN_ON(preemptible());
+
 #ifdef CONFIG_SMP
 	if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
 		giveup_fpu(current);
@@ -80,12 +115,9 @@
 
 int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
 {
-	struct pt_regs *regs = tsk->thread.regs;
-
-	if (!regs)
+	if (!tsk->thread.regs)
 		return 0;
-	if (tsk == current && (regs->msr & MSR_FP))
-		giveup_fpu(current);
+	flush_fp_to_thread(current);
 
 	memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
 
@@ -96,6 +128,8 @@
 
 void enable_kernel_altivec(void)
 {
+	WARN_ON(preemptible());
+
 #ifdef CONFIG_SMP
 	if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
 		giveup_altivec(current);
@@ -107,10 +141,29 @@
 }
 EXPORT_SYMBOL(enable_kernel_altivec);
 
+/*
+ * Make sure the VMX/Altivec register state in the
+ * the thread_struct is up to date for task tsk.
+ */
+void flush_altivec_to_thread(struct task_struct *tsk)
+{
+#ifdef CONFIG_ALTIVEC
+	if (tsk->thread.regs) {
+		preempt_disable();
+		if (tsk->thread.regs->msr & MSR_VEC) {
+#ifdef CONFIG_SMP
+			BUG_ON(tsk != current);
+#endif
+			giveup_altivec(current);
+		}
+		preempt_enable();
+	}
+#endif
+}
+
 int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
 {
-	if (regs->msr & MSR_VEC)
-		giveup_altivec(current);
+	flush_altivec_to_thread(current);
 	memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs));
 	return 1;
 }
@@ -166,6 +219,7 @@
 void show_regs(struct pt_regs * regs)
 {
 	int i;
+	unsigned long trap;
 
 	printk("NIP: %016lX XER: %016lX LR: %016lX\n",
 	       regs->nip, regs->xer, regs->link);
@@ -176,7 +230,8 @@
 	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
 	       regs->msr&MSR_IR ? 1 : 0,
 	       regs->msr&MSR_DR ? 1 : 0);
-	if (regs->trap == 0x300 || regs->trap == 0x380 || regs->trap == 0x600)
+	trap = TRAP(regs);
+	if (trap == 0x300 || trap == 0x380 || trap == 0x600)
 		printk("DAR: %016lx, DSISR: %016lx\n", regs->dar, regs->dsisr);
 	printk("TASK: %p[%d] '%s' THREAD: %p",
 	       current, current->pid, current->comm, current->thread_info);
@@ -191,6 +246,8 @@
 		}
 
 		printk("%016lX ", regs->gpr[i]);
+		if (i == 13 && !FULL_REGS(regs))
+			break;
 	}
 	printk("\n");
 	/*
@@ -245,16 +302,8 @@
  */
 void prepare_to_copy(struct task_struct *tsk)
 {
-	struct pt_regs *regs = tsk->thread.regs;
-
-	if (regs == NULL)
-		return;
-	if (regs->msr & MSR_FP)
-		giveup_fpu(current);
-#ifdef CONFIG_ALTIVEC
-	if (regs->msr & MSR_VEC)
-		giveup_altivec(current);
-#endif /* CONFIG_ALTIVEC */
+	flush_fp_to_thread(current);
+	flush_altivec_to_thread(current);
 }
 
 /*
@@ -439,12 +488,8 @@
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
-	if (regs->msr & MSR_FP)
-		giveup_fpu(current);
-#ifdef CONFIG_ALTIVEC
-	if (regs->msr & MSR_VEC)
-		giveup_altivec(current);
-#endif /* CONFIG_ALTIVEC */
+	flush_fp_to_thread(current);
+	flush_altivec_to_thread(current);
 	error = do_execve(filename, (char __user * __user *) a1,
 				    (char __user * __user *) a2, regs);
   
diff -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
--- a/arch/ppc64/kernel/ptrace.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc64/kernel/ptrace.c	2004-06-23 19:04:28 -07:00
@@ -119,8 +119,7 @@
 		if (index < PT_FPR0) {
 			tmp = get_reg(child, (int)index);
 		} else {
-			if (child->thread.regs->msr & MSR_FP)
-				giveup_fpu(child);
+			flush_fp_to_thread(child);
 			tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
 		}
 		ret = put_user(tmp,(unsigned long __user *) data);
@@ -152,8 +151,7 @@
 		if (index < PT_FPR0) {
 			ret = put_reg(child, index, data);
 		} else {
-			if (child->thread.regs->msr & MSR_FP)
-				giveup_fpu(child);
+			flush_fp_to_thread(child);
 			((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
 			ret = 0;
 		}
@@ -245,8 +243,7 @@
 		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
 		unsigned long __user *tmp = (unsigned long __user *)addr;
 
-		if (child->thread.regs->msr & MSR_FP)
-			giveup_fpu(child);
+		flush_fp_to_thread(child);
 
 		for (i = 0; i < 32; i++) {
 			ret = put_user(*reg, tmp);
@@ -263,8 +260,7 @@
 		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
 		unsigned long __user *tmp = (unsigned long __user *)addr;
 
-		if (child->thread.regs->msr & MSR_FP)
-			giveup_fpu(child);
+		flush_fp_to_thread(child);
 
 		for (i = 0; i < 32; i++) {
 			ret = get_user(*reg, tmp);
diff -Nru a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c
--- a/arch/ppc64/kernel/ptrace32.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/kernel/ptrace32.c	2004-06-23 19:04:27 -07:00
@@ -136,8 +136,7 @@
 		if (index < PT_FPR0) {
 			tmp = get_reg(child, index);
 		} else {
-			if (child->thread.regs->msr & MSR_FP)
-				giveup_fpu(child);
+			flush_fp_to_thread(child);
 			/*
 			 * the user space code considers the floating point
 			 * to be an array of unsigned int (32 bits) - the
@@ -179,8 +178,7 @@
 			break;
 
 		if (numReg >= PT_FPR0) {
-			if (child->thread.regs->msr & MSR_FP)
-				giveup_fpu(child);
+			flush_fp_to_thread(child);
 			tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
 		} else { /* register within PT_REGS struct */
 			tmp = get_reg(child, numReg);
@@ -244,8 +242,7 @@
 		if (index < PT_FPR0) {
 			ret = put_reg(child, index, data);
 		} else {
-			if (child->thread.regs->msr & MSR_FP)
-				giveup_fpu(child);
+			flush_fp_to_thread(child);
 			/*
 			 * the user space code considers the floating point
 			 * to be an array of unsigned int (32 bits) - the
@@ -283,8 +280,7 @@
 				|| ((numReg > PT_CCR) && (numReg < PT_FPR0)))
 			break;
 		if (numReg >= PT_FPR0) {
-			if (child->thread.regs->msr & MSR_FP)
-				giveup_fpu(child);
+			flush_fp_to_thread(child);
 		}
 		if (numReg == PT_MSR)
 			data = (data & MSR_DEBUGCHANGE)
@@ -379,8 +375,7 @@
 		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
 		unsigned int __user *tmp = (unsigned int __user *)addr;
 
-		if (child->thread.regs->msr & MSR_FP)
-			giveup_fpu(child);
+		flush_fp_to_thread(child);
 
 		for (i = 0; i < 32; i++) {
 			ret = put_user(*reg, tmp);
@@ -397,8 +392,7 @@
 		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
 		unsigned int __user *tmp = (unsigned int __user *)addr;
 
-		if (child->thread.regs->msr & MSR_FP)
-			giveup_fpu(child);
+		flush_fp_to_thread(child);
 
 		for (i = 0; i < 32; i++) {
 			ret = get_user(*reg, tmp);
diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
--- a/arch/ppc64/kernel/rtas.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc64/kernel/rtas.c	2004-06-23 19:04:25 -07:00
@@ -68,10 +68,11 @@
 void
 call_rtas_display_status(char c)
 {
-	struct rtas_args *args = &(get_paca()->xRtas);
+	struct rtas_args *args;
 	unsigned long s;
 
 	spin_lock_irqsave(&rtas.lock, s);
+	args = &(get_paca()->xRtas);
 
 	args->token = 10;
 	args->nargs = 1;
@@ -145,7 +146,7 @@
 	va_list list;
 	int i, logit = 0;
 	unsigned long s;
-	struct rtas_args *rtas_args = &(get_paca()->xRtas);
+	struct rtas_args *rtas_args;
 	long ret;
 
 	PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n");
@@ -158,6 +159,7 @@
 
 	/* Gotta do something different here, use global lock for now... */
 	spin_lock_irqsave(&rtas.lock, s);
+	rtas_args = &(get_paca()->xRtas);
 
 	rtas_args->token = token;
 	rtas_args->nargs = nargs;
diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
--- a/arch/ppc64/kernel/signal.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc64/kernel/signal.c	2004-06-23 19:04:25 -07:00
@@ -131,8 +131,7 @@
 #endif
 	long err = 0;
 
-	if (regs->msr & MSR_FP)
-		giveup_fpu(current);
+	flush_fp_to_thread(current);
 
 	/* Make sure signal doesn't get spurrious FP exceptions */
 	current->thread.fpscr = 0;
@@ -141,9 +140,8 @@
 	err |= __put_user(v_regs, &sc->v_regs);
 
 	/* save altivec registers */
-	if (current->thread.used_vr) {		
-		if (regs->msr & MSR_VEC)
-			giveup_altivec(current);
+	if (current->thread.used_vr) {
+		flush_altivec_to_thread(current);
 		/* Copy 33 vec registers (vr0..31 and vscr) to the stack */
 		err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128));
 		/* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg)
@@ -530,13 +528,13 @@
 		struct k_sigaction *ka = &current->sighand->action[signr-1];
 
 		/* Whee!  Actually deliver the signal.  */
-		if (regs->trap == 0x0C00)
+		if (TRAP(regs) == 0x0C00)
 			syscall_restart(regs, ka);
 		handle_signal(signr, ka, &info, oldset, regs);
 		return 1;
 	}
 
-	if (regs->trap == 0x0C00) {	/* System Call! */
+	if (TRAP(regs) == 0x0C00) {	/* System Call! */
 		if ((int)regs->result == -ERESTARTNOHAND ||
 		    (int)regs->result == -ERESTARTSYS ||
 		    (int)regs->result == -ERESTARTNOINTR) {
diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc64/kernel/signal32.c	2004-06-23 19:04:28 -07:00
@@ -130,11 +130,10 @@
 {
 	elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
 	int i, err = 0;
-	
-	/* Make sure floating point registers are stored in regs */ 
-	if (regs->msr & MSR_FP)
-		giveup_fpu(current);
-	
+
+	/* Make sure floating point registers are stored in regs */
+	flush_fp_to_thread(current);
+
 	/* save general and floating-point registers */
 	for (i = 0; i <= PT_RESULT; i ++)
 		err |= __put_user((unsigned int)gregs[i], &frame->mc_gregs[i]);
@@ -148,8 +147,7 @@
 #ifdef CONFIG_ALTIVEC
 	/* save altivec registers */
 	if (current->thread.used_vr) {
-		if (regs->msr & MSR_VEC)
-			giveup_altivec(current);
+		flush_altivec_to_thread(current);
 		if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
 				   ELF_NVRREG32 * sizeof(vector128)))
 			return 1;
@@ -934,7 +932,7 @@
 
 	ka = (signr == 0)? NULL: &current->sighand->action[signr-1];
 
-	if (regs->trap == 0x0C00		/* System Call! */
+	if (TRAP(regs) == 0x0C00		/* System Call! */
 	    && regs->ccr & 0x10000000		/* error signalled */
 	    && ((ret = regs->gpr[3]) == ERESTARTSYS
 		|| ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/kernel/sys_ppc32.c	2004-06-23 19:04:27 -07:00
@@ -617,12 +617,8 @@
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
-	if (regs->msr & MSR_FP)
-		giveup_fpu(current);
-#ifdef CONFIG_ALTIVEC
-	if (regs->msr & MSR_VEC)
-		giveup_altivec(current);
-#endif /* CONFIG_ALTIVEC */
+	flush_fp_to_thread(current);
+	flush_altivec_to_thread(current);
 
 	error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
 
diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c
--- a/arch/ppc64/kernel/syscalls.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/kernel/syscalls.c	2004-06-23 19:04:27 -07:00
@@ -237,5 +237,19 @@
 	return secs;
 }
 
+void do_show_syscall(unsigned long r3, unsigned long r4, unsigned long r5,
+		     unsigned long r6, unsigned long r7, unsigned long r8,
+		     struct pt_regs *regs)
+{
+	printk("syscall %ld(%lx, %lx, %lx, %lx, %lx, %lx) regs=%p current=%p"
+	       " cpu=%d\n", regs->gpr[0], r3, r4, r5, r6, r7, r8, regs,
+	       current, smp_processor_id());
+}
+
+void do_show_syscall_exit(unsigned long r3)
+{
+	printk(" -> %lx, current=%p cpu=%d\n", r3, current, smp_processor_id());
+}
+
 /* Only exists on P-series. */
 cond_syscall(ppc_rtas);
diff -Nru a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
--- a/arch/ppc64/kernel/sysfs.c	2004-06-23 19:04:25 -07:00
+++ b/arch/ppc64/kernel/sysfs.c	2004-06-23 19:04:25 -07:00
@@ -325,6 +325,16 @@
 #ifdef CONFIG_NUMA
 		parent = &node_devices[cpu_to_node(cpu)];
 #endif
+		/*
+		 * For now, we just see if the system supports making
+		 * the RTAS calls for CPU hotplug.  But, there may be a
+		 * more comprehensive way to do this for an individual
+		 * CPU.  For instance, the boot cpu might never be valid
+		 * for hotplugging.
+		 */
+		if (systemcfg->platform != PLATFORM_PSERIES_LPAR)
+			c->no_control = 1;
+
 		register_cpu(c, cpu, parent);
 
 		register_cpu_pmc(&c->sysdev);
diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
--- a/arch/ppc64/kernel/traps.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/kernel/traps.c	2004-06-23 19:04:27 -07:00
@@ -308,8 +308,7 @@
 	siginfo_t info;
 	unsigned long fpscr;
 
-	if (regs->msr & MSR_FP)
-		giveup_fpu(current);
+	flush_fp_to_thread(current);
 
 	fpscr = current->thread.fpscr;
 
@@ -442,8 +441,22 @@
 	die("Unrecoverable FP Unavailable Exception", regs, SIGABRT);
 }
 
-void KernelAltivecUnavailableException(struct pt_regs *regs)
+void AltivecUnavailableException(struct pt_regs *regs)
 {
+#ifndef CONFIG_ALTIVEC
+	if (user_mode(regs)) {
+		/* A user program has executed an altivec instruction,
+		   but this kernel doesn't support altivec. */
+		siginfo_t info;
+
+		memset(&info, 0, sizeof(info));
+		info.si_signo = SIGILL;
+		info.si_code = ILL_ILLOPC;
+		info.si_addr = (void *) regs->nip;
+		_exception(SIGILL, &info, regs);
+		return;
+	}
+#endif
 	printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
 			  "%lx at %lx\n", regs->trap, regs->nip);
 	die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
@@ -531,10 +544,39 @@
 void
 AltivecAssistException(struct pt_regs *regs)
 {
-	if (regs->msr & MSR_VEC)
-		giveup_altivec(current);
-	/* XXX quick hack for now: set the non-Java bit in the VSCR */
-	current->thread.vscr.u[3] |= 0x10000;
+	int err;
+	siginfo_t info;
+
+	if (!user_mode(regs)) {
+		printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode"
+		       " at %lx\n", regs->nip);
+		die("Kernel VMX/Altivec assist exception", regs, SIGILL);
+	}
+
+	flush_altivec_to_thread(current);
+
+	err = emulate_altivec(regs);
+	if (err == 0) {
+		regs->nip += 4;		/* skip emulated instruction */
+		emulate_single_step(regs);
+		return;
+	}
+
+	if (err == -EFAULT) {
+		/* got an error reading the instruction */
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_code = SEGV_MAPERR;
+		info.si_addr = (void *) regs->nip;
+		force_sig_info(SIGSEGV, &info, current);
+	} else {
+		/* didn't recognize the instruction */
+		/* XXX quick hack for now: set the non-Java bit in the VSCR */
+		if (printk_ratelimit())
+			printk(KERN_ERR "Unrecognized altivec instruction "
+			       "in %s at %lx\n", current->comm, regs->nip);
+		current->thread.vscr.u[3] |= 0x10000;
+	}
 }
 #endif /* CONFIG_ALTIVEC */
 
diff -Nru a/arch/ppc64/kernel/vecemu.c b/arch/ppc64/kernel/vecemu.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vecemu.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,346 @@
+/*
+ * Routines to emulate some Altivec/VMX instructions, specifically
+ * those that can trap when given denormalized operands in Java mode.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+/* Functions in vector.S */
+extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b);
+extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b);
+extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
+extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
+extern void vrefp(vector128 *dst, vector128 *src);
+extern void vrsqrtefp(vector128 *dst, vector128 *src);
+extern void vexptep(vector128 *dst, vector128 *src);
+
+static unsigned int exp2s[8] = {
+	0x800000,
+	0x8b95c2,
+	0x9837f0,
+	0xa5fed7,
+	0xb504f3,
+	0xc5672a,
+	0xd744fd,
+	0xeac0c7
+};
+
+/*
+ * Computes an estimate of 2^x.  The `s' argument is the 32-bit
+ * single-precision floating-point representation of x.
+ */
+static unsigned int eexp2(unsigned int s)
+{
+	int exp, pwr;
+	unsigned int mant, frac;
+
+	/* extract exponent field from input */
+	exp = ((s >> 23) & 0xff) - 127;
+	if (exp > 7) {
+		/* check for NaN input */
+		if (exp == 128 && (s & 0x7fffff) != 0)
+			return s | 0x400000;	/* return QNaN */
+		/* 2^-big = 0, 2^+big = +Inf */
+		return (s & 0x80000000)? 0: 0x7f800000;	/* 0 or +Inf */
+	}
+	if (exp < -23)
+		return 0x3f800000;	/* 1.0 */
+
+	/* convert to fixed point integer in 9.23 representation */
+	pwr = (s & 0x7fffff) | 0x800000;
+	if (exp > 0)
+		pwr <<= exp;
+	else
+		pwr >>= -exp;
+	if (s & 0x80000000)
+		pwr = -pwr;
+
+	/* extract integer part, which becomes exponent part of result */
+	exp = (pwr >> 23) + 126;
+	if (exp >= 254)
+		return 0x7f800000;
+	if (exp < -23)
+		return 0;
+
+	/* table lookup on top 3 bits of fraction to get mantissa */
+	mant = exp2s[(pwr >> 20) & 7];
+
+	/* linear interpolation using remaining 20 bits of fraction */
+	asm("mulhwu %0,%1,%2" : "=r" (frac)
+	    : "r" (pwr << 12), "r" (0x172b83ff));
+	asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant));
+	mant += frac;
+
+	if (exp >= 0)
+		return mant + (exp << 23);
+
+	/* denormalized result */
+	exp = -exp;
+	mant += 1 << (exp - 1);
+	return mant >> exp;
+}
+
+/*
+ * Computes an estimate of log_2(x).  The `s' argument is the 32-bit
+ * single-precision floating-point representation of x.
+ */
+static unsigned int elog2(unsigned int s)
+{
+	int exp, mant, lz, frac;
+
+	exp = s & 0x7f800000;
+	mant = s & 0x7fffff;
+	if (exp == 0x7f800000) {	/* Inf or NaN */
+		if (mant != 0)
+			s |= 0x400000;	/* turn NaN into QNaN */
+		return s;
+	}
+	if ((exp | mant) == 0)		/* +0 or -0 */
+		return 0xff800000;	/* return -Inf */
+
+	if (exp == 0) {
+		/* denormalized */
+		asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant));
+		mant <<= lz - 8;
+		exp = (-118 - lz) << 23;
+	} else {
+		mant |= 0x800000;
+		exp -= 127 << 23;
+	}
+
+	if (mant >= 0xb504f3) {				/* 2^0.5 * 2^23 */
+		exp |= 0x400000;			/* 0.5 * 2^23 */
+		asm("mulhwu %0,%1,%2" : "=r" (mant)
+		    : "r" (mant), "r" (0xb504f334));	/* 2^-0.5 * 2^32 */
+	}
+	if (mant >= 0x9837f0) {				/* 2^0.25 * 2^23 */
+		exp |= 0x200000;			/* 0.25 * 2^23 */
+		asm("mulhwu %0,%1,%2" : "=r" (mant)
+		    : "r" (mant), "r" (0xd744fccb));	/* 2^-0.25 * 2^32 */
+	}
+	if (mant >= 0x8b95c2) {				/* 2^0.125 * 2^23 */
+		exp |= 0x100000;			/* 0.125 * 2^23 */
+		asm("mulhwu %0,%1,%2" : "=r" (mant)
+		    : "r" (mant), "r" (0xeac0c6e8));	/* 2^-0.125 * 2^32 */
+	}
+	if (mant > 0x800000) {				/* 1.0 * 2^23 */
+		/* calculate (mant - 1) * 1.381097463 */
+		/* 1.381097463 == 0.125 / (2^0.125 - 1) */
+		asm("mulhwu %0,%1,%2" : "=r" (frac)
+		    : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a));
+		exp += frac;
+	}
+	s = exp & 0x80000000;
+	if (exp != 0) {
+		if (s)
+			exp = -exp;
+		asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp));
+		lz = 8 - lz;
+		if (lz > 0)
+			exp >>= lz;
+		else if (lz < 0)
+			exp <<= -lz;
+		s += ((lz + 126) << 23) + exp;
+	}
+	return s;
+}
+
+#define VSCR_SAT	1
+
+static int ctsxs(unsigned int x, int scale, unsigned int *vscrp)
+{
+	int exp, mant;
+
+	exp = (x >> 23) & 0xff;
+	mant = x & 0x7fffff;
+	if (exp == 255 && mant != 0)
+		return 0;		/* NaN -> 0 */
+	exp = exp - 127 + scale;
+	if (exp < 0)
+		return 0;		/* round towards zero */
+	if (exp >= 31) {
+		/* saturate, unless the result would be -2^31 */
+		if (x + (scale << 23) != 0xcf000000)
+			*vscrp |= VSCR_SAT;
+		return (x & 0x80000000)? 0x80000000: 0x7fffffff;
+	}
+	mant |= 0x800000;
+	mant = (mant << 7) >> (30 - exp);
+	return (x & 0x80000000)? -mant: mant;
+}
+
+static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp)
+{
+	int exp;
+	unsigned int mant;
+
+	exp = (x >> 23) & 0xff;
+	mant = x & 0x7fffff;
+	if (exp == 255 && mant != 0)
+		return 0;		/* NaN -> 0 */
+	exp = exp - 127 + scale;
+	if (exp < 0)
+		return 0;		/* round towards zero */
+	if (x & 0x80000000) {
+		/* negative => saturate to 0 */
+		*vscrp |= VSCR_SAT;
+		return 0;
+	}
+	if (exp >= 32) {
+		/* saturate */
+		*vscrp |= VSCR_SAT;
+		return 0xffffffff;
+	}
+	mant |= 0x800000;
+	mant = (mant << 8) >> (31 - exp);
+	return mant;
+}
+
+/* Round to floating integer, towards 0 */
+static unsigned int rfiz(unsigned int x)
+{
+	int exp;
+
+	exp = ((x >> 23) & 0xff) - 127;
+	if (exp == 128 && (x & 0x7fffff) != 0)
+		return x | 0x400000;	/* NaN -> make it a QNaN */
+	if (exp >= 23)
+		return x;		/* it's an integer already (or Inf) */
+	if (exp < 0)
+		return x & 0x80000000;	/* |x| < 1.0 rounds to 0 */
+	return x & ~(0x7fffff >> exp);
+}
+
+/* Round to floating integer, towards +/- Inf */
+static unsigned int rfii(unsigned int x)
+{
+	int exp, mask;
+
+	exp = ((x >> 23) & 0xff) - 127;
+	if (exp == 128 && (x & 0x7fffff) != 0)
+		return x | 0x400000;	/* NaN -> make it a QNaN */
+	if (exp >= 23)
+		return x;		/* it's an integer already (or Inf) */
+	if ((x & 0x7fffffff) == 0)
+		return x;		/* +/-0 -> +/-0 */
+	if (exp < 0)
+		/* 0 < |x| < 1.0 rounds to +/- 1.0 */
+		return (x & 0x80000000) | 0x3f800000;
+	mask = 0x7fffff >> exp;
+	/* mantissa overflows into exponent - that's OK,
+	   it can't overflow into the sign bit */
+	return (x + mask) & ~mask;
+}
+
+/* Round to floating integer, to nearest */
+static unsigned int rfin(unsigned int x)
+{
+	int exp, half;
+
+	exp = ((x >> 23) & 0xff) - 127;
+	if (exp == 128 && (x & 0x7fffff) != 0)
+		return x | 0x400000;	/* NaN -> make it a QNaN */
+	if (exp >= 23)
+		return x;		/* it's an integer already (or Inf) */
+	if (exp < -1)
+		return x & 0x80000000;	/* |x| < 0.5 -> +/-0 */
+	if (exp == -1)
+		/* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */
+		return (x & 0x80000000) | 0x3f800000;
+	half = 0x400000 >> exp;
+	/* add 0.5 to the magnitude and chop off the fraction bits */
+	return (x + half) & ~(0x7fffff >> exp);
+}
+
+int
+emulate_altivec(struct pt_regs *regs)
+{
+	unsigned int instr, i;
+	unsigned int va, vb, vc, vd;
+	vector128 *vrs;
+
+	if (get_user(instr, (unsigned int *) regs->nip))
+		return -EFAULT;
+	if ((instr >> 26) != 4)
+		return -EINVAL;		/* not an altivec instruction */
+	vd = (instr >> 21) & 0x1f;
+	va = (instr >> 16) & 0x1f;
+	vb = (instr >> 11) & 0x1f;
+	vc = (instr >> 6) & 0x1f;
+
+	vrs = current->thread.vr;
+	switch (instr & 0x3f) {
+	case 10:
+		switch (vc) {
+		case 0:	/* vaddfp */
+			vaddfp(&vrs[vd], &vrs[va], &vrs[vb]);
+			break;
+		case 1:	/* vsubfp */
+			vsubfp(&vrs[vd], &vrs[va], &vrs[vb]);
+			break;
+		case 4:	/* vrefp */
+			vrefp(&vrs[vd], &vrs[vb]);
+			break;
+		case 5:	/* vrsqrtefp */
+			vrsqrtefp(&vrs[vd], &vrs[vb]);
+			break;
+		case 6:	/* vexptefp */
+			for (i = 0; i < 4; ++i)
+				vrs[vd].u[i] = eexp2(vrs[vb].u[i]);
+			break;
+		case 7:	/* vlogefp */
+			for (i = 0; i < 4; ++i)
+				vrs[vd].u[i] = elog2(vrs[vb].u[i]);
+			break;
+		case 8:		/* vrfin */
+			for (i = 0; i < 4; ++i)
+				vrs[vd].u[i] = rfin(vrs[vb].u[i]);
+			break;
+		case 9:		/* vrfiz */
+			for (i = 0; i < 4; ++i)
+				vrs[vd].u[i] = rfiz(vrs[vb].u[i]);
+			break;
+		case 10:	/* vrfip */
+			for (i = 0; i < 4; ++i) {
+				u32 x = vrs[vb].u[i];
+				x = (x & 0x80000000)? rfiz(x): rfii(x);
+				vrs[vd].u[i] = x;
+			}
+			break;
+		case 11:	/* vrfim */
+			for (i = 0; i < 4; ++i) {
+				u32 x = vrs[vb].u[i];
+				x = (x & 0x80000000)? rfii(x): rfiz(x);
+				vrs[vd].u[i] = x;
+			}
+			break;
+		case 14:	/* vctuxs */
+			for (i = 0; i < 4; ++i)
+				vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va,
+						&current->thread.vscr.u[3]);
+			break;
+		case 15:	/* vctsxs */
+			for (i = 0; i < 4; ++i)
+				vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va,
+						&current->thread.vscr.u[3]);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case 46:	/* vmaddfp */
+		vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
+		break;
+	case 47:	/* vnmsubfp */
+		vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff -Nru a/arch/ppc64/kernel/vector.S b/arch/ppc64/kernel/vector.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vector.S	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,172 @@
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+/*
+ * The routines below are in assembler so we can closely control the
+ * usage of floating-point registers.  These routines must be called
+ * with preempt disabled.
+ */
+	.section ".toc","aw"
+fpzero:
+	.tc	FD_0_0[TC],0
+fpone:
+	.tc	FD_3ff00000_0[TC],0x3ff0000000000000	/* 1.0 */
+fphalf:
+	.tc	FD_3fe00000_0[TC],0x3fe0000000000000	/* 0.5 */
+
+	.text
+/*
+ * Internal routine to enable floating point and set FPSCR to 0.
+ * Don't call it from C; it doesn't use the normal calling convention.
+ */
+fpenable:
+	mfmsr	r10
+	ori	r11,r10,MSR_FP
+	mtmsr	r11
+	isync
+	stfd	fr31,-8(r1)
+	stfd	fr0,-16(r1)
+	stfd	fr1,-24(r1)
+	mffs	fr31
+	lfd	fr1,fpzero@toc(r2)
+	mtfsf	0xff,fr1
+	blr
+
+fpdisable:
+	mtlr	r12
+	mtfsf	0xff,fr31
+	lfd	fr1,-24(r1)
+	lfd	fr0,-16(r1)
+	lfd	fr31,-8(r1)
+	mtmsr	r10
+	isync
+	blr
+
+/*
+ * Vector add, floating point.
+ */
+_GLOBAL(vaddfp)
+	mflr	r12
+	bl	fpenable
+	li	r0,4
+	mtctr	r0
+	li	r6,0
+1:	lfsx	fr0,r4,r6
+	lfsx	fr1,r5,r6
+	fadds	fr0,fr0,fr1
+	stfsx	fr0,r3,r6
+	addi	r6,r6,4
+	bdnz	1b
+	b	fpdisable
+
+/*
+ * Vector subtract, floating point.
+ */
+_GLOBAL(vsubfp)
+	mflr	r12
+	bl	fpenable
+	li	r0,4
+	mtctr	r0
+	li	r6,0
+1:	lfsx	fr0,r4,r6
+	lfsx	fr1,r5,r6
+	fsubs	fr0,fr0,fr1
+	stfsx	fr0,r3,r6
+	addi	r6,r6,4
+	bdnz	1b
+	b	fpdisable
+
+/*
+ * Vector multiply and add, floating point.
+ */
+_GLOBAL(vmaddfp)
+	mflr	r12
+	bl	fpenable
+	stfd	fr2,-32(r1)
+	li	r0,4
+	mtctr	r0
+	li	r7,0
+1:	lfsx	fr0,r4,r7
+	lfsx	fr1,r5,r7
+	lfsx	fr2,r6,r7
+	fmadds	fr0,fr0,fr1,fr2
+	stfsx	fr0,r3,r7
+	addi	r7,r7,4
+	bdnz	1b
+	lfd	fr2,-32(r1)
+	b	fpdisable
+
+/*
+ * Vector negative multiply and subtract, floating point.
+ */
+_GLOBAL(vnmsubfp)
+	mflr	r12
+	bl	fpenable
+	stfd	fr2,-32(r1)
+	li	r0,4
+	mtctr	r0
+	li	r7,0
+1:	lfsx	fr0,r4,r7
+	lfsx	fr1,r5,r7
+	lfsx	fr2,r6,r7
+	fnmsubs	fr0,fr0,fr1,fr2
+	stfsx	fr0,r3,r7
+	addi	r7,r7,4
+	bdnz	1b
+	lfd	fr2,-32(r1)
+	b	fpdisable
+
+/*
+ * Vector reciprocal estimate.  We just compute 1.0/x.
+ * r3 -> destination, r4 -> source.
+ */
+_GLOBAL(vrefp)
+	mflr	r12
+	bl	fpenable
+	li	r0,4
+	lfd	fr1,fpone@toc(r2)
+	mtctr	r0
+	li	r6,0
+1:	lfsx	fr0,r4,r6
+	fdivs	fr0,fr1,fr0
+	stfsx	fr0,r3,r6
+	addi	r6,r6,4
+	bdnz	1b
+	b	fpdisable
+
+/*
+ * Vector reciprocal square-root estimate, floating point.
+ * We use the frsqrte instruction for the initial estimate followed
+ * by 2 iterations of Newton-Raphson to get sufficient accuracy.
+ * r3 -> destination, r4 -> source.
+ */
+_GLOBAL(vrsqrtefp)
+	mflr	r12
+	bl	fpenable
+	stfd	fr2,-32(r1)
+	stfd	fr3,-40(r1)
+	stfd	fr4,-48(r1)
+	stfd	fr5,-56(r1)
+	li	r0,4
+	lfd	fr4,fpone@toc(r2)
+	lfd	fr5,fphalf@toc(r2)
+	mtctr	r0
+	li	r6,0
+1:	lfsx	fr0,r4,r6
+	frsqrte	fr1,fr0		/* r = frsqrte(s) */
+	fmuls	fr3,fr1,fr0	/* r * s */
+	fmuls	fr2,fr1,fr5	/* r * 0.5 */
+	fnmsubs	fr3,fr1,fr3,fr4	/* 1 - s * r * r */
+	fmadds	fr1,fr2,fr3,fr1	/* r = r + 0.5 * r * (1 - s * r * r) */
+	fmuls	fr3,fr1,fr0	/* r * s */
+	fmuls	fr2,fr1,fr5	/* r * 0.5 */
+	fnmsubs	fr3,fr1,fr3,fr4	/* 1 - s * r * r */
+	fmadds	fr1,fr2,fr3,fr1	/* r = r + 0.5 * r * (1 - s * r * r) */
+	stfsx	fr1,r3,r6
+	addi	r6,r6,4
+	bdnz	1b
+	lfd	fr5,-56(r1)
+	lfd	fr4,-48(r1)
+	lfd	fr3,-40(r1)
+	lfd	fr2,-32(r1)
+	b	fpdisable
diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
--- a/arch/ppc64/mm/fault.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc64/mm/fault.c	2004-06-23 19:04:28 -07:00
@@ -80,36 +80,45 @@
  *  - DSISR for a non-SLB data access fault,
  *  - SRR1 & 0x08000000 for a non-SLB instruction access fault
  *  - 0 any SLB fault.
+ * The return value is 0 if the fault was handled, or the signal
+ * number if this is a kernel fault that can't be handled here.
  */
-void do_page_fault(struct pt_regs *regs, unsigned long address,
-		   unsigned long error_code)
+int do_page_fault(struct pt_regs *regs, unsigned long address,
+		  unsigned long error_code)
 {
 	struct vm_area_struct * vma;
 	struct mm_struct *mm = current->mm;
 	siginfo_t info;
 	unsigned long code = SEGV_MAPERR;
 	unsigned long is_write = error_code & 0x02000000;
+	unsigned long trap = TRAP(regs);
 
-	if (regs->trap == 0x300 || regs->trap == 0x380) {
+	if (trap == 0x300 || trap == 0x380) {
 		if (debugger_fault_handler(regs))
-			return;
+			return 0;
 	}
 
 	/* On a kernel SLB miss we can only check for a valid exception entry */
-	if (!user_mode(regs) && (regs->trap == 0x380)) {
-		bad_page_fault(regs, address, SIGSEGV);
-		return;
-	}
+	if (!user_mode(regs) && (trap == 0x380 || address >= TASK_SIZE))
+		return SIGSEGV;
 
 	if (error_code & 0x00400000) {
 		if (debugger_dabr_match(regs))
-			return;
+			return 0;
 	}
 
 	if (in_atomic() || mm == NULL) {
-		bad_page_fault(regs, address, SIGSEGV);
-		return;
+		if (!user_mode(regs))
+			return SIGSEGV;
+		/* in_atomic() in user mode is really bad,
+		   as is current->mm == NULL. */
+		printk(KERN_EMERG "Page fault in user mode with"
+		       "in_atomic() = %d mm = %p\n", in_atomic(), mm);
+		printk(KERN_EMERG "NIP = %lx  MSR = %lx\n",
+		       regs->nip, regs->msr);
+		die("Weird page fault", regs, SIGSEGV);
 	}
+
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
 	if (!vma)
@@ -195,7 +204,7 @@
 	}
 
 	up_read(&mm->mmap_sem);
-	return;
+	return 0;
 
 bad_area:
 	up_read(&mm->mmap_sem);
@@ -207,11 +216,10 @@
 		info.si_code = code;
 		info.si_addr = (void *) address;
 		force_sig_info(SIGSEGV, &info, current);
-		return;
+		return 0;
 	}
 
-	bad_page_fault(regs, address, SIGSEGV);
-	return;
+	return SIGSEGV;
 
 /*
  * We ran out of memory, or some other thing happened to us that made
@@ -227,18 +235,19 @@
 	printk("VM: killing process %s\n", current->comm);
 	if (user_mode(regs))
 		do_exit(SIGKILL);
-	bad_page_fault(regs, address, SIGKILL);
-	return;
+	return SIGKILL;
 
 do_sigbus:
 	up_read(&mm->mmap_sem);
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = BUS_ADRERR;
-	info.si_addr = (void *)address;
-	force_sig_info (SIGBUS, &info, current);
-	if (!user_mode(regs))
-		bad_page_fault(regs, address, SIGBUS);
+	if (user_mode(regs)) {
+		info.si_signo = SIGBUS;
+		info.si_errno = 0;
+		info.si_code = BUS_ADRERR;
+		info.si_addr = (void *)address;
+		force_sig_info(SIGBUS, &info, current);
+		return 0;
+	}
+	return SIGBUS;
 }
 
 /*
diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
--- a/arch/ppc64/mm/hash_utils.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/mm/hash_utils.c	2004-06-23 19:04:27 -07:00
@@ -251,6 +251,7 @@
 	struct mm_struct *mm;
 	pte_t *ptep;
 	int ret;
+	int cpu;
 	int user_region = 0;
 	int local = 0;
 	cpumask_t tmp;
@@ -302,7 +303,8 @@
 	if (pgdir == NULL)
 		return 1;
 
-	tmp = cpumask_of_cpu(smp_processor_id());
+	cpu = get_cpu();
+	tmp = cpumask_of_cpu(cpu);
 	if (user_region && cpus_equal(mm->cpu_vm_mask, tmp))
 		local = 1;
 
@@ -311,11 +313,13 @@
 		ret = hash_huge_page(mm, access, ea, vsid, local);
 	else {
 		ptep = find_linux_pte(pgdir, ea);
-		if (ptep == NULL)
+		if (ptep == NULL) {
+			put_cpu();
 			return 1;
+		}
 		ret = __hash_page(ea, access, vsid, ptep, trap, local);
 	}
-
+	put_cpu();
 
 	return ret;
 }
diff -Nru a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
--- a/arch/ppc64/mm/hugetlbpage.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/mm/hugetlbpage.c	2004-06-23 19:04:27 -07:00
@@ -375,6 +375,7 @@
 	unsigned long addr;
 	hugepte_t *ptep;
 	struct page *page;
+	int cpu;
 	int local = 0;
 	cpumask_t tmp;
 
@@ -383,7 +384,8 @@
 	BUG_ON((end % HPAGE_SIZE) != 0);
 
 	/* XXX are there races with checking cpu_vm_mask? - Anton */
-	tmp = cpumask_of_cpu(smp_processor_id());
+	cpu = get_cpu();
+	tmp = cpumask_of_cpu(cpu);
 	if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp))
 		local = 1;
 
@@ -406,6 +408,7 @@
 
 		put_page(page);
 	}
+	put_cpu();
 
 	mm->rss -= (end - start) >> PAGE_SHIFT;
 }
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/mm/init.c	2004-06-23 19:04:27 -07:00
@@ -764,6 +764,7 @@
 	void *pgdir;
 	pte_t *ptep;
 	int local = 0;
+	int cpu;
 	cpumask_t tmp;
 
 	/* handle i-cache coherency */
@@ -794,12 +795,14 @@
 
 	vsid = get_vsid(vma->vm_mm->context.id, ea);
 
-	tmp = cpumask_of_cpu(smp_processor_id());
+	cpu = get_cpu();
+	tmp = cpumask_of_cpu(cpu);
 	if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp))
 		local = 1;
 
 	__hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep,
 		    0x300, local);
+	put_cpu();
 }
 
 void * reserve_phb_iospace(unsigned long size)
diff -Nru a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c
--- a/arch/ppc64/mm/tlb.c	2004-06-23 19:04:27 -07:00
+++ b/arch/ppc64/mm/tlb.c	2004-06-23 19:04:27 -07:00
@@ -41,6 +41,33 @@
 DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
 unsigned long pte_freelist_forced_free;
 
+void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage)
+{
+	/* This is safe as we are holding page_table_lock */
+        cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
+	struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
+
+	if (atomic_read(&tlb->mm->mm_users) < 2 ||
+	    cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
+		pte_free(ptepage);
+		return;
+	}
+
+	if (*batchp == NULL) {
+		*batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);
+		if (*batchp == NULL) {
+			pte_free_now(ptepage);
+			return;
+		}
+		(*batchp)->index = 0;
+	}
+	(*batchp)->pages[(*batchp)->index++] = ptepage;
+	if ((*batchp)->index == PTE_FREELIST_SIZE) {
+		pte_free_submit(*batchp);
+		*batchp = NULL;
+	}
+}
+
 /*
  * Update the MMU hash table to correspond with a change to
  * a Linux PTE.  If wrprot is true, it is permissible to
@@ -91,12 +118,15 @@
 void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
 {
 	int i;
-	cpumask_t tmp = cpumask_of_cpu(smp_processor_id());
+	int cpu;
+	cpumask_t tmp;
 	int local = 0;
 
 	BUG_ON(in_interrupt());
 
+	cpu = get_cpu();
 	i = batch->index;
+	tmp = cpumask_of_cpu(cpu);
 	if (cpus_equal(batch->mm->cpu_vm_mask, tmp))
 		local = 1;
 
@@ -106,6 +136,7 @@
 	else
 		flush_hash_range(batch->context, i, local);
 	batch->index = 0;
+	put_cpu();
 }
 
 #ifdef CONFIG_SMP
diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
--- a/arch/ppc64/xmon/xmon.c	2004-06-23 19:04:28 -07:00
+++ b/arch/ppc64/xmon/xmon.c	2004-06-23 19:04:28 -07:00
@@ -44,9 +44,6 @@
 static int xmon_gate;
 #endif /* CONFIG_SMP */
 
-#define TRAP(regs)	((regs)->trap)
-#define FULL_REGS(regs)	1
-
 static unsigned long in_xmon = 0;
 
 static unsigned long adrs;
diff -Nru a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c
--- a/arch/s390/kernel/init_task.c	2004-06-23 19:04:27 -07:00
+++ b/arch/s390/kernel/init_task.c	2004-06-23 19:04:27 -07:00
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init_task.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
--- a/arch/s390/kernel/s390_ksyms.c	2004-06-23 19:04:27 -07:00
+++ b/arch/s390/kernel/s390_ksyms.c	2004-06-23 19:04:27 -07:00
@@ -76,4 +76,3 @@
 EXPORT_SYMBOL_NOVERS(do_call_softirq);
 EXPORT_SYMBOL(sys_wait4);
 EXPORT_SYMBOL(cpcmd);
-EXPORT_SYMBOL(sys_ioctl);
diff -Nru a/arch/sh/kernel/init_task.c b/arch/sh/kernel/init_task.c
--- a/arch/sh/kernel/init_task.c	2004-06-23 19:04:25 -07:00
+++ b/arch/sh/kernel/init_task.c	2004-06-23 19:04:25 -07:00
@@ -2,6 +2,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init_task.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c
--- a/arch/sparc/kernel/init_task.c	2004-06-23 19:04:27 -07:00
+++ b/arch/sparc/kernel/init_task.c	2004-06-23 19:04:27 -07:00
@@ -2,6 +2,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init_task.h>
+#include <linux/mqueue.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
--- a/arch/sparc64/kernel/entry.S	2004-06-23 19:04:24 -07:00
+++ b/arch/sparc64/kernel/entry.S	2004-06-23 19:04:24 -07:00
@@ -1751,42 +1751,44 @@
 	ldx		[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
 	sra		%o0, 0, %o0
 	mov		%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
-	cmp		%o0, -ENOIOCTLCMD
 	sllx		%g2, 32, %g2
+
+	/* Check if force_successful_syscall_return()
+	 * was invoked.
+	 */
+	ldx		[%curptr + TI_FLAGS], %l0
+	andcc		%l0, _TIF_SYSCALL_SUCCESS, %g0
+	be,pt		%icc, 1f
+	 andn		%l0, _TIF_SYSCALL_SUCCESS, %l0
+	ba,pt		%xcc, 80f
+	 stx		%l0, [%curptr + TI_FLAGS]
+
+1:
+	cmp		%o0, -ENOIOCTLCMD
 	bgeu,pn		%xcc, 1f
 	 andcc		%l0, _TIF_SYSCALL_TRACE, %l6	
 80:
-	andn		%g3, %g2, %g3		/* System call success, clear Carry condition code. */
+	/* System call success, clear Carry condition code. */
+	andn		%g3, %g2, %g3
 	stx		%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]	
 	bne,pn		%icc, linux_syscall_trace2
-	 add		%l1, 0x4, %l2				         ! npc = npc+4
+	 add		%l1, 0x4, %l2			! npc = npc+4
 	stx		%l1, [%sp + PTREGS_OFF + PT_V9_TPC]
 	ba,pt		%xcc, rtrap_clr_l6
 	 stx		%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
 
 1:
-	/* Really a failure?  Check if force_successful_syscall_return()
-	 * was invoked.
-	 */
-	ldx		[%curptr + TI_FLAGS], %l0		! Load
-	andcc		%l0, _TIF_SYSCALL_SUCCESS, %g0
-	be,pt		%icc, 1f
-	 andcc		%l0, _TIF_SYSCALL_TRACE, %l6	
-	andn		%l0, _TIF_SYSCALL_SUCCESS, %l0
-	ba,pt		%xcc, 80b
-	 stx		%l0, [%curptr + TI_FLAGS]
-
 	/* System call failure, set Carry condition code.
 	 * Also, get abs(errno) to return to the process.
 	 */
-1:
+	andcc		%l0, _TIF_SYSCALL_TRACE, %l6	
 	sub		%g0, %o0, %o0
 	or		%g3, %g2, %g3
 	stx		%o0, [%sp + PTREGS_OFF + PT_V9_I0]
 	mov		1, %l6
 	stx		%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
 	bne,pn		%icc, linux_syscall_trace2
-	 add		%l1, 0x4, %l2				         !npc = npc+4
+	 add		%l1, 0x4, %l2			! npc = npc+4
 	stx		%l1, [%sp + PTREGS_OFF + PT_V9_TPC]
 
 	b,pt		%xcc, rtrap
diff -Nru a/arch/sparc64/kernel/init_task.c b/arch/sparc64/kernel/init_task.c
--- a/arch/sparc64/kernel/init_task.c	2004-06-23 19:04:29 -07:00
+++ b/arch/sparc64/kernel/init_task.c	2004-06-23 19:04:29 -07:00
@@ -2,6 +2,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init_task.h>
+#include <linux/mqueue.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
--- a/arch/sparc64/kernel/sparc64_ksyms.c	2004-06-23 19:04:28 -07:00
+++ b/arch/sparc64/kernel/sparc64_ksyms.c	2004-06-23 19:04:28 -07:00
@@ -327,7 +327,6 @@
 EXPORT_SYMBOL(sys_getgid);
 EXPORT_SYMBOL(svr4_getcontext);
 EXPORT_SYMBOL(svr4_setcontext);
-EXPORT_SYMBOL(sys_ioctl);
 EXPORT_SYMBOL(compat_sys_ioctl);
 EXPORT_SYMBOL(sparc32_open);
 EXPORT_SYMBOL(sys_close);
diff -Nru a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
--- a/arch/um/kernel/init_task.c	2004-06-23 19:04:29 -07:00
+++ b/arch/um/kernel/init_task.c	2004-06-23 19:04:29 -07:00
@@ -9,6 +9,7 @@
 #include "linux/sched.h"
 #include "linux/init_task.h"
 #include "linux/version.h"
+#include "linux/mqueue.h"
 #include "asm/uaccess.h"
 #include "asm/pgtable.h"
 #include "user_util.h"
diff -Nru a/arch/v850/kernel/init_task.c b/arch/v850/kernel/init_task.c
--- a/arch/v850/kernel/init_task.c	2004-06-23 19:04:25 -07:00
+++ b/arch/v850/kernel/init_task.c	2004-06-23 19:04:25 -07:00
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile
--- a/arch/x86_64/Makefile	2004-06-23 19:04:28 -07:00
+++ b/arch/x86_64/Makefile	2004-06-23 19:04:28 -07:00
@@ -37,6 +37,8 @@
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux := -e stext
 
+CHECK           := $(CHECK) -D__x86_64__=1
+
 cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,)
 cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=nocona,)
 CFLAGS += $(cflags-y)
diff -Nru a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
--- a/arch/x86_64/kernel/e820.c	2004-06-23 19:04:26 -07:00
+++ b/arch/x86_64/kernel/e820.c	2004-06-23 19:04:26 -07:00
@@ -34,7 +34,7 @@
  */
 unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT;  
 
-extern struct resource code_resource, data_resource, vram_resource;
+extern struct resource code_resource, data_resource;
 
 /* Check for some hardcoded bad areas that early boot is not allowed to touch */ 
 static inline int bad_addr(unsigned long *addrp, unsigned long size)
diff -Nru a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c
--- a/arch/x86_64/kernel/init_task.c	2004-06-23 19:04:27 -07:00
+++ b/arch/x86_64/kernel/init_task.c	2004-06-23 19:04:27 -07:00
@@ -4,6 +4,7 @@
 #include <linux/init.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
+#include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
--- a/arch/x86_64/kernel/mpparse.c	2004-06-23 19:04:26 -07:00
+++ b/arch/x86_64/kernel/mpparse.c	2004-06-23 19:04:26 -07:00
@@ -716,7 +716,7 @@
 } mp_ioapic_routing[MAX_IO_APICS];
 
 
-static int __init mp_find_ioapic (
+static int mp_find_ioapic (
 	int			gsi)
 {
 	int			i = 0;
@@ -859,15 +859,22 @@
 	for (i = 0; i < 16; i++) {
 		int idx;
 
-		for (idx = 0; idx < mp_irq_entries; idx++)
-			if (mp_irqs[idx].mpc_srcbus == MP_ISA_BUS &&
-				(mp_irqs[idx].mpc_srcbusirq == i ||
-				mp_irqs[idx].mpc_dstirq == i))
-					break;
+		for (idx = 0; idx < mp_irq_entries; idx++) {
+			struct mpc_config_intsrc *irq = mp_irqs + idx;
+
+			/* Do we already have a mapping for this ISA IRQ? */
+			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+				break;
+
+			/* Do we already have a mapping for this IOAPIC pin */
+			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+				(irq->mpc_dstirq == i))
+				break;
+		}
 
 		if (idx != mp_irq_entries) {
 			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
-			continue;			 /* IRQ already used */
+			continue;			/* IRQ already used */
 		}
 
 		intsrc.mpc_irqtype = mp_INT;
@@ -888,91 +895,54 @@
 	return;
 }
 
-
-extern FADT_DESCRIPTOR acpi_fadt;
-
-#ifdef CONFIG_ACPI_PCI
-
-void __init mp_parse_prt (void)
+void mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
 {
-	struct list_head	*node = NULL;
-	struct acpi_prt_entry	*entry = NULL;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
-	int			gsi = 0;
 	int			idx, bit = 0;
-	int			edge_level = 0;
-	int			active_high_low = 0;
 
-	/*
-	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
-	 * routing for all static (IOAPIC-direct) entries.
-	 */
-	list_for_each(node, &acpi_prt.entries) {
-		entry = list_entry(node, struct acpi_prt_entry, node);
+	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+		return;
 
-		/* Need to get gsi for dynamic entry */
-		if (entry->link.handle) {
-			gsi = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
-			if (!gsi)
-				continue;
-		} else {
-			/* Hardwired GSI. Assume PCI standard settings */
-			gsi = entry->link.index;
-			edge_level = 1;
-			active_high_low = 1;
-		}
+#ifdef CONFIG_ACPI_BUS
+	/* Don't set up the ACPI SCI because it's already set up */
+	if (acpi_fadt.sci_int == gsi)
+		return;
+#endif
 
-		/* Don't set up the ACPI SCI because it's already set up */
-		if (acpi_fadt.sci_int == gsi) {
-			/* we still need to set up the entry's irq */
-			acpi_gsi_to_irq(gsi, &entry->irq);
-			continue;
-		}
+	ioapic = mp_find_ioapic(gsi);
+	if (ioapic < 0) {
+		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+		return;
+	}
 
-		ioapic = mp_find_ioapic(gsi);
-		if (ioapic < 0)
-			continue;
-		ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
-
-		/* 
-		 * Avoid pin reprogramming.  PRTs typically include entries  
-		 * with redundant pin->gsi mappings (but unique PCI devices);
-		 * we only only program the IOAPIC on the first.
-		 */
-		bit = ioapic_pin % 32;
-		idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
-		if (idx > 3) {
-			printk(KERN_ERR "Invalid reference to IOAPIC pin "
-				"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
-				ioapic_pin);
-			continue;
-		}
-		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
-				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-			acpi_gsi_to_irq(gsi, &entry->irq);
-			continue;
-		}
+	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
 
-		mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
-		if (!io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, edge_level, active_high_low)) {
-			acpi_gsi_to_irq(gsi, &entry->irq);
- 		}
-		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n",
-			entry->id.segment, entry->id.bus,
-			entry->id.device, ('A' + entry->pin), 
-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
-			entry->irq);
+	/* 
+	 * Avoid pin reprogramming.  PRTs typically include entries  
+	 * with redundant pin->gsi mappings (but unique PCI devices);
+	 * we only program the IOAPIC on the first.
+	 */
+	bit = ioapic_pin % 32;
+	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+	if (idx > 3) {
+		printk(KERN_ERR "Invalid reference to IOAPIC pin "
+			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
+			ioapic_pin);
+		return;
+	}
+	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+		return;
 	}
-	
-	print_IO_APIC();
 
-	return;
-}
+	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 
-#endif /*CONFIG_ACPI_PCI*/
+	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+		edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
+		active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
+}
 
 #endif /*CONFIG_X86_IO_APIC*/
-
 #endif /*CONFIG_ACPI_BOOT*/
diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
--- a/arch/x86_64/kernel/setup.c	2004-06-23 19:04:25 -07:00
+++ b/arch/x86_64/kernel/setup.c	2004-06-23 19:04:25 -07:00
@@ -116,9 +116,10 @@
 #define STANDARD_IO_RESOURCES \
 	(sizeof standard_io_resources / sizeof standard_io_resources[0])
 
-struct resource code_resource = { "Kernel code", 0x100000, 0, IORESOURCE_MEM };
-struct resource data_resource = { "Kernel data", 0, 0, IORESOURCE_MEM };
-struct resource vram_resource = { "Video RAM area", 0xa0000, 0xbffff, IORESOURCE_BUSY | IORESOURCE_MEM };
+#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)
+
+struct resource data_resource = { "Kernel data", 0, 0, IORESOURCE_RAM };
+struct resource code_resource = { "Kernel code", 0, 0, IORESOURCE_RAM };
 
 #define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)
 
@@ -138,10 +139,11 @@
 	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
 
 static struct resource video_rom_resource = { "Video ROM", 0xc0000, 0xc7fff, IORESOURCE_ROM };
+static struct resource video_ram_resource = { "Video RAM area", 0xa0000, 0xbffff, IORESOURCE_RAM };
 
 #define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
 
-static int __init checksum(unsigned char *rom, unsigned long length)
+static int __init romchecksum(unsigned char *rom, unsigned long length)
 {
 	unsigned char *p, sum = 0;
 
@@ -169,7 +171,7 @@
 		length = rom[2] * 512;
 
 		/* if checksum okay, trust length byte */
-		if (length && checksum(rom, length))
+		if (length && romchecksum(rom, length))
 			video_rom_resource.end = start + length - 1;
 
 		request_resource(&iomem_resource, &video_rom_resource);
@@ -188,7 +190,7 @@
 	rom = isa_bus_to_virt(extension_rom_resource.start);
 	if (romsignature(rom)) {
 		length = extension_rom_resource.end - extension_rom_resource.start + 1;
-		if (checksum(rom, length)) {
+		if (romchecksum(rom, length)) {
 			request_resource(&iomem_resource, &extension_rom_resource);
 			upper = extension_rom_resource.start;
 		}
@@ -204,7 +206,7 @@
 		length = rom[2] * 512;
 
 		/* but accept any length that fits if checksum okay */
-		if (!length || start + length > upper || !checksum(rom, length))
+		if (!length || start + length > upper || !romchecksum(rom, length))
 			continue;
 
 		adapter_rom_resources[i].start = start;
@@ -555,13 +557,13 @@
 	probe_roms();
 	e820_reserve_resources(); 
 
-	request_resource(&iomem_resource, &vram_resource);
+	request_resource(&iomem_resource, &video_ram_resource);
 
 	{
 	unsigned i;
 	/* request I/O space for devices used on all i[345]86 PCs */
 	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
-		request_resource(&ioport_resource, standard_io_resources+i);
+		request_resource(&ioport_resource, &standard_io_resources[i]);
 	}
 
 	/* Will likely break when you have unassigned resources with more
diff -Nru a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
--- a/arch/x86_64/kernel/x8664_ksyms.c	2004-06-23 19:04:25 -07:00
+++ b/arch/x86_64/kernel/x8664_ksyms.c	2004-06-23 19:04:25 -07:00
@@ -218,4 +218,3 @@
 EXPORT_SYMBOL_GPL(flush_tlb_all);
 #endif
 
-EXPORT_SYMBOL(sys_ioctl);
diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
--- a/arch/x86_64/mm/numa.c	2004-06-23 19:04:28 -07:00
+++ b/arch/x86_64/mm/numa.c	2004-06-23 19:04:28 -07:00
@@ -182,7 +182,7 @@
 	numnodes = 1;
 	for (i = 0; i < NR_CPUS; i++)
 		cpu_to_node[i] = 0;
-	node_to_cpumask[0] = 1;
+	node_to_cpumask[0] = cpumask_of_cpu(0);
 	setup_node_bootmem(0, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
 }
 
diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
--- a/drivers/acpi/Kconfig	2004-06-23 19:04:29 -07:00
+++ b/drivers/acpi/Kconfig	2004-06-23 19:04:29 -07:00
@@ -267,7 +267,7 @@
 	  (TSC) timing source.
 
 	  So, if you see messages like 'Losing too many ticks!' in the
-	  kernel logs, and/or you are using a this on a notebook which
+	  kernel logs, and/or you are using this on a notebook which
 	  does not yet have an HPET, you should say "Y" here.
 
 endmenu
diff -Nru a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
--- a/drivers/acpi/pci_irq.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/acpi/pci_irq.c	2004-06-23 19:04:26 -07:00
@@ -35,12 +35,6 @@
 #include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
-#ifdef CONFIG_X86_IO_APIC
-#include <asm/mpspec.h>
-#endif
-#ifdef CONFIG_IOSAPIC
-# include <asm/iosapic.h>
-#endif
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -50,10 +44,6 @@
 
 struct acpi_prt_list		acpi_prt;
 
-#ifdef CONFIG_X86
-extern void eisa_set_level_irq(unsigned int irq);
-#endif
-
 
 /* --------------------------------------------------------------------------
                          PCI IRQ Routing Table (PRT) Support
@@ -237,12 +227,18 @@
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
 
-int
-acpi_pci_irq_lookup (struct pci_bus *bus, int device, int pin)
+static int
+acpi_pci_irq_lookup (
+	struct pci_bus		*bus,
+	int			device,
+	int			pin,
+	int			*edge_level,
+	int			*active_high_low)
 {
 	struct acpi_prt_entry	*entry = NULL;
 	int segment = pci_domain_nr(bus);
 	int bus_nr = bus->number;
+	int irq;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
 
@@ -255,28 +251,30 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n"));
 		return_VALUE(0);
 	}
-
-	if (!entry->irq && entry->link.handle) {
-		entry->irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, NULL, NULL);
-		if (!entry->irq) {
+	
+	if (entry->link.handle) {
+		irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low);
+		if (!irq) {
 			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
 			return_VALUE(0);
 		}
-	}
-	else if (!entry->irq) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid static routing entry (IRQ 0)\n"));
-		return_VALUE(0);
+	} else {
+		irq = entry->link.index;
+		*edge_level = ACPI_LEVEL_SENSITIVE;
+		*active_high_low = ACPI_ACTIVE_LOW;
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", entry->irq));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
 
-	return_VALUE(entry->irq);
+	return_VALUE(irq);
 }
 
 static int
 acpi_pci_irq_derive (
 	struct pci_dev		*dev,
-	int			pin)
+	int			pin,
+	int			*edge_level,
+	int			*active_high_low)
 {
 	struct pci_dev		*bridge = dev;
 	int			irq = 0;
@@ -308,8 +306,8 @@
 			pin = bridge_pin;
 		}
 
-		irq = acpi_pci_irq_lookup(bridge->bus,
-				PCI_SLOT(bridge->devfn), pin);
+		irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
+			pin, edge_level, active_high_low);
 	}
 
 	if (!irq) {
@@ -330,6 +328,8 @@
 {
 	int			irq = 0;
 	u8			pin = 0;
+	int			edge_level = ACPI_LEVEL_SENSITIVE;
+	int			active_high_low = ACPI_ACTIVE_LOW;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
 
@@ -352,21 +352,22 @@
 	 * First we check the PCI IRQ routing table (PRT) for an IRQ.  PRT
 	 * values override any BIOS-assigned IRQs set during boot.
 	 */
- 	irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin);
+ 	irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, &edge_level, &active_high_low);
 
 	/*
 	 * If no PRT entry was found, we'll try to derive an IRQ from the
 	 * device's parent bridge.
 	 */
 	if (!irq)
- 		irq = acpi_pci_irq_derive(dev, pin);
+ 		irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low);
  
 	/*
 	 * No IRQ known to the ACPI subsystem - maybe the BIOS / 
 	 * driver reported one, then use it. Exit in any case.
 	 */
 	if (!irq) {
-		printk(KERN_WARNING PREFIX "No IRQ known for interrupt pin %c of device %s", ('A' + pin), pci_name(dev));
+		printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI",
+			pci_name(dev), ('A' + pin));
 		/* Interrupt Line values above 0xF are forbidden */
 		if (dev->irq && (dev->irq <= 0xF)) {
 			printk(" - using IRQ %d\n", dev->irq);
@@ -378,62 +379,14 @@
 		}
  	}
 
-	dev->irq = irq;
+	dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s using IRQ %d\n", pci_name(dev), dev->irq));
-
-	/* 
-	 * Make sure all (legacy) PCI IRQs are set as level-triggered.
-	 */
-#ifdef CONFIG_X86
-	{
-		static u16 irq_mask;
-		if ((dev->irq < 16) &&  !((1 << dev->irq) & irq_mask)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Setting IRQ %d as level-triggered\n", dev->irq));
-			irq_mask |= (1 << dev->irq);
-			eisa_set_level_irq(dev->irq);
-		}
-	}
-#endif
-#ifdef CONFIG_IOSAPIC
-	if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC)
-		iosapic_enable_intr(dev->irq);
-#endif
+	printk(KERN_INFO PREFIX "PCI interrupt %s[%c] -> GSI %u "
+		"(%s, %s) -> IRQ %d\n",
+		pci_name(dev), 'A' + pin, irq,
+		(edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
+		(active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high",
+		dev->irq);
 
 	return_VALUE(dev->irq);
-}
-
-
-int __init
-acpi_pci_irq_init (void)
-{
-	struct pci_dev          *dev = NULL;
-
-	ACPI_FUNCTION_TRACE("acpi_pci_irq_init");
-
-	if (!acpi_prt.count) {
-		printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ "
-			"routing entries\n");
-		return_VALUE(-ENODEV);
-	}
-
-	/* Make sure all link devices have a valid IRQ. */
-	if (acpi_pci_link_check()) {
-		return_VALUE(-ENODEV);
-	}
-
-#ifdef CONFIG_X86_IO_APIC
-	/* Program IOAPICs using data from PRT entries. */
-	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		mp_parse_prt();
-#endif
-#ifdef CONFIG_IOSAPIC
-	if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC)
-		iosapic_parse_prt();
-#endif
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
-		acpi_pci_irq_enable(dev);
-
-	return_VALUE(0);
 }
diff -Nru a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
--- a/drivers/acpi/pci_link.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/acpi/pci_link.c	2004-06-23 19:04:25 -07:00
@@ -308,31 +308,12 @@
 		struct acpi_resource	end;
 	}                       resource;
 	struct acpi_buffer	buffer = {sizeof(resource)+1, &resource};
-	int			i = 0;
-	int			valid = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_link_set");
 
 	if (!link || !irq)
 		return_VALUE(-EINVAL);
 
-	/* We don't check irqs the first time around */
-	if (link->irq.setonboot) {
-		/* See if we're already at the target IRQ. */
-		if (irq == link->irq.active)
-			return_VALUE(0);
-
-		/* Make sure the target IRQ in the list of possible IRQs. */
-		for (i=0; i<link->irq.possible_count; i++) {
-			if (irq == link->irq.possible[i])
-				valid = 1;
-		}
-		if (!valid) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Target IRQ %d invalid\n", irq));
-			return_VALUE(-EINVAL);
-		}
-	}
-
 	memset(&resource, 0, sizeof(resource));
 
 	switch(link->irq.resource_type) {
@@ -487,13 +468,13 @@
 };
 
 int
-acpi_pci_link_check (void)
+acpi_irq_penalty_init(void)
 {
 	struct list_head	*node = NULL;
 	struct acpi_pci_link    *link = NULL;
 	int			i = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_pci_link_check");
+	ACPI_FUNCTION_TRACE("acpi_irq_penalty_init");
 
 	/*
 	 * Update penalties to facilitate IRQ balancing.
@@ -703,6 +684,9 @@
 	acpi_link.count++;
 
 end:
+	/* disable all links -- to be activated on use */
+	acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
+
 	if (result)
 		kfree(link);
 
diff -Nru a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
--- a/drivers/acpi/pci_root.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/acpi/pci_root.c	2004-06-23 19:04:26 -07:00
@@ -113,6 +113,40 @@
 	}
 }
 
+static acpi_status
+get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data)
+{
+	int *busnr = (int *)data;
+	struct acpi_resource_address64 address;
+
+	if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
+	    resource->id != ACPI_RSTYPE_ADDRESS32 &&
+	    resource->id != ACPI_RSTYPE_ADDRESS64)
+		return AE_OK;
+
+	acpi_resource_to_address64(resource, &address);
+	if ((address.address_length > 0) && 
+	   (address.resource_type == ACPI_BUS_NUMBER_RANGE))
+		*busnr = address.min_address_range;
+
+	return AE_OK;
+}
+
+static acpi_status 
+try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
+{
+	acpi_status status;
+
+	*busnum = -1;
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS, get_root_bridge_busnr_callback, busnum);
+	if (ACPI_FAILURE(status))
+		return status;
+	/* Check if we really get a bus number from _CRS */
+	if (*busnum == -1)
+		return AE_ERROR;
+	return AE_OK;
+}
+
 static int
 acpi_pci_root_add (
 	struct acpi_device	*device)
@@ -190,9 +224,22 @@
 	/* Some systems have wrong _BBN */
 	list_for_each_entry(tmp, &acpi_pci_roots, node) {
 		if ((tmp->id.segment == root->id.segment)
-				&& (tmp->id.bus == root->id.bus))
+				&& (tmp->id.bus == root->id.bus)) {
+			int bus = 0;
+			acpi_status status;
+
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
 				"Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
+
+			status = try_get_root_bridge_busnr(root->handle, &bus);
+			if (ACPI_FAILURE(status))
+				break;
+			if (bus != root->id.bus) {
+				printk(KERN_INFO PREFIX "PCI _CRS %d overrides _BBN 0\n", bus);
+				root->id.bus = bus;
+			}
+			break;
+		}
 	}
 	/*
 	 * Device & Function
diff -Nru a/drivers/acpi/tables.c b/drivers/acpi/tables.c
--- a/drivers/acpi/tables.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/acpi/tables.c	2004-06-23 19:04:26 -07:00
@@ -131,7 +131,7 @@
 	{
 		struct acpi_table_ioapic *p =
 			(struct acpi_table_ioapic*) header;
-		printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] global_irq_base[0x%x])\n",
+		printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
 			p->id, p->address, p->global_irq_base);
 	}
 		break;
@@ -185,8 +185,8 @@
 	{
 		struct acpi_table_iosapic *p =
 			(struct acpi_table_iosapic*) header;
-		printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] global_irq_base[0x%x] address[%p])\n",
-			p->id, p->global_irq_base, (void *) (unsigned long) p->address);
+		printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
+			p->id, (void *) (unsigned long) p->address, p->global_irq_base);
 	}
 		break;
 
diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
--- a/drivers/acpi/thermal.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/acpi/thermal.c	2004-06-23 19:04:28 -07:00
@@ -289,6 +289,13 @@
 	status = acpi_get_handle(tz->handle, "_SCP", &handle);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
+		status = acpi_get_handle(tz->handle, "_PSV", &handle);
+		if(!ACPI_FAILURE(status)) {
+			tz->cooling_mode = 1;
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", 
+				mode?"passive":"active"));
+			return_VALUE(0);
+		}
 		return_VALUE(-ENODEV);
 	}
 
diff -Nru a/drivers/base/Kconfig b/drivers/base/Kconfig
--- a/drivers/base/Kconfig	2004-06-23 19:04:25 -07:00
+++ b/drivers/base/Kconfig	2004-06-23 19:04:25 -07:00
@@ -1,5 +1,14 @@
 menu "Generic Driver Options"
 
+config PREVENT_FIRMWARE_BUILD
+	bool "Prevent firmware from being built"
+	default y
+	help
+	  Say yes to avoid building firmware. Firmware is usually shipped
+	  with the driver, and only when updating the firware a rebuild
+	  should be made.
+	  If unsure say Y here.
+
 config FW_LOADER
 	tristate "Hotplug firmware loading support"
 	depends on HOTPLUG
diff -Nru a/drivers/base/base.h b/drivers/base/base.h
--- a/drivers/base/base.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/base/base.h	2004-06-23 19:04:26 -07:00
@@ -6,12 +6,13 @@
 
 static inline struct class_device *to_class_dev(struct kobject *obj)
 {
-	return container_of(obj,struct class_device,kobj);
+	return container_of(obj, struct class_device, kobj);
 }
+
 static inline
 struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
 {
-	return container_of(_attr,struct class_device_attribute,attr);
+	return container_of(_attr, struct class_device_attribute, attr);
 }
 
 
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/base/bus.c	2004-06-23 19:04:26 -07:00
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -17,17 +17,17 @@
 #include "base.h"
 #include "power/power.h"
 
-#define to_dev(node) container_of(node,struct device,bus_list)
-#define to_drv(node) container_of(node,struct device_driver,kobj.entry)
+#define to_dev(node) container_of(node, struct device, bus_list)
+#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
 
-#define to_bus_attr(_attr) container_of(_attr,struct bus_attribute,attr)
-#define to_bus(obj) container_of(obj,struct bus_type,subsys.kset.kobj)
+#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
+#define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj)
 
 /*
  * sysfs bindings for drivers
  */
 
-#define to_drv_attr(_attr) container_of(_attr,struct driver_attribute,attr)
+#define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr)
 #define to_driver(obj) container_of(obj, struct device_driver, kobj)
 
 
@@ -39,12 +39,12 @@
 	ssize_t ret = 0;
 
 	if (drv_attr->show)
-		ret = drv_attr->show(drv,buf);
+		ret = drv_attr->show(drv, buf);
 	return ret;
 }
 
 static ssize_t
-drv_attr_store(struct kobject * kobj, struct attribute * attr, 
+drv_attr_store(struct kobject * kobj, struct attribute * attr,
 	       const char * buf, size_t count)
 {
 	struct driver_attribute * drv_attr = to_drv_attr(attr);
@@ -52,7 +52,7 @@
 	ssize_t ret = 0;
 
 	if (drv_attr->store)
-		ret = drv_attr->store(drv,buf,count);
+		ret = drv_attr->store(drv, buf, count);
 	return ret;
 }
 
@@ -87,12 +87,12 @@
 	ssize_t ret = 0;
 
 	if (bus_attr->show)
-		ret = bus_attr->show(bus,buf);
+		ret = bus_attr->show(bus, buf);
 	return ret;
 }
 
 static ssize_t
-bus_attr_store(struct kobject * kobj, struct attribute * attr, 
+bus_attr_store(struct kobject * kobj, struct attribute * attr,
 	       const char * buf, size_t count)
 {
 	struct bus_attribute * bus_attr = to_bus_attr(attr);
@@ -100,7 +100,7 @@
 	ssize_t ret = 0;
 
 	if (bus_attr->store)
-		ret = bus_attr->store(bus,buf,count);
+		ret = bus_attr->store(bus, buf, count);
 	return ret;
 }
 
@@ -113,7 +113,7 @@
 {
 	int error;
 	if (get_bus(bus)) {
-		error = sysfs_create_file(&bus->subsys.kset.kobj,&attr->attr);
+		error = sysfs_create_file(&bus->subsys.kset.kobj, &attr->attr);
 		put_bus(bus);
 	} else
 		error = -EINVAL;
@@ -123,7 +123,7 @@
 void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
 {
 	if (get_bus(bus)) {
-		sysfs_remove_file(&bus->subsys.kset.kobj,&attr->attr);
+		sysfs_remove_file(&bus->subsys.kset.kobj, &attr->attr);
 		put_bus(bus);
 	}
 }
@@ -133,7 +133,7 @@
 
 };
 
-decl_subsys(bus,&ktype_bus,NULL);
+decl_subsys(bus, &ktype_bus, NULL);
 
 /**
  *	bus_for_each_dev - device iterator.
@@ -151,10 +151,10 @@
  *
  *	NOTE: The device that returns a non-zero value is not retained
  *	in any way, nor is its refcount incremented. If the caller needs
- *	to retain this data, it should do, and increment the reference 
+ *	to retain this data, it should do, and increment the reference
  *	count in the supplied callback.
  */
-int bus_for_each_dev(struct bus_type * bus, struct device * start, 
+int bus_for_each_dev(struct bus_type * bus, struct device * start,
 		     void * data, int (*fn)(struct device *, void *))
 {
 	struct device *dev;
@@ -170,7 +170,7 @@
 	down_read(&bus->subsys.rwsem);
 	list_for_each_entry_continue(dev, head, bus_list) {
 		get_device(dev);
-		error = fn(dev,data);
+		error = fn(dev, data);
 		put_device(dev);
 		if (error)
 			break;
@@ -193,7 +193,7 @@
  *	and return it. If @start is not NULL, we use it as the head
  *	of the list.
  *
- *	NOTE: we don't return the driver that returns a non-zero 
+ *	NOTE: we don't return the driver that returns a non-zero
  *	value, nor do we leave the reference count incremented for that
  *	driver. If the caller needs to know that info, it must set it
  *	in the callback. It must also be sure to increment the refcount
@@ -216,7 +216,7 @@
 	down_read(&bus->subsys.rwsem);
 	list_for_each_entry_continue(drv, head, kobj.entry) {
 		get_driver(drv);
-		error = fn(drv,data);
+		error = fn(drv, data);
 		put_driver(drv);
 		if(error)
 			break;
@@ -233,8 +233,8 @@
  *	Allow manual attachment of a driver to a deivce.
  *	Caller must have already set @dev->driver.
  *
- *	Note that this does not modify the bus reference count 
- *	nor take the bus's rwsem. Please verify those are accounted 
+ *	Note that this does not modify the bus reference count
+ *	nor take the bus's rwsem. Please verify those are accounted
  *	for before calling this. (It is ok to call with no other effort
  *	from a driver's probe() method.)
  */
@@ -242,9 +242,9 @@
 void device_bind_driver(struct device * dev)
 {
 	pr_debug("bound device '%s' to driver '%s'\n",
-		 dev->bus_id,dev->driver->name);
-	list_add_tail(&dev->driver_list,&dev->driver->devices);
-	sysfs_create_link(&dev->driver->kobj,&dev->kobj,
+		 dev->bus_id, dev->driver->name);
+	list_add_tail(&dev->driver_list, &dev->driver->devices);
+	sysfs_create_link(&dev->driver->kobj, &dev->kobj,
 			  kobject_name(&dev->kobj));
 }
 
@@ -255,18 +255,18 @@
  *	@drv:	driver.
  *
  *	First, we call the bus's match function, which should compare
- *	the device IDs the driver supports with the device IDs of the 
- *	device. Note we don't do this ourselves because we don't know 
+ *	the device IDs the driver supports with the device IDs of the
+ *	device. Note we don't do this ourselves because we don't know
  *	the format of the ID structures, nor what is to be considered
  *	a match and what is not.
- *	
- *	If we find a match, we call @drv->probe(@dev) if it exists, and 
+ *
+ *	If we find a match, we call @drv->probe(@dev) if it exists, and
  *	call attach() above.
  */
 static int bus_match(struct device * dev, struct device_driver * drv)
 {
 	int error = -ENODEV;
-	if (dev->bus->match(dev,drv)) {
+	if (dev->bus->match(dev, drv)) {
 		dev->driver = drv;
 		if (drv->probe) {
 			if ((error = drv->probe(dev))) {
@@ -285,7 +285,7 @@
  *	device_attach - try to attach device to a driver.
  *	@dev:	device.
  *
- *	Walk the list of drivers that the bus has and call bus_match() 
+ *	Walk the list of drivers that the bus has and call bus_match()
  *	for each pair. If a compatible pair is found, break out and return.
  */
 static int device_attach(struct device * dev)
@@ -300,15 +300,15 @@
 	}
 
 	if (bus->match) {
-		list_for_each(entry,&bus->drivers.list) {
+		list_for_each(entry, &bus->drivers.list) {
 			struct device_driver * drv = to_drv(entry);
-			error = bus_match(dev,drv);
-			if (!error )  
+			error = bus_match(dev, drv);
+			if (!error)
 				/* success, driver matched */
-				return 1; 
-			if (error != -ENODEV) 
+				return 1;
+			if (error != -ENODEV)
 				/* driver matched but the probe failed */
-				printk(KERN_WARNING 
+				printk(KERN_WARNING
 				    "%s: probe of %s failed with error %d\n",
 				    drv->name, dev->bus_id, error);
 		}
@@ -327,7 +327,7 @@
  *	If bus_match() returns 0 and the @dev->driver is set, we've found
  *	a compatible pair.
  *
- *	Note that we ignore the -ENODEV error from bus_match(), since it's 
+ *	Note that we ignore the -ENODEV error from bus_match(), since it's
  *	perfectly valid for a driver not to bind to any devices.
  */
 void driver_attach(struct device_driver * drv)
@@ -339,13 +339,13 @@
 	if (!bus->match)
 		return;
 
-	list_for_each(entry,&bus->devices.list) {
-		struct device * dev = container_of(entry,struct device,bus_list);
+	list_for_each(entry, &bus->devices.list) {
+		struct device * dev = container_of(entry, struct device, bus_list);
 		if (!dev->driver) {
-			error = bus_match(dev,drv);
+			error = bus_match(dev, drv);
 			if (error && (error != -ENODEV))
 				/* driver matched but the probe failed */
-				printk(KERN_WARNING 
+				printk(KERN_WARNING
 				    "%s: probe of %s failed with error %d\n",
 				    drv->name, dev->bus_id, error);
 		}
@@ -367,7 +367,7 @@
 {
 	struct device_driver * drv = dev->driver;
 	if (drv) {
-		sysfs_remove_link(&drv->kobj,kobject_name(&dev->kobj));
+		sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
 		list_del_init(&dev->driver_list);
 		device_detach_shutdown(dev);
 		if (drv->remove)
@@ -385,13 +385,44 @@
 static void driver_detach(struct device_driver * drv)
 {
 	struct list_head * entry, * next;
-	list_for_each_safe(entry,next,&drv->devices) {
-		struct device * dev = container_of(entry,struct device,driver_list);
+	list_for_each_safe(entry, next, &drv->devices) {
+		struct device * dev = container_of(entry, struct device, driver_list);
 		device_release_driver(dev);
 	}
+}
+
+static int device_add_attrs(struct bus_type * bus, struct device * dev)
+{
+	int error = 0;
+	int i;
+
+	if (bus->dev_attrs) {
+		for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
+			error = device_create_file(dev,&bus->dev_attrs[i]);
+			if (error)
+				goto Err;
+		}
+	}
+ Done:
+	return error;
+ Err:
+	while (--i >= 0)
+		device_remove_file(dev,&bus->dev_attrs[i]);
+	goto Done;
+}
+
+
+static void device_remove_attrs(struct bus_type * bus, struct device * dev)
+{
+	int i;
 	
+	if (bus->dev_attrs) {
+		for (i = 0; attr_name(bus->dev_attrs[i]); i++)
+			device_remove_file(dev,&bus->dev_attrs[i]);
+	}
 }
 
+
 /**
  *	bus_add_device - add device to bus
  *	@dev:	device being added
@@ -407,11 +438,12 @@
 
 	if (bus) {
 		down_write(&dev->bus->subsys.rwsem);
-		pr_debug("bus %s: add device %s\n",bus->name,dev->bus_id);
-		list_add_tail(&dev->bus_list,&dev->bus->devices.list);
+		pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
+		list_add_tail(&dev->bus_list, &dev->bus->devices.list);
 		device_attach(dev);
 		up_write(&dev->bus->subsys.rwsem);
-		sysfs_create_link(&bus->devices.kobj,&dev->kobj,dev->bus_id);
+		device_add_attrs(bus, dev);
+		sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
 	}
 	return error;
 }
@@ -428,9 +460,10 @@
 void bus_remove_device(struct device * dev)
 {
 	if (dev->bus) {
-		sysfs_remove_link(&dev->bus->devices.kobj,dev->bus_id);
+		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
+		device_remove_attrs(dev->bus, dev);
 		down_write(&dev->bus->subsys.rwsem);
-		pr_debug("bus %s: remove device %s\n",dev->bus->name,dev->bus_id);
+		pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
 		device_release_driver(dev);
 		list_del_init(&dev->bus_list);
 		up_write(&dev->bus->subsys.rwsem);
@@ -450,8 +483,8 @@
 	int error = 0;
 
 	if (bus) {
-		pr_debug("bus %s: add driver %s\n",bus->name,drv->name);
-		error = kobject_set_name(&drv->kobj,drv->name);
+		pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
+		error = kobject_set_name(&drv->kobj, drv->name);
 		if (error) {
 			put_bus(bus);
 			return error;
@@ -484,7 +517,7 @@
 {
 	if (drv->bus) {
 		down_write(&drv->bus->subsys.rwsem);
-		pr_debug("bus %s: remove driver %s\n",drv->bus->name,drv->name);
+		pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
 		driver_detach(drv);
 		up_write(&drv->bus->subsys.rwsem);
 		kobject_unregister(&drv->kobj);
@@ -526,7 +559,7 @@
 
 struct bus_type * get_bus(struct bus_type * bus)
 {
-	return bus ? container_of(subsys_get(&bus->subsys),struct bus_type,subsys) : NULL;
+	return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL;
 }
 
 void put_bus(struct bus_type * bus)
@@ -545,29 +578,64 @@
 
 struct bus_type * find_bus(char * name)
 {
-	struct kobject * k = kset_find_obj(&bus_subsys.kset,name);
+	struct kobject * k = kset_find_obj(&bus_subsys.kset, name);
 	return k ? to_bus(k) : NULL;
 }
 
+
+/**
+ *	bus_add_attrs - Add default attributes for this bus.
+ *	@bus:	Bus that has just been registered.
+ */
+
+static int bus_add_attrs(struct bus_type * bus)
+{
+	int error = 0;
+	int i;
+
+	if (bus->bus_attrs) {
+		for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
+			if ((error = bus_create_file(bus,&bus->bus_attrs[i])))
+				goto Err;
+		}
+	}
+ Done:
+	return error;
+ Err:
+	while (--i >= 0)
+		bus_remove_file(bus,&bus->bus_attrs[i]);
+	goto Done;
+}
+
+static void bus_remove_attrs(struct bus_type * bus)
+{
+	int i;
+	
+	if (bus->bus_attrs) {
+		for (i = 0; attr_name(bus->bus_attrs[i]); i++)
+			bus_remove_file(bus,&bus->bus_attrs[i]);
+	}
+}
+
 /**
  *	bus_register - register a bus with the system.
  *	@bus:	bus.
  *
  *	Once we have that, we registered the bus with the kobject
  *	infrastructure, then register the children subsystems it has:
- *	the devices and drivers that belong to the bus. 
+ *	the devices and drivers that belong to the bus.
  */
 int bus_register(struct bus_type * bus)
 {
 	int retval;
 
-	retval = kobject_set_name(&bus->subsys.kset.kobj,bus->name);
+	retval = kobject_set_name(&bus->subsys.kset.kobj, bus->name);
 	if (retval)
 		goto out;
 
-	subsys_set_kset(bus,bus_subsys);
+	subsys_set_kset(bus, bus_subsys);
 	retval = subsystem_register(&bus->subsys);
-	if (retval) 
+	if (retval)
 		goto out;
 
 	kobject_set_name(&bus->devices.kobj, "devices");
@@ -582,8 +650,9 @@
 	retval = kset_register(&bus->drivers);
 	if (retval)
 		goto bus_drivers_fail;
+	bus_add_attrs(bus);
 
-	pr_debug("bus type '%s' registered\n",bus->name);
+	pr_debug("bus type '%s' registered\n", bus->name);
 	return 0;
 
 bus_drivers_fail:
@@ -596,7 +665,7 @@
 
 
 /**
- *	bus_unregister - remove a bus from the system 
+ *	bus_unregister - remove a bus from the system
  *	@bus:	bus.
  *
  *	Unregister the child subsystems and the bus itself.
@@ -604,7 +673,8 @@
  */
 void bus_unregister(struct bus_type * bus)
 {
-	pr_debug("bus %s: unregistering\n",bus->name);
+	pr_debug("bus %s: unregistering\n", bus->name);
+	bus_remove_attrs(bus);
 	kset_unregister(&bus->drivers);
 	kset_unregister(&bus->devices);
 	subsystem_unregister(&bus->subsys);
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/base/class.c	2004-06-23 19:04:29 -07:00
@@ -5,7 +5,7 @@
  * Copyright (c) 2002-3 Open Source Development Labs
  * Copyright (c) 2003-2004 Greg Kroah-Hartman
  * Copyright (c) 2003-2004 IBM Corp.
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -17,8 +17,8 @@
 #include <linux/string.h>
 #include "base.h"
 
-#define to_class_attr(_attr) container_of(_attr,struct class_attribute,attr)
-#define to_class(obj) container_of(obj,struct class,subsys.kset.kobj)
+#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
+#define to_class(obj) container_of(obj, struct class, subsys.kset.kobj)
 
 static ssize_t
 class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
@@ -28,12 +28,12 @@
 	ssize_t ret = 0;
 
 	if (class_attr->show)
-		ret = class_attr->show(dc,buf);
+		ret = class_attr->show(dc, buf);
 	return ret;
 }
 
 static ssize_t
-class_attr_store(struct kobject * kobj, struct attribute * attr, 
+class_attr_store(struct kobject * kobj, struct attribute * attr,
 		 const char * buf, size_t count)
 {
 	struct class_attribute * class_attr = to_class_attr(attr);
@@ -41,7 +41,7 @@
 	ssize_t ret = 0;
 
 	if (class_attr->store)
-		ret = class_attr->store(dc,buf,count);
+		ret = class_attr->store(dc, buf, count);
 	return ret;
 }
 
@@ -69,14 +69,14 @@
 };
 
 /* Hotplug events for classes go to the class_obj subsys */
-static decl_subsys(class,&ktype_class,NULL);
+static decl_subsys(class, &ktype_class, NULL);
 
 
 int class_create_file(struct class * cls, const struct class_attribute * attr)
 {
 	int error;
 	if (cls) {
-		error = sysfs_create_file(&cls->subsys.kset.kobj,&attr->attr);
+		error = sysfs_create_file(&cls->subsys.kset.kobj, &attr->attr);
 	} else
 		error = -EINVAL;
 	return error;
@@ -85,13 +85,13 @@
 void class_remove_file(struct class * cls, const struct class_attribute * attr)
 {
 	if (cls)
-		sysfs_remove_file(&cls->subsys.kset.kobj,&attr->attr);
+		sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr);
 }
 
 struct class * class_get(struct class * cls)
 {
 	if (cls)
-		return container_of(subsys_get(&cls->subsys),struct class,subsys);
+		return container_of(subsys_get(&cls->subsys), struct class, subsys);
 	return NULL;
 }
 
@@ -100,33 +100,67 @@
 	subsys_put(&cls->subsys);
 }
 
+
+static int add_class_attrs(struct class * cls)
+{
+	int i;
+	int error = 0;
+
+	if (cls->class_attrs) {
+		for (i = 0; attr_name(cls->class_attrs[i]); i++) {
+			error = class_create_file(cls,&cls->class_attrs[i]);
+			if (error)
+				goto Err;
+		}
+	}
+ Done:
+	return error;
+ Err:
+	while (--i >= 0)
+		class_remove_file(cls,&cls->class_attrs[i]);
+	goto Done;
+}
+
+static void remove_class_attrs(struct class * cls)
+{
+	int i;
+
+	if (cls->class_attrs) {
+		for (i = 0; attr_name(cls->class_attrs[i]); i++)
+			class_remove_file(cls,&cls->class_attrs[i]);
+	}
+}
+
 int class_register(struct class * cls)
 {
 	int error;
 
-	pr_debug("device class '%s': registering\n",cls->name);
+	pr_debug("device class '%s': registering\n", cls->name);
 
 	INIT_LIST_HEAD(&cls->children);
 	INIT_LIST_HEAD(&cls->interfaces);
-	error = kobject_set_name(&cls->subsys.kset.kobj,cls->name);
+	error = kobject_set_name(&cls->subsys.kset.kobj, cls->name);
 	if (error)
 		return error;
 
-	subsys_set_kset(cls,class_subsys);
+	subsys_set_kset(cls, class_subsys);
 
 	error = subsystem_register(&cls->subsys);
-	if (error)
-		return error;
-
-	return 0;
+	if (!error) {
+		error = add_class_attrs(class_get(cls));
+		class_put(cls);
+	}
+	return error;
 }
 
 void class_unregister(struct class * cls)
 {
-	pr_debug("device class '%s': unregistering\n",cls->name);
+	pr_debug("device class '%s': unregistering\n", cls->name);
+	remove_class_attrs(cls);
 	subsystem_unregister(&cls->subsys);
 }
 
+
 /* Class Device Stuff */
 
 int class_device_create_file(struct class_device * class_dev,
@@ -181,12 +215,12 @@
 	ssize_t ret = 0;
 
 	if (class_dev_attr->show)
-		ret = class_dev_attr->show(cd,buf);
+		ret = class_dev_attr->show(cd, buf);
 	return ret;
 }
 
 static ssize_t
-class_device_attr_store(struct kobject * kobj, struct attribute * attr, 
+class_device_attr_store(struct kobject * kobj, struct attribute * attr,
 			const char * buf, size_t count)
 {
 	struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
@@ -194,7 +228,7 @@
 	ssize_t ret = 0;
 
 	if (class_dev_attr->store)
-		ret = class_dev_attr->store(cd,buf,count);
+		ret = class_dev_attr->store(cd, buf, count);
 	return ret;
 }
 
@@ -208,7 +242,7 @@
 	struct class_device *cd = to_class_dev(kobj);
 	struct class * cls = cd->class;
 
-	pr_debug("device class '%s': release.\n",cd->class_id);
+	pr_debug("device class '%s': release.\n", cd->class_id);
 
 	if (cls->release)
 		cls->release(cd);
@@ -272,6 +306,40 @@
 
 static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops);
 
+
+static int class_device_add_attrs(struct class_device * cd)
+{
+	int i;
+	int error = 0;
+	struct class * cls = cd->class;
+
+	if (cls->class_dev_attrs) {
+		for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) {
+			error = class_device_create_file(cd,
+							 &cls->class_dev_attrs[i]);
+			if (error)
+				goto Err;
+		}
+	}
+ Done:
+	return error;
+ Err:
+	while (--i >= 0)
+		class_device_remove_file(cd,&cls->class_dev_attrs[i]);
+	goto Done;
+}
+
+static void class_device_remove_attrs(struct class_device * cd)
+{
+	int i;
+	struct class * cls = cd->class;
+
+	if (cls->class_dev_attrs) {
+		for (i = 0; attr_name(cls->class_dev_attrs[i]); i++)
+			class_device_remove_file(cd,&cls->class_dev_attrs[i]);
+	}
+}
+
 void class_device_initialize(struct class_device *class_dev)
 {
 	kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -311,7 +379,7 @@
 				class_intf->add(class_dev);
 		up_write(&parent->subsys.rwsem);
 	}
-
+	class_device_add_attrs(class_dev);
 	class_device_dev_link(class_dev);
 	class_device_driver_link(class_dev);
 
@@ -344,7 +412,8 @@
 
 	class_device_dev_unlink(class_dev);
 	class_device_driver_unlink(class_dev);
-	
+	class_device_remove_attrs(class_dev);
+
 	kobject_del(&class_dev->kobj);
 
 	if (parent)
diff -Nru a/drivers/base/class_simple.c b/drivers/base/class_simple.c
--- a/drivers/base/class_simple.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/base/class_simple.c	2004-06-23 19:04:26 -07:00
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
  * Copyright (c) 2003-2004 IBM Corp.
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -111,7 +111,7 @@
 
 /**
  * class_simple_device_add - adds a class device to sysfs for a character driver
- * @cs: pointer to the struct class_simple that this device should be registered to.  
+ * @cs: pointer to the struct class_simple that this device should be registered to.
  * @dev: the dev_t for the device to be added.
  * @device: a pointer to a struct device that is assiociated with this class device.
  * @fmt: string for the class device's name
@@ -146,8 +146,8 @@
 	s_dev->dev = dev;
 	s_dev->class_dev.dev = device;
 	s_dev->class_dev.class = &cs->class;
-	
-	va_start(args,fmt);
+
+	va_start(args, fmt);
 	vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
 	va_end(args);
 	retval = class_device_register(&s_dev->class_dev);
@@ -173,10 +173,10 @@
  * @cs: pointer to the struct class_simple to hold the pointer
  * @hotplug: function pointer to the hotplug function
  *
- * Implement and set a hotplug function to add environment variables specific to this 
+ * Implement and set a hotplug function to add environment variables specific to this
  * class on the hotplug event.
  */
-int class_simple_set_hotplug(struct class_simple *cs, 
+int class_simple_set_hotplug(struct class_simple *cs,
 	int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size))
 {
 	if ((cs == NULL) || (IS_ERR(cs)))
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/base/core.c	2004-06-23 19:04:25 -07:00
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -28,8 +28,8 @@
  * sysfs bindings for devices.
  */
 
-#define to_dev(obj) container_of(obj,struct device,kobj)
-#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+#define to_dev(obj) container_of(obj, struct device, kobj)
+#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
 
 extern struct attribute * dev_default_attrs[];
 
@@ -41,12 +41,12 @@
 	ssize_t ret = 0;
 
 	if (dev_attr->show)
-		ret = dev_attr->show(dev,buf);
+		ret = dev_attr->show(dev, buf);
 	return ret;
 }
 
 static ssize_t
-dev_attr_store(struct kobject * kobj, struct attribute * attr, 
+dev_attr_store(struct kobject * kobj, struct attribute * attr,
 	       const char * buf, size_t count)
 {
 	struct device_attribute * dev_attr = to_dev_attr(attr);
@@ -54,7 +54,7 @@
 	ssize_t ret = 0;
 
 	if (dev_attr->store)
-		ret = dev_attr->store(dev,buf,count);
+		ret = dev_attr->store(dev, buf, count);
 	return ret;
 }
 
@@ -153,7 +153,7 @@
 {
 	int error = 0;
 	if (get_device(dev)) {
-		error = sysfs_create_file(&dev->kobj,&attr->attr);
+		error = sysfs_create_file(&dev->kobj, &attr->attr);
 		put_device(dev);
 	}
 	return error;
@@ -168,7 +168,7 @@
 void device_remove_file(struct device * dev, struct device_attribute * attr)
 {
 	if (get_device(dev)) {
-		sysfs_remove_file(&dev->kobj,&attr->attr);
+		sysfs_remove_file(&dev->kobj, &attr->attr);
 		put_device(dev);
 	}
 }
@@ -179,7 +179,7 @@
  *	@dev:	device.
  *
  *	This prepares the device for use by other layers,
- *	including adding it to the device hierarchy. 
+ *	including adding it to the device hierarchy.
  *	It is the first half of device_register(), if called by
  *	that, though it can also be called separately, so one
  *	may use @dev's fields (e.g. the refcount).
@@ -187,7 +187,7 @@
 
 void device_initialize(struct device *dev)
 {
-	kobj_set_kset_s(dev,devices_subsys);
+	kobj_set_kset_s(dev, devices_subsys);
 	kobject_init(&dev->kobj);
 	INIT_LIST_HEAD(&dev->node);
 	INIT_LIST_HEAD(&dev->children);
@@ -200,7 +200,7 @@
  *	device_add - add device to device hierarchy.
  *	@dev:	device.
  *
- *	This is part 2 of device_register(), though may be called 
+ *	This is part 2 of device_register(), though may be called
  *	separately _iff_ device_initialize() has been called separately.
  *
  *	This adds it to the kobject hierarchy via kobject_add(), adds it
@@ -221,7 +221,7 @@
 	pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
 
 	/* first, register with generic layer. */
-	kobject_set_name(&dev->kobj,dev->bus_id);
+	kobject_set_name(&dev->kobj, dev->bus_id);
 	if (parent)
 		dev->kobj.parent = &parent->kobj;
 
@@ -233,7 +233,7 @@
 		goto BusError;
 	down_write(&devices_subsys.rwsem);
 	if (parent)
-		list_add_tail(&dev->node,&parent->children);
+		list_add_tail(&dev->node, &parent->children);
 	up_write(&devices_subsys.rwsem);
 
 	/* notify platform of device entry */
@@ -245,7 +245,7 @@
  BusError:
 	device_pm_remove(dev);
  PMError:
-	kobject_unregister(&dev->kobj);
+	kobject_del(&dev->kobj);
  Error:
 	if (parent)
 		put_device(parent);
@@ -258,9 +258,9 @@
  *	@dev:	pointer to the device structure
  *
  *	This happens in two clean steps - initialize the device
- *	and add it to the system. The two steps can be called 
- *	separately, but this is the easiest and most common. 
- *	I.e. you should only call the two helpers separately if 
+ *	and add it to the system. The two steps can be called
+ *	separately, but this is the easiest and most common.
+ *	I.e. you should only call the two helpers separately if
  *	have a clearly defined need to use and refcount the device
  *	before it is added to the hierarchy.
  */
@@ -301,13 +301,13 @@
  *	device_del - delete device from system.
  *	@dev:	device.
  *
- *	This is the first part of the device unregistration 
+ *	This is the first part of the device unregistration
  *	sequence. This removes the device from the lists we control
- *	from here, has it removed from the other driver model 
+ *	from here, has it removed from the other driver model
  *	subsystems it was added to in device_add(), and removes it
  *	from the kobject hierarchy.
  *
- *	NOTE: this should be called manually _iff_ device_add() was 
+ *	NOTE: this should be called manually _iff_ device_add() was
  *	also called manually.
  */
 
@@ -340,7 +340,7 @@
  *	we remove it from all the subsystems with device_del(), then
  *	we decrement the reference count via put_device(). If that
  *	is the final reference count, the device will be cleaned up
- *	via device_release() above. Otherwise, the structure will 
+ *	via device_release() above. Otherwise, the structure will
  *	stick around until the final reference to the device is dropped.
  */
 void device_unregister(struct device * dev)
@@ -358,7 +358,7 @@
  *	@fn:	function to be called for each device.
  *
  *	Iterate over @dev's child devices, and call @fn for each,
- *	passing it @data. 
+ *	passing it @data.
  *
  *	We check the return of @fn each time. If it returns anything
  *	other than 0, we break out and return that value.
@@ -370,8 +370,8 @@
 	int error = 0;
 
 	down_read(&devices_subsys.rwsem);
-	list_for_each_entry(child,&dev->children,node) {
-		if((error = fn(child,data)))
+	list_for_each_entry(child, &dev->children, node) {
+		if((error = fn(child, data)))
 			break;
 	}
 	up_read(&devices_subsys.rwsem);
diff -Nru a/drivers/base/cpu.c b/drivers/base/cpu.c
--- a/drivers/base/cpu.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/base/cpu.c	2004-06-23 19:04:26 -07:00
@@ -58,6 +58,8 @@
 
 /*
  * register_cpu - Setup a driverfs device for a CPU.
+ * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to
+ *		  generate a control file in sysfs for this CPU.
  * @num - CPU number to use when creating the device.
  *
  * Initialize and register the CPU device.
@@ -75,7 +77,7 @@
 		error = sysfs_create_link(&root->sysdev.kobj,
 					  &cpu->sysdev.kobj,
 					  kobject_name(&cpu->sysdev.kobj));
-	if (!error)
+	if (!error && !cpu->no_control)
 		register_cpu_control(cpu);
 	return error;
 }
diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c
--- a/drivers/base/driver.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/base/driver.c	2004-06-23 19:04:28 -07:00
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -15,8 +15,8 @@
 #include <linux/string.h>
 #include "base.h"
 
-#define to_dev(node) container_of(node,struct device,driver_list)
-#define to_drv(obj) container_of(obj,struct device_driver,kobj)
+#define to_dev(node) container_of(node, struct device, driver_list)
+#define to_drv(obj) container_of(obj, struct device_driver, kobj)
 
 /**
  *	driver_create_file - create sysfs file for driver.
@@ -28,7 +28,7 @@
 {
 	int error;
 	if (get_driver(drv)) {
-		error = sysfs_create_file(&drv->kobj,&attr->attr);
+		error = sysfs_create_file(&drv->kobj, &attr->attr);
 		put_driver(drv);
 	} else
 		error = -EINVAL;
@@ -45,7 +45,7 @@
 void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
 {
 	if (get_driver(drv)) {
-		sysfs_remove_file(&drv->kobj,&attr->attr);
+		sysfs_remove_file(&drv->kobj, &attr->attr);
 		put_driver(drv);
 	}
 }
@@ -76,7 +76,7 @@
  *	@drv:	driver to register
  *
  *	We pass off most of the work to the bus_add_driver() call,
- *	since most of the things we have to do deal with the bus 
+ *	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
@@ -99,8 +99,8 @@
  *
  *	Though, once that is done, we attempt to take @drv->unload_sem.
  *	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 
+ *	released. Only modular drivers will call this function, and we
+ *	have to guarantee that it won't complete, letting the driver
  *	unload until all references are gone.
  */
 
diff -Nru a/drivers/base/firmware.c b/drivers/base/firmware.c
--- a/drivers/base/firmware.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/base/firmware.c	2004-06-23 19:04:27 -07:00
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -12,11 +12,11 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-static decl_subsys(firmware,NULL,NULL);
+static decl_subsys(firmware, NULL, NULL);
 
 int firmware_register(struct subsystem * s)
 {
-	kset_set_kset_s(s,firmware_subsys);
+	kset_set_kset_s(s, firmware_subsys);
 	return subsystem_register(s);
 }
 
diff -Nru a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
--- a/drivers/base/firmware_class.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/base/firmware_class.c	2004-06-23 19:04:25 -07:00
@@ -68,7 +68,7 @@
  *	firmware will be provided.
  *
  *	Note: zero means 'wait for ever'
- *  
+ *
  **/
 static ssize_t
 firmware_timeout_store(struct class *class, const char *buf, size_t count)
@@ -121,7 +121,7 @@
 /**
  * firmware_loading_store: - loading control file
  * Description:
- *	The relevant values are: 
+ *	The relevant values are:
  *
  *	 1: Start a load, discarding any previous partial load.
  *	 0: Conclude the load and handle the data to the driver code.
@@ -376,7 +376,7 @@
 	return retval;
 }
 
-/** 
+/**
  * request_firmware: - request firmware to hotplug and wait for it
  * Description:
  *	@firmware will be used to return a firmware image by the name
@@ -457,7 +457,7 @@
 
 /**
  * register_firmware: - provide a firmware image for later usage
- * 
+ *
  * Description:
  *	Make sure that @data will be available by requesting firmware @name.
  *
@@ -541,7 +541,7 @@
 
 	ret = kernel_thread(request_firmware_work_func, fw_work,
 			    CLONE_FS | CLONE_FILES);
-	
+
 	if (ret < 0) {
 		fw_work->cont(NULL, fw_work->context);
 		return ret;
diff -Nru a/drivers/base/init.c b/drivers/base/init.c
--- a/drivers/base/init.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/base/init.c	2004-06-23 19:04:25 -07:00
@@ -2,7 +2,7 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -33,7 +33,7 @@
 	classes_init();
 	firmware_init();
 
-	/* These are also core pieces, but must come after the 
+	/* These are also core pieces, but must come after the
 	 * core core pieces.
 	 */
 	platform_bus_init();
diff -Nru a/drivers/base/interface.c b/drivers/base/interface.c
--- a/drivers/base/interface.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/base/interface.c	2004-06-23 19:04:25 -07:00
@@ -1,10 +1,10 @@
 /*
- * drivers/base/interface.c - common driverfs interface that's exported to 
+ * drivers/base/interface.c - common driverfs interface that's exported to
  * 	the world for all devices.
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -16,33 +16,33 @@
 
 /**
  *	detach_state - control the default power state for the device.
- *	
- *	This is the state the device enters when it's driver module is 
+ *
+ *	This is the state the device enters when it's driver module is
  *	unloaded. The value is an unsigned integer, in the range of 0-4.
  *	'0' indicates 'On', so no action will be taken when the driver is
  *	unloaded. This is the default behavior.
  *	'4' indicates 'Off', meaning the driver core will call the driver's
  *	shutdown method to quiesce the device.
- *	1-3 indicate a low-power state for the device to enter via the 
- *	driver's suspend method. 
+ *	1-3 indicate a low-power state for the device to enter via the
+ *	driver's suspend method.
  */
 
 static ssize_t detach_show(struct device * dev, char * buf)
 {
-	return sprintf(buf,"%u\n",dev->detach_state);
+	return sprintf(buf, "%u\n", dev->detach_state);
 }
 
 static ssize_t detach_store(struct device * dev, const char * buf, size_t n)
 {
 	u32 state;
-	state = simple_strtoul(buf,NULL,10);
+	state = simple_strtoul(buf, NULL, 10);
 	if (state > 4)
 		return -EINVAL;
 	dev->detach_state = state;
 	return n;
 }
 
-static DEVICE_ATTR(detach_state,0644,detach_show,detach_store);
+static DEVICE_ATTR(detach_state, 0644, detach_show, detach_store);
 
 
 struct attribute * dev_default_attrs[] = {
diff -Nru a/drivers/base/node.c b/drivers/base/node.c
--- a/drivers/base/node.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/base/node.c	2004-06-23 19:04:25 -07:00
@@ -29,7 +29,7 @@
 	return len;
 }
 
-static SYSDEV_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL);
+static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumap, NULL);
 
 /* Can be overwritten by architecture specific code. */
 int __attribute__((weak)) hugetlb_report_node_meminfo(int node, char *buf)
@@ -54,17 +54,17 @@
 		       "Node %d LowFree:      %8lu kB\n",
 		       nid, K(i.totalram),
 		       nid, K(i.freeram),
-		       nid, K(i.totalram-i.freeram),
+		       nid, K(i.totalram - i.freeram),
 		       nid, K(i.totalhigh),
 		       nid, K(i.freehigh),
-		       nid, K(i.totalram-i.totalhigh),
-		       nid, K(i.freeram-i.freehigh));
+		       nid, K(i.totalram - i.totalhigh),
+		       nid, K(i.freeram - i.freehigh));
 	n += hugetlb_report_node_meminfo(nid, buf + n);
 	return n;
 }
 
-#undef K 
-static SYSDEV_ATTR(meminfo,S_IRUGO,node_read_meminfo,NULL);
+#undef K
+static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
 
 static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
 {
@@ -104,7 +104,7 @@
 		       local_node,
 		       other_node);
 }
-static SYSDEV_ATTR(numastat,S_IRUGO,node_read_numastat,NULL);
+static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
 
 /*
  * register_node - Setup a driverfs device for a node.
diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c
--- a/drivers/base/platform.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/base/platform.c	2004-06-23 19:04:25 -07:00
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
- * 
+ *
  * This file is released under the GPLv2
  *
  * Please see Documentation/driver-model/platform.txt for more
@@ -19,12 +19,71 @@
 };
 
 /**
+ *	platform_get_resource - get a resource for a device
+ *	@dev: platform device
+ *	@type: resource type
+ *	@num: resource index
+ */
+struct resource *
+platform_get_resource(struct platform_device *dev, unsigned int type,
+		      unsigned int num)
+{
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++) {
+		struct resource *r = &dev->resource[i];
+
+		if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
+				 IORESOURCE_IRQ|IORESOURCE_DMA))
+		    == type)
+			if (num-- == 0)
+				return r;
+	}
+	return NULL;
+}
+
+/**
+ *	platform_get_irq - get an IRQ for a device
+ *	@dev: platform device
+ *	@num: IRQ number index
+ */
+int platform_get_irq(struct platform_device *dev, unsigned int num)
+{
+	struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
+
+	return r ? r->start : 0;
+}
+
+/**
+ *	platform_add_devices - add a numbers of platform devices
+ *	@devs: array of platform devices to add
+ *	@num: number of platform devices in array
+ */
+int platform_add_devices(struct platform_device **devs, int num)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < num; i++) {
+		ret = platform_device_register(devs[i]);
+		if (ret) {
+			while (--i >= 0)
+				platform_device_unregister(devs[i]);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/**
  *	platform_device_register - add a platform-level device
  *	@dev:	platform device we're adding
  *
  */
 int platform_device_register(struct platform_device * pdev)
 {
+	int i, ret = 0;
+
 	if (!pdev)
 		return -EINVAL;
 
@@ -32,18 +91,59 @@
 		pdev->dev.parent = &platform_bus;
 
 	pdev->dev.bus = &platform_bus_type;
-	
-	snprintf(pdev->dev.bus_id,BUS_ID_SIZE,"%s%u",pdev->name,pdev->id);
+
+	if (pdev->id != -1)
+		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);
+
+	for (i = 0; i < pdev->num_resources; i++) {
+		struct resource *p, *r = &pdev->resource[i];
+
+		r->name = pdev->dev.bus_id;
+
+		p = NULL;
+		if (r->flags & IORESOURCE_MEM)
+			p = &iomem_resource;
+		else if (r->flags & IORESOURCE_IO)
+			p = &ioport_resource;
+
+		if (p && request_resource(p, r)) {
+			printk(KERN_ERR
+			       "%s: failed to claim resource %d\n",
+			       pdev->dev.bus_id, i);
+			ret = -EBUSY;
+			goto failed;
+		}
+	}
 
 	pr_debug("Registering platform device '%s'. Parent at %s\n",
-		 pdev->dev.bus_id,pdev->dev.parent->bus_id);
-	return device_register(&pdev->dev);
+		 pdev->dev.bus_id, pdev->dev.parent->bus_id);
+
+	ret = device_register(&pdev->dev);
+	if (ret == 0)
+		return ret;
+
+ failed:
+	while (--i >= 0)
+		if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
+			release_resource(&pdev->resource[i]);
+	return ret;
 }
 
 void platform_device_unregister(struct platform_device * pdev)
 {
-	if (pdev)
+	int i;
+
+	if (pdev) {
 		device_unregister(&pdev->dev);
+
+		for (i = 0; i < pdev->num_resources; i++) {
+			struct resource *r = &pdev->resource[i];
+			if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
+				release_resource(r);
+		}
+	}
 }
 
 
@@ -52,13 +152,13 @@
  *	@dev:	device.
  *	@drv:	driver.
  *
- *	Platform device IDs are assumed to be encoded like this: 
- *	"<name><instance>", where <name> is a short description of the 
- *	type of device, like "pci" or "floppy", and <instance> is the 
+ *	Platform device IDs are assumed to be encoded like this:
+ *	"<name><instance>", where <name> is a short description of the
+ *	type of device, like "pci" or "floppy", and <instance> is the
  *	enumerated instance of the device, like '0' or '42'.
- *	Driver IDs are simply "<name>". 
- *	So, extract the <name> from the platform_device structure, 
- *	and compare it against the name of the driver. Return whether 
+ *	Driver IDs are simply "<name>".
+ *	So, extract the <name> from the platform_device structure,
+ *	and compare it against the name of the driver. Return whether
  *	they match or not.
  */
 
@@ -114,3 +214,5 @@
 EXPORT_SYMBOL(platform_bus_type);
 EXPORT_SYMBOL(platform_device_register);
 EXPORT_SYMBOL(platform_device_unregister);
+EXPORT_SYMBOL(platform_get_irq);
+EXPORT_SYMBOL(platform_get_resource);
diff -Nru a/drivers/base/power/main.c b/drivers/base/power/main.c
--- a/drivers/base/power/main.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/base/power/main.c	2004-06-23 19:04:28 -07:00
@@ -12,10 +12,10 @@
  * and add it to the list of power-controlled devices. sysfs entries for
  * controlling device power management will also be added.
  *
- * A different set of lists than the global subsystem list are used to 
- * keep track of power info because we use different lists to hold 
- * devices based on what stage of the power management process they 
- * are in. The power domain dependencies may also differ from the 
+ * A different set of lists than the global subsystem list are used to
+ * keep track of power info because we use different lists to hold
+ * devices based on what stage of the power management process they
+ * are in. The power domain dependencies may also differ from the
  * ancestral dependencies that the subsystem list maintains.
  */
 
@@ -74,10 +74,10 @@
 
 	pr_debug("PM: Adding info for %s:%s\n",
 		 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
-	atomic_set(&dev->power.pm_users,0);
+	atomic_set(&dev->power.pm_users, 0);
 	down(&dpm_sem);
-	list_add_tail(&dev->power.entry,&dpm_active);
-	device_pm_set_parent(dev,dev->parent);
+	list_add_tail(&dev->power.entry, &dpm_active);
+	device_pm_set_parent(dev, dev->parent);
 	if ((error = dpm_sysfs_add(dev)))
 		list_del(&dev->power.entry);
 	up(&dpm_sem);
diff -Nru a/drivers/base/power/power.h b/drivers/base/power/power.h
--- a/drivers/base/power/power.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/base/power/power.h	2004-06-23 19:04:25 -07:00
@@ -27,7 +27,7 @@
  */
 extern struct semaphore dpm_sem;
 
-/* 
+/*
  * The PM lists.
  */
 extern struct list_head dpm_active;
@@ -37,12 +37,12 @@
 
 static inline struct dev_pm_info * to_pm_info(struct list_head * entry)
 {
-	return container_of(entry,struct dev_pm_info,entry);
+	return container_of(entry, struct dev_pm_info, entry);
 }
 
 static inline struct device * to_device(struct list_head * entry)
 {
-	return container_of(to_pm_info(entry),struct device,power);
+	return container_of(to_pm_info(entry), struct device, power);
 }
 
 extern int device_pm_add(struct device *);
@@ -56,7 +56,7 @@
 extern void dpm_sysfs_remove(struct device *);
 
 /*
- * resume.c 
+ * resume.c
  */
 
 extern void dpm_resume(void);
diff -Nru a/drivers/base/power/resume.c b/drivers/base/power/resume.c
--- a/drivers/base/power/resume.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/base/power/resume.c	2004-06-23 19:04:28 -07:00
@@ -39,7 +39,7 @@
 		if (!dev->power.prev_state)
 			resume_device(dev);
 
-		list_add_tail(entry,&dpm_active);
+		list_add_tail(entry, &dpm_active);
 	}
 }
 
@@ -48,7 +48,7 @@
  *	device_resume - Restore state of each device in system.
  *
  *	Walk the dpm_off list, remove each entry, resume the device,
- *	then add it to the dpm_active list. 
+ *	then add it to the dpm_active list.
  */
 
 void device_resume(void)
@@ -62,14 +62,14 @@
 
 
 /**
- *	device_power_up_irq - Power on some devices. 
+ *	device_power_up_irq - Power on some devices.
  *
- *	Walk the dpm_off_irq list and power each device up. This 
+ *	Walk the dpm_off_irq list and power each device up. This
  *	is used for devices that required they be powered down with
  *	interrupts disabled. As devices are powered on, they are moved to
  *	the dpm_suspended list.
  *
- *	Interrupts must be disabled when calling this. 
+ *	Interrupts must be disabled when calling this.
  */
 
 void dpm_power_up(void)
@@ -78,7 +78,7 @@
 		struct list_head * entry = dpm_off_irq.next;
 		list_del_init(entry);
 		resume_device(to_device(entry));
-		list_add_tail(entry,&dpm_active);
+		list_add_tail(entry, &dpm_active);
 	}
 }
 
diff -Nru a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
--- a/drivers/base/power/runtime.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/base/power/runtime.c	2004-06-23 19:04:28 -07:00
@@ -24,9 +24,9 @@
  *	dpm_runtime_resume - Power one device back on.
  *	@dev:	Device.
  *
- *	Bring one device back to the on state by first powering it 
+ *	Bring one device back to the on state by first powering it
  *	on, then restoring state. We only operate on devices that aren't
- *	already on. 
+ *	already on.
  *	FIXME: We need to handle devices that are in an unknown state.
  */
 
@@ -55,7 +55,7 @@
 	if (dev->power.power_state)
 		runtime_resume(dev);
 
-	if (!(error = suspend_device(dev,state)))
+	if (!(error = suspend_device(dev, state)))
 		dev->power.power_state = state;
  Done:
 	up(&dpm_sem);
@@ -70,7 +70,7 @@
  *
  *	This is an update mechanism for drivers to notify the core
  *	what power state a device is in. Device probing code may not
- *	always be able to tell, but we need accurate information to 
+ *	always be able to tell, but we need accurate information to
  *	work reliably.
  */
 void dpm_set_power_state(struct device * dev, u32 state)
diff -Nru a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
--- a/drivers/base/power/shutdown.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/base/power/shutdown.c	2004-06-23 19:04:27 -07:00
@@ -1,9 +1,9 @@
 /*
  * shutdown.c - power management functions for the device tree.
- * 
+ *
  * Copyright (c) 2002-3 Patrick Mochel
  *		 2002-3 Open Source Development Lab
- * 
+ *
  * This file is released under the GPLv2
  *
  */
@@ -14,7 +14,7 @@
 
 #include "power.h"
 
-#define to_dev(node) container_of(node,struct device,kobj.entry)
+#define to_dev(node) container_of(node, struct device, kobj.entry)
 
 extern struct subsystem devices_subsys;
 
@@ -29,7 +29,7 @@
 			dev->driver->shutdown(dev);
 		return 0;
 	}
-	return dpm_runtime_suspend(dev,dev->detach_state);
+	return dpm_runtime_suspend(dev, dev->detach_state);
 }
 
 
@@ -38,8 +38,8 @@
  * down last and resume them first. That way, we don't do anything stupid like
  * shutting down the interrupt controller before any devices..
  *
- * Note that there are not different stages for power management calls - 
- * they only get one called once when interrupts are disabled. 
+ * Note that there are not different stages for power management calls -
+ * they only get one called once when interrupts are disabled.
  */
 
 extern int sysdev_shutdown(void);
@@ -50,10 +50,10 @@
 void device_shutdown(void)
 {
 	struct device * dev;
-	
+
 	down_write(&devices_subsys.rwsem);
-	list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) {
-		pr_debug("shutting down %s: ",dev->bus_id);
+	list_for_each_entry_reverse(dev, &devices_subsys.kset.list, kobj.entry) {
+		pr_debug("shutting down %s: ", dev->bus_id);
 		if (dev->driver && dev->driver->shutdown) {
 			pr_debug("Ok\n");
 			dev->driver->shutdown(dev);
diff -Nru a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
--- a/drivers/base/power/suspend.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/base/power/suspend.c	2004-06-23 19:04:28 -07:00
@@ -1,5 +1,5 @@
 /*
- * suspend.c - Functions for putting devices to sleep. 
+ * suspend.c - Functions for putting devices to sleep.
  *
  * Copyright (c) 2003 Patrick Mochel
  * Copyright (c) 2003 Open Source Development Labs
@@ -10,18 +10,18 @@
 
 #include <linux/device.h>
 #include "power.h"
- 
+
 extern int sysdev_suspend(u32 state);
 
 /*
  * The entries in the dpm_active list are in a depth first order, simply
- * because children are guaranteed to be discovered after parents, and 
- * are inserted at the back of the list on discovery. 
- * 
+ * because children are guaranteed to be discovered after parents, and
+ * are inserted at the back of the list on discovery.
+ *
  * All list on the suspend path are done in reverse order, so we operate
  * on the leaves of the device tree (or forests, depending on how you want
- * to look at it ;) first. As nodes are removed from the back of the list, 
- * they are inserted into the front of their destintation lists. 
+ * to look at it ;) first. As nodes are removed from the back of the list,
+ * they are inserted into the front of their destintation lists.
  *
  * Things are the reverse on the resume path - iterations are done in
  * forward order, and nodes are inserted at the back of their destination
@@ -44,7 +44,7 @@
 	dev->power.prev_state = dev->power.power_state;
 
 	if (dev->bus && dev->bus->suspend && !dev->power.power_state)
-		error = dev->bus->suspend(dev,state);
+		error = dev->bus->suspend(dev, state);
 
 	return error;
 }
@@ -52,16 +52,16 @@
 
 /**
  *	device_suspend - Save state and stop all devices in system.
- *	@state:		Power state to put each device in. 
+ *	@state:		Power state to put each device in.
  *
  *	Walk the dpm_active list, call ->suspend() for each device, and move
- *	it to dpm_off. 
+ *	it to dpm_off.
  *	Check the return value for each. If it returns 0, then we move the
- *	the device to the dpm_off list. If it returns -EAGAIN, we move it to 
- *	the dpm_off_irq list. If we get a different error, try and back out. 
+ *	the device to the dpm_off list. If it returns -EAGAIN, we move it to
+ *	the dpm_off_irq list. If we get a different error, try and back out.
  *
  *	If we hit a failure with any of the devices, call device_resume()
- *	above to bring the suspended devices back to life. 
+ *	above to bring the suspended devices back to life.
  *
  *	Note this function leaves dpm_sem held to
  *	a) block other devices from registering.
@@ -78,14 +78,14 @@
 	while(!list_empty(&dpm_active)) {
 		struct list_head * entry = dpm_active.prev;
 		struct device * dev = to_device(entry);
-		error = suspend_device(dev,state);
+		error = suspend_device(dev, state);
 
 		if (!error) {
 			list_del(&dev->power.entry);
-			list_add(&dev->power.entry,&dpm_off);
+			list_add(&dev->power.entry, &dpm_off);
 		} else if (error == -EAGAIN) {
 			list_del(&dev->power.entry);
-			list_add(&dev->power.entry,&dpm_off_irq);
+			list_add(&dev->power.entry, &dpm_off_irq);
 		} else {
 			printk(KERN_ERR "Could not suspend device %s: "
 				"error %d\n", kobject_name(&dev->kobj), error);
@@ -108,8 +108,8 @@
  *	@state:		Power state to enter.
  *
  *	Walk the dpm_off_irq list, calling ->power_down() for each device that
- *	couldn't power down the device with interrupts enabled. When we're 
- *	done, power down system devices. 
+ *	couldn't power down the device with interrupts enabled. When we're
+ *	done, power down system devices.
  */
 
 int device_power_down(u32 state)
@@ -117,10 +117,10 @@
 	int error = 0;
 	struct device * dev;
 
-	list_for_each_entry_reverse(dev,&dpm_off_irq,power.entry) {
-		if ((error = suspend_device(dev,state)))
+	list_for_each_entry_reverse(dev, &dpm_off_irq, power.entry) {
+		if ((error = suspend_device(dev, state)))
 			break;
-	} 
+	}
 	if (error)
 		goto Error;
 	if ((error = sysdev_suspend(state)))
diff -Nru a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
--- a/drivers/base/power/sysfs.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/base/power/sysfs.c	2004-06-23 19:04:29 -07:00
@@ -11,10 +11,10 @@
  *
  *	show() returns the current power state of the device. '0' indicates
  *	the device is on. Other values (1-3) indicate the device is in a low
- *	power state. 
+ *	power state.
  *
- *	store() sets the current power state, which is an integer value 
- *	between 0-3. If the device is on ('0'), and the value written is 
+ *	store() sets the current power state, which is an integer value
+ *	between 0-3. If the device is on ('0'), and the value written is
  *	greater than 0, then the device is placed directly into the low-power
  *	state (via its driver's ->suspend() method).
  *	If the device is currently in a low-power state, and the value is 0,
@@ -26,7 +26,7 @@
 
 static ssize_t state_show(struct device * dev, char * buf)
 {
-	return sprintf(buf,"%u\n",dev->power.power_state);
+	return sprintf(buf, "%u\n", dev->power.power_state);
 }
 
 static ssize_t state_store(struct device * dev, const char * buf, size_t n)
@@ -35,17 +35,17 @@
 	char * rest;
 	int error = 0;
 
-	state = simple_strtoul(buf,&rest,10);
+	state = simple_strtoul(buf, &rest, 10);
 	if (*rest)
 		return -EINVAL;
 	if (state)
-		error = dpm_runtime_suspend(dev,state);
+		error = dpm_runtime_suspend(dev, state);
 	else
 		dpm_runtime_resume(dev);
 	return error ? error : n;
 }
 
-static DEVICE_ATTR(state,0644,state_show,state_store);
+static DEVICE_ATTR(state, 0644, state_show, state_store);
 
 
 static struct attribute * power_attrs[] = {
@@ -59,10 +59,10 @@
 
 int dpm_sysfs_add(struct device * dev)
 {
-	return sysfs_create_group(&dev->kobj,&pm_attr_group);
+	return sysfs_create_group(&dev->kobj, &pm_attr_group);
 }
 
 void dpm_sysfs_remove(struct device * dev)
 {
-	sysfs_remove_group(&dev->kobj,&pm_attr_group);
+	sysfs_remove_group(&dev->kobj, &pm_attr_group);
 }
diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c
--- a/drivers/base/sys.c	2004-06-23 19:04:24 -07:00
+++ b/drivers/base/sys.c	2004-06-23 19:04:24 -07:00
@@ -5,8 +5,8 @@
  *               2002-3 Open Source Development Lab
  *
  * This file is released under the GPLv2
- * 
- * This exports a 'system' bus type. 
+ *
+ * This exports a 'system' bus type.
  * By default, a 'sys' bus gets added to the root of the system. There will
  * always be core system devices. Devices can use sysdev_register() to
  * add themselves as children of the system bus.
@@ -24,31 +24,31 @@
 
 extern struct subsystem devices_subsys;
 
-#define to_sysdev(k) container_of(k,struct sys_device,kobj)
-#define to_sysdev_attr(a) container_of(a,struct sysdev_attribute,attr)
+#define to_sysdev(k) container_of(k, struct sys_device, kobj)
+#define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr)
 
 
-static ssize_t 
+static ssize_t
 sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
 {
 	struct sys_device * sysdev = to_sysdev(kobj);
 	struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
 
 	if (sysdev_attr->show)
-		return sysdev_attr->show(sysdev,buffer);
+		return sysdev_attr->show(sysdev, buffer);
 	return 0;
 }
 
 
 static ssize_t
-sysdev_store(struct kobject * kobj, struct attribute * attr, 
+sysdev_store(struct kobject * kobj, struct attribute * attr,
 	     const char * buffer, size_t count)
 {
 	struct sys_device * sysdev = to_sysdev(kobj);
 	struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
 
 	if (sysdev_attr->store)
-		return sysdev_attr->store(sysdev,buffer,count);
+		return sysdev_attr->store(sysdev, buffer, count);
 	return 0;
 }
 
@@ -64,22 +64,22 @@
 
 int sysdev_create_file(struct sys_device * s, struct sysdev_attribute * a)
 {
-	return sysfs_create_file(&s->kobj,&a->attr);
+	return sysfs_create_file(&s->kobj, &a->attr);
 }
 
 
 void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a)
 {
-	sysfs_remove_file(&s->kobj,&a->attr);
+	sysfs_remove_file(&s->kobj, &a->attr);
 }
 
 EXPORT_SYMBOL(sysdev_create_file);
 EXPORT_SYMBOL(sysdev_remove_file);
 
-/* 
- * declare system_subsys 
+/*
+ * declare system_subsys
  */
-decl_subsys(system,&ktype_sysdev,NULL);
+decl_subsys(system, &ktype_sysdev, NULL);
 
 int sysdev_class_register(struct sysdev_class * cls)
 {
@@ -87,7 +87,7 @@
 		 kobject_name(&cls->kset.kobj));
 	INIT_LIST_HEAD(&cls->drivers);
 	cls->kset.subsys = &system_subsys;
-	kset_set_kset_s(cls,system_subsys);
+	kset_set_kset_s(cls, system_subsys);
 	return kset_register(&cls->kset);
 }
 
@@ -109,19 +109,19 @@
  * 	@cls:	Device class driver belongs to.
  *	@drv:	Driver.
  *
- *	If @cls is valid, then @drv is inserted into @cls->drivers to be 
+ *	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 
+ *	of @cls is incremented.
+ *	Otherwise, @drv is inserted into global_drivers, and called for
  *	each device.
  */
 
-int sysdev_driver_register(struct sysdev_class * cls, 
+int sysdev_driver_register(struct sysdev_class * cls,
 			   struct sysdev_driver * drv)
 {
 	down_write(&system_subsys.rwsem);
 	if (cls && kset_get(&cls->kset)) {
-		list_add_tail(&drv->entry,&cls->drivers);
+		list_add_tail(&drv->entry, &cls->drivers);
 
 		/* If devices of this class already exist, tell the driver */
 		if (drv->add) {
@@ -130,7 +130,7 @@
 				drv->add(dev);
 		}
 	} else
-		list_add_tail(&drv->entry,&global_drivers);
+		list_add_tail(&drv->entry, &global_drivers);
 	up_write(&system_subsys.rwsem);
 	return 0;
 }
@@ -180,12 +180,12 @@
 
 	/* But make sure we point to the right type for sysfs translation */
 	sysdev->kobj.ktype = &ktype_sysdev;
-	error = kobject_set_name(&sysdev->kobj,"%s%d",
-			 kobject_name(&cls->kset.kobj),sysdev->id);
+	error = kobject_set_name(&sysdev->kobj, "%s%d",
+			 kobject_name(&cls->kset.kobj), sysdev->id);
 	if (error)
 		return error;
 
-	pr_debug("Registering sys device '%s'\n",kobject_name(&sysdev->kobj));
+	pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
 
 	/* Register the object */
 	error = kobject_register(&sysdev->kobj);
@@ -194,18 +194,18 @@
 		struct sysdev_driver * drv;
 
 		down_write(&system_subsys.rwsem);
-		/* Generic notification is implicit, because it's that 
-		 * code that should have called us. 
+		/* 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, &global_drivers, entry) {
 			if (drv->add)
 				drv->add(sysdev);
 		}
 
 		/* Notify class auxillary drivers */
-		list_for_each_entry(drv,&cls->drivers,entry) {
+		list_for_each_entry(drv, &cls->drivers, entry) {
 			if (drv->add)
 				drv->add(sysdev);
 		}
@@ -219,12 +219,12 @@
 	struct sysdev_driver * drv;
 
 	down_write(&system_subsys.rwsem);
-	list_for_each_entry(drv,&global_drivers,entry) {
+	list_for_each_entry(drv, &global_drivers, entry) {
 		if (drv->remove)
 			drv->remove(sysdev);
 	}
 
-	list_for_each_entry(drv,&sysdev->cls->drivers,entry) {
+	list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
 		if (drv->remove)
 			drv->remove(sysdev);
 	}
@@ -241,12 +241,12 @@
  *	Loop over each class of system devices, and the devices in each
  *	of those classes. For each device, we call the shutdown method for
  *	each driver registered for the device - the globals, the auxillaries,
- *	and the class driver. 
+ *	and the class driver.
  *
  *	Note: The list is iterated in reverse order, so that we shut down
  *	child devices before we shut down thier parents. The list ordering
  *	is guaranteed by virtue of the fact that child devices are registered
- *	after their parents. 
+ *	after their parents.
  */
 
 void sysdev_shutdown(void)
@@ -256,25 +256,25 @@
 	pr_debug("Shutting Down System Devices\n");
 
 	down_write(&system_subsys.rwsem);
-	list_for_each_entry_reverse(cls,&system_subsys.kset.list,
+	list_for_each_entry_reverse(cls, &system_subsys.kset.list,
 				    kset.kobj.entry) {
 		struct sys_device * sysdev;
 
 		pr_debug("Shutting down type '%s':\n",
 			 kobject_name(&cls->kset.kobj));
 
-		list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
+		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
 			struct sysdev_driver * drv;
-			pr_debug(" %s\n",kobject_name(&sysdev->kobj));
+			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, &global_drivers, entry) {
 				if (drv->shutdown)
 					drv->shutdown(sysdev);
 			}
 
 			/* Call auxillary drivers next. */
-			list_for_each_entry(drv,&cls->drivers,entry) {
+			list_for_each_entry(drv, &cls->drivers, entry) {
 				if (drv->shutdown)
 					drv->shutdown(sysdev);
 			}
@@ -295,7 +295,7 @@
  *	We perform an almost identical operation as sys_device_shutdown()
  *	above, though calling ->suspend() instead. Interrupts are disabled
  *	when this called. Devices are responsible for both saving state and
- *	quiescing or powering down the device. 
+ *	quiescing or powering down the device.
  *
  *	This is only called by the device PM core, so we let them handle
  *	all synchronization.
@@ -307,32 +307,32 @@
 
 	pr_debug("Suspending System Devices\n");
 
-	list_for_each_entry_reverse(cls,&system_subsys.kset.list,
+	list_for_each_entry_reverse(cls, &system_subsys.kset.list,
 				    kset.kobj.entry) {
 		struct sys_device * sysdev;
 
 		pr_debug("Suspending type '%s':\n",
 			 kobject_name(&cls->kset.kobj));
 
-		list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
+		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
 			struct sysdev_driver * drv;
-			pr_debug(" %s\n",kobject_name(&sysdev->kobj));
+			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, &global_drivers, entry) {
 				if (drv->suspend)
-					drv->suspend(sysdev,state);
+					drv->suspend(sysdev, state);
 			}
 
 			/* Call auxillary drivers next. */
-			list_for_each_entry(drv,&cls->drivers,entry) {
+			list_for_each_entry(drv, &cls->drivers, entry) {
 				if (drv->suspend)
-					drv->suspend(sysdev,state);
+					drv->suspend(sysdev, state);
 			}
 
 			/* Now call the generic one */
 			if (cls->suspend)
-				cls->suspend(sysdev,state);
+				cls->suspend(sysdev, state);
 		}
 	}
 	return 0;
@@ -345,7 +345,7 @@
  *	Similar to sys_device_suspend(), but we iterate the list forwards
  *	to guarantee that parent devices are resumed before their children.
  *
- *	Note: Interrupts are disabled when called. 
+ *	Note: Interrupts are disabled when called.
  */
 
 int sysdev_resume(void)
@@ -354,28 +354,28 @@
 
 	pr_debug("Resuming System Devices\n");
 
-	list_for_each_entry(cls,&system_subsys.kset.list,kset.kobj.entry) {
+	list_for_each_entry(cls, &system_subsys.kset.list, kset.kobj.entry) {
 		struct sys_device * sysdev;
 
 		pr_debug("Resuming type '%s':\n",
 			 kobject_name(&cls->kset.kobj));
 
-		list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
+		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
 			struct sysdev_driver * drv;
-			pr_debug(" %s\n",kobject_name(&sysdev->kobj));
+			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
 			/* First, call the class-specific one */
 			if (cls->resume)
 				cls->resume(sysdev);
 
 			/* Call auxillary drivers next. */
-			list_for_each_entry(drv,&cls->drivers,entry) {
+			list_for_each_entry(drv, &cls->drivers, entry) {
 				if (drv->resume)
 					drv->resume(sysdev);
 			}
 
 			/* Call global drivers. */
-			list_for_each_entry(drv,&global_drivers,entry) {
+			list_for_each_entry(drv, &global_drivers, entry) {
 				if (drv->resume)
 					drv->resume(sysdev);
 			}
diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig
--- a/drivers/block/Kconfig	2004-06-23 19:04:26 -07:00
+++ b/drivers/block/Kconfig	2004-06-23 19:04:26 -07:00
@@ -6,7 +6,7 @@
 
 config BLK_DEV_FD
 	tristate "Normal floppy disk support"
-	depends on (!X86_PC9800 && !ARCH_S390 && !M68K && !IA64) || Q40 || (SUN3X && BROKEN)
+	depends on (!ARCH_S390 && !M68K && !IA64) || Q40 || (SUN3X && BROKEN)
 	---help---
 	  If you want to use the floppy disk drive(s) of your PC under Linux,
 	  say Y. Information about this driver, especially important for IBM
@@ -26,13 +26,6 @@
 	tristate "Atari floppy support"
 	depends on ATARI
 
-config BLK_DEV_FD98
-	tristate "NEC PC-9800 floppy disk support"
-	depends on X86_PC9800
-	---help---
-	  If you want to use the floppy disk drive(s) of NEC PC-9801/PC-9821,
-	  say Y.
-
 config BLK_DEV_SWIM_IOP
 	bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)"
 	depends on MAC && EXPERIMENTAL && BROKEN
@@ -292,14 +285,14 @@
 
 	  If unsure, say N.
 
-config BLK_DEV_CARMEL
-	tristate "Promise SATA SX8 (carmel) support"
+config BLK_DEV_SX8
+	tristate "Promise SATA SX8 support"
 	depends on PCI
 	---help---
 	  Saying Y or M here will enable support for the 
-	  Promise SATA SX8 ("carmel") controllers.
+	  Promise SATA SX8 controllers.
 
-	  Use devices /dev/carmel/$N and /dev/carmel/$Np$M.
+	  Use devices /dev/sx8/$N and /dev/sx8/$Np$M.
 
 config BLK_DEV_RAM
 	tristate "RAM disk support"
diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile
--- a/drivers/block/Makefile	2004-06-23 19:04:28 -07:00
+++ b/drivers/block/Makefile	2004-06-23 19:04:28 -07:00
@@ -41,5 +41,5 @@
 obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
 
 obj-$(CONFIG_VIODASD)		+= viodasd.o
-obj-$(CONFIG_BLK_DEV_CARMEL)	+= carmel.o
+obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
 
diff -Nru a/drivers/block/carmel.c b/drivers/block/carmel.c
--- a/drivers/block/carmel.c	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,1763 +0,0 @@
-/*
- *  carmel.c: Driver for Promise SATA SX8 looks-like-I2O hardware
- *
- *  Copyright 2004 Red Hat, Inc.
- *
- *  Author/maintainer:  Jeff Garzik <jgarzik@pobox.com>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file "COPYING" in the main directory of this archive
- *  for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/blkdev.h>
-#include <linux/sched.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/interrupt.h>
-#include <linux/compiler.h>
-#include <linux/workqueue.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/hdreg.h>
-#include <asm/io.h>
-#include <asm/semaphore.h>
-#include <asm/uaccess.h>
-
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Promise SATA SX8 (carmel) block driver");
-
-#if 0
-#define CARM_DEBUG
-#define CARM_VERBOSE_DEBUG
-#else
-#undef CARM_DEBUG
-#undef CARM_VERBOSE_DEBUG
-#endif
-#undef CARM_NDEBUG
-
-#define DRV_NAME "carmel"
-#define DRV_VERSION "0.8"
-#define PFX DRV_NAME ": "
-
-#define NEXT_RESP(idx)	((idx + 1) % RMSG_Q_LEN)
-
-/* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */
-#define TAG_ENCODE(tag)	(((tag) << 16) | 0xf)
-#define TAG_DECODE(tag)	(((tag) >> 16) & 0x1f)
-#define TAG_VALID(tag)	((((tag) & 0xf) == 0xf) && (TAG_DECODE(tag) < 32))
-
-/* note: prints function name for you */
-#ifdef CARM_DEBUG
-#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
-#ifdef CARM_VERBOSE_DEBUG
-#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
-#else
-#define VPRINTK(fmt, args...)
-#endif	/* CARM_VERBOSE_DEBUG */
-#else
-#define DPRINTK(fmt, args...)
-#define VPRINTK(fmt, args...)
-#endif	/* CARM_DEBUG */
-
-#ifdef CARM_NDEBUG
-#define assert(expr)
-#else
-#define assert(expr) \
-        if(unlikely(!(expr))) {                                   \
-        printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
-        #expr,__FILE__,__FUNCTION__,__LINE__);          \
-        }
-#endif
-
-/* defines only for the constants which don't work well as enums */
-struct carm_host;
-
-enum {
-	/* adapter-wide limits */
-	CARM_MAX_PORTS		= 8,
-	CARM_SHM_SIZE		= (4096 << 7),
-	CARM_MINORS_PER_MAJOR	= 256 / CARM_MAX_PORTS,
-	CARM_MAX_WAIT_Q		= CARM_MAX_PORTS + 1,
-
-	/* command message queue limits */
-	CARM_MAX_REQ		= 64,	       /* max command msgs per host */
-	CARM_MAX_Q		= 1,		   /* one command at a time */
-	CARM_MSG_LOW_WATER	= (CARM_MAX_REQ / 4),	     /* refill mark */
-
-	/* S/G limits, host-wide and per-request */
-	CARM_MAX_REQ_SG		= 32,	     /* max s/g entries per request */
-	CARM_SG_BOUNDARY	= 0xffffUL,	    /* s/g segment boundary */
-	CARM_MAX_HOST_SG	= 600,		/* max s/g entries per host */
-	CARM_SG_LOW_WATER	= (CARM_MAX_HOST_SG / 4),   /* re-fill mark */
-
-	/* hardware registers */
-	CARM_IHQP		= 0x1c,
-	CARM_INT_STAT		= 0x10, /* interrupt status */
-	CARM_INT_MASK		= 0x14, /* interrupt mask */
-	CARM_HMUC		= 0x18, /* host message unit control */
-	RBUF_ADDR_LO		= 0x20, /* response msg DMA buf low 32 bits */
-	RBUF_ADDR_HI		= 0x24, /* response msg DMA buf high 32 bits */
-	RBUF_BYTE_SZ		= 0x28,
-	CARM_RESP_IDX		= 0x2c,
-	CARM_CMS0		= 0x30, /* command message size reg 0 */
-	CARM_LMUC		= 0x48,
-	CARM_HMPHA		= 0x6c,
-	CARM_INITC		= 0xb5,
-
-	/* bits in CARM_INT_{STAT,MASK} */
-	INT_RESERVED		= 0xfffffff0,
-	INT_WATCHDOG		= (1 << 3),	/* watchdog timer */
-	INT_Q_OVERFLOW		= (1 << 2),	/* cmd msg q overflow */
-	INT_Q_AVAILABLE		= (1 << 1),	/* cmd msg q has free space */
-	INT_RESPONSE		= (1 << 0),	/* response msg available */
-	INT_ACK_MASK		= INT_WATCHDOG | INT_Q_OVERFLOW,
-	INT_DEF_MASK		= INT_RESERVED | INT_Q_OVERFLOW |
-				  INT_RESPONSE,
-
-	/* command messages, and related register bits */
-	CARM_HAVE_RESP		= 0x01,
-	CARM_MSG_READ		= 1,
-	CARM_MSG_WRITE		= 2,
-	CARM_MSG_VERIFY		= 3,
-	CARM_MSG_GET_CAPACITY	= 4,
-	CARM_MSG_FLUSH		= 5,
-	CARM_MSG_IOCTL		= 6,
-	CARM_MSG_ARRAY		= 8,
-	CARM_MSG_MISC		= 9,
-	CARM_CME		= (1 << 2),
-	CARM_RME		= (1 << 1),
-	CARM_WZBC		= (1 << 0),
-	CARM_RMI		= (1 << 0),
-	CARM_Q_FULL		= (1 << 3),
-	CARM_MSG_SIZE		= 288,
-	CARM_Q_LEN		= 48,
-
-	/* CARM_MSG_IOCTL messages */
-	CARM_IOC_SCAN_CHAN	= 5,	/* scan channels for devices */
-	CARM_IOC_GET_TCQ	= 13,	/* get tcq/ncq depth */
-	CARM_IOC_SET_TCQ	= 14,	/* set tcq/ncq depth */
-
-	IOC_SCAN_CHAN_NODEV	= 0x1f,
-	IOC_SCAN_CHAN_OFFSET	= 0x40,
-
-	/* CARM_MSG_ARRAY messages */
-	CARM_ARRAY_INFO		= 0,
-
-	ARRAY_NO_EXIST		= (1 << 31),
-
-	/* response messages */
-	RMSG_SZ			= 8,	/* sizeof(struct carm_response) */
-	RMSG_Q_LEN		= 48,	/* resp. msg list length */
-	RMSG_OK			= 1,	/* bit indicating msg was successful */
-					/* length of entire resp. msg buffer */
-	RBUF_LEN		= RMSG_SZ * RMSG_Q_LEN,
-
-	PDC_SHM_SIZE		= (4096 << 7), /* length of entire h/w buffer */
-
-	/* CARM_MSG_MISC messages */
-	MISC_GET_FW_VER		= 2,
-	MISC_ALLOC_MEM		= 3,
-	MISC_SET_TIME		= 5,
-
-	/* MISC_GET_FW_VER feature bits */
-	FW_VER_4PORT		= (1 << 2), /* 1=4 ports, 0=8 ports */
-	FW_VER_NON_RAID		= (1 << 1), /* 1=non-RAID firmware, 0=RAID */
-	FW_VER_ZCR		= (1 << 0), /* zero channel RAID (whatever that is) */
-
-	/* carm_host flags */
-	FL_NON_RAID		= FW_VER_NON_RAID,
-	FL_4PORT		= FW_VER_4PORT,
-	FL_FW_VER_MASK		= (FW_VER_NON_RAID | FW_VER_4PORT),
-	FL_DAC			= (1 << 16),
-	FL_DYN_MAJOR		= (1 << 17),
-};
-
-enum scatter_gather_types {
-	SGT_32BIT		= 0,
-	SGT_64BIT		= 1,
-};
-
-enum host_states {
-	HST_INVALID,		/* invalid state; never used */
-	HST_ALLOC_BUF,		/* setting up master SHM area */
-	HST_ERROR,		/* we never leave here */
-	HST_PORT_SCAN,		/* start dev scan */
-	HST_DEV_SCAN_START,	/* start per-device probe */
-	HST_DEV_SCAN,		/* continue per-device probe */
-	HST_DEV_ACTIVATE,	/* activate devices we found */
-	HST_PROBE_FINISHED,	/* probe is complete */
-	HST_PROBE_START,	/* initiate probe */
-	HST_SYNC_TIME,		/* tell firmware what time it is */
-	HST_GET_FW_VER,		/* get firmware version, adapter port cnt */
-};
-
-#ifdef CARM_DEBUG
-static const char *state_name[] = {
-	"HST_INVALID",
-	"HST_ALLOC_BUF",
-	"HST_ERROR",
-	"HST_PORT_SCAN",
-	"HST_DEV_SCAN_START",
-	"HST_DEV_SCAN",
-	"HST_DEV_ACTIVATE",
-	"HST_PROBE_FINISHED",
-	"HST_PROBE_START",
-	"HST_SYNC_TIME",
-	"HST_GET_FW_VER",
-};
-#endif
-
-struct carm_port {
-	unsigned int			port_no;
-	unsigned int			n_queued;
-	struct gendisk			*disk;
-	struct carm_host		*host;
-
-	/* attached device characteristics */
-	u64				capacity;
-	char				name[41];
-	u16				dev_geom_head;
-	u16				dev_geom_sect;
-	u16				dev_geom_cyl;
-};
-
-struct carm_request {
-	unsigned int			tag;
-	int				n_elem;
-	unsigned int			msg_type;
-	unsigned int			msg_subtype;
-	unsigned int			msg_bucket;
-	struct request			*rq;
-	struct carm_port		*port;
-	struct scatterlist		sg[CARM_MAX_REQ_SG];
-};
-
-struct carm_host {
-	unsigned long			flags;
-	void				*mmio;
-	void				*shm;
-	dma_addr_t			shm_dma;
-
-	int				major;
-	int				id;
-	char				name[32];
-
-	spinlock_t			lock;
-	struct pci_dev			*pdev;
-	unsigned int			state;
-	u32				fw_ver;
-
-	request_queue_t			*oob_q;
-	unsigned int			n_oob;
-
-	unsigned int			hw_sg_used;
-
-	unsigned int			resp_idx;
-
-	unsigned int			wait_q_prod;
-	unsigned int			wait_q_cons;
-	request_queue_t			*wait_q[CARM_MAX_WAIT_Q];
-
-	unsigned int			n_msgs;
-	u64				msg_alloc;
-	struct carm_request		req[CARM_MAX_REQ];
-	void				*msg_base;
-	dma_addr_t			msg_dma;
-
-	int				cur_scan_dev;
-	unsigned long			dev_active;
-	unsigned long			dev_present;
-	struct carm_port		port[CARM_MAX_PORTS];
-
-	struct work_struct		fsm_task;
-
-	struct semaphore		probe_sem;
-};
-
-struct carm_response {
-	u32 ret_handle;
-	u32 status;
-}  __attribute__((packed));
-
-struct carm_msg_sg {
-	u32 start;
-	u32 len;
-}  __attribute__((packed));
-
-struct carm_msg_rw {
-	u8 type;
-	u8 id;
-	u8 sg_count;
-	u8 sg_type;
-	u32 handle;
-	u32 lba;
-	u16 lba_count;
-	u16 lba_high;
-	struct carm_msg_sg sg[32];
-}  __attribute__((packed));
-
-struct carm_msg_allocbuf {
-	u8 type;
-	u8 subtype;
-	u8 n_sg;
-	u8 sg_type;
-	u32 handle;
-	u32 addr;
-	u32 len;
-	u32 evt_pool;
-	u32 n_evt;
-	u32 rbuf_pool;
-	u32 n_rbuf;
-	u32 msg_pool;
-	u32 n_msg;
-	struct carm_msg_sg sg[8];
-}  __attribute__((packed));
-
-struct carm_msg_ioctl {
-	u8 type;
-	u8 subtype;
-	u8 array_id;
-	u8 reserved1;
-	u32 handle;
-	u32 data_addr;
-	u32 reserved2;
-}  __attribute__((packed));
-
-struct carm_msg_sync_time {
-	u8 type;
-	u8 subtype;
-	u16 reserved1;
-	u32 handle;
-	u32 reserved2;
-	u32 timestamp;
-}  __attribute__((packed));
-
-struct carm_msg_get_fw_ver {
-	u8 type;
-	u8 subtype;
-	u16 reserved1;
-	u32 handle;
-	u32 data_addr;
-	u32 reserved2;
-}  __attribute__((packed));
-
-struct carm_fw_ver {
-	u32 version;
-	u8 features;
-	u8 reserved1;
-	u16 reserved2;
-}  __attribute__((packed));
-
-struct carm_array_info {
-	u32 size;
-
-	u16 size_hi;
-	u16 stripe_size;
-
-	u32 mode;
-
-	u16 stripe_blk_sz;
-	u16 reserved1;
-
-	u16 cyl;
-	u16 head;
-
-	u16 sect;
-	u8 array_id;
-	u8 reserved2;
-
-	char name[40];
-
-	u32 array_status;
-
-	/* device list continues beyond this point? */
-}  __attribute__((packed));
-
-static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void carm_remove_one (struct pci_dev *pdev);
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
-			   unsigned int cmd, unsigned long arg);
-
-static struct pci_device_id carm_pci_tbl[] = {
-	{ PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{ PCI_VENDOR_ID_PROMISE, 0x8002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{ }	/* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, carm_pci_tbl);
-
-static struct pci_driver carm_driver = {
-	.name		= DRV_NAME,
-	.id_table	= carm_pci_tbl,
-	.probe		= carm_init_one,
-	.remove		= carm_remove_one,
-};
-
-static struct block_device_operations carm_bd_ops = {
-	.owner		= THIS_MODULE,
-	.ioctl		= carm_bdev_ioctl,
-};
-
-static unsigned int carm_host_id;
-static unsigned long carm_major_alloc;
-
-
-
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
-			   unsigned int cmd, unsigned long arg)
-{
-	void __user *usermem = (void __user *) arg;
-	struct carm_port *port = ino->i_bdev->bd_disk->private_data;
-	struct hd_geometry geom;
-
-	switch (cmd) {
-	case HDIO_GETGEO:
-		if (!usermem)
-			return -EINVAL;
-
-		geom.heads = (u8) port->dev_geom_head;
-		geom.sectors = (u8) port->dev_geom_sect;
-		geom.cylinders = port->dev_geom_cyl;
-		geom.start = get_start_sect(ino->i_bdev);
-
-		if (copy_to_user(usermem, &geom, sizeof(geom)))
-			return -EFAULT;
-		return 0;
-
-	default:
-		break;
-	}
-
-	return -EOPNOTSUPP;
-}
-
-static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE };
-
-static inline int carm_lookup_bucket(u32 msg_size)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
-		if (msg_size <= msg_sizes[i])
-			return i;
-	
-	return -ENOENT;
-}
-
-static void carm_init_buckets(void *mmio)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
-		writel(msg_sizes[i], mmio + CARM_CMS0 + (4 * i));
-}
-
-static inline void *carm_ref_msg(struct carm_host *host,
-				 unsigned int msg_idx)
-{
-	return host->msg_base + (msg_idx * CARM_MSG_SIZE);
-}
-
-static inline dma_addr_t carm_ref_msg_dma(struct carm_host *host,
-					  unsigned int msg_idx)
-{
-	return host->msg_dma + (msg_idx * CARM_MSG_SIZE);
-}
-
-static int carm_send_msg(struct carm_host *host,
-			 struct carm_request *crq)
-{
-	void *mmio = host->mmio;
-	u32 msg = (u32) carm_ref_msg_dma(host, crq->tag);
-	u32 cm_bucket = crq->msg_bucket;
-	u32 tmp;
-	int rc = 0;
-
-	VPRINTK("ENTER\n");
-
-	tmp = readl(mmio + CARM_HMUC);
-	if (tmp & CARM_Q_FULL) {
-#if 0
-		tmp = readl(mmio + CARM_INT_MASK);
-		tmp |= INT_Q_AVAILABLE;
-		writel(tmp, mmio + CARM_INT_MASK);
-		readl(mmio + CARM_INT_MASK);	/* flush */
-#endif
-		DPRINTK("host msg queue full\n");
-		rc = -EBUSY;
-	} else {
-		writel(msg | (cm_bucket << 1), mmio + CARM_IHQP);
-		readl(mmio + CARM_IHQP);	/* flush */
-	}
-
-	return rc;
-}
-
-static struct carm_request *carm_get_request(struct carm_host *host)
-{
-	unsigned int i;
-
-	/* obey global hardware limit on S/G entries */
-	if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG))
-		return NULL;
-
-	for (i = 0; i < CARM_MAX_Q; i++)
-		if ((host->msg_alloc & (1ULL << i)) == 0) {
-			struct carm_request *crq = &host->req[i];
-			crq->port = NULL;
-			crq->n_elem = 0;
-
-			host->msg_alloc |= (1ULL << i);
-			host->n_msgs++;
-
-			assert(host->n_msgs <= CARM_MAX_REQ);
-			return crq;
-		}
-	
-	DPRINTK("no request available, returning NULL\n");
-	return NULL;
-}
-
-static int carm_put_request(struct carm_host *host, struct carm_request *crq)
-{
-	assert(crq->tag < CARM_MAX_Q);
-
-	if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0))
-		return -EINVAL; /* tried to clear a tag that was not active */
-
-	assert(host->hw_sg_used >= crq->n_elem);
-
-	host->msg_alloc &= ~(1ULL << crq->tag);
-	host->hw_sg_used -= crq->n_elem;
-	host->n_msgs--;
-
-	return 0;
-}
-
-static struct carm_request *carm_get_special(struct carm_host *host)
-{
-	unsigned long flags;
-	struct carm_request *crq = NULL;
-	struct request *rq;
-	int tries = 5000;
-
-	while (tries-- > 0) {
-		spin_lock_irqsave(&host->lock, flags);
-		crq = carm_get_request(host);
-		spin_unlock_irqrestore(&host->lock, flags);
-
-		if (crq)
-			break;
-		msleep(10);
-	}
-
-	if (!crq)
-		return NULL;
-
-	rq = blk_get_request(host->oob_q, WRITE /* bogus */, GFP_KERNEL);
-	if (!rq) {
-		spin_lock_irqsave(&host->lock, flags);
-		carm_put_request(host, crq);
-		spin_unlock_irqrestore(&host->lock, flags);
-		return NULL;
-	}
-
-	crq->rq = rq;
-	return crq;
-}
-
-static int carm_array_info (struct carm_host *host, unsigned int array_idx)
-{
-	struct carm_msg_ioctl *ioc;
-	unsigned int idx;
-	u32 msg_data;
-	dma_addr_t msg_dma;
-	struct carm_request *crq;
-	int rc;
-
-	crq = carm_get_special(host);
-	if (!crq) {
-		rc = -ENOMEM;
-		goto err_out;
-	}
-
-	idx = crq->tag;
-
-	ioc = carm_ref_msg(host, idx);
-	msg_dma = carm_ref_msg_dma(host, idx);
-	msg_data = (u32) (msg_dma + sizeof(struct carm_array_info));
-
-	crq->msg_type = CARM_MSG_ARRAY;
-	crq->msg_subtype = CARM_ARRAY_INFO;
-	rc = carm_lookup_bucket(sizeof(struct carm_msg_ioctl) +
-				sizeof(struct carm_array_info));
-	BUG_ON(rc < 0);
-	crq->msg_bucket = (u32) rc;
-
-	memset(ioc, 0, sizeof(*ioc));
-	ioc->type	= CARM_MSG_ARRAY;
-	ioc->subtype	= CARM_ARRAY_INFO;
-	ioc->array_id	= (u8) array_idx;
-	ioc->handle	= cpu_to_le32(TAG_ENCODE(idx));
-	ioc->data_addr	= cpu_to_le32(msg_data);
-
-	spin_lock_irq(&host->lock);
-	assert(host->state == HST_DEV_SCAN_START ||
-	       host->state == HST_DEV_SCAN);
-	spin_unlock_irq(&host->lock);
-
-	DPRINTK("blk_insert_request, tag == %u\n", idx);
-	blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
-
-	return 0;
-
-err_out:
-	spin_lock_irq(&host->lock);
-	host->state = HST_ERROR;
-	spin_unlock_irq(&host->lock);
-	return rc;
-}
-
-typedef unsigned int (*carm_sspc_t)(struct carm_host *, unsigned int, void *);
-
-static int carm_send_special (struct carm_host *host, carm_sspc_t func)
-{
-	struct carm_request *crq;
-	struct carm_msg_ioctl *ioc;
-	void *mem;
-	unsigned int idx, msg_size;
-	int rc;
-
-	crq = carm_get_special(host);
-	if (!crq)
-		return -ENOMEM;
-
-	idx = crq->tag;
-
-	mem = carm_ref_msg(host, idx);
-
-	msg_size = func(host, idx, mem);
-
-	ioc = mem;
-	crq->msg_type = ioc->type;
-	crq->msg_subtype = ioc->subtype;
-	rc = carm_lookup_bucket(msg_size);
-	BUG_ON(rc < 0);
-	crq->msg_bucket = (u32) rc;
-
-	DPRINTK("blk_insert_request, tag == %u\n", idx);
-	blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
-
-	return 0;
-}
-
-static unsigned int carm_fill_sync_time(struct carm_host *host,
-					unsigned int idx, void *mem)
-{
-	struct timeval tv;
-	struct carm_msg_sync_time *st = mem;
-
-	do_gettimeofday(&tv);
-
-	memset(st, 0, sizeof(*st));
-	st->type	= CARM_MSG_MISC;
-	st->subtype	= MISC_SET_TIME;
-	st->handle	= cpu_to_le32(TAG_ENCODE(idx));
-	st->timestamp	= cpu_to_le32(tv.tv_sec);
-
-	return sizeof(struct carm_msg_sync_time);
-}
-
-static unsigned int carm_fill_alloc_buf(struct carm_host *host,
-					unsigned int idx, void *mem)
-{
-	struct carm_msg_allocbuf *ab = mem;
-
-	memset(ab, 0, sizeof(*ab));
-	ab->type	= CARM_MSG_MISC;
-	ab->subtype	= MISC_ALLOC_MEM;
-	ab->handle	= cpu_to_le32(TAG_ENCODE(idx));
-	ab->n_sg	= 1;
-	ab->sg_type	= SGT_32BIT;
-	ab->addr	= cpu_to_le32(host->shm_dma + (PDC_SHM_SIZE >> 1));
-	ab->len		= cpu_to_le32(PDC_SHM_SIZE >> 1);
-	ab->evt_pool	= cpu_to_le32(host->shm_dma + (16 * 1024));
-	ab->n_evt	= cpu_to_le32(1024);
-	ab->rbuf_pool	= cpu_to_le32(host->shm_dma);
-	ab->n_rbuf	= cpu_to_le32(RMSG_Q_LEN);
-	ab->msg_pool	= cpu_to_le32(host->shm_dma + RBUF_LEN);
-	ab->n_msg	= cpu_to_le32(CARM_Q_LEN);
-	ab->sg[0].start	= cpu_to_le32(host->shm_dma + (PDC_SHM_SIZE >> 1));
-	ab->sg[0].len	= cpu_to_le32(65536);
-
-	return sizeof(struct carm_msg_allocbuf);
-}
-
-static unsigned int carm_fill_scan_channels(struct carm_host *host,
-					    unsigned int idx, void *mem)
-{
-	struct carm_msg_ioctl *ioc = mem;
-	u32 msg_data = (u32) (carm_ref_msg_dma(host, idx) +
-			      IOC_SCAN_CHAN_OFFSET);
-
-	memset(ioc, 0, sizeof(*ioc));
-	ioc->type	= CARM_MSG_IOCTL;
-	ioc->subtype	= CARM_IOC_SCAN_CHAN;
-	ioc->handle	= cpu_to_le32(TAG_ENCODE(idx));
-	ioc->data_addr	= cpu_to_le32(msg_data);
-
-	/* fill output data area with "no device" default values */
-	mem += IOC_SCAN_CHAN_OFFSET;
-	memset(mem, IOC_SCAN_CHAN_NODEV, CARM_MAX_PORTS);
-
-	return IOC_SCAN_CHAN_OFFSET + CARM_MAX_PORTS;
-}
-
-static unsigned int carm_fill_get_fw_ver(struct carm_host *host,
-					 unsigned int idx, void *mem)
-{
-	struct carm_msg_get_fw_ver *ioc = mem;
-	u32 msg_data = (u32) (carm_ref_msg_dma(host, idx) + sizeof(*ioc));
-
-	memset(ioc, 0, sizeof(*ioc));
-	ioc->type	= CARM_MSG_MISC;
-	ioc->subtype	= MISC_GET_FW_VER;
-	ioc->handle	= cpu_to_le32(TAG_ENCODE(idx));
-	ioc->data_addr	= cpu_to_le32(msg_data);
-
-	return sizeof(struct carm_msg_get_fw_ver) +
-	       sizeof(struct carm_fw_ver);
-}
-
-static inline void carm_end_request_queued(struct carm_host *host,
-					   struct carm_request *crq,
-					   int uptodate)
-{
-	struct request *req = crq->rq;
-	int rc;
-
-	rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
-	assert(rc == 0);
-
-	end_that_request_last(req);
-
-	rc = carm_put_request(host, crq);
-	assert(rc == 0);
-}
-
-static inline void carm_push_q (struct carm_host *host, request_queue_t *q)
-{
-	unsigned int idx = host->wait_q_prod % CARM_MAX_WAIT_Q;
-
-	blk_stop_queue(q);
-	VPRINTK("STOPPED QUEUE %p\n", q);
-
-	host->wait_q[idx] = q;
-	host->wait_q_prod++;
-	BUG_ON(host->wait_q_prod == host->wait_q_cons); /* overrun */
-}
-
-static inline request_queue_t *carm_pop_q(struct carm_host *host)
-{
-	unsigned int idx;
-
-	if (host->wait_q_prod == host->wait_q_cons)
-		return NULL;
-
-	idx = host->wait_q_cons % CARM_MAX_WAIT_Q;
-	host->wait_q_cons++;
-
-	return host->wait_q[idx];
-}
-
-static inline void carm_round_robin(struct carm_host *host)
-{
-	request_queue_t *q = carm_pop_q(host);
-	if (q) {
-		blk_start_queue(q);
-		VPRINTK("STARTED QUEUE %p\n", q);
-	}
-}
-
-static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
-			int is_ok)
-{
-	carm_end_request_queued(host, crq, is_ok);
-	if (CARM_MAX_Q == 1)
-		carm_round_robin(host);
-	else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
-		 (host->hw_sg_used <= CARM_SG_LOW_WATER)) {
-		carm_round_robin(host);
-	}
-}
-
-static void carm_oob_rq_fn(request_queue_t *q)
-{
-	struct carm_host *host = q->queuedata;
-	struct carm_request *crq;
-	struct request *rq;
-	int rc;
-
-	while (1) {
-		DPRINTK("get req\n");
-		rq = elv_next_request(q);
-		if (!rq)
-			break;
-
-		blkdev_dequeue_request(rq);
-
-		crq = rq->special;
-		assert(crq != NULL);
-		assert(crq->rq == rq);
-
-		crq->n_elem = 0;
-
-		DPRINTK("send req\n");
-		rc = carm_send_msg(host, crq);
-		if (rc) {
-			blk_requeue_request(q, rq);
-			carm_push_q(host, q);
-			return;		/* call us again later, eventually */
-		}
-	}
-}
-
-static void carm_rq_fn(request_queue_t *q)
-{
-	struct carm_port *port = q->queuedata;
-	struct carm_host *host = port->host;
-	struct carm_msg_rw *msg;
-	struct carm_request *crq;
-	struct request *rq;
-	struct scatterlist *sg;
-	int writing = 0, pci_dir, i, n_elem, rc;
-	u32 tmp;
-	unsigned int msg_size;
-
-queue_one_request:
-	VPRINTK("get req\n");
-	rq = elv_next_request(q);
-	if (!rq)
-		return;
-
-	crq = carm_get_request(host);
-	if (!crq) {
-		carm_push_q(host, q);
-		return;		/* call us again later, eventually */
-	}
-	crq->rq = rq;
-
-	blkdev_dequeue_request(rq);
-
-	if (rq_data_dir(rq) == WRITE) {
-		writing = 1;
-		pci_dir = PCI_DMA_TODEVICE;
-	} else {
-		pci_dir = PCI_DMA_FROMDEVICE;
-	}
-
-	/* get scatterlist from block layer */
-	sg = &crq->sg[0];
-	n_elem = blk_rq_map_sg(q, rq, sg);
-	if (n_elem <= 0) {
-		carm_end_rq(host, crq, 0);
-		return;		/* request with no s/g entries? */
-	}
-
-	/* map scatterlist to PCI bus addresses */
-	n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir);
-	if (n_elem <= 0) {
-		carm_end_rq(host, crq, 0);
-		return;		/* request with no s/g entries? */
-	}
-	crq->n_elem = n_elem;
-	crq->port = port;
-	host->hw_sg_used += n_elem;
-
-	/*
-	 * build read/write message
-	 */
-
-	VPRINTK("build msg\n");
-	msg = (struct carm_msg_rw *) carm_ref_msg(host, crq->tag);
-
-	if (writing) {
-		msg->type = CARM_MSG_WRITE;
-		crq->msg_type = CARM_MSG_WRITE;
-	} else {
-		msg->type = CARM_MSG_READ;
-		crq->msg_type = CARM_MSG_READ;
-	}
-
-	msg->id		= port->port_no;
-	msg->sg_count	= n_elem;
-	msg->sg_type	= SGT_32BIT;
-	msg->handle	= cpu_to_le32(TAG_ENCODE(crq->tag));
-	msg->lba	= cpu_to_le32(rq->sector & 0xffffffff);
-	tmp		= (rq->sector >> 16) >> 16;
-	msg->lba_high	= cpu_to_le16( (u16) tmp );
-	msg->lba_count	= cpu_to_le16(rq->nr_sectors);
-
-	msg_size = sizeof(struct carm_msg_rw) - sizeof(msg->sg);
-	for (i = 0; i < n_elem; i++) {
-		struct carm_msg_sg *carm_sg = &msg->sg[i];
-		carm_sg->start = cpu_to_le32(sg_dma_address(&crq->sg[i]));
-		carm_sg->len = cpu_to_le32(sg_dma_len(&crq->sg[i]));
-		msg_size += sizeof(struct carm_msg_sg);
-	}
-
-	rc = carm_lookup_bucket(msg_size);
-	BUG_ON(rc < 0);
-	crq->msg_bucket = (u32) rc;
-
-	/*
-	 * queue read/write message to hardware
-	 */
-
-	VPRINTK("send msg, tag == %u\n", crq->tag);
-	rc = carm_send_msg(host, crq);
-	if (rc) {
-		carm_put_request(host, crq);
-		blk_requeue_request(q, rq);
-		carm_push_q(host, q);
-		return;		/* call us again later, eventually */
-	}
-
-	goto queue_one_request;
-}
-
-static void carm_handle_array_info(struct carm_host *host,
-				   struct carm_request *crq, u8 *mem,
-				   int is_ok)
-{
-	struct carm_port *port;
-	u8 *msg_data = mem + sizeof(struct carm_array_info);
-	struct carm_array_info *desc = (struct carm_array_info *) msg_data;
-	u64 lo, hi;
-	int cur_port;
-	size_t slen;
-
-	DPRINTK("ENTER\n");
-
-	carm_end_rq(host, crq, is_ok);
-
-	if (!is_ok)
-		goto out;
-	if (le32_to_cpu(desc->array_status) & ARRAY_NO_EXIST)
-		goto out;
-
-	cur_port = host->cur_scan_dev;
-
-	/* should never occur */
-	if ((cur_port < 0) || (cur_port >= CARM_MAX_PORTS)) {
-		printk(KERN_ERR PFX "BUG: cur_scan_dev==%d, array_id==%d\n",
-		       cur_port, (int) desc->array_id);
-		goto out;
-	}
-
-	port = &host->port[cur_port];
-
-	lo = (u64) le32_to_cpu(desc->size);
-	hi = (u64) le32_to_cpu(desc->size_hi);
-
-	port->capacity = lo | (hi << 32);
-	port->dev_geom_head = le16_to_cpu(desc->head);
-	port->dev_geom_sect = le16_to_cpu(desc->sect);
-	port->dev_geom_cyl = le16_to_cpu(desc->cyl);
-
-	host->dev_active |= (1 << cur_port);
-
-	strncpy(port->name, desc->name, sizeof(port->name));
-	port->name[sizeof(port->name) - 1] = 0;
-	slen = strlen(port->name);
-	while (slen && (port->name[slen - 1] == ' ')) {
-		port->name[slen - 1] = 0;
-		slen--;
-	}
-
-	printk(KERN_INFO DRV_NAME "(%s): port %u device %Lu sectors\n",
-	       pci_name(host->pdev), port->port_no,
-	       (unsigned long long) port->capacity);
-	printk(KERN_INFO DRV_NAME "(%s): port %u device \"%s\"\n",
-	       pci_name(host->pdev), port->port_no, port->name);
-
-out:
-	assert(host->state == HST_DEV_SCAN);
-	schedule_work(&host->fsm_task);
-}
-
-static void carm_handle_scan_chan(struct carm_host *host,
-				  struct carm_request *crq, u8 *mem,
-				  int is_ok)
-{
-	u8 *msg_data = mem + IOC_SCAN_CHAN_OFFSET;
-	unsigned int i, dev_count = 0;
-	int new_state = HST_DEV_SCAN_START;
-
-	DPRINTK("ENTER\n");
-
-	carm_end_rq(host, crq, is_ok);
-
-	if (!is_ok) {
-		new_state = HST_ERROR;
-		goto out;
-	}
-
-	/* TODO: scan and support non-disk devices */
-	for (i = 0; i < 8; i++)
-		if (msg_data[i] == 0) { /* direct-access device (disk) */
-			host->dev_present |= (1 << i);
-			dev_count++;
-		}
-
-	printk(KERN_INFO DRV_NAME "(%s): found %u interesting devices\n",
-	       pci_name(host->pdev), dev_count);
-
-out:
-	assert(host->state == HST_PORT_SCAN);
-	host->state = new_state;
-	schedule_work(&host->fsm_task);
-}
-
-static void carm_handle_generic(struct carm_host *host,
-				struct carm_request *crq, int is_ok,
-				int cur_state, int next_state)
-{
-	DPRINTK("ENTER\n");
-
-	carm_end_rq(host, crq, is_ok);
-
-	assert(host->state == cur_state);
-	if (is_ok)
-		host->state = next_state;
-	else
-		host->state = HST_ERROR;
-	schedule_work(&host->fsm_task);
-}
-
-static inline void carm_handle_rw(struct carm_host *host,
-				  struct carm_request *crq, int is_ok)
-{
-	int pci_dir;
-
-	VPRINTK("ENTER\n");
-
-	if (rq_data_dir(crq->rq) == WRITE)
-		pci_dir = PCI_DMA_TODEVICE;
-	else
-		pci_dir = PCI_DMA_FROMDEVICE;
-
-	pci_unmap_sg(host->pdev, &crq->sg[0], crq->n_elem, pci_dir);
-
-	carm_end_rq(host, crq, is_ok);
-}
-
-static inline void carm_handle_resp(struct carm_host *host,
-				    u32 ret_handle_le, u32 status)
-{
-	u32 handle = le32_to_cpu(ret_handle_le);
-	unsigned int msg_idx;
-	struct carm_request *crq;
-	int is_ok = (status == RMSG_OK);
-	u8 *mem;
-
-	VPRINTK("ENTER, handle == 0x%x\n", handle);
-
-	if (unlikely(!TAG_VALID(handle))) {
-		printk(KERN_ERR DRV_NAME "(%s): BUG: invalid tag 0x%x\n",
-		       pci_name(host->pdev), handle);
-		return;
-	}
-
-	msg_idx = TAG_DECODE(handle);
-	VPRINTK("tag == %u\n", msg_idx);
-
-	crq = &host->req[msg_idx];
-
-	/* fast path */
-	if (likely(crq->msg_type == CARM_MSG_READ ||
-		   crq->msg_type == CARM_MSG_WRITE)) {
-		carm_handle_rw(host, crq, is_ok);
-		return;
-	}
-
-	mem = carm_ref_msg(host, msg_idx);
-
-	switch (crq->msg_type) {
-	case CARM_MSG_IOCTL: {
-		switch (crq->msg_subtype) {
-		case CARM_IOC_SCAN_CHAN:
-			carm_handle_scan_chan(host, crq, mem, is_ok);
-			break;
-		default:
-			/* unknown / invalid response */
-			goto err_out;
-		}
-		break;
-	}
-
-	case CARM_MSG_MISC: {
-		switch (crq->msg_subtype) {
-		case MISC_ALLOC_MEM:
-			carm_handle_generic(host, crq, is_ok,
-					    HST_ALLOC_BUF, HST_SYNC_TIME);
-			break;
-		case MISC_SET_TIME:
-			carm_handle_generic(host, crq, is_ok,
-					    HST_SYNC_TIME, HST_GET_FW_VER);
-			break;
-		case MISC_GET_FW_VER: {
-			struct carm_fw_ver *ver = (struct carm_fw_ver *)
-				mem + sizeof(struct carm_msg_get_fw_ver);
-			if (is_ok) {
-				host->fw_ver = le32_to_cpu(ver->version);
-				host->flags |= (ver->features & FL_FW_VER_MASK);
-			}
-			carm_handle_generic(host, crq, is_ok,
-					    HST_GET_FW_VER, HST_PORT_SCAN);
-			break;
-		}
-		default:
-			/* unknown / invalid response */
-			goto err_out;
-		}
-		break;
-	}
-
-	case CARM_MSG_ARRAY: {
-		switch (crq->msg_subtype) {
-		case CARM_ARRAY_INFO:
-			carm_handle_array_info(host, crq, mem, is_ok);
-			break;
-		default:
-			/* unknown / invalid response */
-			goto err_out;
-		}
-		break;
-	}
-
-	default:
-		/* unknown / invalid response */
-		goto err_out;
-	}
-
-	return;
-
-err_out:
-	printk(KERN_WARNING DRV_NAME "(%s): BUG: unhandled message type %d/%d\n",
-	       pci_name(host->pdev), crq->msg_type, crq->msg_subtype);
-	carm_end_rq(host, crq, 0);
-}
-
-static inline void carm_handle_responses(struct carm_host *host)
-{
-	void *mmio = host->mmio;
-	struct carm_response *resp = (struct carm_response *) host->shm;
-	unsigned int work = 0;
-	unsigned int idx = host->resp_idx % RMSG_Q_LEN;
-
-	while (1) {
-		u32 status = le32_to_cpu(resp[idx].status);
-
-		if (status == 0xffffffff) {
-			VPRINTK("ending response on index %u\n", idx);
-			writel(idx << 3, mmio + CARM_RESP_IDX);
-			break;
-		}
-
-		/* response to a message we sent */
-		else if ((status & (1 << 31)) == 0) {
-			VPRINTK("handling msg response on index %u\n", idx);
-			carm_handle_resp(host, resp[idx].ret_handle, status);
-			resp[idx].status = 0xffffffff;
-		}
-
-		/* asynchronous events the hardware throws our way */
-		else if ((status & 0xff000000) == (1 << 31)) {
-			u8 *evt_type_ptr = (u8 *) &resp[idx];
-			u8 evt_type = *evt_type_ptr;
-			printk(KERN_WARNING DRV_NAME "(%s): unhandled event type %d\n",
-			       pci_name(host->pdev), (int) evt_type);
-			resp[idx].status = 0xffffffff;
-		}
-
-		idx = NEXT_RESP(idx);
-		work++;
-	}
-
-	VPRINTK("EXIT, work==%u\n", work);
-	host->resp_idx += work;
-}
-
-static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs)
-{
-	struct carm_host *host = __host;
-	void *mmio;
-	u32 mask;
-	int handled = 0;
-	unsigned long flags;
-
-	if (!host) {
-		VPRINTK("no host\n");
-		return IRQ_NONE;
-	}
-
-	spin_lock_irqsave(&host->lock, flags);
-
-	mmio = host->mmio;
-
-	/* reading should also clear interrupts */
-	mask = readl(mmio + CARM_INT_STAT);
-
-	if (mask == 0 || mask == 0xffffffff) {
-		VPRINTK("no work, mask == 0x%x\n", mask);
-		goto out;
-	}
-
-	if (mask & INT_ACK_MASK)
-		writel(mask, mmio + CARM_INT_STAT);
-
-	if (unlikely(host->state == HST_INVALID)) {
-		VPRINTK("not initialized yet, mask = 0x%x\n", mask);
-		goto out;
-	}
-
-	if (mask & CARM_HAVE_RESP) {
-		handled = 1;
-		carm_handle_responses(host);
-	}
-
-out:
-	spin_unlock_irqrestore(&host->lock, flags);
-	VPRINTK("EXIT\n");
-	return IRQ_RETVAL(handled);
-}
-
-static void carm_fsm_task (void *_data)
-{
-	struct carm_host *host = _data;
-	unsigned long flags;
-	unsigned int state;
-	int rc, i, next_dev;
-	int reschedule = 0;
-	int new_state = HST_INVALID;
-
-	spin_lock_irqsave(&host->lock, flags);
-	state = host->state;
-	spin_unlock_irqrestore(&host->lock, flags);
-
-	DPRINTK("ENTER, state == %s\n", state_name[state]);
-
-	switch (state) {
-	case HST_PROBE_START:
-		new_state = HST_ALLOC_BUF;
-		reschedule = 1;
-		break;
-
-	case HST_ALLOC_BUF:
-		rc = carm_send_special(host, carm_fill_alloc_buf);
-		if (rc) {
-			new_state = HST_ERROR;
-			reschedule = 1;
-		}
-		break;
-
-	case HST_SYNC_TIME:
-		rc = carm_send_special(host, carm_fill_sync_time);
-		if (rc) {
-			new_state = HST_ERROR;
-			reschedule = 1;
-		}
-		break;
-
-	case HST_GET_FW_VER:
-		rc = carm_send_special(host, carm_fill_get_fw_ver);
-		if (rc) {
-			new_state = HST_ERROR;
-			reschedule = 1;
-		}
-		break;
-
-	case HST_PORT_SCAN:
-		rc = carm_send_special(host, carm_fill_scan_channels);
-		if (rc) {
-			new_state = HST_ERROR;
-			reschedule = 1;
-		}
-		break;
-
-	case HST_DEV_SCAN_START:
-		host->cur_scan_dev = -1;
-		new_state = HST_DEV_SCAN;
-		reschedule = 1;
-		break;
-
-	case HST_DEV_SCAN:
-		next_dev = -1;
-		for (i = host->cur_scan_dev + 1; i < CARM_MAX_PORTS; i++)
-			if (host->dev_present & (1 << i)) {
-				next_dev = i;
-				break;
-			}
-
-		if (next_dev >= 0) {
-			host->cur_scan_dev = next_dev;
-			rc = carm_array_info(host, next_dev);
-			if (rc) {
-				new_state = HST_ERROR;
-				reschedule = 1;
-			}
-		} else {
-			new_state = HST_DEV_ACTIVATE;
-			reschedule = 1;
-		}
-		break;
-
-	case HST_DEV_ACTIVATE: {
-		int activated = 0;
-		for (i = 0; i < CARM_MAX_PORTS; i++)
-			if (host->dev_active & (1 << i)) {
-				struct carm_port *port = &host->port[i];
-				struct gendisk *disk = port->disk;
-
-				set_capacity(disk, port->capacity);
-				add_disk(disk);
-				activated++;
-			}
-
-		printk(KERN_INFO DRV_NAME "(%s): %d ports activated\n",
-		       pci_name(host->pdev), activated);
-
-		new_state = HST_PROBE_FINISHED;
-		reschedule = 1;
-		break;
-	}
-
-	case HST_PROBE_FINISHED:
-		up(&host->probe_sem);
-		break;
-
-	case HST_ERROR:
-		/* FIXME: TODO */
-		break;
-
-	default:
-		/* should never occur */
-		printk(KERN_ERR PFX "BUG: unknown state %d\n", state);
-		assert(0);
-		break;
-	}
-
-	if (new_state != HST_INVALID) {
-		spin_lock_irqsave(&host->lock, flags);
-		host->state = new_state;
-		spin_unlock_irqrestore(&host->lock, flags);
-	}
-	if (reschedule)
-		schedule_work(&host->fsm_task);
-}
-
-static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit)
-{
-	unsigned int i;
-
-	for (i = 0; i < 50000; i++) {
-		u32 tmp = readl(mmio + CARM_LMUC);
-		udelay(100);
-
-		if (test_bit) {
-			if ((tmp & bits) == bits)
-				return 0;
-		} else {
-			if ((tmp & bits) == 0)
-				return 0;
-		}
-
-		cond_resched();
-	}
-
-	printk(KERN_ERR PFX "carm_init_wait timeout, bits == 0x%x, test_bit == %s\n",
-	       bits, test_bit ? "yes" : "no");
-	return -EBUSY;
-}
-
-static void carm_init_responses(struct carm_host *host)
-{
-	void *mmio = host->mmio;
-	unsigned int i;
-	struct carm_response *resp = (struct carm_response *) host->shm;
-
-	for (i = 0; i < RMSG_Q_LEN; i++)
-		resp[i].status = 0xffffffff;
-
-	writel(0, mmio + CARM_RESP_IDX);
-}
-
-static int carm_init_host(struct carm_host *host)
-{
-	void *mmio = host->mmio;
-	u32 tmp;
-	u8 tmp8;
-	int rc;
-
-	DPRINTK("ENTER\n");
-
-	writel(0, mmio + CARM_INT_MASK);
-
-	tmp8 = readb(mmio + CARM_INITC);
-	if (tmp8 & 0x01) {
-		tmp8 &= ~0x01;
-		writeb(tmp8, CARM_INITC);
-		readb(mmio + CARM_INITC);	/* flush */
-
-		DPRINTK("snooze...\n");
-		msleep(5000);
-	}
-
-	tmp = readl(mmio + CARM_HMUC);
-	if (tmp & CARM_CME) {
-		DPRINTK("CME bit present, waiting\n");
-		rc = carm_init_wait(mmio, CARM_CME, 1);
-		if (rc) {
-			DPRINTK("EXIT, carm_init_wait 1 failed\n");
-			return rc;
-		}
-	}
-	if (tmp & CARM_RME) {
-		DPRINTK("RME bit present, waiting\n");
-		rc = carm_init_wait(mmio, CARM_RME, 1);
-		if (rc) {
-			DPRINTK("EXIT, carm_init_wait 2 failed\n");
-			return rc;
-		}
-	}
-
-	tmp &= ~(CARM_RME | CARM_CME);
-	writel(tmp, mmio + CARM_HMUC);
-	readl(mmio + CARM_HMUC);	/* flush */
-
-	rc = carm_init_wait(mmio, CARM_RME | CARM_CME, 0);
-	if (rc) {
-		DPRINTK("EXIT, carm_init_wait 3 failed\n");
-		return rc;
-	}
-
-	carm_init_buckets(mmio);
-
-	writel(host->shm_dma & 0xffffffff, mmio + RBUF_ADDR_LO);
-	writel((host->shm_dma >> 16) >> 16, mmio + RBUF_ADDR_HI);
-	writel(RBUF_LEN, mmio + RBUF_BYTE_SZ);
-
-	tmp = readl(mmio + CARM_HMUC);
-	tmp |= (CARM_RME | CARM_CME | CARM_WZBC);
-	writel(tmp, mmio + CARM_HMUC);
-	readl(mmio + CARM_HMUC);	/* flush */
-
-	rc = carm_init_wait(mmio, CARM_RME | CARM_CME, 1);
-	if (rc) {
-		DPRINTK("EXIT, carm_init_wait 4 failed\n");
-		return rc;
-	}
-
-	writel(0, mmio + CARM_HMPHA);
-	writel(INT_DEF_MASK, mmio + CARM_INT_MASK);
-
-	carm_init_responses(host);
-
-	/* start initialization, probing state machine */
-	spin_lock_irq(&host->lock);
-	assert(host->state == HST_INVALID);
-	host->state = HST_PROBE_START;
-	spin_unlock_irq(&host->lock);
-	schedule_work(&host->fsm_task);
-
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-static int carm_init_disks(struct carm_host *host)
-{
-	unsigned int i;
-	int rc = 0;
-
-	for (i = 0; i < CARM_MAX_PORTS; i++) {
-		struct gendisk *disk;
-		request_queue_t *q;
-		struct carm_port *port;
-
-		port = &host->port[i];
-		port->host = host;
-		port->port_no = i;
-
-		disk = alloc_disk(CARM_MINORS_PER_MAJOR);
-		if (!disk) {
-			rc = -ENOMEM;
-			break;
-		}
-
-		port->disk = disk;
-		sprintf(disk->disk_name, DRV_NAME "%u_%u", host->id, i);
-		sprintf(disk->devfs_name, DRV_NAME "/%u_%u", host->id, i);
-		disk->major = host->major;
-		disk->first_minor = i * CARM_MINORS_PER_MAJOR;
-		disk->fops = &carm_bd_ops;
-		disk->private_data = port;
-
-		q = blk_init_queue(carm_rq_fn, &host->lock);
-		if (!q) {
-			rc = -ENOMEM;
-			break;
-		}
-		disk->queue = q;
-		blk_queue_max_hw_segments(q, CARM_MAX_REQ_SG);
-		blk_queue_max_phys_segments(q, CARM_MAX_REQ_SG);
-		blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
-
-		q->queuedata = port;
-	}
-
-	return rc;
-}
-
-static void carm_free_disks(struct carm_host *host)
-{
-	unsigned int i;
-
-	for (i = 0; i < CARM_MAX_PORTS; i++) {
-		struct gendisk *disk = host->port[i].disk;
-		if (disk) {
-			request_queue_t *q = disk->queue;
-
-			if (disk->flags & GENHD_FL_UP)
-				del_gendisk(disk);
-			if (q)
-				blk_cleanup_queue(q);
-			put_disk(disk);
-		}
-	}
-}
-
-static int carm_init_shm(struct carm_host *host)
-{
-	host->shm = pci_alloc_consistent(host->pdev, CARM_SHM_SIZE,
-					 &host->shm_dma);
-	if (!host->shm)
-		return -ENOMEM;
-
-	host->msg_base = host->shm + RBUF_LEN;
-	host->msg_dma = host->shm_dma + RBUF_LEN;
-
-	memset(host->shm, 0xff, RBUF_LEN);
-	memset(host->msg_base, 0, PDC_SHM_SIZE - RBUF_LEN);
-
-	return 0;
-}
-
-static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	static unsigned int printed_version;
-	struct carm_host *host;
-	unsigned int pci_dac;
-	int rc;
-	request_queue_t *q;
-	unsigned int i;
-
-	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
-
-	rc = pci_enable_device(pdev);
-	if (rc)
-		return rc;
-
-	rc = pci_request_regions(pdev, DRV_NAME);
-	if (rc)
-		goto err_out;
-
-#if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */
-	rc = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
-	if (!rc) {
-		rc = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
-		if (rc) {
-			printk(KERN_ERR DRV_NAME "(%s): consistent DMA mask failure\n",
-				pci_name(pdev));
-			goto err_out_regions;
-		}
-		pci_dac = 1;
-	} else {
-#endif
-		rc = pci_set_dma_mask(pdev, 0xffffffffULL);
-		if (rc) {
-			printk(KERN_ERR DRV_NAME "(%s): DMA mask failure\n",
-				pci_name(pdev));
-			goto err_out_regions;
-		}
-		pci_dac = 0;
-#if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */
-	}
-#endif
-
-	host = kmalloc(sizeof(*host), GFP_KERNEL);
-	if (!host) {
-		printk(KERN_ERR DRV_NAME "(%s): memory alloc failure\n",
-		       pci_name(pdev));
-		rc = -ENOMEM;
-		goto err_out_regions;
-	}
-
-	memset(host, 0, sizeof(*host));
-	host->pdev = pdev;
-	host->flags = pci_dac ? FL_DAC : 0;
-	spin_lock_init(&host->lock);
-	INIT_WORK(&host->fsm_task, carm_fsm_task, host);
-	init_MUTEX_LOCKED(&host->probe_sem);
-
-	for (i = 0; i < ARRAY_SIZE(host->req); i++)
-		host->req[i].tag = i;
-
-	host->mmio = ioremap(pci_resource_start(pdev, 0),
-			     pci_resource_len(pdev, 0));
-	if (!host->mmio) {
-		printk(KERN_ERR DRV_NAME "(%s): MMIO alloc failure\n",
-		       pci_name(pdev));
-		rc = -ENOMEM;
-		goto err_out_kfree;
-	}
-
-	rc = carm_init_shm(host);
-	if (rc) {
-		printk(KERN_ERR DRV_NAME "(%s): DMA SHM alloc failure\n",
-		       pci_name(pdev));
-		goto err_out_iounmap;
-	}
-
-	q = blk_init_queue(carm_oob_rq_fn, &host->lock);
-	if (!q) {
-		printk(KERN_ERR DRV_NAME "(%s): OOB queue alloc failure\n",
-		       pci_name(pdev));
-		rc = -ENOMEM;
-		goto err_out_pci_free;
-	}
-	host->oob_q = q;
-	q->queuedata = host;
-
-	/*
-	 * Figure out which major to use: 160, 161, or dynamic
-	 */
-	if (!test_and_set_bit(0, &carm_major_alloc))
-		host->major = 160;
-	else if (!test_and_set_bit(1, &carm_major_alloc))
-		host->major = 161;
-	else
-		host->flags |= FL_DYN_MAJOR;
-
-	host->id = carm_host_id;
-	sprintf(host->name, DRV_NAME "%d", carm_host_id);
-
-	rc = register_blkdev(host->major, host->name);
-	if (rc < 0)
-		goto err_out_free_majors;
-	if (host->flags & FL_DYN_MAJOR)
-		host->major = rc;
-
-	devfs_mk_dir(DRV_NAME);
-
-	rc = carm_init_disks(host);
-	if (rc)
-		goto err_out_blkdev_disks;
-
-	pci_set_master(pdev);
-
-	rc = request_irq(pdev->irq, carm_interrupt, SA_SHIRQ, DRV_NAME, host);
-	if (rc) {
-		printk(KERN_ERR DRV_NAME "(%s): irq alloc failure\n",
-		       pci_name(pdev));
-		goto err_out_blkdev_disks;
-	}
-
-	rc = carm_init_host(host);
-	if (rc)
-		goto err_out_free_irq;
-
-	DPRINTK("waiting for probe_sem\n");
-	down(&host->probe_sem);
-
-	printk(KERN_INFO "%s: pci %s, ports %d, io %lx, irq %u, major %d\n",
-	       host->name, pci_name(pdev), (int) CARM_MAX_PORTS,
-	       pci_resource_start(pdev, 0), pdev->irq, host->major);
-
-	carm_host_id++;
-	pci_set_drvdata(pdev, host);
-	return 0;
-
-err_out_free_irq:
-	free_irq(pdev->irq, host);
-err_out_blkdev_disks:
-	carm_free_disks(host);
-	unregister_blkdev(host->major, host->name);
-err_out_free_majors:
-	if (host->major == 160)
-		clear_bit(0, &carm_major_alloc);
-	else if (host->major == 161)
-		clear_bit(1, &carm_major_alloc);
-	blk_cleanup_queue(host->oob_q);
-err_out_pci_free:
-	pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma);
-err_out_iounmap:
-	iounmap(host->mmio);
-err_out_kfree:
-	kfree(host);
-err_out_regions:
-	pci_release_regions(pdev);
-err_out:
-	pci_disable_device(pdev);
-	return rc;
-}
-
-static void carm_remove_one (struct pci_dev *pdev)
-{
-	struct carm_host *host = pci_get_drvdata(pdev);
-
-	if (!host) {
-		printk(KERN_ERR PFX "BUG: no host data for PCI(%s)\n",
-		       pci_name(pdev));
-		return;
-	}
-
-	free_irq(pdev->irq, host);
-	carm_free_disks(host);
-	devfs_remove(DRV_NAME);
-	unregister_blkdev(host->major, host->name);
-	if (host->major == 160)
-		clear_bit(0, &carm_major_alloc);
-	else if (host->major == 161)
-		clear_bit(1, &carm_major_alloc);
-	blk_cleanup_queue(host->oob_q);
-	pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma);
-	iounmap(host->mmio);
-	kfree(host);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-}
-
-static int __init carm_init(void)
-{
-	return pci_module_init(&carm_driver);
-}
-
-static void __exit carm_exit(void)
-{
-	pci_unregister_driver(&carm_driver);
-}
-
-module_init(carm_init);
-module_exit(carm_exit);
-
-
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/block/cciss.c	2004-06-23 19:04:28 -07:00
@@ -479,6 +479,148 @@
 	return 0;
 }
 
+#ifdef CONFIG_COMPAT
+/* for AMD 64 bit kernel compatibility with 32-bit userland ioctls */
+extern long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+extern int
+register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int,
+      unsigned int, unsigned long, struct file *));
+extern int unregister_ioctl32_conversion(unsigned int cmd);
+
+static int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg, struct file *file);
+static int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg,
+	struct file *file);
+
+typedef int (*handler_type) (unsigned int, unsigned int, unsigned long, struct file *);
+
+static struct ioctl32_map {
+	unsigned int cmd;
+	handler_type handler;
+	int registered;
+} cciss_ioctl32_map[] = {
+	{ CCISS_GETPCIINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETINTINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_SETINTINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETNODENAME,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_SETNODENAME,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETHEARTBEAT,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETBUSTYPES,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETFIRMVER,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETDRIVVER,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_REVALIDVOLS,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_PASSTHRU32,	cciss_ioctl32_passthru, 0 },
+	{ CCISS_DEREGDISK,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_REGNEWDISK,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_REGNEWD,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_RESCANDISK,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETLUNINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_BIG_PASSTHRU32,	cciss_ioctl32_big_passthru, 0 },
+};
+#define NCCISS_IOCTL32_ENTRIES (sizeof(cciss_ioctl32_map) / sizeof(cciss_ioctl32_map[0]))
+static void register_cciss_ioctl32(void)
+{
+	int i, rc;
+
+	for (i=0; i < NCCISS_IOCTL32_ENTRIES; i++) {
+		rc = register_ioctl32_conversion(
+			cciss_ioctl32_map[i].cmd,
+			cciss_ioctl32_map[i].handler);
+		if (rc != 0) {
+			printk(KERN_WARNING "cciss: failed to register "
+				"32 bit compatible ioctl 0x%08x\n",
+				cciss_ioctl32_map[i].cmd);
+			cciss_ioctl32_map[i].registered = 0;
+		} else
+			cciss_ioctl32_map[i].registered = 1;
+	}
+}
+static void unregister_cciss_ioctl32(void)
+{
+	int i, rc;
+
+	for (i=0; i < NCCISS_IOCTL32_ENTRIES; i++) {
+		if (!cciss_ioctl32_map[i].registered)
+			continue;
+		rc = unregister_ioctl32_conversion(
+			cciss_ioctl32_map[i].cmd);
+		if (rc == 0) {
+			cciss_ioctl32_map[i].registered = 0;
+			continue;
+		}
+		printk(KERN_WARNING "cciss: failed to unregister "
+			"32 bit compatible ioctl 0x%08x\n",
+			cciss_ioctl32_map[i].cmd);
+	}
+}
+int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg,
+	struct file *file)
+{
+	IOCTL32_Command_struct *arg32 =
+		(IOCTL32_Command_struct *) arg;
+	IOCTL_Command_struct arg64;
+	mm_segment_t old_fs;
+	int err;
+	unsigned long cp;
+
+	err = 0;
+	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
+	err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
+	err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+	err |= get_user(arg64.buf_size, &arg32->buf_size);
+	err |= get_user(cp, &arg32->buf);
+	arg64.buf = (BYTE *)cp;
+
+	if (err)
+		return -EFAULT;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, CCISS_PASSTHRU, (unsigned long) &arg64);
+	set_fs(old_fs);
+	if (err)
+		return err;
+	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info));
+	if (err)
+		return -EFAULT;
+	return err;
+}
+int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg,
+	struct file *file)
+{
+	BIG_IOCTL32_Command_struct *arg32 =
+		(BIG_IOCTL32_Command_struct *) arg;
+	BIG_IOCTL_Command_struct arg64;
+	mm_segment_t old_fs;
+	int err;
+	unsigned long cp;
+
+	err = 0;
+	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
+	err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
+	err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+	err |= get_user(arg64.buf_size, &arg32->buf_size);
+	err |= get_user(arg64.malloc_size, &arg32->malloc_size);
+	err |= get_user(cp, &arg32->buf);
+	arg64.buf = (BYTE *)cp;
+
+	if (err)
+		 return -EFAULT;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, CCISS_BIG_PASSTHRU, (unsigned long) &arg64);
+	set_fs(old_fs);
+	if (err)
+		return err;
+	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info));
+	if (err)
+		return -EFAULT;
+	return err;
+}
+#else
+static inline void register_cciss_ioctl32(void) {}
+static inline void unregister_cciss_ioctl32(void) {}
+#endif
 /*
  * ioctl 
  */
@@ -2728,6 +2870,7 @@
 
 static int __init init_cciss_module(void)
 {
+	register_cciss_ioctl32();
 	return ( cciss_init());
 }
 
@@ -2735,6 +2878,7 @@
 {
 	int i;
 
+	unregister_cciss_ioctl32();
 	pci_unregister_driver(&cciss_pci_driver);
 	/* double check that all controller entrys have been removed */
 	for (i=0; i< MAX_CTLR; i++) 
diff -Nru a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
--- a/drivers/block/cfq-iosched.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/block/cfq-iosched.c	2004-06-23 19:04:27 -07:00
@@ -59,6 +59,14 @@
 	unsigned int max_queued;
 
 	mempool_t *crq_pool;
+
+	request_queue_t *queue;
+
+	/*
+	 * tunables
+	 */
+	unsigned int cfq_quantum;
+	unsigned int cfq_queued;
 };
 
 struct cfq_queue {
@@ -89,7 +97,8 @@
 
 static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq);
 static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid);
-static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq);
+static void cfq_dispatch_sort(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+			      struct cfq_rq *crq);
 
 /*
  * lots of deadline iosched dupes, can be abstracted later...
@@ -206,8 +215,7 @@
 		return;
 	}
 
-	cfq_del_crq_rb(cfqq, __alias);
-	cfq_dispatch_sort(cfqd->dispatch, __alias);
+	cfq_dispatch_sort(cfqd, cfqq, __alias);
 	goto retry;
 }
 
@@ -321,11 +329,16 @@
 	cfq_remove_request(q, next);
 }
 
-static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq)
+static void
+cfq_dispatch_sort(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+		  struct cfq_rq *crq)
 {
-	struct list_head *entry = head;
+	struct list_head *head = cfqd->dispatch, *entry = head;
 	struct request *__rq;
 
+	cfq_del_crq_rb(cfqq, crq);
+	cfq_remove_merge_hints(cfqd->queue, crq);
+
 	if (!list_empty(head)) {
 		__rq = list_entry_rq(head->next);
 
@@ -352,9 +365,7 @@
 {
 	struct cfq_rq *crq = rb_entry_crq(rb_first(&cfqq->sort_list));
 
-	cfq_del_crq_rb(cfqq, crq);
-	cfq_remove_merge_hints(q, crq);
-	cfq_dispatch_sort(cfqd->dispatch, crq);
+	cfq_dispatch_sort(cfqd, cfqq, crq);
 }
 
 static int cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd)
@@ -385,7 +396,7 @@
 		ret = 1;
 	}
 
-	if ((queued < cfq_quantum) && good_queues)
+	if ((queued < cfqd->cfq_quantum) && good_queues)
 		goto restart;
 
 	return ret;
@@ -556,7 +567,7 @@
 
 	cfqq = cfq_find_cfq_hash(cfqd, current->tgid);
 	if (cfqq) {
-		int limit = (q->nr_requests - cfq_queued) / cfqd->busy_queues;
+		int limit = (q->nr_requests - cfqd->cfq_queued) / cfqd->busy_queues;
 
 		if (limit < 3)
 			limit = 3;
@@ -574,6 +585,8 @@
 {
 	struct cfq_data *cfqd = q->elevator.elevator_data;
 	struct cfq_rq *crq = RQ_DATA(rq);
+	struct request_list *rl;
+	int other_rw;
 
 	if (crq) {
 		BUG_ON(q->last_merge == rq);
@@ -582,6 +595,23 @@
 		mempool_free(crq, cfqd->crq_pool);
 		rq->elevator_private = NULL;
 	}
+
+	/*
+	 * work-around for may_queue "bug": if a read gets issued and refused
+	 * to queue because writes ate all the allowed slots and no other
+	 * reads are pending for this queue, it could get stuck infinitely
+	 * since freed_request() only checks the waitqueue for writes when
+	 * freeing them. or vice versa for a single write vs many reads.
+	 * so check here whether "the other" data direction might be able
+	 * to queue and wake them
+	 */
+	rl = &q->rq;
+	other_rw = rq_data_dir(rq) ^ 1;
+	if (rl->count[other_rw] <= q->nr_requests) {
+		smp_mb();
+		if (waitqueue_active(&rl->wait[other_rw]))
+			wake_up(&rl->wait[other_rw]);
+	}
 }
 
 static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
@@ -643,6 +673,7 @@
 
 	cfqd->dispatch = &q->queue_head;
 	e->elevator_data = cfqd;
+	cfqd->queue = q;
 
 	/*
 	 * just set it to some high value, we want anyone to be able to queue
@@ -651,6 +682,9 @@
 	cfqd->max_queued = q->nr_requests;
 	q->nr_requests = 8192;
 
+	cfqd->cfq_queued = cfq_queued;
+	cfqd->cfq_quantum = cfq_quantum;
+
 	return 0;
 out_crqpool:
 	kfree(cfqd->cfq_hash);
@@ -685,8 +719,110 @@
 
 subsys_initcall(cfq_slab_setup);
 
+/*
+ * sysfs parts below -->
+ */
+struct cfq_fs_entry {
+	struct attribute attr;
+	ssize_t (*show)(struct cfq_data *, char *);
+	ssize_t (*store)(struct cfq_data *, const char *, size_t);
+};
+
+static ssize_t
+cfq_var_show(unsigned int var, char *page)
+{
+	return sprintf(page, "%d\n", var);
+}
+
+static ssize_t
+cfq_var_store(unsigned int *var, const char *page, size_t count)
+{
+	char *p = (char *) page;
+
+	*var = simple_strtoul(p, &p, 10);
+	return count;
+}
+
+#define SHOW_FUNCTION(__FUNC, __VAR)					\
+static ssize_t __FUNC(struct cfq_data *cfqd, char *page)		\
+{									\
+	return cfq_var_show(__VAR, (page));				\
+}
+SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum);
+SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued);
+#undef SHOW_FUNCTION
+
+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX)				\
+static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count)	\
+{									\
+	int ret = cfq_var_store(__PTR, (page), count);			\
+	if (*(__PTR) < (MIN))						\
+		*(__PTR) = (MIN);					\
+	else if (*(__PTR) > (MAX))					\
+		*(__PTR) = (MAX);					\
+	return ret;							\
+}
+STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, INT_MAX);
+STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, INT_MAX);
+#undef STORE_FUNCTION
+
+static struct cfq_fs_entry cfq_quantum_entry = {
+	.attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR },
+	.show = cfq_quantum_show,
+	.store = cfq_quantum_store,
+};
+static struct cfq_fs_entry cfq_queued_entry = {
+	.attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR },
+	.show = cfq_queued_show,
+	.store = cfq_queued_store,
+};
+
+static struct attribute *default_attrs[] = {
+	&cfq_quantum_entry.attr,
+	&cfq_queued_entry.attr,
+	NULL,
+};
+
+#define to_cfq(atr) container_of((atr), struct cfq_fs_entry, attr)
+
+static ssize_t
+cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+	elevator_t *e = container_of(kobj, elevator_t, kobj);
+	struct cfq_fs_entry *entry = to_cfq(attr);
+
+	if (!entry->show)
+		return 0;
+
+	return entry->show(e->elevator_data, page);
+}
+
+static ssize_t
+cfq_attr_store(struct kobject *kobj, struct attribute *attr,
+	       const char *page, size_t length)
+{
+	elevator_t *e = container_of(kobj, elevator_t, kobj);
+	struct cfq_fs_entry *entry = to_cfq(attr);
+
+	if (!entry->store)
+		return -EINVAL;
+
+	return entry->store(e->elevator_data, page, length);
+}
+
+static struct sysfs_ops cfq_sysfs_ops = {
+	.show	= cfq_attr_show,
+	.store	= cfq_attr_store,
+};
+
+struct kobj_type cfq_ktype = {
+	.sysfs_ops	= &cfq_sysfs_ops,
+	.default_attrs	= default_attrs,
+};
+
 elevator_t iosched_cfq = {
 	.elevator_name =		"cfq",
+	.elevator_ktype =		&cfq_ktype,
 	.elevator_merge_fn = 		cfq_merge,
 	.elevator_merged_fn =		cfq_merged_request,
 	.elevator_merge_req_fn =	cfq_merged_requests,
diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c
--- a/drivers/block/elevator.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/block/elevator.c	2004-06-23 19:04:28 -07:00
@@ -181,6 +181,14 @@
 
 	rq->q = q;
 	q->elevator.elevator_add_req_fn(q, rq, where);
+
+	if (blk_queue_plugged(q)) {
+		int nrq = q->rq.count[READ] + q->rq.count[WRITE] - q->in_flight;
+
+		if (nrq == q->unplug_thresh)
+			__generic_unplug_device(q);
+	}
+
 }
 
 void elv_add_request(request_queue_t *q, struct request *rq, int where,
diff -Nru a/drivers/block/floppy98.c b/drivers/block/floppy98.c
--- a/drivers/block/floppy98.c	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,4682 +0,0 @@
-/*
- *  linux/drivers/block/floppy.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  Copyright (C) 1993, 1994  Alain Knaff
- *  Copyright (C) 1998 Alan Cox
- */
-/*
- * 02.12.91 - Changed to static variables to indicate need for reset
- * and recalibrate. This makes some things easier (output_byte reset
- * checking etc), and means less interrupt jumping in case of errors,
- * so the code is hopefully easier to understand.
- */
-
-/*
- * This file is certainly a mess. I've tried my best to get it working,
- * but I don't like programming floppies, and I have only one anyway.
- * Urgel. I should check for more errors, and do more graceful error
- * recovery. Seems there are problems with several drives. I've tried to
- * correct them. No promises.
- */
-
-/*
- * As with hd.c, all routines within this file can (and will) be called
- * by interrupts, so extreme caution is needed. A hardware interrupt
- * handler may not sleep, or a kernel panic will happen. Thus I cannot
- * call "floppy-on" directly, but have to set a special timer interrupt
- * etc.
- */
-
-/*
- * 28.02.92 - made track-buffering routines, based on the routines written
- * by entropy@wintermute.wpi.edu (Lawrence Foard). Linus.
- */
-
-/*
- * Automatic floppy-detection and formatting written by Werner Almesberger
- * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with
- * the floppy-change signal detection.
- */
-
-/*
- * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed
- * FDC data overrun bug, added some preliminary stuff for vertical
- * recording support.
- *
- * 1992/9/17: Added DMA allocation & DMA functions. -- hhb.
- *
- * TODO: Errors are still not counted properly.
- */
-
-/* 1992/9/20
- * Modifications for ``Sector Shifting'' by Rob Hooft (hooft@chem.ruu.nl)
- * modeled after the freeware MS-DOS program fdformat/88 V1.8 by
- * Christoph H. Hochst\"atter.
- * I have fixed the shift values to the ones I always use. Maybe a new
- * ioctl() should be created to be able to modify them.
- * There is a bug in the driver that makes it impossible to format a
- * floppy as the first thing after bootup.
- */
-
-/*
- * 1993/4/29 -- Linus -- cleaned up the timer handling in the kernel, and
- * this helped the floppy driver as well. Much cleaner, and still seems to
- * work.
- */
-
-/* 1994/6/24 --bbroad-- added the floppy table entries and made
- * minor modifications to allow 2.88 floppies to be run.
- */
-
-/* 1994/7/13 -- Paul Vojta -- modified the probing code to allow three or more
- * disk types.
- */
-
-/*
- * 1994/8/8 -- Alain Knaff -- Switched to fdpatch driver: Support for bigger
- * format bug fixes, but unfortunately some new bugs too...
- */
-
-/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write
- * errors to allow safe writing by specialized programs.
- */
-
-/* 1995/4/24 -- Dan Fandrich -- added support for Commodore 1581 3.5" disks
- * by defining bit 1 of the "stretch" parameter to mean put sectors on the
- * opposite side of the disk, leaving the sector IDs alone (i.e. Commodore's
- * drives are "upside-down").
- */
-
-/*
- * 1995/8/26 -- Andreas Busse -- added Mips support.
- */
-
-/*
- * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependent
- * features to asm/floppy.h.
- */
-
-/*
- * 1998/05/07 -- Russell King -- More portability cleanups; moved definition of
- * interrupt and dma channel to asm/floppy.h. Cleaned up some formatting &
- * use of '0' for NULL.
- */
- 
-/*
- * 1998/06/07 -- Alan Cox -- Merged the 2.0.34 fixes for resource allocation
- * failures.
- */
-
-/*
- * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives.
- */
-
-/*
- * 1999/01/19 -- N.Fujita & Linux/98 Project -- Added code for NEC PC-9800
- * series.
- */
-
-/*
- * 1999/08/13 -- Paul Slootman -- floppy stopped working on Alpha after 24
- * days, 6 hours, 32 minutes and 32 seconds (i.e. MAXINT jiffies; ints were
- * being used to store jiffies, which are unsigned longs).
- */
-
-/*
- * 2000/08/28 -- Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * - get rid of check_region
- * - s/suser/capable/
- */
-
-/*
- * 2001/08/26 -- Paul Gortmaker - fix insmod oops on machines with no
- * floppy controller (lingering task on list after module is gone... boom.)
- */
-
-/*
- * 2002/02/07 -- Anton Altaparmakov - Fix io ports reservation to correct range
- * (0x3f2-0x3f5, 0x3f7). This fix is a bit of a hack but the proper fix
- * requires many non-obvious changes in arch dependent code.
- */
-
-/*
- * 2002/10/12 -- Osamu Tomita <tomita@cinet.co.jp>
- * split code from floppy.c
- * support NEC PC-9800 only
- */
-
-#define FLOPPY_SANITY_CHECK
-#undef  FLOPPY_SILENT_DCL_CLEAR
-
-/*
-#define PC9800_DEBUG_FLOPPY
-#define PC9800_DEBUG_FLOPPY2
-*/
-
-#define REALLY_SLOW_IO
-
-#define DEBUGT 2
-#define DCL_DEBUG /* debug disk change line */
-
-/* do print messages for unexpected interrupts */
-static int print_unex=1;
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-#include <linux/version.h>
-#include <linux/fdreg.h>
-#include <linux/blkdev.h>
-#include <linux/blkpg.h>
-#include <linux/cdrom.h>	/* for the compatibility eject ioctl */
-#include <linux/completion.h>
-
-/*
- * 1998/1/21 -- Richard Gooch <rgooch@atnf.csiro.au> -- devfs support
- */
-
-
-#include <linux/fd.h>
-#define FLOPPY98_MOTOR_MASK 0x08
-
-#include <linux/hdreg.h>
-#define FD98_STATUS	(0 + FD_IOPORT )
-#define FD98_DATA	(2 + FD_IOPORT )
-#define FD_MODE		(4 + FD_IOPORT )
-#define FD_MODE_CHANGE	0xbe
-#define FD_EMODE_CHANGE	0x4be
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/bio.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/mc146818rtc.h> /* CMOS defines */
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/device.h>
-#include <linux/buffer_head.h>		/* for invalidate_buffers() */
-
-/*
- * PS/2 floppies have much slower step rates than regular floppies.
- * It's been recommended that take about 1/4 of the default speed
- * in some more extreme cases.
- */
-static int slow_floppy;
-
-#include <asm/dma.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#ifndef DEFAULT_FLOPPY_IRQ
-# define DEFAULT_FLOPPY_IRQ	11
-#endif
-#ifndef DEFAULT_FLOPPY_DMA
-# define DEFAULT_FLOPPY_DMA	2
-#endif
-
-static int FLOPPY_IRQ=DEFAULT_FLOPPY_IRQ;
-static int FLOPPY_DMA=DEFAULT_FLOPPY_DMA;
-static int can_use_virtual_dma=2;
-static int auto_detect_mode = 0;
-static int retry_auto_detect = 0;
-#define FD_AFTER_RESET_DELAY 1000
-
-/* =======
- * can use virtual DMA:
- * 0 = use of virtual DMA disallowed by config
- * 1 = use of virtual DMA prescribed by config
- * 2 = no virtual DMA preference configured.  By default try hard DMA,
- * but fall back on virtual DMA when not enough memory available
- */
-
-static int use_virtual_dma;
-/* =======
- * use virtual DMA
- * 0 using hard DMA
- * 1 using virtual DMA
- * This variable is set to virtual when a DMA mem problem arises, and
- * reset back in floppy_grab_irq_and_dma.
- * It is not safe to reset it in other circumstances, because the floppy
- * driver may have several buffers in use at once, and we do currently not
- * record each buffers capabilities
- */
-
-static spinlock_t floppy_lock = SPIN_LOCK_UNLOCKED;
-static struct completion device_release;
-
-static unsigned short virtual_dma_port=0x3f0;
-irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs);
-static int set_mode(char mask, char data);
-static void register_devfs_entries (int drive) __init;
-
-#define K_64	0x10000		/* 64KB */
-
-/* the following is the mask of allowed drives. By default units 2 and
- * 3 of both floppy controllers are disabled, because switching on the
- * motor of these drives causes system hangs on some PCI computers. drive
- * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if
- * a drive is allowed.
- *
- * NOTE: This must come before we include the arch floppy header because
- *       some ports reference this variable from there. -DaveM
- */
-
-static int allowed_drive_mask = 0x0f;
-
-#include <asm/floppy.h>
-
-static int irqdma_allocated;
-
-#define LOCAL_END_REQUEST
-#define DEVICE_NAME "floppy"
-
-#include <linux/blkpg.h>
-#include <linux/cdrom.h> /* for the compatibility eject ioctl */
-#include <linux/completion.h>
-
-static struct request *current_req;
-static struct request_queue *floppy_queue;
-
-#ifndef fd_get_dma_residue
-#define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
-#endif
-
-/* Dma Memory related stuff */
-
-#ifndef fd_dma_mem_free
-#define fd_dma_mem_free(addr, size) free_pages(addr, get_order(size))
-#endif
-
-#ifndef fd_dma_mem_alloc
-#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size))
-#endif
-
-static inline void fallback_on_nodma_alloc(char **addr, size_t l)
-{
-#ifdef FLOPPY_CAN_FALLBACK_ON_NODMA
-	if (*addr)
-		return; /* we have the memory */
-	if (can_use_virtual_dma != 2)
-		return; /* no fallback allowed */
-	printk("DMA memory shortage. Temporarily falling back on virtual DMA\n");
-	*addr = (char *) nodma_mem_alloc(l);
-#else
-	return;
-#endif
-}
-
-/* End dma memory related stuff */
-
-static unsigned long fake_change;
-static int initialising=1;
-
-#define ITYPE(x) (((x)>>2) & 0x1f)
-#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
-#define UNIT(x) ((x) & 0x03)		/* drive on fdc */
-#define FDC(x) (((x) & 0x04) >> 2)  /* fdc of drive */
-#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2))
-				/* reverse mapping from unit and fdc to drive */
-#define DP (&drive_params[current_drive])
-#define DRS (&drive_state[current_drive])
-#define DRWE (&write_errors[current_drive])
-#define FDCS (&fdc_state[fdc])
-#define CLEARF(x) (clear_bit(x##_BIT, &DRS->flags))
-#define SETF(x) (set_bit(x##_BIT, &DRS->flags))
-#define TESTF(x) (test_bit(x##_BIT, &DRS->flags))
-
-#define UDP (&drive_params[drive])
-#define UDRS (&drive_state[drive])
-#define UDRWE (&write_errors[drive])
-#define UFDCS (&fdc_state[FDC(drive)])
-#define UCLEARF(x) (clear_bit(x##_BIT, &UDRS->flags))
-#define USETF(x) (set_bit(x##_BIT, &UDRS->flags))
-#define UTESTF(x) (test_bit(x##_BIT, &UDRS->flags))
-
-#define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args)
-
-#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
-#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
-
-#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x)))
-
-/* read/write */
-#define COMMAND raw_cmd->cmd[0]
-#define DR_SELECT raw_cmd->cmd[1]
-#define TRACK raw_cmd->cmd[2]
-#define HEAD raw_cmd->cmd[3]
-#define SECTOR raw_cmd->cmd[4]
-#define SIZECODE raw_cmd->cmd[5]
-#define SECT_PER_TRACK raw_cmd->cmd[6]
-#define GAP raw_cmd->cmd[7]
-#define SIZECODE2 raw_cmd->cmd[8]
-#define NR_RW 9
-
-/* format */
-#define F_SIZECODE raw_cmd->cmd[2]
-#define F_SECT_PER_TRACK raw_cmd->cmd[3]
-#define F_GAP raw_cmd->cmd[4]
-#define F_FILL raw_cmd->cmd[5]
-#define NR_F 6
-
-/*
- * Maximum disk size (in kilobytes). This default is used whenever the
- * current disk size is unknown.
- * [Now it is rather a minimum]
- */
-#define MAX_DISK_SIZE 4 /* 3984*/
-
-
-/*
- * globals used by 'result()'
- */
-#define MAX_REPLIES 16
-static unsigned char reply_buffer[MAX_REPLIES];
-static int inr; /* size of reply buffer, when called from interrupt */
-#define ST0 (reply_buffer[0])
-#define ST1 (reply_buffer[1])
-#define ST2 (reply_buffer[2])
-#define ST3 (reply_buffer[0]) /* result of GETSTATUS */
-#define R_TRACK (reply_buffer[3])
-#define R_HEAD (reply_buffer[4])
-#define R_SECTOR (reply_buffer[5])
-#define R_SIZECODE (reply_buffer[6])
-
-#define SEL_DLY (2*HZ/100)
-
-/*
- * this struct defines the different floppy drive types.
- */
-static struct {
-	struct floppy_drive_params params;
-	const char *name; /* name printed while booting */
-} default_drive_params[]= {
-/* NOTE: the time values in jiffies should be in msec!
- CMOS drive type
-  |     Maximum data rate supported by drive type
-  |     |   Head load time, msec
-  |     |   |   Head unload time, msec (not used)
-  |     |   |   |     Step rate interval, usec
-  |     |   |   |     |       Time needed for spinup time (jiffies)
-  |     |   |   |     |       |      Timeout for spinning down (jiffies)
-  |     |   |   |     |       |      |   Spindown offset (where disk stops)
-  |     |   |   |     |       |      |   |     Select delay
-  |     |   |   |     |       |      |   |     |     RPS
-  |     |   |   |     |       |      |   |     |     |    Max number of tracks
-  |     |   |   |     |       |      |   |     |     |    |     Interrupt timeout
-  |     |   |   |     |       |      |   |     |     |    |     |   Max nonintlv. sectors
-  |     |   |   |     |       |      |   |     |     |    |     |   | -Max Errors- flags */
-{{0,  500, 16, 16, 8000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  80, 3*HZ, 20, {3,1,2,0,2}, 0,
-      0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" },
-
-{{1,  300, 16, 16, 8000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  40, 3*HZ, 17, {3,1,2,0,2}, 0,
-      0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
-
-{{2,  500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6,  83, 3*HZ, 17, {3,1,2,0,2}, 0,
-      0, { 2, 6, 4, 0, 0, 0, 0, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
-
-{{3,  250, 16, 16, 3000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
-      0, { 4, 6, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/
-
-{{4,  500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
-      0, { 7,10, 2, 4, 6, 0, 0, 0}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/
-
-{{5, 1000, 15,  8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,
-      0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/
-
-{{6, 1000, 15,  8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,
-      0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/
-/*    |  --autodetected formats---    |      |      |
- *    read_track                      |      |    Name printed when booting
- *				      |     Native format
- *	            Frequency of disk change checks */
-};
-
-static struct floppy_drive_params drive_params[N_DRIVE];
-static struct floppy_drive_struct drive_state[N_DRIVE];
-static struct floppy_write_errors write_errors[N_DRIVE];
-static struct timer_list motor_off_timer[N_DRIVE];
-static struct gendisk *disks[N_DRIVE];
-static struct block_device *opened_bdev[N_DRIVE];
-static DECLARE_MUTEX(open_lock);
-static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
-
-/*
- * This struct defines the different floppy types.
- *
- * Bit 0 of 'stretch' tells if the tracks need to be doubled for some
- * types (e.g. 360kB diskette in 1.2MB drive, etc.).  Bit 1 of 'stretch'
- * tells if the disk is in Commodore 1581 format, which means side 0 sectors
- * are located on side 1 of the disk but with a side 0 ID, and vice-versa.
- * This is the same as the Sharp MZ-80 5.25" CP/M disk format, except that the
- * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical
- * side 0 is on physical side 0 (but with the misnamed sector IDs).
- * 'stretch' should probably be renamed to something more general, like
- * 'options'.  Other parameters should be self-explanatory (see also
- * setfdprm(8)).
- */
-/*
-	    Size
-	     |  Sectors per track
-	     |  | Head
-	     |  | |  Tracks
-	     |  | |  | Stretch
-	     |  | |  | |  Gap 1 size
-	     |  | |  | |    |  Data rate, | 0x40 for perp
-	     |  | |  | |    |    |  Spec1 (stepping rate, head unload
-	     |  | |  | |    |    |    |    /fmt gap (gap2) */
-static struct floppy_struct floppy_type[32] = {
-	{    0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL    },	/*  0 no testing    */
-#if 0
-	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360"  }, /*  1 360KB PC      */
-#else
-	{ 2464,16,2,77,0,0x35,0x48,0xDF,0x74,"d360"  }, /*  1 1.25MB 98     */
-#endif
-	{ 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" },	/*  2 1.2MB AT      */
-	{  720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360"  },	/*  3 360KB SS 3.5" */
-	{ 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720"  },	/*  4 720KB 3.5"    */
-	{  720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360"  },	/*  5 360KB AT      */
-	{ 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720"  },	/*  6 720KB AT      */
-	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" },	/*  7 1.44MB 3.5"   */
-	{ 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" },	/*  8 2.88MB 3.5"   */
-	{ 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" },	/*  9 3.12MB 3.5"   */
-
-	{ 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25"  */
-	{ 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5"   */
-	{  820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410"  },	/* 12 410KB 5.25"   */
-	{ 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820"  },	/* 13 820KB 3.5"    */
-	{ 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" },	/* 14 1.48MB 5.25"  */
-	{ 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" },	/* 15 1.72MB 3.5"   */
-	{  840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420"  },	/* 16 420KB 5.25"   */
-	{ 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830"  },	/* 17 830KB 3.5"    */
-	{ 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" },	/* 18 1.49MB 5.25"  */
-	{ 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5"  */
-
-	{ 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880"  }, /* 20 880KB 5.25"   */
-	{ 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5"   */
-	{ 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5"   */
-	{ 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25"   */
-	{ 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5"   */
-	{ 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5"   */
-	{ 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5"   */
-	{ 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5"   */
-	{ 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5"   */
-
-	{ 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5"   */
-	{ 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800"  },	/* 30 800KB 3.5"    */
-	{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5"    */
-};
-
-#define	NUMBER(x)	(sizeof(x) / sizeof(*(x)))
-#define SECTSIZE (_FD_SECTSIZE(*floppy))
-
-/* Auto-detection: Disk type used until the next media change occurs. */
-static struct floppy_struct *current_type[N_DRIVE];
-
-/*
- * User-provided type information. current_type points to
- * the respective entry of this array.
- */
-static struct floppy_struct user_params[N_DRIVE];
-
-static sector_t floppy_sizes[256];
-
-/*
- * The driver is trying to determine the correct media format
- * while probing is set. rw_interrupt() clears it after a
- * successful access.
- */
-static int probing;
-
-/* Synchronization of FDC access. */
-#define FD_COMMAND_NONE -1
-#define FD_COMMAND_ERROR 2
-#define FD_COMMAND_OKAY 3
-
-static volatile int command_status = FD_COMMAND_NONE;
-static unsigned long fdc_busy;
-static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
-static DECLARE_WAIT_QUEUE_HEAD(command_done);
-
-#define NO_SIGNAL (!interruptible || !signal_pending(current))
-#define CALL(x) if ((x) == -EINTR) return -EINTR
-#define ECALL(x) if ((ret = (x))) return ret;
-#define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
-#define WAIT(x) _WAIT((x),interruptible)
-#define IWAIT(x) _WAIT((x),1)
-
-/* Errors during formatting are counted here. */
-static int format_errors;
-
-/* Format request descriptor. */
-static struct format_descr format_req;
-
-/*
- * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps
- * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
- * H is head unload time (1=16ms, 2=32ms, etc)
- */
-
-/*
- * Track buffer
- * Because these are written to by the DMA controller, they must
- * not contain a 64k byte boundary crossing, or data will be
- * corrupted/lost.
- */
-static char *floppy_track_buffer;
-static int max_buffer_sectors;
-
-static int *errors;
-typedef void (*done_f)(int);
-static struct cont_t {
-	void (*interrupt)(void); /* this is called after the interrupt of the
-				  * main command */
-	void (*redo)(void); /* this is called to retry the operation */
-	void (*error)(void); /* this is called to tally an error */
-	done_f done; /* this is called to say if the operation has 
-		      * succeeded/failed */
-} *cont;
-
-static void floppy_ready(void);
-static void floppy_start(void);
-static void process_fd_request(void);
-static void recalibrate_floppy(void);
-static void floppy_shutdown(unsigned long);
-
-static int floppy_grab_irq_and_dma(void);
-static void floppy_release_irq_and_dma(void);
-
-/*
- * The "reset" variable should be tested whenever an interrupt is scheduled,
- * after the commands have been sent. This is to ensure that the driver doesn't
- * get wedged when the interrupt doesn't come because of a failed command.
- * reset doesn't need to be tested before sending commands, because
- * output_byte is automatically disabled when reset is set.
- */
-#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } }
-static void reset_fdc(void);
-
-/*
- * These are global variables, as that's the easiest way to give
- * information to interrupts. They are the data used for the current
- * request.
- */
-#define NO_TRACK -1
-#define NEED_1_RECAL -2
-#define NEED_2_RECAL -3
-
-static int usage_count;
-
-/* buffer related variables */
-static int buffer_track = -1;
-static int buffer_drive = -1;
-static int buffer_min = -1;
-static int buffer_max = -1;
-
-/* fdc related variables, should end up in a struct */
-static struct floppy_fdc_state fdc_state[N_FDC];
-static int fdc; /* current fdc */
-
-static struct floppy_struct *_floppy = floppy_type;
-static unsigned char current_drive;
-static long current_count_sectors;
-static unsigned char fsector_t; /* sector in track */
-static unsigned char in_sector_offset;	/* offset within physical sector,
-					 * expressed in units of 512 bytes */
-
-#ifndef fd_eject
-static inline int fd_eject(int drive)
-{
-	return -EINVAL;
-}
-#endif
-
-#ifdef DEBUGT
-static long unsigned debugtimer;
-#endif
-
-/*
- * Debugging
- * =========
- */
-static inline void set_debugt(void)
-{
-#ifdef DEBUGT
-	debugtimer = jiffies;
-#endif
-}
-
-static inline void debugt(const char *message)
-{
-#ifdef DEBUGT
-	if (DP->flags & DEBUGT)
-		printk("%s dtime=%lu\n", message, jiffies-debugtimer);
-#endif
-}
-
-typedef void (*timeout_fn)(unsigned long);
-static struct timer_list fd_timeout = TIMER_INITIALIZER(floppy_shutdown, 0, 0);
-
-static const char *timeout_message;
-
-#ifdef FLOPPY_SANITY_CHECK
-static void is_alive(const char *message)
-{
-	/* this routine checks whether the floppy driver is "alive" */
-	if (fdc_busy && command_status < 2 && !timer_pending(&fd_timeout)){
-		DPRINT("timeout handler died: %s\n",message);
-	}
-}
-#endif
-
-static void (*do_floppy)(void) = NULL;
-
-#ifdef FLOPPY_SANITY_CHECK
-
-#define OLOGSIZE 20
-
-static void (*lasthandler)(void);
-static unsigned long interruptjiffies;
-static unsigned long resultjiffies;
-static int resultsize;
-static unsigned long lastredo;
-
-static struct output_log {
-	unsigned char data;
-	unsigned char status;
-	unsigned long jiffies;
-} output_log[OLOGSIZE];
-
-static int output_log_pos;
-#endif
-
-#define current_reqD -1
-#define MAXTIMEOUT -2
-
-static void reschedule_timeout(int drive, const char *message, int marg)
-{
-	unsigned long delay;
-
-	if (drive == current_reqD)
-		drive = current_drive;
-	if (drive < 0 || drive > N_DRIVE) {
-		delay = 20UL*HZ;
-		drive=0;
-	} else
-		delay = UDP->timeout;
-	mod_timer(&fd_timeout, delay + jiffies);
-	if (UDP->flags & FD_DEBUG){
-		DPRINT("reschedule timeout ");
-		printk(message, marg);
-		printk("\n");
-	}
-	timeout_message = message;
-}
-
-static int maximum(int a, int b)
-{
-	if (a > b)
-		return a;
-	else
-		return b;
-}
-#define INFBOUND(a,b) (a)=maximum((a),(b));
-
-static int minimum(int a, int b)
-{
-	if (a < b)
-		return a;
-	else
-		return b;
-}
-#define SUPBOUND(a,b) (a)=minimum((a),(b));
-
-
-/*
- * Bottom half floppy driver.
- * ==========================
- *
- * This part of the file contains the code talking directly to the hardware,
- * and also the main service loop (seek-configure-spinup-command)
- */
-
-/*
- * disk change.
- * This routine is responsible for maintaining the FD_DISK_CHANGE flag,
- * and the last_checked date.
- *
- * last_checked is the date of the last check which showed 'no disk change'
- * FD_DISK_CHANGE is set under two conditions:
- * 1. The floppy has been changed after some i/o to that floppy already
- *    took place.
- * 2. No floppy disk is in the drive. This is done in order to ensure that
- *    requests are quickly flushed in case there is no disk in the drive. It
- *    follows that FD_DISK_CHANGE can only be cleared if there is a disk in
- *    the drive.
- *
- * For 1., maxblock is observed. Maxblock is 0 if no i/o has taken place yet.
- * For 2., FD_DISK_NEWCHANGE is watched. FD_DISK_NEWCHANGE is cleared on
- *  each seek. If a disk is present, the disk change line should also be
- *  cleared on each seek. Thus, if FD_DISK_NEWCHANGE is clear, but the disk
- *  change line is set, this means either that no disk is in the drive, or
- *  that it has been removed since the last seek.
- *
- * This means that we really have a third possibility too:
- *  The floppy has been changed after the last seek.
- */
-
-static int disk_change(int drive)
-{
-	return UTESTF(FD_DISK_CHANGED);
-}
-
-static int set_mode(char mask, char data)
-{
-	register unsigned char newdor, olddor;
-
-	olddor = FDCS->dor;
-	newdor = (olddor & mask) | data;
-	if (newdor != olddor) {
-		FDCS->dor = newdor;
-		fd_outb(newdor, FD_MODE);
-	}
-
-	if (newdor & FLOPPY98_MOTOR_MASK)
-		floppy_grab_irq_and_dma();
-
-	if (olddor & FLOPPY98_MOTOR_MASK)
-		floppy_release_irq_and_dma();
-
-	return olddor;
-}
-
-static void twaddle(void)
-{
-	if (DP->select_delay)
-		return;
-
-	fd_outb(FDCS->dor & 0xf7, FD_MODE);
-	fd_outb(FDCS->dor, FD_MODE);
-	DRS->select_date = jiffies;
-}
-
-/* reset all driver information about the current fdc. This is needed after
- * a reset, and after a raw command. */
-static void reset_fdc_info(int mode)
-{
-	int drive;
-
-	FDCS->spec1 = FDCS->spec2 = -1;
-	FDCS->need_configure = 1;
-	FDCS->perp_mode = 1;
-	FDCS->rawcmd = 0;
-	for (drive = 0; drive < N_DRIVE; drive++)
-		if (FDC(drive) == fdc &&
-		    (mode || UDRS->track != NEED_1_RECAL))
-			UDRS->track = NEED_2_RECAL;
-}
-
-/* selects the fdc and drive, and enables the fdc's input/dma. */
-static void set_fdc(int drive)
-{
-	fdc = 0;
-	current_drive = drive;
-	set_mode(~0, 0x10);
-	if (FDCS->rawcmd == 2)
-		reset_fdc_info(1);
-
-	if (fd_inb(FD98_STATUS) != STATUS_READY)
-		FDCS->reset = 1;
-}
-
-/* locks the driver */
-static int _lock_fdc(int drive, int interruptible, int line)
-{
-	if (!usage_count){
-		printk(KERN_ERR "Trying to lock fdc while usage count=0 at line %d\n", line);
-		return -1;
-	}
-	if(floppy_grab_irq_and_dma()==-1)
-		return -EBUSY;
-
-	if (test_and_set_bit(0, &fdc_busy)) {
-		DECLARE_WAITQUEUE(wait, current);
-		add_wait_queue(&fdc_wait, &wait);
-
-		for (;;) {
-			set_current_state(TASK_INTERRUPTIBLE);
-
-			if (!test_and_set_bit(0, &fdc_busy))
-				break;
-
-			schedule();
-
-			if (!NO_SIGNAL) {
-				remove_wait_queue(&fdc_wait, &wait);
-				return -EINTR;
-			}
-		}
-
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&fdc_wait, &wait);
-	}
-	command_status = FD_COMMAND_NONE;
-
-	reschedule_timeout(drive, "lock fdc", 0);
-	set_fdc(drive);
-	return 0;
-}
-
-#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__)
-
-#define LOCK_FDC(drive,interruptible) \
-if (lock_fdc(drive,interruptible)) return -EINTR;
-
-
-/* unlocks the driver */
-static inline void unlock_fdc(void)
-{
-	raw_cmd = 0;
-	if (!fdc_busy)
-		DPRINT("FDC access conflict!\n");
-
-	if (do_floppy)
-		DPRINT("device interrupt still active at FDC release: %p!\n",
-			do_floppy);
-	command_status = FD_COMMAND_NONE;
-	del_timer(&fd_timeout);
-	cont = NULL;
-	clear_bit(0, &fdc_busy);
-	floppy_release_irq_and_dma();
-	wake_up(&fdc_wait);
-}
-
-#ifndef CONFIG_PC9800_MOTOR_OFF /* tomita */
-
-/* switches the motor off after a given timeout */
-static void motor_off_callback(unsigned long nr)
-{
-	printk(KERN_DEBUG "fdc%lu: turn off motor\n", nr);
-}
-
-/* schedules motor off */
-static void floppy_off(unsigned int drive)
-{
-}
-
-#else /* CONFIG_PC9800_MOTOR_OFF */
-
-/* switches the motor off after a given timeout */
-static void motor_off_callback(unsigned long fdc)
-{
-	printk(KERN_DEBUG "fdc%u: turn off motor\n", (unsigned int) fdc);
-
-	fd_outb(0, FD_MODE);	/* MTON = 0 */
-}
-
-static struct timer_list motor_off_timer[N_FDC] = {
-	{ data: 0, function: motor_off_callback },
-#if N_FDC > 1
-	{ data: 1, function: motor_off_callback },
-#endif
-#if N_FDC > 2
-# error "N_FDC > 2; please fix initializer for motor_off_timer[]"
-#endif
-};
-
-/* schedules motor off */
-static void floppy_off(unsigned int drive)
-{
-	unsigned long volatile delta;
-	register int fdc = FDC(drive);
-
-	if (!(FDCS->dor & (0x10 << UNIT(drive))))
-		return;
-
-	del_timer(motor_off_timer + fdc);
-
-#if 0
-	/* make spindle stop in a position which minimizes spinup time
-	 * next time */
-	if (UDP->rps){
-		delta = jiffies - UDRS->first_read_date + HZ -
-			UDP->spindown_offset;
-		delta = ((delta * UDP->rps) % HZ) / UDP->rps;
-		motor_off_timer[drive].expires = jiffies + UDP->spindown - delta;
-	}
-#else
-	if (UDP->rps)
-		motor_off_timer[drive].expires = jiffies + UDP->spindown;
-#endif
-
-	add_timer(motor_off_timer + fdc);
-}
-
-#endif /* CONFIG_PC9800_MOTOR_OFF */
-
-/*
- * cycle through all N_DRIVE floppy drives, for disk change testing.
- * stopping at current drive. This is done before any long operation, to
- * be sure to have up to date disk change information.
- */
-static void scandrives(void)
-{
-	int i, drive, saved_drive;
-
-	if (DP->select_delay)
-		return;
-
-	saved_drive = current_drive;
-	for (i=0; i < N_DRIVE; i++){
-		drive = (saved_drive + i + 1) % N_DRIVE;
-		if (UDRS->fd_ref == 0 || UDP->select_delay != 0)
-			continue; /* skip closed drives */
-		set_fdc(drive);
-	}
-	set_fdc(saved_drive);
-}
-
-static void empty(void)
-{
-}
-
-static DECLARE_WORK(floppy_work, NULL, NULL);
-
-static void schedule_bh(void (*handler) (void))
-{
-	PREPARE_WORK(&floppy_work, (void (*)(void *))handler, NULL);
-	schedule_work(&floppy_work);
-}
-
-static struct timer_list fd_timer = TIMER_INITIALIZER(NULL, 0, 0);
-
-static void cancel_activity(void)
-{
-	do_floppy = NULL;
-	PREPARE_WORK(&floppy_work, (void*)(void*)empty, NULL);
-	del_timer(&fd_timer);
-}
-
-/* this function makes sure that the disk stays in the drive during the
- * transfer */
-static void fd_watchdog(void)
-{
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG){
-		DPRINT("calling disk change from watchdog\n");
-	}
-#endif
-
-	if (disk_change(current_drive)){
-		DPRINT("disk removed during i/o\n");
-		cancel_activity();
-		cont->done(0);
-		reset_fdc();
-	} else {
-		del_timer(&fd_timer);
-		fd_timer.function = (timeout_fn) fd_watchdog;
-		fd_timer.expires = jiffies + HZ / 10;
-		add_timer(&fd_timer);
-	}
-}
-
-static void main_command_interrupt(void)
-{
-	del_timer(&fd_timer);
-	cont->interrupt();
-}
-
-/* waits for a delay (spinup or select) to pass */
-static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
-{
-	if (FDCS->reset){
-		reset_fdc(); /* do the reset during sleep to win time
-			      * if we don't need to sleep, it's a good
-			      * occasion anyways */
-		return 1;
-	}
-
-	if ((signed) (jiffies - delay) < 0){
-		del_timer(&fd_timer);
-		fd_timer.function = function;
-		fd_timer.expires = delay;
-		add_timer(&fd_timer);
-		return 1;
-	}
-	return 0;
-}
-
-static spinlock_t floppy_hlt_lock = SPIN_LOCK_UNLOCKED;
-static int hlt_disabled;
-static void floppy_disable_hlt(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&floppy_hlt_lock, flags);
-	if (!hlt_disabled) {
-		hlt_disabled=1;
-#ifdef HAVE_DISABLE_HLT
-		disable_hlt();
-#endif
-	}
-	spin_unlock_irqrestore(&floppy_hlt_lock, flags);
-}
-
-static void floppy_enable_hlt(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&floppy_hlt_lock, flags);
-	if (hlt_disabled){
-		hlt_disabled=0;
-#ifdef HAVE_DISABLE_HLT
-		enable_hlt();
-#endif
-	}
-	spin_unlock_irqrestore(&floppy_hlt_lock, flags);
-}
-
-
-static void setup_DMA(void)
-{
-	unsigned long f;
-
-#ifdef FLOPPY_SANITY_CHECK
-	if (raw_cmd->length == 0){
-		int i;
-
-		printk("zero dma transfer size:");
-		for (i=0; i < raw_cmd->cmd_count; i++)
-			printk("%x,", raw_cmd->cmd[i]);
-		printk("\n");
-		cont->done(0);
-		FDCS->reset = 1;
-		return;
-	}
-	if (((unsigned long) raw_cmd->kernel_data) % 512){
-		printk("non aligned address: %p\n", raw_cmd->kernel_data);
-		cont->done(0);
-		FDCS->reset=1;
-		return;
-	}
-#endif
-	f=claim_dma_lock();
-	fd_disable_dma();
-#ifdef fd_dma_setup
-	if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, 
-			(raw_cmd->flags & FD_RAW_READ)?
-			DMA_MODE_READ : DMA_MODE_WRITE,
-			FDCS->address) < 0) {
-		release_dma_lock(f);
-		cont->done(0);
-		FDCS->reset=1;
-		return;
-	}
-	release_dma_lock(f);
-#else	
-	fd_clear_dma_ff();
-	fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length);
-	fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ)?
-			DMA_MODE_READ : DMA_MODE_WRITE);
-	fd_set_dma_addr(raw_cmd->kernel_data);
-	fd_set_dma_count(raw_cmd->length);
-	virtual_dma_port = FDCS->address;
-	fd_enable_dma();
-	release_dma_lock(f);
-#endif
-	floppy_disable_hlt();
-}
-
-static void show_floppy(void);
-
-/* waits until the fdc becomes ready */
-
-#ifdef PC9800_DEBUG_FLOPPY
-#define READY_DELAY 10000000
-#else
-#define READY_DELAY 100000
-#endif
-
-static int wait_til_ready(void)
-{
-	int counter, status;
-	if (FDCS->reset)
-		return -1;
-	for (counter = 0; counter < READY_DELAY; counter++) {
-		status = fd_inb(FD98_STATUS);		
-		if (status & STATUS_READY)
-			return status;
-	}
-	if (!initialising) {
-		DPRINT("Getstatus times out (%x) on fdc %d\n",
-			status, fdc);
-		show_floppy();
-	}
-	FDCS->reset = 1;
-	return -1;
-}
-
-/* sends a command byte to the fdc */
-static int output_byte(char byte)
-{
-	int status;
-
-	if ((status = wait_til_ready()) < 0)
-		return -1;
-	if ((status & (STATUS_READY|STATUS_DIR|STATUS_DMA)) == STATUS_READY){
-		fd_outb(byte,FD98_DATA);
-#ifdef FLOPPY_SANITY_CHECK
-		output_log[output_log_pos].data = byte;
-		output_log[output_log_pos].status = status;
-		output_log[output_log_pos].jiffies = jiffies;
-		output_log_pos = (output_log_pos + 1) % OLOGSIZE;
-#endif
-		return 0;
-	}
-	FDCS->reset = 1;
-	if (!initialising) {
-		DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
-		       byte, fdc, status);
-		show_floppy();
-	}
-	return -1;
-}
-#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;}
-
-/* gets the response from the fdc */
-static int result(void)
-{
-	int i, status=0;
-
-	for(i=0; i < MAX_REPLIES; i++) {
-		if ((status = wait_til_ready()) < 0)
-			break;
-		status &= STATUS_DIR|STATUS_READY|STATUS_BUSY|STATUS_DMA;
-		if ((status & ~STATUS_BUSY) == STATUS_READY){
-#ifdef FLOPPY_SANITY_CHECK
-			resultjiffies = jiffies;
-			resultsize = i;
-#endif
-			return i;
-		}
-		if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY))
-			reply_buffer[i] = fd_inb(FD98_DATA);
-		else
-			break;
-	}
-	if (!initialising) {
-		DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
-		       fdc, status, i);
-		show_floppy();
-	}
-	FDCS->reset = 1;
-	return -1;
-}
-
-static int fifo_depth = 0xa;
-static int no_fifo;
-
-#define NOMINAL_DTR 500
-
-/* Issue a "SPECIFY" command to set the step rate time, head unload time,
- * head load time, and DMA disable flag to values needed by floppy.
- *
- * The value "dtr" is the data transfer rate in Kbps.  It is needed
- * to account for the data rate-based scaling done by the 82072 and 82077
- * FDC types.  This parameter is ignored for other types of FDCs (i.e.
- * 8272a).
- *
- * Note that changing the data transfer rate has a (probably deleterious)
- * effect on the parameters subject to scaling for 82072/82077 FDCs, so
- * fdc_specify is called again after each data transfer rate
- * change.
- *
- * srt: 1000 to 16000 in microseconds
- * hut: 16 to 240 milliseconds
- * hlt: 2 to 254 milliseconds
- *
- * These values are rounded up to the next highest available delay time.
- */
-static void fdc_specify(void)
-{
-	output_byte(FD_SPECIFY);
-	output_byte(FDCS->spec1 = 0xdf);
-	output_byte(FDCS->spec2 = 0x24);
-}
-
-static void tell_sector(void)
-{
-	printk(": track %d, head %d, sector %d, size %d",
-	       R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
-} /* tell_sector */
-
-static int auto_detect_mode_pc9800(void)
-{
-#ifdef PC9800_DEBUG_FLOPPY
-	printk("auto_detect_mode_pc9800: retry_auto_detect=%d\n",
-		retry_auto_detect);
-#endif
-	if (retry_auto_detect > 4) {
-		retry_auto_detect = 0;	   
-		return 1;
-	}
-
-	switch ((int)(_floppy - floppy_type)) {
-		case 2:
-			_floppy = floppy_type + 4;
-			break;
-
-		case 4:
-		case 6:
-			_floppy = floppy_type + 7;
-			break;
-
-		case 7:
-		case 10:
-			_floppy = floppy_type + 2;
-			break;
-
-		default:
-			_floppy = floppy_type + 7;
-	}
-
-	retry_auto_detect++;
-	return 0;
-}
-
-static void access_mode_change_pc9800(void);
-
-/*
- * OK, this error interpreting routine is called after a
- * DMA read/write has succeeded
- * or failed, so we check the results, and copy any buffers.
- * hhb: Added better error reporting.
- * ak: Made this into a separate routine.
- */
-static int interpret_errors(void)
-{
-	char bad;
-
-	if (inr!=7) {
-		DPRINT("-- FDC reply error");
-		FDCS->reset = 1;
-		return 1;
-	}
-
-	/* check IC to find cause of interrupt */
-	switch (ST0 & ST0_INTR) {
-		case 0x40:	/* error occurred during command execution */
-			if (ST1 & ST1_EOC)
-				return 0; /* occurs with pseudo-DMA */
-			bad = 1;
-			if (ST1 & ST1_WP) {
-				DPRINT("Drive is write protected\n");
-				CLEARF(FD_DISK_WRITABLE);
-				cont->done(0);
-				bad = 2;
-			} else if (ST1 & ST1_ND) {
-				SETF(FD_NEED_TWADDLE);
-			} else if (ST1 & ST1_OR) {
-				if (DP->flags & FTD_MSG)
-					DPRINT("Over/Underrun - retrying\n");
-				bad = 0;
-			}else if (*errors >= DP->max_errors.reporting){
-				if (ST0 & ST0_ECE) {
-					printk("Recalibrate failed!");
-				} else if (ST2 & ST2_CRC) {
-					printk("data CRC error");
-					tell_sector();
-				} else if (ST1 & ST1_CRC) {
-					printk("CRC error");
-					tell_sector();
-				} else if ((ST1 & (ST1_MAM|ST1_ND)) || (ST2 & ST2_MAM)) {
-					if (auto_detect_mode) {
-						bad = (char)auto_detect_mode_pc9800();
-						access_mode_change_pc9800();
-					}
-
-					if (bad) {
-						printk("floppy error: MA: _floppy - floppy_type=%d\n", (int)(_floppy - floppy_type));
-						printk("bad=%d\n", (int)bad);
-						if (!probing) {
-							printk("sector not found");
-							tell_sector();
-						} else
-							printk("probe failed...");
-					}
-				} else if (ST2 & ST2_WC) {	/* seek error */
-					printk("wrong cylinder");
-				} else if (ST2 & ST2_BC) {	/* cylinder marked as bad */
-					printk("bad cylinder");
-				} else {
-					printk("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", ST0, ST1, ST2);
-					tell_sector();
-				}
-				printk("\n");
-
-			}
-			if (ST2 & ST2_WC || ST2 & ST2_BC)
-				/* wrong cylinder => recal */
-				DRS->track = NEED_2_RECAL;
-			return bad;
-		case 0x80: /* invalid command given */
-			DPRINT("Invalid FDC command given!\n");
-			cont->done(0);
-			return 2;
-		case 0xc0:
-			SETF(FD_DISK_CHANGED);
-			SETF(FD_DISK_WRITABLE);
-			DPRINT("Abnormal termination caused by polling\n");
-			cont->error();
-			return 2;
-		default: /* (0) Normal command termination */
-			auto_detect_mode = 0;
-			return 0;
-	}
-}
-
-/*
- * This routine is called when everything should be correctly set up
- * for the transfer (i.e. floppy motor is on, the correct floppy is
- * selected, and the head is sitting on the right track).
- */
-static void setup_rw_floppy(void)
-{
-	int i,r, flags,dflags;
-	unsigned long ready_date;
-	timeout_fn function;
-
-	access_mode_change_pc9800();
-	flags = raw_cmd->flags;
-	if (flags & (FD_RAW_READ | FD_RAW_WRITE))
-		flags |= FD_RAW_INTR;
-
-	if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)){
-		ready_date = DRS->spinup_date + DP->spinup;
-		/* If spinup will take a long time, rerun scandrives
-		 * again just before spinup completion. Beware that
-		 * after scandrives, we must again wait for selection.
-		 */
-		if ((signed) (ready_date - jiffies) > DP->select_delay){
-			ready_date -= DP->select_delay;
-			function = (timeout_fn) floppy_start;
-		} else
-			function = (timeout_fn) setup_rw_floppy;
-
-		/* wait until the floppy is spinning fast enough */
-		if (fd_wait_for_completion(ready_date,function))
-			return;
-	}
-	dflags = DRS->flags;
-
-	if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
-		setup_DMA();
-
-	if (flags & FD_RAW_INTR)
-		do_floppy = main_command_interrupt;
-
-	r=0;
-	for (i=0; i< raw_cmd->cmd_count; i++)
-		r|=output_byte(raw_cmd->cmd[i]);
-
-#ifdef DEBUGT
-	debugt("rw_command: ");
-#endif
-	if (r){
-		cont->error();
-		reset_fdc();
-		return;
-	}
-
-	if (!(flags & FD_RAW_INTR)){
-		inr = result();
-		cont->interrupt();
-	} else if (flags & FD_RAW_NEED_DISK)
-		fd_watchdog();
-}
-
-static int blind_seek;
-
-/*
- * This is the routine called after every seek (or recalibrate) interrupt
- * from the floppy controller.
- */
-static void seek_interrupt(void)
-{
-#ifdef DEBUGT
-	debugt("seek interrupt:");
-#endif
-	if (inr != 2 || (ST0 & 0xF8) != 0x20) {
-		DRS->track = NEED_2_RECAL;
-		cont->error();
-		cont->redo();
-		return;
-	}
-	if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek){
-#ifdef DCL_DEBUG
-		if (DP->flags & FD_DEBUG){
-			DPRINT("clearing NEWCHANGE flag because of effective seek\n");
-			DPRINT("jiffies=%lu\n", jiffies);
-		}
-#endif
-		CLEARF(FD_DISK_NEWCHANGE); /* effective seek */
-		CLEARF(FD_DISK_CHANGED); /* effective seek */
-		DRS->select_date = jiffies;
-	}
-	DRS->track = ST1;
-	floppy_ready();
-}
-
-static void check_wp(void)
-{
-	if (TESTF(FD_VERIFY)) {
-		/* check write protection */
-		output_byte(FD_GETSTATUS);
-		output_byte(UNIT(current_drive));
-		if (result() != 1){
-			FDCS->reset = 1;
-			return;
-		}
-		CLEARF(FD_VERIFY);
-		CLEARF(FD_NEED_TWADDLE);
-#ifdef DCL_DEBUG
-		if (DP->flags & FD_DEBUG){
-			DPRINT("checking whether disk is write protected\n");
-			DPRINT("wp=%x\n",ST3 & 0x40);
-		}
-#endif
-		if (!(ST3  & 0x40))
-			SETF(FD_DISK_WRITABLE);
-		else
-			CLEARF(FD_DISK_WRITABLE);
-	}
-}
-
-static void seek_floppy(void)
-{
-	int track;
-
-	blind_seek=0;
-
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG){
-		DPRINT("calling disk change from seek\n");
-	}
-#endif
-
-	if (!TESTF(FD_DISK_NEWCHANGE) &&
-	    disk_change(current_drive) &&
-	    (raw_cmd->flags & FD_RAW_NEED_DISK)){
-		/* the media changed flag should be cleared after the seek.
-		 * If it isn't, this means that there is really no disk in
-		 * the drive.
-		 */
-		SETF(FD_DISK_CHANGED);
-		cont->done(0);
-		cont->redo();
-		return;
-	}
-	if (DRS->track <= NEED_1_RECAL){
-		recalibrate_floppy();
-		return;
-	} else if (TESTF(FD_DISK_NEWCHANGE) &&
-		   (raw_cmd->flags & FD_RAW_NEED_DISK) &&
-		   (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
-		/* we seek to clear the media-changed condition. Does anybody
-		 * know a more elegant way, which works on all drives? */
-		if (raw_cmd->track)
-			track = raw_cmd->track - 1;
-		else {
-			if (DP->flags & FD_SILENT_DCL_CLEAR){
-				blind_seek = 1;
-				raw_cmd->flags |= FD_RAW_NEED_SEEK;
-			}
-			track = 1;
-		}
-	} else {
-		check_wp();
-		if (raw_cmd->track != DRS->track &&
-		    (raw_cmd->flags & FD_RAW_NEED_SEEK))
-			track = raw_cmd->track;
-		else {
-			setup_rw_floppy();
-			return;
-		}
-	}
-
-	do_floppy = seek_interrupt;
-	output_byte(FD_SEEK);
-	output_byte(UNIT(current_drive));
-	LAST_OUT(track);
-#ifdef DEBUGT
-	debugt("seek command:");
-#endif
-}
-
-static void recal_interrupt(void)
-{
-#ifdef DEBUGT
-	debugt("recal interrupt:");
-#endif
-	if (inr !=2)
-		FDCS->reset = 1;
-	else if (ST0 & ST0_ECE) {
-	       	switch(DRS->track){
-			case NEED_1_RECAL:
-#ifdef DEBUGT
-				debugt("recal interrupt need 1 recal:");
-#endif
-				/* after a second recalibrate, we still haven't
-				 * reached track 0. Probably no drive. Raise an
-				 * error, as failing immediately might upset
-				 * computers possessed by the Devil :-) */
-				cont->error();
-				cont->redo();
-				return;
-			case NEED_2_RECAL:
-#ifdef DEBUGT
-				debugt("recal interrupt need 2 recal:");
-#endif
-				/* If we already did a recalibrate,
-				 * and we are not at track 0, this
-				 * means we have moved. (The only way
-				 * not to move at recalibration is to
-				 * be already at track 0.) Clear the
-				 * new change flag */
-#ifdef DCL_DEBUG
-				if (DP->flags & FD_DEBUG){
-					DPRINT("clearing NEWCHANGE flag because of second recalibrate\n");
-				}
-#endif
-
-				CLEARF(FD_DISK_NEWCHANGE);
-				DRS->select_date = jiffies;
-				/* fall through */
-			default:
-#ifdef DEBUGT
-				debugt("recal interrupt default:");
-#endif
-				/* Recalibrate moves the head by at
-				 * most 80 steps. If after one
-				 * recalibrate we don't have reached
-				 * track 0, this might mean that we
-				 * started beyond track 80.  Try
-				 * again.  */
-				DRS->track = NEED_1_RECAL;
-				break;
-		}
-	} else
-		DRS->track = ST1;
-	floppy_ready();
-}
-
-static void print_result(char *message, int inr)
-{
-	int i;
-
-	DPRINT("%s ", message);
-	if (inr >= 0)
-		for (i=0; i<inr; i++)
-			printk("repl[%d]=%x ", i, reply_buffer[i]);
-	printk("\n");
-}
-
-/* interrupt handler. Note that this can be called externally on the Sparc */
-irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
-	void (*handler)(void) = do_floppy;
-	int do_print;
-	unsigned long f;
-
-	lasthandler = handler;
-	interruptjiffies = jiffies;
-
-	f=claim_dma_lock();
-	fd_disable_dma();
-	release_dma_lock(f);
-
-	floppy_enable_hlt();
-	do_floppy = NULL;
-	if (fdc >= N_FDC || FDCS->address == -1){
-		/* we don't even know which FDC is the culprit */
-		printk("DOR0=%x\n", fdc_state[0].dor);
-		printk("floppy interrupt on bizarre fdc %d\n",fdc);
-		printk("handler=%p\n", handler);
-		is_alive("bizarre fdc");
-		return IRQ_NONE;
-	}
-
-	FDCS->reset = 0;
-	/* We have to clear the reset flag here, because apparently on boxes
-	 * with level triggered interrupts (PS/2, Sparc, ...), it is needed to
-	 * emit SENSEI's to clear the interrupt line. And FDCS->reset blocks the
-	 * emission of the SENSEI's.
-	 * It is OK to emit floppy commands because we are in an interrupt
-	 * handler here, and thus we have to fear no interference of other
-	 * activity.
-	 */
-
-	do_print = !handler && print_unex && !initialising;
-
-	inr = result();
-	if (inr && do_print)
-		print_result("unexpected interrupt", inr);
-	if (inr == 0){
-		do {
-			output_byte(FD_SENSEI);
-			inr = result();
-			if ((ST0 & ST0_INTR) == 0xC0) {
-				int drive = ST0 & ST0_DS;
-
-				/* Attention Interrupt. */
-				if (ST0 & ST0_NR) {
-#ifdef PC9800_DEBUG_FLOPPY
-					if (do_print)
-						printk(KERN_DEBUG
-							"floppy debug: floppy ejected (drive %d)\n",
-							drive);
-#endif
-					USETF(FD_DISK_CHANGED);
-					USETF(FD_VERIFY);
-				} else {
-#ifdef PC9800_DEBUG_FLOPPY
-					if (do_print)
-						printk(KERN_DEBUG
-							"floppy debug: floppy inserted (drive %d)\n",
-							drive);
-#endif
-				}
-			} /* Attention Interrupt */
-#ifdef PC9800_DEBUG_FLOPPY
-			else {
-				printk(KERN_DEBUG
-					"floppy debug : unknown interrupt\n");
-			}
-#endif
-		} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
-	}
-	if (handler) {
-		schedule_bh(handler);
-	} else {
-#if 0
-		FDCS->reset = 1;
-#endif
-	}
-	is_alive("normal interrupt end");
-
-	/* FIXME! Was it really for us? */
-	return IRQ_HANDLED;
-}
-
-static void recalibrate_floppy(void)
-{
-#ifdef DEBUGT
-	debugt("recalibrate floppy:");
-#endif
-	do_floppy = recal_interrupt;
-	output_byte(FD_RECALIBRATE);
-	LAST_OUT(UNIT(current_drive));
-}
-
-/*
- * Must do 4 FD_SENSEIs after reset because of ``drive polling''.
- */
-static void reset_interrupt(void)
-{
-#ifdef PC9800_DEBUG_FLOPPY
-	printk("floppy debug: reset interrupt\n");
-#endif
-#ifdef DEBUGT
-	debugt("reset interrupt:");
-#endif
-	result();		/* get the status ready for set_fdc */
-	if (FDCS->reset) {
-		printk("reset set in interrupt, calling %p\n", cont->error);
-		cont->error(); /* a reset just after a reset. BAD! */
-	}
-	cont->redo();
-}
-
-/*
- * reset is done by pulling bit 2 of DOR low for a while (old FDCs),
- * or by setting the self clearing bit 7 of STATUS (newer FDCs)
- */
-static void reset_fdc(void)
-{
-	unsigned long flags;
-
-#ifdef PC9800_DEBUG_FLOPPY
-	printk("floppy debug: reset_fdc\n");
-#endif
-
-	do_floppy = reset_interrupt;
-	FDCS->reset = 0;
-	reset_fdc_info(0);
-
-	/* Pseudo-DMA may intercept 'reset finished' interrupt.  */
-	/* Irrelevant for systems with true DMA (i386).          */
-
-	flags=claim_dma_lock();
-	fd_disable_dma();
-	release_dma_lock(flags);
-
-	fd_outb(FDCS->dor | 0x80, FD_MODE);
-	udelay(FD_RESET_DELAY);
-	fd_outb(FDCS->dor, FD_MODE);
-	udelay(FD_AFTER_RESET_DELAY);
-}
-
-static void show_floppy(void)
-{
-	int i;
-
-	printk("\n");
-	printk("floppy driver state\n");
-	printk("-------------------\n");
-	printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
-	       jiffies, interruptjiffies, jiffies-interruptjiffies, lasthandler);
-
-
-#ifdef FLOPPY_SANITY_CHECK
-	printk("timeout_message=%s\n", timeout_message);
-	printk("last output bytes:\n");
-	for (i=0; i < OLOGSIZE; i++)
-		printk("%2x %2x %lu\n",
-		       output_log[(i+output_log_pos) % OLOGSIZE].data,
-		       output_log[(i+output_log_pos) % OLOGSIZE].status,
-		       output_log[(i+output_log_pos) % OLOGSIZE].jiffies);
-	printk("last result at %lu\n", resultjiffies);
-	printk("last redo_fd_request at %lu\n", lastredo);
-	for (i=0; i<resultsize; i++){
-		printk("%2x ", reply_buffer[i]);
-	}
-	printk("\n");
-#endif
-
-	printk("status=%x\n", fd_inb(FD98_STATUS));
-	printk("fdc_busy=%lu\n", fdc_busy);
-	if (do_floppy)
-		printk("do_floppy=%p\n", do_floppy);
-	if (floppy_work.pending)
-		printk("floppy_work.func=%p\n", floppy_work.func);
-	if (timer_pending(&fd_timer))
-		printk("fd_timer.function=%p\n", fd_timer.function);
-	if (timer_pending(&fd_timeout)){
-		printk("timer_function=%p\n",fd_timeout.function);
-		printk("expires=%lu\n",fd_timeout.expires-jiffies);
-		printk("now=%lu\n",jiffies);
-	}
-	printk("cont=%p\n", cont);
-	printk("current_req=%p\n", current_req);
-	printk("command_status=%d\n", command_status);
-	printk("\n");
-}
-
-static void floppy_shutdown(unsigned long data)
-{
-	unsigned long flags;
-	
-	if (!initialising)
-		show_floppy();
-	cancel_activity();
-
-	floppy_enable_hlt();
-	
-	flags=claim_dma_lock();
-	fd_disable_dma();
-	release_dma_lock(flags);
-	
-	/* avoid dma going to a random drive after shutdown */
-
-	if (!initialising)
-		DPRINT("floppy timeout called\n");
-	FDCS->reset = 1;
-	if (cont){
-		cont->done(0);
-		cont->redo(); /* this will recall reset when needed */
-	} else {
-		printk("no cont in shutdown!\n");
-		process_fd_request();
-	}
-	is_alive("floppy shutdown");
-}
-/*typedef void (*timeout_fn)(unsigned long);*/
-
-static void access_mode_change_pc9800(void)
-{
-	static int access_mode, mode_change_now, old_mode, new_set = 1;
-#ifdef PC9800_DEBUG_FLOPPY2
-	printk("enter access_mode_change\n");
-#endif
-	access_mode = mode_change_now = 0;
-	if (DP->cmos==4) {
-		switch ((int)(_floppy - &floppy_type[0])) {
-		case 1:
-		case 2:
-			new_set = 1;
-			access_mode = 2;
-			break;
-
-		case 4:
-		case 6:
-			new_set = 1;
-			access_mode = 3;
-			break;
-
-		case 7:
-		case 10:
-			new_set = 1;
-			access_mode = 1;
-			break;
-
-		default:
-			access_mode = 1;
-			break;
-		}
-
-		old_mode = fd_inb(FD_MODE_CHANGE) & 3;
-
-		switch (access_mode) {
-		case 1:
-			if ((old_mode & 2) == 0) {
-				fd_outb(old_mode | 2, FD_MODE_CHANGE);
-				mode_change_now = 1;
-			} else {
-				fd_outb(current_drive << 5, FD_EMODE_CHANGE);
-				if (fd_inb(FD_EMODE_CHANGE) == 0xff)
-					return;
-			}
-
-			fd_outb((current_drive << 5) | 0x11, FD_EMODE_CHANGE);
-			mode_change_now = 1;
-			break;
-
-		case 2:
-			if ((old_mode & 2) == 0) {
-				fd_outb(old_mode | 2, FD_MODE_CHANGE);
-				mode_change_now = 1;
-			} else {
-				fd_outb(current_drive << 5, FD_EMODE_CHANGE);
-				if ((fd_inb(FD_EMODE_CHANGE) & 1) == 0)
-					return;
-				fd_outb((current_drive << 5) | 0x10, FD_EMODE_CHANGE);
-				mode_change_now = 1;
-			}
-
-			break;
-
-		case 3:
-			if ((old_mode & 2) == 0)
-				return;
-			fd_outb(current_drive << 5, FD_EMODE_CHANGE);
-			if (fd_inb(FD_EMODE_CHANGE) & 1)
-				fd_outb((current_drive << 5) | 0x10, FD_EMODE_CHANGE);
-			fd_outb(old_mode & 0xfd, FD_MODE_CHANGE);
-			mode_change_now = 1;
-			break;
-
-		default:
-			break;
-		}
-	} else {
-		switch ((int)(_floppy - &floppy_type[0])) {
-		case 1:
-		case 2:
-			new_set = 1;
-			access_mode = 2;
-			break;
-
-		case 4:
-		case 6:
-			new_set = 1;
-			access_mode = 3;
-			break;
-
-		default:
-			switch (DP->cmos) {
-			case 2:
-				access_mode = 2;
-				break;
-
-			case 3:
-				access_mode = 3;
-				break;
-
-			default:
-				break;
-			}
-
-			break;
-		}
-
-		old_mode = fd_inb(FD_MODE_CHANGE) & 3;
-
-		switch (access_mode) {
-		case 2:
-			if ((old_mode & 2) == 0) {
-				fd_outb(old_mode | 2, FD_MODE_CHANGE);
-				mode_change_now = 1;
-			}
-
-			break;
-
-		case 3:
-			if (old_mode & 2) {
-				fd_outb(old_mode & 0xfd, FD_MODE_CHANGE);
-				mode_change_now = 1;
-			}
-
-			break;
-
-		default:
-			break;
-		}
-	}
-#ifdef PC9800_DEBUG_FLOPPY2
-	printk("floppy debug: DP->cmos=%d\n", DP->cmos);
-	printk("floppy debug: mode_change_now=%d\n", mode_change_now);
-	printk("floppy debug: access_mode=%d\n", access_mode);
-	printk("floppy debug: old_mode=%d\n", old_mode);
-	printk("floppy debug: _floppy - &floppy_type[0]=%d\n", (int)(_floppy - &floppy_type[0]));
-#endif /* PC9800_DEBUG_FLOPPY2 */
-	if(mode_change_now)
-		reset_fdc();
-}
-
-/* start motor, check media-changed condition and write protection */
-static int start_motor(void (*function)(void) )
-{
-	access_mode_change_pc9800();
-	set_mode(~0, 0x8);
-
-	/* wait_for_completion also schedules reset if needed. */
-	return(fd_wait_for_completion(DRS->select_date+DP->select_delay,
-				   (timeout_fn) function));
-}
-
-static void floppy_ready(void)
-{
-	CHECK_RESET;
-	if (start_motor(floppy_ready)) return;
-
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG){
-		DPRINT("calling disk change from floppy_ready\n");
-	}
-#endif
-	if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
-	   disk_change(current_drive) &&
-	   !DP->select_delay)
-		twaddle(); /* this clears the dcl on certain drive/controller
-			    * combinations */
-
-#ifdef fd_chose_dma_mode
-	if ((raw_cmd->flags & FD_RAW_READ) || 
-	    (raw_cmd->flags & FD_RAW_WRITE))
-	{
-		unsigned long flags = claim_dma_lock();
-		fd_chose_dma_mode(raw_cmd->kernel_data,
-				  raw_cmd->length);
-		release_dma_lock(flags);
-	}
-#endif
-
-#if 0
-	access_mode_change_pc9800();
-#endif
-	if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){
-		fdc_specify(); /* must be done here because of hut, hlt ... */
-		seek_floppy();
-	} else {
-		if ((raw_cmd->flags & FD_RAW_READ) || 
-		    (raw_cmd->flags & FD_RAW_WRITE))
-			fdc_specify();
-		setup_rw_floppy();
-	}
-}
-
-static void floppy_start(void)
-{
-	reschedule_timeout(current_reqD, "floppy start", 0);
-
-	scandrives();
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG){
-		DPRINT("setting NEWCHANGE in floppy_start\n");
-	}
-#endif
-	SETF(FD_DISK_NEWCHANGE);
-	floppy_ready();
-}
-
-/*
- * ========================================================================
- * here ends the bottom half. Exported routines are:
- * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc,
- * start_motor, reset_fdc, reset_fdc_info, interpret_errors.
- * Initialization also uses output_byte, result, set_dor, floppy_interrupt
- * and set_dor.
- * ========================================================================
- */
-/*
- * General purpose continuations.
- * ==============================
- */
-
-static void do_wakeup(void)
-{
-	reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
-	cont = 0;
-	command_status += 2;
-	wake_up(&command_done);
-}
-
-static struct cont_t wakeup_cont={
-	empty,
-	do_wakeup,
-	empty,
-	(done_f)empty
-};
-
-
-static struct cont_t intr_cont={
-	empty,
-	process_fd_request,
-	empty,
-	(done_f) empty
-};
-
-static int wait_til_done(void (*handler)(void), int interruptible)
-{
-	int ret;
-
-	schedule_bh((void *)(void *)handler);
-
-	if (command_status < 2 && NO_SIGNAL) {
-		DECLARE_WAITQUEUE(wait, current);
-
-		add_wait_queue(&command_done, &wait);
-		for (;;) {
-			set_current_state(interruptible?
-					  TASK_INTERRUPTIBLE:
-					  TASK_UNINTERRUPTIBLE);
-
-			if (command_status >= 2 || !NO_SIGNAL)
-				break;
-
-			is_alive("wait_til_done");
-
-			schedule();
-		}
-
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&command_done, &wait);
-	}
-
-	if (command_status < 2){
-		cancel_activity();
-		cont = &intr_cont;
-		reset_fdc();
-		return -EINTR;
-	}
-
-#ifdef PC9800_DEBUG_FLOPPY
-	if (command_status != FD_COMMAND_OKAY)
-		printk("floppy check: wait_til_done out:%d\n", command_status);
-#endif
-	if (FDCS->reset)
-		command_status = FD_COMMAND_ERROR;
-	if (command_status == FD_COMMAND_OKAY)
-		ret=0;
-	else
-		ret=-EIO;
-	command_status = FD_COMMAND_NONE;
-	return ret;
-}
-
-static void generic_done(int result)
-{
-	command_status = result;
-	cont = &wakeup_cont;
-}
-
-static void generic_success(void)
-{
-	cont->done(1);
-}
-
-static void generic_failure(void)
-{
-	cont->done(0);
-}
-
-static void success_and_wakeup(void)
-{
-	generic_success();
-	cont->redo();
-}
-
-
-/*
- * formatting and rw support.
- * ==========================
- */
-
-static int next_valid_format(void)
-{
-	int probed_format;
-
-	probed_format = DRS->probed_format;
-	while(1){
-		if (probed_format >= 8 ||
-		     !DP->autodetect[probed_format]){
-			DRS->probed_format = 0;
-			return 1;
-		}
-		if (floppy_type[DP->autodetect[probed_format]].sect){
-			DRS->probed_format = probed_format;
-			return 0;
-		}
-		probed_format++;
-	}
-}
-
-static void bad_flp_intr(void)
-{
-	if (probing){
-		DRS->probed_format++;
-		if (!next_valid_format())
-			return;
-	}
-	(*errors)++;
-	INFBOUND(DRWE->badness, *errors);
-	if (*errors > DP->max_errors.abort)
-		cont->done(0);
-	if (*errors > DP->max_errors.reset)
-		FDCS->reset = 1;
-	else if (*errors > DP->max_errors.recal)
-		DRS->track = NEED_2_RECAL;
-}
-
-static void set_floppy(int drive)
-{
-	int type = ITYPE(UDRS->fd_device);
-	if (type) {
-		auto_detect_mode = 0;
-		_floppy = floppy_type + type;
-	} else if (auto_detect_mode == 0) {
-		auto_detect_mode = 1;
-		retry_auto_detect = 0;
-		_floppy = current_type[drive];
-	}
-#ifdef PC9800_DEBUG_FLOPPY2
-	printk("set_floppy: set floppy type=%d\n", (int)(_floppy - floppy_type));
-#endif
-}
-
-/*
- * formatting support.
- * ===================
- */
-static void format_interrupt(void)
-{
-	switch (interpret_errors()){
-		case 1:
-			cont->error();
-		case 2:
-			break;
-		case 0:
-			cont->done(1);
-	}
-	cont->redo();
-}
-
-#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
-#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1))
-#define CT(x) ((x) | 0xc0)
-static void setup_format_params(int track)
-{
-	struct fparm {
-		unsigned char track,head,sect,size;
-	} *here = (struct fparm *)floppy_track_buffer;
-	int il,n;
-	int count,head_shift,track_shift;
-
-	raw_cmd = &default_raw_cmd;
-	raw_cmd->track = track;
-
-	raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
-		FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK;
-	raw_cmd->rate = _floppy->rate & 0x43;
-	raw_cmd->cmd_count = NR_F;
-	COMMAND = FM_MODE(_floppy,FD_FORMAT);
-	DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy,format_req.head);
-	F_SIZECODE = FD_SIZECODE(_floppy);
-	F_SECT_PER_TRACK = _floppy->sect << 2 >> F_SIZECODE;
-	F_GAP = _floppy->fmt_gap;
-	F_FILL = FD_FILL_BYTE;
-
-	raw_cmd->kernel_data = floppy_track_buffer;
-	raw_cmd->length = 4 * F_SECT_PER_TRACK;
-
-	/* allow for about 30ms for data transport per track */
-	head_shift  = (F_SECT_PER_TRACK + 5) / 6;
-
-	/* a ``cylinder'' is two tracks plus a little stepping time */
-	track_shift = 2 * head_shift + 3;
-
-	/* position of logical sector 1 on this track */
-	n = (track_shift * format_req.track + head_shift * format_req.head)
-		% F_SECT_PER_TRACK;
-
-	/* determine interleave */
-	il = 1;
-	if (_floppy->fmt_gap < 0x22)
-		il++;
-
-	/* initialize field */
-	for (count = 0; count < F_SECT_PER_TRACK; ++count) {
-		here[count].track = format_req.track;
-		here[count].head = format_req.head;
-		here[count].sect = 0;
-		here[count].size = F_SIZECODE;
-	}
-	/* place logical sectors */
-	for (count = 1; count <= F_SECT_PER_TRACK; ++count) {
-		here[n].sect = count;
-		n = (n+il) % F_SECT_PER_TRACK;
-		if (here[n].sect) { /* sector busy, find next free sector */
-			++n;
-			if (n>= F_SECT_PER_TRACK) {
-				n-=F_SECT_PER_TRACK;
-				while (here[n].sect) ++n;
-			}
-		}
-	}
-}
-
-static void redo_format(void)
-{
-	buffer_track = -1;
-	setup_format_params(format_req.track << STRETCH(_floppy));
-	floppy_start();
-#ifdef DEBUGT
-	debugt("queue format request");
-#endif
-}
-
-static struct cont_t format_cont={
-	format_interrupt,
-	redo_format,
-	bad_flp_intr,
-	generic_done };
-
-static int do_format(int drive, struct format_descr *tmp_format_req)
-{
-	int ret;
-
-	LOCK_FDC(drive,1);
-	set_floppy(drive);
-	if (!_floppy ||
-	    _floppy->track > DP->tracks ||
-	    tmp_format_req->track >= _floppy->track ||
-	    tmp_format_req->head >= _floppy->head ||
-	    (_floppy->sect << 2) % (1 <<  FD_SIZECODE(_floppy)) ||
-	    !_floppy->fmt_gap) {
-		process_fd_request();
-		return -EINVAL;
-	}
-	format_req = *tmp_format_req;
-	format_errors = 0;
-	cont = &format_cont;
-	errors = &format_errors;
-	IWAIT(redo_format);
-	process_fd_request();
-	return ret;
-}
-
-/*
- * Buffer read/write and support
- * =============================
- */
-
-static void floppy_end_request(struct request *req, int uptodate)
-{
-	if (end_that_request_first(req, uptodate, current_count_sectors))
-		return;
-	add_disk_randomness(req->rq_disk);
-	floppy_off((long)req->rq_disk->private_data);
-	blkdev_dequeue_request(req);
-	end_that_request_last(req);
-
-	/* We're done with the request */
-	current_req = NULL;
-}
-
-
-/* new request_done. Can handle physical sectors which are smaller than a
- * logical buffer */
-static void request_done(int uptodate)
-{
-	struct request_queue *q = floppy_queue;
-	struct request *req = current_req;
-	unsigned long flags;
-	int block;
-
-	probing = 0;
-	reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
-
-	if (!req) {
-		printk("floppy.c: no request in request_done\n");
-		return;
-	}
-
-	if (uptodate){
-		/* maintain values for invalidation on geometry
-		 * change */
-		block = current_count_sectors + req->sector;
-		INFBOUND(DRS->maxblock, block);
-		if (block > _floppy->sect)
-			DRS->maxtrack = 1;
-
-		/* unlock chained buffers */
-		spin_lock_irqsave(q->queue_lock, flags);
-		floppy_end_request(req, 1);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-	} else {
-		if (rq_data_dir(req) == WRITE) {
-			/* record write error information */
-			DRWE->write_errors++;
-			if (DRWE->write_errors == 1) {
-				DRWE->first_error_sector = req->sector;
-				DRWE->first_error_generation = DRS->generation;
-			}
-			DRWE->last_error_sector = req->sector;
-			DRWE->last_error_generation = DRS->generation;
-		}
-		spin_lock_irqsave(q->queue_lock, flags);
-		floppy_end_request(req, 0);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-	}
-}
-
-/* Interrupt handler evaluating the result of the r/w operation */
-static void rw_interrupt(void)
-{
-	int nr_sectors, ssize, eoc, heads;
-
-	if (R_HEAD >= 2) {
-	    /* some Toshiba floppy controllers occasionnally seem to
-	     * return bogus interrupts after read/write operations, which
-	     * can be recognized by a bad head number (>= 2) */
-	     return;
-	}  
-
-	if (!DRS->first_read_date)
-		DRS->first_read_date = jiffies;
-
-	nr_sectors = 0;
-	CODE2SIZE;
-
-	if (ST1 & ST1_EOC)
-		eoc = 1;
-	else
-		eoc = 0;
-
-	if (COMMAND & 0x80)
-		heads = 2;
-	else
-		heads = 1;
-
-	nr_sectors = (((R_TRACK-TRACK) * heads +
-				   R_HEAD-HEAD) * SECT_PER_TRACK +
-				   R_SECTOR-SECTOR + eoc) << SIZECODE >> 2;
-
-#ifdef FLOPPY_SANITY_CHECK
-	if (nr_sectors / ssize > 
-		(in_sector_offset + current_count_sectors + ssize - 1) / ssize) {
-		DPRINT("long rw: %x instead of %lx\n",
-			nr_sectors, current_count_sectors);
-		printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
-		printk("rh=%d h=%d\n", R_HEAD, HEAD);
-		printk("rt=%d t=%d\n", R_TRACK, TRACK);
-		printk("heads=%d eoc=%d\n", heads, eoc);
-		printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
-		       fsector_t, ssize);
-		printk("in_sector_offset=%d\n", in_sector_offset);
-	}
-#endif
-
-	nr_sectors -= in_sector_offset;
-	INFBOUND(nr_sectors,0);
-	SUPBOUND(current_count_sectors, nr_sectors);
-
-	switch (interpret_errors()){
-		case 2:
-			cont->redo();
-			return;
-		case 1:
-			if (!current_count_sectors){
-				cont->error();
-				cont->redo();
-				return;
-			}
-			break;
-		case 0:
-			if (!current_count_sectors){
-				cont->redo();
-				return;
-			}
-			current_type[current_drive] = _floppy;
-			floppy_sizes[TOMINOR(current_drive) ]= _floppy->size;
-			break;
-	}
-
-	if (probing) {
-		if (DP->flags & FTD_MSG)
-			DPRINT("Auto-detected floppy type %s in fd%d\n",
-				_floppy->name,current_drive);
-		current_type[current_drive] = _floppy;
-		floppy_sizes[TOMINOR(current_drive)] = _floppy->size;
-		probing = 0;
-	}
-
-	if (CT(COMMAND) != FD_READ || 
-	     raw_cmd->kernel_data == current_req->buffer){
-		/* transfer directly from buffer */
-		cont->done(1);
-	} else if (CT(COMMAND) == FD_READ){
-		buffer_track = raw_cmd->track;
-		buffer_drive = current_drive;
-		INFBOUND(buffer_max, nr_sectors + fsector_t);
-	}
-	cont->redo();
-}
-
-/* Compute maximal contiguous buffer size. */
-static int buffer_chain_size(void)
-{
-	struct bio *bio;
-	struct bio_vec *bv;
-	int size, i;
-	char *base;
-
-	base = bio_data(current_req->bio);
-	size = 0;
-
-	rq_for_each_bio(bio, current_req) {
-		bio_for_each_segment(bv, bio, i) {
-			if (page_address(bv->bv_page) + bv->bv_offset != base + size)
-				break;
-
-			size += bv->bv_len;
-		}
-	}
-
-	return size >> 9;
-}
-
-/* Compute the maximal transfer size */
-static int transfer_size(int ssize, int max_sector, int max_size)
-{
-	SUPBOUND(max_sector, fsector_t + max_size);
-
-	/* alignment */
-	max_sector -= (max_sector % _floppy->sect) % ssize;
-
-	/* transfer size, beginning not aligned */
-	current_count_sectors = max_sector - fsector_t ;
-
-	return max_sector;
-}
-
-/*
- * Move data from/to the track buffer to/from the buffer cache.
- */
-static void copy_buffer(int ssize, int max_sector, int max_sector_2)
-{
-	int remaining; /* number of transferred 512-byte sectors */
-	struct bio_vec *bv;
-	struct bio *bio;
-	char *buffer, *dma_buffer;
-	int size, i;
-
-	max_sector = transfer_size(ssize,
-				   minimum(max_sector, max_sector_2),
-				   current_req->nr_sectors);
-
-	if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
-	    buffer_max > fsector_t + current_req->nr_sectors)
-		current_count_sectors = minimum(buffer_max - fsector_t,
-						current_req->nr_sectors);
-
-	remaining = current_count_sectors << 9;
-#ifdef FLOPPY_SANITY_CHECK
-	if ((remaining >> 9) > current_req->nr_sectors  &&
-	    CT(COMMAND) == FD_WRITE){
-		DPRINT("in copy buffer\n");
-		printk("current_count_sectors=%ld\n", current_count_sectors);
-		printk("remaining=%d\n", remaining >> 9);
-		printk("current_req->nr_sectors=%ld\n",current_req->nr_sectors);
-		printk("current_req->current_nr_sectors=%u\n",
-		       current_req->current_nr_sectors);
-		printk("max_sector=%d\n", max_sector);
-		printk("ssize=%d\n", ssize);
-	}
-#endif
-
-	buffer_max = maximum(max_sector, buffer_max);
-
-	dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9);
-
-	size = current_req->current_nr_sectors << 9;
-
-	rq_for_each_bio(bio, current_req) {
-		bio_for_each_segment(bv, bio, i) {
-			if (!remaining)
-				break;
-
-			size = bv->bv_len;
-			SUPBOUND(size, remaining);
-
-			buffer = page_address(bv->bv_page) + bv->bv_offset;
-#ifdef FLOPPY_SANITY_CHECK
-		if (dma_buffer + size >
-		    floppy_track_buffer + (max_buffer_sectors << 10) ||
-		    dma_buffer < floppy_track_buffer){
-			DPRINT("buffer overrun in copy buffer %d\n",
-				(int) ((floppy_track_buffer - dma_buffer) >>9));
-			printk("fsector_t=%d buffer_min=%d\n",
-			       fsector_t, buffer_min);
-			printk("current_count_sectors=%ld\n",
-			       current_count_sectors);
-			if (CT(COMMAND) == FD_READ)
-				printk("read\n");
-			if (CT(COMMAND) == FD_WRITE)
-				printk("write\n");
-			break;
-		}
-		if (((unsigned long)buffer) % 512)
-			DPRINT("%p buffer not aligned\n", buffer);
-#endif
-			if (CT(COMMAND) == FD_READ)
-				memcpy(buffer, dma_buffer, size);
-			else
-				memcpy(dma_buffer, buffer, size);
-
-			remaining -= size;
-			dma_buffer += size;
-		}
-	}
-#ifdef FLOPPY_SANITY_CHECK
-	if (remaining){
-		if (remaining > 0)
-			max_sector -= remaining >> 9;
-		DPRINT("weirdness: remaining %d\n", remaining>>9);
-	}
-#endif
-}
-
-#if 0
-static inline int check_dma_crossing(char *start, 
-				     unsigned long length, char *message)
-{
-	if (CROSS_64KB(start, length)) {
-		printk("DMA xfer crosses 64KB boundary in %s %p-%p\n", 
-		       message, start, start+length);
-		return 1;
-	} else
-		return 0;
-}
-#endif
-
-/* work around a bug in pseudo DMA
- * (on some FDCs) pseudo DMA does not stop when the CPU stops
- * sending data.  Hence we need a different way to signal the
- * transfer length:  We use SECT_PER_TRACK.  Unfortunately, this
- * does not work with MT, hence we can only transfer one head at
- * a time
- */
-static void virtualdmabug_workaround(void)
-{
-	int hard_sectors, end_sector;
-
-	if(CT(COMMAND) == FD_WRITE) {
-		COMMAND &= ~0x80; /* switch off multiple track mode */
-
-		hard_sectors = raw_cmd->length >> (7 + SIZECODE);
-		end_sector = SECTOR + hard_sectors - 1;
-#ifdef FLOPPY_SANITY_CHECK
-		if(end_sector > SECT_PER_TRACK) {
-			printk("too many sectors %d > %d\n",
-			       end_sector, SECT_PER_TRACK);
-			return;
-		}
-#endif
-		SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points
-					      * to end of transfer */
-	}
-}
-
-/*
- * Formulate a read/write request.
- * this routine decides where to load the data (directly to buffer, or to
- * tmp floppy area), how much data to load (the size of the buffer, the whole
- * track, or a single sector)
- * All floppy_track_buffer handling goes in here. If we ever add track buffer
- * allocation on the fly, it should be done here. No other part should need
- * modification.
- */
-
-static int make_raw_rw_request(void)
-{
-	int aligned_sector_t;
-	int max_sector, max_size, tracksize, ssize;
-
-	if(max_buffer_sectors == 0) {
-		printk("VFS: Block I/O scheduled on unopened device\n");
-		return 0;
-	}
-
-	set_fdc((long)current_req->rq_disk->private_data);
-
-	raw_cmd = &default_raw_cmd;
-	raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
-		FD_RAW_NEED_SEEK;
-	raw_cmd->cmd_count = NR_RW;
-	if (rq_data_dir(current_req) == READ) {
-		raw_cmd->flags |= FD_RAW_READ;
-		COMMAND = FM_MODE(_floppy,FD_READ);
-	} else if (rq_data_dir(current_req) == WRITE){
-		raw_cmd->flags |= FD_RAW_WRITE;
-		COMMAND = FM_MODE(_floppy,FD_WRITE);
-	} else {
-		DPRINT("make_raw_rw_request: unknown command\n");
-		return 0;
-	}
-
-	max_sector = _floppy->sect * _floppy->head;
-
-	TRACK = (int)current_req->sector / max_sector;
-	fsector_t = (int)current_req->sector % max_sector;
-	if (_floppy->track && TRACK >= _floppy->track) {
-		if (current_req->current_nr_sectors & 1) {
-			current_count_sectors = 1;
-			return 1;
-		} else
-			return 0;
-	}
-	HEAD = fsector_t / _floppy->sect;
-
-	if (((_floppy->stretch & FD_SWAPSIDES) || TESTF(FD_NEED_TWADDLE)) &&
-	    fsector_t < _floppy->sect)
-		max_sector = _floppy->sect;
-
-	/* 2M disks have phantom sectors on the first track */
-	if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)){
-		max_sector = 2 * _floppy->sect / 3;
-		if (fsector_t >= max_sector){
-			current_count_sectors = minimum(_floppy->sect - fsector_t,
-							current_req->nr_sectors);
-			return 1;
-		}
-		SIZECODE = 2;
-	} else
-		SIZECODE = FD_SIZECODE(_floppy);
-	raw_cmd->rate = _floppy->rate & 0x43;
-	if ((_floppy->rate & FD_2M) &&
-	    (TRACK || HEAD) &&
-	    raw_cmd->rate == 2)
-		raw_cmd->rate = 1;
-
-	if (SIZECODE)
-		SIZECODE2 = 0xff;
-	else
-		SIZECODE2 = 0x80;
-	raw_cmd->track = TRACK << STRETCH(_floppy);
-	DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy,HEAD);
-	GAP = _floppy->gap;
-	CODE2SIZE;
-	SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
-	SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + 1;
-
-	/* tracksize describes the size which can be filled up with sectors
-	 * of size ssize.
-	 */
-	tracksize = _floppy->sect - _floppy->sect % ssize;
-	if (tracksize < _floppy->sect){
-		SECT_PER_TRACK ++;
-		if (tracksize <= fsector_t % _floppy->sect)
-			SECTOR--;
-
-		/* if we are beyond tracksize, fill up using smaller sectors */
-		while (tracksize <= fsector_t % _floppy->sect){
-			while(tracksize + ssize > _floppy->sect){
-				SIZECODE--;
-				ssize >>= 1;
-			}
-			SECTOR++; SECT_PER_TRACK ++;
-			tracksize += ssize;
-		}
-		max_sector = HEAD * _floppy->sect + tracksize;
-	} else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) {
-		max_sector = _floppy->sect;
-	} else if (!HEAD && CT(COMMAND) == FD_WRITE) {
-		/* for virtual DMA bug workaround */
-		max_sector = _floppy->sect;
-	}
-
-	in_sector_offset = (fsector_t % _floppy->sect) % ssize;
-	aligned_sector_t = fsector_t - in_sector_offset;
-	max_size = current_req->nr_sectors;
-	if ((raw_cmd->track == buffer_track) && 
-	    (current_drive == buffer_drive) &&
-	    (fsector_t >= buffer_min) && (fsector_t < buffer_max)) {
-		/* data already in track buffer */
-		if (CT(COMMAND) == FD_READ) {
-			copy_buffer(1, max_sector, buffer_max);
-			return 1;
-		}
-	} else if (in_sector_offset || current_req->nr_sectors < ssize){
-		if (CT(COMMAND) == FD_WRITE){
-			if (fsector_t + current_req->nr_sectors > ssize &&
-			    fsector_t + current_req->nr_sectors < ssize + ssize)
-				max_size = ssize + ssize;
-			else
-				max_size = ssize;
-		}
-		raw_cmd->flags &= ~FD_RAW_WRITE;
-		raw_cmd->flags |= FD_RAW_READ;
-		COMMAND = FM_MODE(_floppy,FD_READ);
-	} else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) {
-		unsigned long dma_limit;
-		int direct, indirect;
-
-		indirect= transfer_size(ssize,max_sector,max_buffer_sectors*2) -
-			fsector_t;
-
-		/*
-		 * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide
-		 * on a 64 bit machine!
-		 */
-		max_size = buffer_chain_size();
-		dma_limit = (MAX_DMA_ADDRESS - ((unsigned long) current_req->buffer)) >> 9;
-		if ((unsigned long) max_size > dma_limit) {
-			max_size = dma_limit;
-		}
-		/* 64 kb boundaries */
-		if (CROSS_64KB(current_req->buffer, max_size << 9))
-			max_size = (K_64 - 
-				    ((unsigned long)current_req->buffer) % K_64)>>9;
-		direct = transfer_size(ssize,max_sector,max_size) - fsector_t;
-		/*
-		 * We try to read tracks, but if we get too many errors, we
-		 * go back to reading just one sector at a time.
-		 *
-		 * This means we should be able to read a sector even if there
-		 * are other bad sectors on this track.
-		 */
-		if (!direct ||
-		    (indirect * 2 > direct * 3 &&
-		     *errors < DP->max_errors.read_track &&
-		     /*!TESTF(FD_NEED_TWADDLE) &&*/
-		     ((!probing || (DP->read_track&(1<<DRS->probed_format)))))){
-			max_size = current_req->nr_sectors;
-		} else {
-			raw_cmd->kernel_data = current_req->buffer;
-			raw_cmd->length = current_count_sectors << 9;
-			if (raw_cmd->length == 0){
-				DPRINT("zero dma transfer attempted from make_raw_request\n");
-				DPRINT("indirect=%d direct=%d fsector_t=%d",
-					indirect, direct, fsector_t);
-				return 0;
-			}
-/*			check_dma_crossing(raw_cmd->kernel_data, 
-					   raw_cmd->length, 
-					   "end of make_raw_request [1]");*/
-
-			virtualdmabug_workaround();
-			return 2;
-		}
-	}
-
-	if (CT(COMMAND) == FD_READ)
-		max_size = max_sector; /* unbounded */
-
-	/* claim buffer track if needed */
-	if (buffer_track != raw_cmd->track ||  /* bad track */
-	    buffer_drive !=current_drive || /* bad drive */
-	    fsector_t > buffer_max ||
-	    fsector_t < buffer_min ||
-	    ((CT(COMMAND) == FD_READ ||
-	      (!in_sector_offset && current_req->nr_sectors >= ssize))&&
-	     max_sector > 2 * max_buffer_sectors + buffer_min &&
-	     max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)
-	    /* not enough space */){
-		buffer_track = -1;
-		buffer_drive = current_drive;
-		buffer_max = buffer_min = aligned_sector_t;
-	}
-	raw_cmd->kernel_data = floppy_track_buffer + 
-		((aligned_sector_t-buffer_min)<<9);
-
-	if (CT(COMMAND) == FD_WRITE){
-		/* copy write buffer to track buffer.
-		 * if we get here, we know that the write
-		 * is either aligned or the data already in the buffer
-		 * (buffer will be overwritten) */
-#ifdef FLOPPY_SANITY_CHECK
-		if (in_sector_offset && buffer_track == -1)
-			DPRINT("internal error offset !=0 on write\n");
-#endif
-		buffer_track = raw_cmd->track;
-		buffer_drive = current_drive;
-		copy_buffer(ssize, max_sector, 2*max_buffer_sectors+buffer_min);
-	} else
-		transfer_size(ssize, max_sector,
-			      2*max_buffer_sectors+buffer_min-aligned_sector_t);
-
-	/* round up current_count_sectors to get dma xfer size */
-	raw_cmd->length = in_sector_offset+current_count_sectors;
-	raw_cmd->length = ((raw_cmd->length -1)|(ssize-1))+1;
-	raw_cmd->length <<= 9;
-#ifdef FLOPPY_SANITY_CHECK
-	/*check_dma_crossing(raw_cmd->kernel_data, raw_cmd->length, 
-	  "end of make_raw_request");*/
-	if ((raw_cmd->length < current_count_sectors << 9) ||
-	    (raw_cmd->kernel_data != current_req->buffer &&
-	     CT(COMMAND) == FD_WRITE &&
-	     (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max ||
-	      aligned_sector_t < buffer_min)) ||
-	    raw_cmd->length % (128 << SIZECODE) ||
-	    raw_cmd->length <= 0 || current_count_sectors <= 0){
-		DPRINT("fractionary current count b=%lx s=%lx\n",
-			raw_cmd->length, current_count_sectors);
-		if (raw_cmd->kernel_data != current_req->buffer)
-			printk("addr=%d, length=%ld\n",
-			       (int) ((raw_cmd->kernel_data - 
-				       floppy_track_buffer) >> 9),
-			       current_count_sectors);
-		printk("st=%d ast=%d mse=%d msi=%d\n",
-		       fsector_t, aligned_sector_t, max_sector, max_size);
-		printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
-		printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
-		       COMMAND, SECTOR, HEAD, TRACK);
-		printk("buffer drive=%d\n", buffer_drive);
-		printk("buffer track=%d\n", buffer_track);
-		printk("buffer_min=%d\n", buffer_min);
-		printk("buffer_max=%d\n", buffer_max);
-		return 0;
-	}
-
-	if (raw_cmd->kernel_data != current_req->buffer){
-		if (raw_cmd->kernel_data < floppy_track_buffer ||
-		    current_count_sectors < 0 ||
-		    raw_cmd->length < 0 ||
-		    raw_cmd->kernel_data + raw_cmd->length >
-		    floppy_track_buffer + (max_buffer_sectors  << 10)){
-			DPRINT("buffer overrun in schedule dma\n");
-			printk("fsector_t=%d buffer_min=%d current_count=%ld\n",
-			       fsector_t, buffer_min,
-			       raw_cmd->length >> 9);
-			printk("current_count_sectors=%ld\n",
-			       current_count_sectors);
-			if (CT(COMMAND) == FD_READ)
-				printk("read\n");
-			if (CT(COMMAND) == FD_WRITE)
-				printk("write\n");
-			return 0;
-		}
-	} else if (raw_cmd->length > current_req->nr_sectors << 9 ||
-		   current_count_sectors > current_req->nr_sectors){
-		DPRINT("buffer overrun in direct transfer\n");
-		return 0;
-	} else if (raw_cmd->length < current_count_sectors << 9){
-		DPRINT("more sectors than bytes\n");
-		printk("bytes=%ld\n", raw_cmd->length >> 9);
-		printk("sectors=%ld\n", current_count_sectors);
-	}
-	if (raw_cmd->length == 0){
-		DPRINT("zero dma transfer attempted from make_raw_request\n");
-		return 0;
-	}
-#endif
-
-	virtualdmabug_workaround();
-	return 2;
-}
-
-static void redo_fd_request(void)
-{
-#define REPEAT {request_done(0); continue; }
-	int drive;
-	int tmp;
-
-	lastredo = jiffies;
-	if (current_drive < N_DRIVE)
-		floppy_off(current_drive);
-
-	for (;;) {
-		if (!current_req) {
-			struct request *req;
-
-			spin_lock_irq(floppy_queue->queue_lock);
-			req = elv_next_request(floppy_queue);
-			spin_unlock_irq(floppy_queue->queue_lock);
-			if (!req) {
-				do_floppy = NULL;
-				unlock_fdc();
-				return;
-			}
-			current_req = req;
-		}
-		drive = (long)current_req->rq_disk->private_data;
-		set_fdc(drive);
-		reschedule_timeout(current_reqD, "redo fd request", 0);
-
-		set_floppy(drive);
-		raw_cmd = & default_raw_cmd;
-		raw_cmd->flags = 0;
-		if (start_motor(redo_fd_request)) return;
-		disk_change(current_drive);
-		if (test_bit(current_drive, &fake_change) ||
-		   TESTF(FD_DISK_CHANGED)){
-			DPRINT("disk absent or changed during operation\n");
-			REPEAT;
-		}
-		if (!_floppy) { /* Autodetection */
-			if (!probing){
-				DRS->probed_format = 0;
-				if (next_valid_format()){
-					DPRINT("no autodetectable formats\n");
-					_floppy = NULL;
-					REPEAT;
-				}
-			}
-			probing = 1;
-			_floppy = floppy_type+DP->autodetect[DRS->probed_format];
-		} else
-			probing = 0;
-		errors = & (current_req->errors);
-		tmp = make_raw_rw_request();
-		if (tmp < 2){
-			request_done(tmp);
-			continue;
-		}
-
-		if (TESTF(FD_NEED_TWADDLE))
-			twaddle();
-		schedule_bh( (void *)(void *) floppy_start);
-#ifdef DEBUGT
-		debugt("queue fd request");
-#endif
-		return;
-	}
-#undef REPEAT
-}
-
-static struct cont_t rw_cont={
-	rw_interrupt,
-	redo_fd_request,
-	bad_flp_intr,
-	request_done };
-
-static void process_fd_request(void)
-{
-	cont = &rw_cont;
-	schedule_bh( (void *)(void *) redo_fd_request);
-}
-
-static void do_fd_request(request_queue_t * q)
-{
-	if(max_buffer_sectors == 0) {
-		printk("VFS: do_fd_request called on non-open device\n");
-		return;
-	}
-
-	if (usage_count == 0) {
-		printk("warning: usage count=0, current_req=%p exiting\n", current_req);
-		printk("sect=%ld flags=%lx\n", (long)current_req->sector, current_req->flags);
-		return;
-	}
-	if (fdc_busy){
-		/* fdc busy, this new request will be treated when the
-		   current one is done */
-		is_alive("do fd request, old request running");
-		return;
-	}
-	lock_fdc(MAXTIMEOUT,0);
-	process_fd_request();
-	is_alive("do fd request");
-}
-
-static struct cont_t poll_cont={
-	success_and_wakeup,
-	floppy_ready,
-	generic_failure,
-	generic_done };
-
-static int poll_drive(int interruptible, int flag)
-{
-	int ret;
-	/* no auto-sense, just clear dcl */
-	raw_cmd = &default_raw_cmd;
-	raw_cmd->flags= flag;
-	raw_cmd->track=0;
-	raw_cmd->cmd_count=0;
-	cont = &poll_cont;
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG){
-		DPRINT("setting NEWCHANGE in poll_drive\n");
-	}
-#endif
-	SETF(FD_DISK_NEWCHANGE);
-	WAIT(floppy_ready);
-	return ret;
-}
-
-/*
- * User triggered reset
- * ====================
- */
-
-static void reset_intr(void)
-{
-	printk("weird, reset interrupt called\n");
-}
-
-static struct cont_t reset_cont={
-	reset_intr,
-	success_and_wakeup,
-	generic_failure,
-	generic_done };
-
-static int user_reset_fdc(int drive, int arg, int interruptible)
-{
-	int ret;
-
-	ret=0;
-	LOCK_FDC(drive,interruptible);
-	if (arg == FD_RESET_ALWAYS)
-		FDCS->reset=1;
-	if (FDCS->reset){
-		cont = &reset_cont;
-		WAIT(reset_fdc);
-	}
-	process_fd_request();
-	return ret;
-}
-
-/*
- * Misc Ioctl's and support
- * ========================
- */
-static inline int fd_copyout(void *param, const void *address, unsigned long size)
-{
-	return copy_to_user(param,address, size) ? -EFAULT : 0;
-}
-
-static inline int fd_copyin(void *param, void *address, unsigned long size)
-{
-	return copy_from_user(address, param, size) ? -EFAULT : 0;
-}
-
-#define _COPYOUT(x) (copy_to_user((void *)param, &(x), sizeof(x)) ? -EFAULT : 0)
-#define _COPYIN(x) (copy_from_user(&(x), (void *)param, sizeof(x)) ? -EFAULT : 0)
-
-#define COPYOUT(x) ECALL(_COPYOUT(x))
-#define COPYIN(x) ECALL(_COPYIN(x))
-
-static inline const char *drive_name(int type, int drive)
-{
-	struct floppy_struct *floppy;
-
-	if (type)
-		floppy = floppy_type + type;
-	else {
-		if (UDP->native_format)
-			floppy = floppy_type + UDP->native_format;
-		else
-			return "(null)";
-	}
-	if (floppy->name)
-		return floppy->name;
-	else
-		return "(null)";
-}
-
-
-/* raw commands */
-static void raw_cmd_done(int flag)
-{
-	int i;
-
-	if (!flag) {
-		raw_cmd->flags |= FD_RAW_FAILURE;
-		raw_cmd->flags |= FD_RAW_HARDFAILURE;
-	} else {
-		raw_cmd->reply_count = inr;
-		if (raw_cmd->reply_count > MAX_REPLIES)
-			raw_cmd->reply_count=0;
-		for (i=0; i< raw_cmd->reply_count; i++)
-			raw_cmd->reply[i] = reply_buffer[i];
-
-		if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE))
-		{
-			unsigned long flags;
-			flags=claim_dma_lock();
-			raw_cmd->length = fd_get_dma_residue();
-			release_dma_lock(flags);
-		}
-		
-		if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
-		    (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
-			raw_cmd->flags |= FD_RAW_FAILURE;
-
-		if (disk_change(current_drive))
-			raw_cmd->flags |= FD_RAW_DISK_CHANGE;
-		else
-			raw_cmd->flags &= ~FD_RAW_DISK_CHANGE;
-		if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER)
-			motor_off_callback(current_drive);
-
-		if (raw_cmd->next &&
-		   (!(raw_cmd->flags & FD_RAW_FAILURE) ||
-		    !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) &&
-		   ((raw_cmd->flags & FD_RAW_FAILURE) ||
-		    !(raw_cmd->flags &FD_RAW_STOP_IF_SUCCESS))) {
-			raw_cmd = raw_cmd->next;
-			return;
-		}
-	}
-	generic_done(flag);
-}
-
-
-static struct cont_t raw_cmd_cont={
-	success_and_wakeup,
-	floppy_start,
-	generic_failure,
-	raw_cmd_done
-};
-
-static inline int raw_cmd_copyout(int cmd, char *param,
-				  struct floppy_raw_cmd *ptr)
-{
-	int ret;
-
-	while(ptr) {
-		COPYOUT(*ptr);
-		param += sizeof(struct floppy_raw_cmd);
-		if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length){
-			if (ptr->length>=0 && ptr->length<=ptr->buffer_length)
-				ECALL(fd_copyout(ptr->data, 
-						 ptr->kernel_data, 
-						 ptr->buffer_length - 
-						 ptr->length));
-		}
-		ptr = ptr->next;
-	}
-	return 0;
-}
-
-
-static void raw_cmd_free(struct floppy_raw_cmd **ptr)
-{
-	struct floppy_raw_cmd *next,*this;
-
-	this = *ptr;
-	*ptr = 0;
-	while(this) {
-		if (this->buffer_length) {
-			fd_dma_mem_free((unsigned long)this->kernel_data,
-					this->buffer_length);
-			this->buffer_length = 0;
-		}
-		next = this->next;
-		kfree(this);
-		this = next;
-	}
-}
-
-
-static inline int raw_cmd_copyin(int cmd, char *param,
-				 struct floppy_raw_cmd **rcmd)
-{
-	struct floppy_raw_cmd *ptr;
-	int ret;
-	int i;
-	
-	*rcmd = 0;
-	while(1) {
-		ptr = (struct floppy_raw_cmd *) 
-			kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
-		if (!ptr)
-			return -ENOMEM;
-		*rcmd = ptr;
-		COPYIN(*ptr);
-		ptr->next = 0;
-		ptr->buffer_length = 0;
-		param += sizeof(struct floppy_raw_cmd);
-		if (ptr->cmd_count > 33)
-			/* the command may now also take up the space
-			 * initially intended for the reply & the
-			 * reply count. Needed for long 82078 commands
-			 * such as RESTORE, which takes ... 17 command
-			 * bytes. Murphy's law #137: When you reserve
-			 * 16 bytes for a structure, you'll one day
-			 * discover that you really need 17...
-			 */
-			return -EINVAL;
-
-		for (i=0; i< 16; i++)
-			ptr->reply[i] = 0;
-		ptr->resultcode = 0;
-		ptr->kernel_data = 0;
-
-		if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
-			if (ptr->length <= 0)
-				return -EINVAL;
-			ptr->kernel_data =(char*)fd_dma_mem_alloc(ptr->length);
-			fallback_on_nodma_alloc(&ptr->kernel_data,
-						ptr->length);
-			if (!ptr->kernel_data)
-				return -ENOMEM;
-			ptr->buffer_length = ptr->length;
-		}
-		if (ptr->flags & FD_RAW_WRITE)
-			ECALL(fd_copyin(ptr->data, ptr->kernel_data, 
-					ptr->length));
-		rcmd = & (ptr->next);
-		if (!(ptr->flags & FD_RAW_MORE))
-			return 0;
-		ptr->rate &= 0x43;
-	}
-}
-
-
-static int raw_cmd_ioctl(int cmd, void *param)
-{
-	int drive, ret, ret2;
-	struct floppy_raw_cmd *my_raw_cmd;
-
-	if (FDCS->rawcmd <= 1)
-		FDCS->rawcmd = 1;
-	for (drive= 0; drive < N_DRIVE; drive++){
-		if (FDC(drive) != fdc)
-			continue;
-		if (drive == current_drive){
-			if (UDRS->fd_ref > 1){
-				FDCS->rawcmd = 2;
-				break;
-			}
-		} else if (UDRS->fd_ref){
-			FDCS->rawcmd = 2;
-			break;
-		}
-	}
-
-	if (FDCS->reset)
-		return -EIO;
-
-	ret = raw_cmd_copyin(cmd, param, &my_raw_cmd);
-	if (ret) {
-		raw_cmd_free(&my_raw_cmd);
-		return ret;
-	}
-
-	raw_cmd = my_raw_cmd;
-	cont = &raw_cmd_cont;
-	ret=wait_til_done(floppy_start,1);
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG){
-		DPRINT("calling disk change from raw_cmd ioctl\n");
-	}
-#endif
-
-	if (ret != -EINTR && FDCS->reset)
-		ret = -EIO;
-
-	DRS->track = NO_TRACK;
-
-	ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd);
-	if (!ret)
-		ret = ret2;
-	raw_cmd_free(&my_raw_cmd);
-	return ret;
-}
-
-static int invalidate_drive(struct block_device *bdev)
-{
-	/* invalidate the buffer track to force a reread */
-	set_bit((long)bdev->bd_disk->private_data, &fake_change);
-	process_fd_request();
-	check_disk_change(bdev);
-	return 0;
-}
-
-
-static inline void clear_write_error(int drive)
-{
-	CLEARSTRUCT(UDRWE);
-}
-
-static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
-			       int drive, int type, struct block_device *bdev)
-{
-	int cnt;
-
-	/* sanity checking for parameters.*/
-	if (g->sect <= 0 ||
-	    g->head <= 0 ||
-	    g->track <= 0 ||
-	    g->track > UDP->tracks>>STRETCH(g) ||
-	    /* check if reserved bits are set */
-	    (g->stretch&~(FD_STRETCH|FD_SWAPSIDES)) != 0)
-		return -EINVAL;
-	if (type){
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		down(&open_lock);
-		LOCK_FDC(drive,1);
-		floppy_type[type] = *g;
-		floppy_type[type].name="user format";
-		for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
-			floppy_sizes[cnt]= floppy_sizes[cnt+0x80]=
-				floppy_type[type].size+1;
-		process_fd_request();
-		for (cnt = 0; cnt < N_DRIVE; cnt++) {
-			struct block_device *bdev = opened_bdev[cnt];
-			if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
-				continue;
-			__invalidate_device(bdev, 0);
-		}
-		up(&open_lock);
-	} else {
-		LOCK_FDC(drive,1);
-		if (cmd != FDDEFPRM)
-			/* notice a disk change immediately, else
-			 * we lose our settings immediately*/
-			CALL(poll_drive(1, FD_RAW_NEED_DISK));
-		user_params[drive] = *g;
-		if (buffer_drive == drive)
-			SUPBOUND(buffer_max, user_params[drive].sect);
-		current_type[drive] = &user_params[drive];
-		floppy_sizes[drive] = user_params[drive].size;
-		if (cmd == FDDEFPRM)
-			DRS->keep_data = -1;
-		else
-			DRS->keep_data = 1;
-		/* invalidation. Invalidate only when needed, i.e.
-		 * when there are already sectors in the buffer cache
-		 * whose number will change. This is useful, because
-		 * mtools often changes the geometry of the disk after
-		 * looking at the boot block */
-		if (DRS->maxblock > user_params[drive].sect || DRS->maxtrack)
-			invalidate_drive(bdev);
-		else
-			process_fd_request();
-	}
-	return 0;
-}
-
-/* handle obsolete ioctl's */
-static int ioctl_table[]= {
-	FDCLRPRM,
-	FDSETPRM,
-	FDDEFPRM,
-	FDGETPRM,
-	FDMSGON,
-	FDMSGOFF,
-	FDFMTBEG,
-	FDFMTTRK,
-	FDFMTEND,
-	FDSETEMSGTRESH,
-	FDFLUSH,
-	FDSETMAXERRS,
-	FDGETMAXERRS,
-	FDGETDRVTYP,
-	FDSETDRVPRM,
-	FDGETDRVPRM,
-	FDGETDRVSTAT,
-	FDPOLLDRVSTAT,
-	FDRESET,
-	FDGETFDCSTAT,
-	FDWERRORCLR,
-	FDWERRORGET,
-	FDRAWCMD,
-	FDEJECT,
-	FDTWADDLE
-};
-
-static inline int normalize_ioctl(int *cmd, int *size)
-{
-	int i;
-
-	for (i=0; i < ARRAY_SIZE(ioctl_table); i++) {
-		if ((*cmd & 0xffff) == (ioctl_table[i] & 0xffff)){
-			*size = _IOC_SIZE(*cmd);
-			*cmd = ioctl_table[i];
-			if (*size > _IOC_SIZE(*cmd)) {
-				printk("ioctl not yet supported\n");
-				return -EFAULT;
-			}
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
-static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
-{
-	if (type)
-		*g = &floppy_type[type];
-	else {
-		LOCK_FDC(drive,0);
-		CALL(poll_drive(0,0));
-		process_fd_request();		
-		*g = current_type[drive];
-	}
-	if (!*g)
-		return -ENODEV;
-	return 0;
-}
-
-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-		    unsigned long param)
-{
-#define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data)
-#define OUT(c,x) case c: outparam = (const char *) (x); break
-#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
-
-	int drive = (long)inode->i_bdev->bd_disk->private_data;
-	int i, type = ITYPE(UDRS->fd_device);
-	int ret;
-	int size;
-	union inparam {
-		struct floppy_struct g; /* geometry */
-		struct format_descr f;
-		struct floppy_max_errors max_errors;
-		struct floppy_drive_params dp;
-	} inparam; /* parameters coming from user space */
-	const char *outparam; /* parameters passed back to user space */
-
-	/* convert compatibility eject ioctls into floppy eject ioctl.
-	 * We do this in order to provide a means to eject floppy disks before
-	 * installing the new fdutils package */
-	if (cmd == CDROMEJECT || /* CD-ROM eject */
-	    cmd == 0x6470 /* SunOS floppy eject */) {
-		DPRINT("obsolete eject ioctl\n");
-		DPRINT("please use floppycontrol --eject\n");
-		cmd = FDEJECT;
-	}
-
-	/* generic block device ioctls */
-	switch(cmd) {
-		/* the following have been inspired by the corresponding
-		 * code for other block devices. */
-		struct floppy_struct *g;
-		case HDIO_GETGEO:
-		{
-			struct hd_geometry loc;
-			ECALL(get_floppy_geometry(drive, type, &g));
-			loc.heads = g->head;
-			loc.sectors = g->sect;
-			loc.cylinders = g->track;
-			loc.start = 0;
-			return _COPYOUT(loc);
-		}
-	}
-
-	/* convert the old style command into a new style command */
-	if ((cmd & 0xff00) == 0x0200) {
-		ECALL(normalize_ioctl(&cmd, &size));
-	} else
-		return -EINVAL;
-
-	/* permission checks */
-	if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) ||
-	    ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
-		return -EPERM;
-
-	/* copyin */
-	CLEARSTRUCT(&inparam);
-	if (_IOC_DIR(cmd) & _IOC_WRITE)
-		ECALL(fd_copyin((void *)param, &inparam, size))
-
-	switch (cmd) {
-		case FDEJECT:
-			if (UDRS->fd_ref != 1)
-				/* somebody else has this drive open */
-				return -EBUSY;
-			LOCK_FDC(drive,1);
-
-			/* do the actual eject. Fails on
-			 * non-Sparc architectures */
-			ret=fd_eject(UNIT(drive));
-
-			USETF(FD_DISK_CHANGED);
-			USETF(FD_VERIFY);
-			process_fd_request();
-			return ret;			
-		case FDCLRPRM:
-			LOCK_FDC(drive,1);
-			current_type[drive] = NULL;
-			floppy_sizes[drive] = MAX_DISK_SIZE << 1;
-			UDRS->keep_data = 0;
-			return invalidate_drive(inode->i_bdev);
-		case FDSETPRM:
-		case FDDEFPRM:
-			return set_geometry(cmd, & inparam.g,
-					    drive, type, inode->i_bdev);
-		case FDGETPRM:
-			ECALL(get_floppy_geometry(drive, type, 
-						  (struct floppy_struct**)
-						  &outparam));
-			break;
-
-		case FDMSGON:
-			UDP->flags |= FTD_MSG;
-			return 0;
-		case FDMSGOFF:
-			UDP->flags &= ~FTD_MSG;
-			return 0;
-
-		case FDFMTBEG:
-			LOCK_FDC(drive,1);
-			CALL(poll_drive(1, FD_RAW_NEED_DISK));
-			ret = UDRS->flags;
-			if (ret & FD_VERIFY) {
-				CALL(poll_drive(1, FD_RAW_NEED_DISK));
-				ret = UDRS->flags;
-			}
-
-			if (ret & FD_VERIFY) {
-				CALL(poll_drive(1, FD_RAW_NEED_DISK));
-				ret = UDRS->flags;
-			}
-
-			if (ret & FD_VERIFY) {
-				CALL(poll_drive(1, FD_RAW_NEED_DISK));
-				ret = UDRS->flags;
-			}
-
-			if (ret & FD_VERIFY) {
-				CALL(poll_drive(1, FD_RAW_NEED_DISK));
-				ret = UDRS->flags;
-			}
-
-			if(ret & FD_VERIFY){
-				CALL(poll_drive(1, FD_RAW_NEED_DISK));
-				ret = UDRS->flags;
-			}
-			process_fd_request();
-			if (ret & FD_VERIFY)
-				return -ENODEV;
-			if (!(ret & FD_DISK_WRITABLE))
-				return -EROFS;
-			return 0;
-		case FDFMTTRK:
-			if (UDRS->fd_ref != 1)
-				return -EBUSY;
-			return do_format(drive, &inparam.f);
-		case FDFMTEND:
-		case FDFLUSH:
-			LOCK_FDC(drive,1);
-			return invalidate_drive(inode->i_bdev);
-
-		case FDSETEMSGTRESH:
-			UDP->max_errors.reporting =
-				(unsigned short) (param & 0x0f);
-			return 0;
-		OUT(FDGETMAXERRS, &UDP->max_errors);
-		IN(FDSETMAXERRS, &UDP->max_errors, max_errors);
-
-		case FDGETDRVTYP:
-			outparam = drive_name(type,drive);
-			SUPBOUND(size,strlen(outparam)+1);
-			break;
-
-		IN(FDSETDRVPRM, UDP, dp);
-		OUT(FDGETDRVPRM, UDP);
-
-		case FDPOLLDRVSTAT:
-			LOCK_FDC(drive,1);
-			CALL(poll_drive(1, FD_RAW_NEED_DISK));
-			process_fd_request();
-			/* fall through */
-	       	OUT(FDGETDRVSTAT, UDRS);
-
-		case FDRESET:
-			return user_reset_fdc(drive, (int)param, 1);
-
-		OUT(FDGETFDCSTAT,UFDCS);
-
-		case FDWERRORCLR:
-			CLEARSTRUCT(UDRWE);
-			return 0;
-		OUT(FDWERRORGET,UDRWE);
-
-		case FDRAWCMD:
-			if (type)
-				return -EINVAL;
-			LOCK_FDC(drive,1);
-			set_floppy(drive);
-			CALL(i = raw_cmd_ioctl(cmd,(void *) param));
-			process_fd_request();
-			return i;
-
-		case FDTWADDLE:
-			LOCK_FDC(drive,1);
-			twaddle();
-			process_fd_request();
-			return 0;
-
-		default:
-			return -EINVAL;
-	}
-
-	if (_IOC_DIR(cmd) & _IOC_READ)
-		return fd_copyout((void *)param, outparam, size);
-	else
-		return 0;
-#undef OUT
-#undef IN
-}
-
-static void __init config_types(void)
-{
-	int first=1;
-	int drive;
-	extern struct fd_info {
-		unsigned char dummy[4 * 6];
-		unsigned char fd_types[8];
-	} drive_info;
-
-	for (drive = 0; drive < 4; drive++)
-		UDP->cmos = drive_info.fd_types[drive];
-
-	/* XXX */
-	/* additional physical CMOS drive detection should go here */
-
-	for (drive=0; drive < N_DRIVE; drive++){
-		unsigned int type = UDP->cmos;
-		struct floppy_drive_params *params;
-		const char *name = NULL;
-		static char temparea[32];
-
-		if (type < NUMBER(default_drive_params)) {
-			params = &default_drive_params[type].params;
-			if (type) {
-				name = default_drive_params[type].name;
-				allowed_drive_mask |= 1 << drive;
-			}
-			else
-				allowed_drive_mask &= ~(1 << drive);
-		} else {
-			params = &default_drive_params[0].params;
-			sprintf(temparea, "unknown type %d (usb?)", type);
-			name = temparea;
-		}
-		if (name) {
-			const char * prepend = ",";
-			if (first) {
-				prepend = KERN_INFO "Floppy drive(s):";
-				first = 0;
-			}
-			printk("%s fd%d is %s", prepend, drive, name);
-			register_devfs_entries (drive);
-		}
-		*UDP = *params;
-	}
-	if (!first)
-		printk("\n");
-}
-
-static int floppy_release(struct inode * inode, struct file * filp)
-{
-	int drive = (long)inode->i_bdev->bd_disk->private_data;
-
-	down(&open_lock);
-	if (UDRS->fd_ref < 0)
-		UDRS->fd_ref=0;
-	else if (!UDRS->fd_ref--) {
-		DPRINT("floppy_release with fd_ref == 0");
-		UDRS->fd_ref = 0;
-	}
-	if (!UDRS->fd_ref)
-		opened_bdev[drive] = NULL;
-	floppy_release_irq_and_dma();
-	up(&open_lock);
-	return 0;
-}
-
-/*
- * floppy_open check for aliasing (/dev/fd0 can be the same as
- * /dev/PS0 etc), and disallows simultaneous access to the same
- * drive with different device numbers.
- */
-#define RETERR(x) do{floppy_release(inode,filp); return -(x);}while(0)
-
-static int floppy_open(struct inode * inode, struct file * filp)
-{
-	int drive = (long)inode->i_bdev->bd_disk->private_data;
-	int old_dev;
-	int try;
-	int res = -EBUSY;
-	char *tmp;
-
-#ifdef PC9800_DEBUG_FLOPPY
-	printk("floppy open: start\n");
-#endif
-	filp->private_data = (void*) 0;
-
-#ifdef PC9800_DEBUG_FLOPPY
-	printk("floppy open: drive=%d, current_drive=%d, UDP->cmos=%d\n"
-		   "floppy open: FDCS={spec1=%d, spec2=%d, dtr=%d, version=%d, dor=%d, address=%lu}\n",
-		   drive, current_drive, UDP->cmos, FDCS->spec1, FDCS->spec2,
-		   FDCS->dtr, FDCS->version, FDCS->dor, FDCS->address);
-	if (_floppy) {
-		printk("floppy open: _floppy={size=%d, sect=%d, head=%d, track=%d, spec1=%d}\n",
-			   _floppy->size, _floppy->sect, _floppy->head,
-			   _floppy->track, _floppy->spec1);
-	} else {
-		printk("floppy open: _floppy=NULL\n");
-	}
-#endif /* PC9800_DEBUG_FLOPPY */
-
-	down(&open_lock);
-	old_dev = UDRS->fd_device;
-	if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
-		goto out2;
-
-	if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
-		USETF(FD_DISK_CHANGED);
-		USETF(FD_VERIFY);
-	}
-
-	if (UDRS->fd_ref == -1 ||
-	   (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
-		goto out2;
-
-	if (floppy_grab_irq_and_dma())
-		goto out2;
-
-	if (filp->f_flags & O_EXCL)
-		UDRS->fd_ref = -1;
-	else
-		UDRS->fd_ref++;
-
-	opened_bdev[drive] = inode->i_bdev;
-
-	res = -ENXIO;
-
-	if (!floppy_track_buffer){
-		/* if opening an ED drive, reserve a big buffer,
-		 * else reserve a small one */
-		if ((UDP->cmos == 6) || (UDP->cmos == 5))
-			try = 64; /* Only 48 actually useful */
-		else
-			try = 32; /* Only 24 actually useful */
-
-		tmp=(char *)fd_dma_mem_alloc(1024 * try);
-		if (!tmp && !floppy_track_buffer) {
-			try >>= 1; /* buffer only one side */
-			INFBOUND(try, 16);
-			tmp= (char *)fd_dma_mem_alloc(1024*try);
-		}
-		if (!tmp && !floppy_track_buffer) {
-			fallback_on_nodma_alloc(&tmp, 2048 * try);
-		}
-		if (!tmp && !floppy_track_buffer) {
-			DPRINT("Unable to allocate DMA memory\n");
-			goto out;
-		}
-		if (floppy_track_buffer) {
-			if (tmp)
-				fd_dma_mem_free((unsigned long)tmp,try*1024);
-		} else {
-			buffer_min = buffer_max = -1;
-			floppy_track_buffer = tmp;
-			max_buffer_sectors = try;
-		}
-	}
-
-	UDRS->fd_device = iminor(inode);
-	set_capacity(disks[drive], floppy_sizes[iminor(inode)]);
-	if (old_dev != -1 && old_dev != iminor(inode)) {
-		if (buffer_drive == drive)
-			buffer_track = -1;
-	}
-
-#ifdef PC9800_DEBUG_FLOPPY
-	printk("floppy open: floppy.c:%d passed\n", __LINE__);
-#endif
-
-
-	/* Allow ioctls if we have write-permissions even if read-only open.
-	 * Needed so that programs such as fdrawcmd still can work on write
-	 * protected disks */
-	if (filp->f_mode & 2 || permission(filp->f_dentry->d_inode,2,NULL) == 0)
-	    filp->private_data = (void*) 8;
-
-	if (UFDCS->rawcmd == 1)
-		UFDCS->rawcmd = 2;
-
-#ifdef PC9800_DEBUG_FLOPPY
-	printk("floppy open: floppy.c:%d passed\n", __LINE__);
-#endif
-
-	if (!(filp->f_flags & O_NDELAY)) {
-		if (filp->f_mode & 3) {
-			UDRS->last_checked = 0;
-			check_disk_change(inode->i_bdev);
-			if (UTESTF(FD_DISK_CHANGED))
-				goto out;
-		}
-		res = -EROFS;
-		if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
-			goto out;
-#ifdef PC9800_DEBUG_FLOPPY
-		printk("floppy open: end normally\n");
-#endif
-	}
-	up(&open_lock);
-	return 0;
-out:
-	if (UDRS->fd_ref < 0)
-		UDRS->fd_ref=0;
-	else
-		UDRS->fd_ref--;
-	if (!UDRS->fd_ref)
-		opened_bdev[drive] = NULL;
-	floppy_release_irq_and_dma();
-out2:
-	up(&open_lock);
-	return res;
-}
-
-/*
- * Check if the disk has been changed or if a change has been faked.
- */
-static int check_floppy_change(struct gendisk *disk)
-{
-	int drive = (long)disk->private_data;
-
-#ifdef PC9800_DEBUG_FLOPPY
-	printk("check_floppy_change: MINOR=%d\n", minor(dev));
-#endif
-
-	if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
-		return 1;
-
-	if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) {
-		if(floppy_grab_irq_and_dma()) {
-			return 1;
-		}
-
-		lock_fdc(drive,0);
-		poll_drive(0,0);
-		process_fd_request();
-		floppy_release_irq_and_dma();
-	}
-
-	if (UTESTF(FD_DISK_CHANGED) ||
-	   UTESTF(FD_VERIFY) ||
-	   test_bit(drive, &fake_change) ||
-	   (!ITYPE(UDRS->fd_device) && !current_type[drive]))
-		return 1;
-	return 0;
-}
-
-/*
- * This implements "read block 0" for floppy_revalidate().
- * Needed for format autodetection, checking whether there is
- * a disk in the drive, and whether that disk is writable.
- */
-
-static int floppy_rb0_complete(struct bio *bio, unsigned int bytes_done, int err)
-{
-	if (bio->bi_size)
-		return 1;
-
-	complete((struct completion*)bio->bi_private);
-	return 0;
-}
-
-static int __floppy_read_block_0(struct block_device *bdev)
-{
-	struct bio bio;
-	struct bio_vec bio_vec;
-	struct completion complete;
-	struct page *page;
-	size_t size;
-
-	page = alloc_page(GFP_NOIO);
-	if (!page) {
-		process_fd_request();
-		return -ENOMEM;
-	}
-
-	size = bdev->bd_block_size;
-	if (!size)
-		size = 1024;
-
-	bio_init(&bio);
-	bio.bi_io_vec = &bio_vec;
-	bio_vec.bv_page = page;
-	bio_vec.bv_len = size;
-	bio_vec.bv_offset = 0;
-	bio.bi_vcnt = 1;
-	bio.bi_idx = 0;
-	bio.bi_size = size;
-	bio.bi_bdev = bdev;
-	bio.bi_sector = 0;
-	init_completion(&complete);
-	bio.bi_private = &complete;
-	bio.bi_end_io = floppy_rb0_complete;
-
-	submit_bio(READ, &bio);
-	generic_unplug_device(bdev_get_queue(bdev));
-	process_fd_request();
-	wait_for_completion(&complete);
-
-	__free_page(page);
-
-	return 0;
-}
-
-/* revalidate the floppy disk, i.e. trigger format autodetection by reading
- * the bootblock (block 0). "Autodetection" is also needed to check whether
- * there is a disk in the drive at all... Thus we also do it for fixed
- * geometry formats */
-static int floppy_revalidate(struct gendisk *disk)
-{
-	int drive=(long)disk->private_data;
-#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device))
-	int cf;
-	int res = 0;
-
-	if (UTESTF(FD_DISK_CHANGED) ||
-	    UTESTF(FD_VERIFY) ||
-	    test_bit(drive, &fake_change) ||
-	    NO_GEOM){
-		if(usage_count == 0) {
-			printk("VFS: revalidate called on non-open device.\n");
-			return -EFAULT;
-		}
-		lock_fdc(drive,0);
-		cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
-		if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)){
-			process_fd_request(); /*already done by another thread*/
-			return 0;
-		}
-		UDRS->maxblock = 0;
-		UDRS->maxtrack = 0;
-		if (buffer_drive == drive)
-			buffer_track = -1;
-		clear_bit(drive, &fake_change);
-		UCLEARF(FD_DISK_CHANGED);
-		if (cf)
-			UDRS->generation++;
-		if (NO_GEOM){
-			/* auto-sensing */
-			res = __floppy_read_block_0(opened_bdev[drive]);
-		} else {
-			if (cf)
-				poll_drive(0, FD_RAW_NEED_DISK);
-			process_fd_request();
-		}
-	}
-	set_capacity(disk, floppy_sizes[UDRS->fd_device]);
-	return res;
-}
-
-static struct block_device_operations floppy_fops = {
-	.owner		= THIS_MODULE,
-	.open		= floppy_open,
-	.release	= floppy_release,
-	.ioctl		= fd_ioctl,
-	.media_changed	= check_floppy_change,
-	.revalidate_disk= floppy_revalidate,
-};
-
-static char *table[] =
-{"",
-#if 0
-	"d360", 
-#else
-	"h1232",
-#endif
-	"h1200", "u360", "u720", "h360", "h720",
-	"u1440", "u2880", "CompaQ", "h1440", "u1680", "h410",
-	"u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743",
-	"h880", "u1040", "u1120", "h1600", "u1760", "u1920",
-	"u3200", "u3520", "u3840", "u1840", "u800", "u1600",
-NULL
-};
-
-static int t360[] = {
-	1,0
-};
-static int t1200[] = {
-	2,5,6,10,12,14,16,18,20,23,0
-};
-static int t3in[] = {
-	 8, 9,26,27,28, 7,11,15,19,24,25,
-	29,31, 3, 4,13,17,21,22,30, 0
-};
-
-static int *table_sup[] = {
-	NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in
-};
-
-static void __init register_devfs_entries (int drive)
-{
-	int base_minor = (drive < 4) ? drive : (124 + drive);
-
-	if (UDP->cmos < NUMBER(default_drive_params)) {
-		int i = 0;
-		do {
-			int minor = base_minor + (table_sup[UDP->cmos][i] << 2);
-
-			devfs_mk_bdev(MKDEV(FLOPPY_MAJOR, minor), 
-					S_IFBLK|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
-					"floppy/%d%s",
-					drive, table[table_sup[UDP->cmos][i]]);
-		} while (table_sup[UDP->cmos][i++]);
-	}
-}
-
-/*
- * Floppy Driver initialization
- * =============================
- */
-
-static inline char __init get_fdc_version(void)
-{
-	return FDC_8272A;
-}
-
-/* lilo configuration */
-
-static void __init floppy_set_flags(int *ints,int param, int param2)
-{
-	int i;
-
-	for (i=0; i < ARRAY_SIZE(default_drive_params); i++){
-		if (param)
-			default_drive_params[i].params.flags |= param2;
-		else
-			default_drive_params[i].params.flags &= ~param2;
-	}
-	DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param);
-}
-
-static void __init daring(int *ints,int param, int param2)
-{
-	int i;
-
-	for (i=0; i < ARRAY_SIZE(default_drive_params); i++){
-		if (param){
-			default_drive_params[i].params.select_delay = 0;
-			default_drive_params[i].params.flags |= FD_SILENT_DCL_CLEAR;
-		} else {
-			default_drive_params[i].params.select_delay = 2*HZ/100;
-			default_drive_params[i].params.flags &= ~FD_SILENT_DCL_CLEAR;
-		}
-	}
-	DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken");
-}
-
-static void __init set_cmos(int *ints, int dummy, int dummy2)
-{
-	int current_drive=0;
-
-	if (ints[0] != 2){
-		DPRINT("wrong number of parameters for CMOS\n");
-		return;
-	}
-	current_drive = ints[1];
-	if (current_drive < 0 || current_drive >= 8){
-		DPRINT("bad drive for set_cmos\n");
-		return;
-	}
-#if N_FDC > 1
-	if (current_drive >= 4 && !FDC2)
-		FDC2 = 0x370;
-#endif
-	DP->cmos = ints[2];
-	DPRINT("setting CMOS code to %d\n", ints[2]);
-}
-
-static struct param_table {
-	const char *name;
-	void (*fn)(int *ints, int param, int param2);
-	int *var;
-	int def_param;
-	int param2;
-} config_params[]={
-	{ "allowed_drive_mask", 0, &allowed_drive_mask, 0xff, 0}, /* obsolete */
-	{ "all_drives", 0, &allowed_drive_mask, 0xff, 0 }, /* obsolete */
-	{ "irq", 0, &FLOPPY_IRQ, DEFAULT_FLOPPY_IRQ, 0 },
-	{ "dma", 0, &FLOPPY_DMA, DEFAULT_FLOPPY_DMA, 0 },
-
-	{ "daring", daring, 0, 1, 0},
-#if N_FDC > 1
-	{ "two_fdc",  0, &FDC2, 0x370, 0 },
-	{ "one_fdc", 0, &FDC2, 0, 0 },
-#endif
-	{ "broken_dcl", floppy_set_flags, 0, 1, FD_BROKEN_DCL },
-	{ "messages", floppy_set_flags, 0, 1, FTD_MSG },
-	{ "silent_dcl_clear", floppy_set_flags, 0, 1, FD_SILENT_DCL_CLEAR },
-	{ "debug", floppy_set_flags, 0, 1, FD_DEBUG },
-
-	{ "nodma", 0, &can_use_virtual_dma, 1, 0 },
-	{ "yesdma", 0, &can_use_virtual_dma, 0, 0 },
-
-	{ "fifo_depth", 0, &fifo_depth, 0xa, 0 },
-	{ "nofifo", 0, &no_fifo, 0x20, 0 },
-	{ "usefifo", 0, &no_fifo, 0, 0 },
-
-	{ "cmos", set_cmos, 0, 0, 0 },
-	{ "slow", 0, &slow_floppy, 1, 0 },
-
-	{ "unexpected_interrupts", 0, &print_unex, 1, 0 },
-	{ "no_unexpected_interrupts", 0, &print_unex, 0, 0 },
-
-	EXTRA_FLOPPY_PARAMS
-};
-
-static int __init floppy_setup(char *str)
-{
-	int i;
-	int param;
-	int ints[11];
-
-	str = get_options(str,ARRAY_SIZE(ints),ints);
-	if (str) {
-		for (i=0; i< ARRAY_SIZE(config_params); i++){
-			if (strcmp(str,config_params[i].name) == 0){
-				if (ints[0])
-					param = ints[1];
-				else
-					param = config_params[i].def_param;
-				if (config_params[i].fn)
-					config_params[i].
-						fn(ints,param,
-						   config_params[i].param2);
-				if (config_params[i].var) {
-					DPRINT("%s=%d\n", str, param);
-					*config_params[i].var = param;
-				}
-				return 1;
-			}
-		}
-	}
-	if (str) {
-		DPRINT("unknown floppy option [%s]\n", str);
-		
-		DPRINT("allowed options are:");
-		for (i=0; i< ARRAY_SIZE(config_params); i++)
-			printk(" %s",config_params[i].name);
-		printk("\n");
-	} else
-		DPRINT("botched floppy option\n");
-	DPRINT("Read linux/Documentation/floppy.txt\n");
-	return 0;
-}
-
-static int have_no_fdc= -ENODEV;
-
-static void floppy_device_release(struct device *dev)
-{
-	complete(&device_release);
-}
-
-static struct platform_device floppy_device = {
-	.name		= "floppy",
-	.id		= 0,
-	.dev		= {
-			.release = floppy_device_release,
-	},
-};
-
-static struct kobject *floppy_find(dev_t dev, int *part, void *data)
-{
-	int drive = (*part&3) | ((*part&0x80) >> 5);
-	if (drive >= N_DRIVE ||
-	    !(allowed_drive_mask & (1 << drive)) ||
-	    fdc_state[FDC(drive)].version == FDC_NONE)
-		return NULL;
-	if (((*part>>2) & 0x1f) >= NUMBER(floppy_type))
-		return NULL;
-	*part = 0;
-	return get_disk(disks[drive]);
-}
-
-int __init floppy_init(void)
-{
-	int i,unit,drive;
-	int err;
-
-	raw_cmd = NULL;
-	FDC1 = 0x90;
-
-	for (i=0; i<N_DRIVE; i++) {
-		disks[i] = alloc_disk(1);
-		if (!disks[i])
-			goto Enomem;
-	}
-
-	devfs_mk_dir (NULL, "floppy", NULL);
-	if ((err = register_blkdev(FLOPPY_MAJOR,"fd")))
-		goto out;
-
-	for (i=0; i<N_DRIVE; i++) {
-		disks[i]->major = FLOPPY_MAJOR;
-		disks[i]->first_minor = TOMINOR(i);
-		disks[i]->fops = &floppy_fops;
-		sprintf(disks[i]->disk_name, "fd%d", i);
-	}
-
-	blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
-				floppy_find, NULL, NULL);
-
-	for (i=0; i<256; i++)
-		if (ITYPE(i))
-			floppy_sizes[i] = floppy_type[ITYPE(i)].size;
-		else
-			floppy_sizes[i] = MAX_DISK_SIZE << 1;
-
-	floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
-	if (!floppy_queue)
-		goto out_queue;
-
-	reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
-	config_types();
-
-	for (i = 0; i < N_FDC; i++) {
-		fdc = i;
-		CLEARSTRUCT(FDCS);
-		FDCS->dtr = -1;
-		FDCS->dor = 0;
-	}
-
-	if ((fd_inb(FD_MODE_CHANGE) & 1) == 0)
-		FDC1 = 0xc8;
-
-	use_virtual_dma = can_use_virtual_dma & 1;
-	fdc_state[0].address = FDC1;
-	if (fdc_state[0].address == -1) {
-		err = -ENODEV;
-		goto out1;
-	}
-#if N_FDC > 1
-	fdc_state[1].address = FDC2;
-#endif
-
-	fdc = 0; /* reset fdc in case of unexpected interrupt */
-	if (floppy_grab_irq_and_dma()){
-		err = -EBUSY;
-		goto out1;
-	}
-
-	/* initialise drive state */
-	for (drive = 0; drive < N_DRIVE; drive++) {
-		CLEARSTRUCT(UDRS);
-		CLEARSTRUCT(UDRWE);
-		USETF(FD_DISK_NEWCHANGE);
-		USETF(FD_DISK_CHANGED);
-		USETF(FD_VERIFY);
-		UDRS->fd_device = -1;
-		floppy_track_buffer = NULL;
-		max_buffer_sectors = 0;
-	}
-
-	for (i = 0; i < N_FDC; i++) {
-		fdc = i;
-		FDCS->driver_version = FD_DRIVER_VERSION;
-		for (unit=0; unit<4; unit++)
-			FDCS->track[unit] = 0;
-		if (FDCS->address == -1)
-			continue;
-		FDCS->rawcmd = 2;
-		user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
-
-		/* Try to determine the floppy controller type */
-		FDCS->version = get_fdc_version();
-		if (FDCS->version == FDC_NONE){
- 			/* free ioports reserved by floppy_grab_irq_and_dma() */
-			release_region(FDCS->address, 1);
-			release_region(FDCS->address + 2, 1);
-			release_region(FDCS->address + 4, 1);
-			release_region(0xbe, 1);
-			release_region(0x4be, 1);
-			FDCS->address = -1;
-			continue;
-		}
-		if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A)
-			can_use_virtual_dma = 0;
-
-		have_no_fdc = 0;
-		/* Not all FDCs seem to be able to handle the version command
-		 * properly, so force a reset for the standard FDC clones,
-		 * to avoid interrupt garbage.
-		 */
-		user_reset_fdc(-1,FD_RESET_ALWAYS,0);
-	}
-	fdc=0;
-	del_timer(&fd_timeout);
-	current_drive = 0;
-	floppy_release_irq_and_dma();
-#if 0  /* no message */
-	initialising=0;
-#endif
-	if (have_no_fdc) {
-		DPRINT("no floppy controllers found\n");
-		flush_scheduled_work();
-		if (usage_count)
-			floppy_release_irq_and_dma();
-		err = have_no_fdc;
-		goto out2;
-	}
-	
-	for (drive = 0; drive < N_DRIVE; drive++) {
-		init_timer(&motor_off_timer[drive]);
-		motor_off_timer[drive].data = drive;
-		motor_off_timer[drive].function = motor_off_callback;
-		if (!(allowed_drive_mask & (1 << drive)))
-			continue;
-		if (fdc_state[FDC(drive)].version == FDC_NONE)
-			continue;
-		/* to be cleaned up... */
-		disks[drive]->private_data = (void*)(long)drive;
-		disks[drive]->queue = floppy_queue;
-		add_disk(disks[drive]);
-	}
-
-	platform_device_register(&floppy_device);
-	return 0;
-
-out1:
-	del_timer_sync(&fd_timeout);
-out2:
-	blk_cleanup_queue(floppy_queue);
-out_queue:
-	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
-	unregister_blkdev(FLOPPY_MAJOR,"fd");
-out:
-	for (i=0; i<N_DRIVE; i++)
-		put_disk(disks[i]);
-	return err;
-
-Enomem:
-	while (i--)
-		put_disk(disks[i]);
-	return -ENOMEM;
-}
-
-static spinlock_t floppy_usage_lock = SPIN_LOCK_UNLOCKED;
-
-static int floppy_grab_irq_and_dma(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&floppy_usage_lock, flags);
-	if (usage_count++){
-		spin_unlock_irqrestore(&floppy_usage_lock, flags);
-		return 0;
-	}
-	spin_unlock_irqrestore(&floppy_usage_lock, flags);
-	if (fd_request_irq()) {
-		DPRINT("Unable to grab IRQ%d for the floppy driver\n",
-			FLOPPY_IRQ);
-		spin_lock_irqsave(&floppy_usage_lock, flags);
-		usage_count--;
-		spin_unlock_irqrestore(&floppy_usage_lock, flags);
-		return -1;
-	}
-	if (fd_request_dma()) {
-		DPRINT("Unable to grab DMA%d for the floppy driver\n",
-			FLOPPY_DMA);
-		fd_free_irq();
-		spin_lock_irqsave(&floppy_usage_lock, flags);
-		usage_count--;
-		spin_unlock_irqrestore(&floppy_usage_lock, flags);
-		return -1;
-	}
-
-	for (fdc=0; fdc< N_FDC; fdc++){
-		if (FDCS->address != -1){
-			static char floppy[] = "floppy";
-			if (!request_region(FDCS->address, 1, floppy))
-				goto cleanup0;
-
-			if (!request_region(FDCS->address + 2, 1, floppy)) {
-				release_region(FDCS->address, 1);
-				goto cleanup0;
-			}
-
-			if (!request_region(FDCS->address + 4, 1, floppy)) {
-				release_region(FDCS->address, 1);
-				release_region(FDCS->address + 2, 1);
-				goto cleanup0;
-			}
-
-			if (fdc == 0) {  /* internal FDC */
-				if (request_region(0xbe, 1, "floppy mode change")) {
-					if (request_region(0x4be, 1, "floppy ex. mode change"))
-						continue;
-					else
-						DPRINT("Floppy io-port 0x4be in use\n");
-
-					release_region(0xbe, 1);
-				} else
-					DPRINT("Floppy io-port 0xbe in use\n");
-
-				release_region(FDCS->address, 1);
-				release_region(FDCS->address + 2, 1);
-				release_region(FDCS->address + 4, 1);
-			}
-
-			goto cleanup1;
-		}
-	}
-	for (fdc=0; fdc< N_FDC; fdc++){
-		if (FDCS->address != -1){
-			reset_fdc_info(1);
-			fd_outb(FDCS->dor, FD_MODE);
-		}
-	}
-	fdc = 0;
-	fd_outb((FDCS->dor & 8), FD_MODE);
-
-	for (fdc = 0; fdc < N_FDC; fdc++)
-		if (FDCS->address != -1)
-			fd_outb(FDCS->dor, FD_MODE);
-	/*
-	 *	The driver will try and free resources and relies on us
-	 *	to know if they were allocated or not.
-	 */
-	fdc = 0;
-	irqdma_allocated = 1;
-	return 0;
-
-cleanup0:
-	DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address);
-cleanup1:
-	fd_free_irq();
-	fd_free_dma();
-	while(--fdc >= 0) {
-		release_region(FDCS->address, 1);
-		release_region(FDCS->address + 2, 1);
-		release_region(FDCS->address + 4, 1);
-		if (fdc == 0) {
-			release_region(0x00be, 1);
-			release_region(0x04be, 1);
-		}
-	}
-	spin_lock_irqsave(&floppy_usage_lock, flags);
-	usage_count--;
-	spin_unlock_irqrestore(&floppy_usage_lock, flags);
-	return -1;
-}
-
-static void floppy_release_irq_and_dma(void)
-{
-	int old_fdc;
-#ifdef FLOPPY_SANITY_CHECK
-	int drive;
-#endif
-	long tmpsize;
-	unsigned long tmpaddr;
-	unsigned long flags;
-
-	spin_lock_irqsave(&floppy_usage_lock, flags);
-	if (--usage_count){
-		spin_unlock_irqrestore(&floppy_usage_lock, flags);
-		return;
-	}
-	spin_unlock_irqrestore(&floppy_usage_lock, flags);
-	if(irqdma_allocated)
-	{
-		fd_disable_dma();
-		fd_free_dma();
-		fd_free_irq();
-		irqdma_allocated=0;
-	}
-	fd_outb(0, FD_MODE);
-	floppy_enable_hlt();
-
-	if (floppy_track_buffer && max_buffer_sectors) {
-		tmpsize = max_buffer_sectors*1024;
-		tmpaddr = (unsigned long)floppy_track_buffer;
-		floppy_track_buffer = NULL;
-		max_buffer_sectors = 0;
-		buffer_min = buffer_max = -1;
-		fd_dma_mem_free(tmpaddr, tmpsize);
-	}
-
-#ifdef FLOPPY_SANITY_CHECK
-	for (drive=0; drive < N_FDC * 4; drive++)
-		if (timer_pending(motor_off_timer + drive))
-			printk("motor off timer %d still active\n", drive);
-
-	if (timer_pending(&fd_timeout))
-		printk("floppy timer still active:%s\n", timeout_message);
-	if (timer_pending(&fd_timer))
-		printk("auxiliary floppy timer still active\n");
-	if (floppy_work.pending)
-		printk("work still pending\n");
-#endif
-	old_fdc = fdc;
-	for (fdc = 0; fdc < N_FDC; fdc++)
-		if (FDCS->address != -1) {
-			release_region(FDCS->address, 1);
-			release_region(FDCS->address + 2, 1);
-			release_region(FDCS->address + 4, 1);
-			if (fdc == 0) {
-				release_region(0xbe, 1);
-				release_region(0x4be, 1);
-			}
-		}
-	fdc = old_fdc;
-}
-
-
-#ifdef MODULE
-
-char *floppy;
-
-static void unregister_devfs_entries (int drive)
-{
-    int i;
-
-    if (UDP->cmos < NUMBER(default_drive_params)) {
-	i = 0;
-	do {
-	    devfs_remove("floppy/%d%s", drive, table[table_sup[UDP->cmos][i]]);
-	} while (table_sup[UDP->cmos][i++]);
-    }
-}
-
-static void __init parse_floppy_cfg_string(char *cfg)
-{
-	char *ptr;
-
-	while(*cfg) {
-		for(ptr = cfg;*cfg && *cfg != ' ' && *cfg != '\t'; cfg++);
-		if (*cfg) {
-			*cfg = '\0';
-			cfg++;
-		}
-		if (*ptr)
-			floppy_setup(ptr);
-	}
-}
-
-int init_module(void)
-{
-	printk(KERN_INFO "inserting floppy driver for " UTS_RELEASE "\n");
-		
-	if (floppy)
-		parse_floppy_cfg_string(floppy);
-	return floppy_init();
-}
-
-void cleanup_module(void)
-{
-	int drive;
-		
-	init_completion(&device_release);
-	platform_device_unregister(&floppy_device);
-	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
-	unregister_blkdev(FLOPPY_MAJOR, "fd");
-
-	for (drive = 0; drive < N_DRIVE; drive++) {
-		del_timer_sync(&motor_off_timer[drive]);
-
-		if ((allowed_drive_mask & (1 << drive)) &&
-		    fdc_state[FDC(drive)].version != FDC_NONE) {
-			del_gendisk(disks[drive]);
-			unregister_devfs_entries(drive);
-		}
-		put_disk(disks[drive]);
-	}
-	devfs_remove("floppy");
-
-	del_timer_sync(&fd_timeout);
-	del_timer_sync(&fd_timer);
-	blk_cleanup_queue(floppy_queue);
-
-	if (usage_count)
-		floppy_release_irq_and_dma();
-
-	/* eject disk, if any */
-	fd_eject(0);
-
-	wait_for_completion(&device_release);
-}
-
-MODULE_PARM(floppy,"s");
-MODULE_PARM(FLOPPY_IRQ,"i");
-MODULE_PARM(FLOPPY_DMA,"i");
-MODULE_AUTHOR("Osamu Tomita");
-MODULE_SUPPORTED_DEVICE("fd");
-MODULE_LICENSE("GPL");
-
-#else
-
-__setup ("floppy=", floppy_setup);
-module_init(floppy_init)
-#endif
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/block/ll_rw_blk.c	2004-06-23 19:04:25 -07:00
@@ -817,14 +817,14 @@
 void blk_recount_segments(request_queue_t *q, struct bio *bio)
 {
 	struct bio_vec *bv, *bvprv = NULL;
-	int i, nr_phys_segs, nr_hw_segs, seg_size, cluster;
+	int i, nr_phys_segs, nr_hw_segs, seg_size, hw_seg_size, cluster;
 	int high, highprv = 1;
 
 	if (unlikely(!bio->bi_io_vec))
 		return;
 
 	cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
-	seg_size = nr_phys_segs = nr_hw_segs = 0;
+	hw_seg_size = seg_size = nr_phys_segs = nr_hw_segs = 0;
 	bio_for_each_segment(bv, bio, i) {
 		/*
 		 * the trick here is making sure that a high page is never
@@ -841,22 +841,35 @@
 				goto new_segment;
 			if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv))
 				goto new_segment;
+			if (BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len))
+				goto new_hw_segment;
 
 			seg_size += bv->bv_len;
+			hw_seg_size += bv->bv_len;
 			bvprv = bv;
 			continue;
 		}
 new_segment:
-		if (!BIOVEC_VIRT_MERGEABLE(bvprv, bv))
+		if (BIOVEC_VIRT_MERGEABLE(bvprv, bv) &&
+		    !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) {
+			hw_seg_size += bv->bv_len;
+		} else {
 new_hw_segment:
+			if (hw_seg_size > bio->bi_hw_front_size)
+				bio->bi_hw_front_size = hw_seg_size;
+			hw_seg_size = BIOVEC_VIRT_START_SIZE(bv) + bv->bv_len;
 			nr_hw_segs++;
+		}
 
 		nr_phys_segs++;
 		bvprv = bv;
 		seg_size = bv->bv_len;
 		highprv = high;
 	}
-
+	if (hw_seg_size > bio->bi_hw_back_size)
+		bio->bi_hw_back_size = hw_seg_size;
+	if (nr_hw_segs == 1 && hw_seg_size > bio->bi_hw_front_size)
+		bio->bi_hw_front_size = hw_seg_size;
 	bio->bi_phys_segments = nr_phys_segs;
 	bio->bi_hw_segments = nr_hw_segs;
 	bio->bi_flags |= (1 << BIO_SEG_VALID);
@@ -889,22 +902,17 @@
 int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
 				 struct bio *nxt)
 {
-	if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
-		return 0;
-
-	if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)))
+	if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
+		blk_recount_segments(q, bio);
+	if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID)))
+		blk_recount_segments(q, nxt);
+	if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) ||
+	    BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size))
 		return 0;
 	if (bio->bi_size + nxt->bi_size > q->max_segment_size)
 		return 0;
 
-	/*
-	 * bio and nxt are contigous in memory, check if the queue allows
-	 * these two to be merged into one
-	 */
-	if (BIO_SEG_BOUNDARY(q, bio, nxt))
-		return 1;
-
-	return 0;
+	return 1;
 }
 
 EXPORT_SYMBOL(blk_hw_contig_segment);
@@ -974,7 +982,8 @@
 
 	if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
 		req->flags |= REQ_NOMERGE;
-		q->last_merge = NULL;
+		if (req == q->last_merge)
+			q->last_merge = NULL;
 		return 0;
 	}
 
@@ -996,7 +1005,8 @@
 	if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments
 	    || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
 		req->flags |= REQ_NOMERGE;
-		q->last_merge = NULL;
+		if (req == q->last_merge)
+			q->last_merge = NULL;
 		return 0;
 	}
 
@@ -1012,14 +1022,31 @@
 static int ll_back_merge_fn(request_queue_t *q, struct request *req, 
 			    struct bio *bio)
 {
+	int len;
+
 	if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
 		req->flags |= REQ_NOMERGE;
-		q->last_merge = NULL;
+		if (req == q->last_merge)
+			q->last_merge = NULL;
 		return 0;
 	}
-
-	if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio)))
-		return ll_new_mergeable(q, req, bio);
+	if (unlikely(!bio_flagged(req->biotail, BIO_SEG_VALID)))
+		blk_recount_segments(q, req->biotail);
+	if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
+		blk_recount_segments(q, bio);
+	len = req->biotail->bi_hw_back_size + bio->bi_hw_front_size;
+	if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio)) &&
+	    !BIOVEC_VIRT_OVERSIZE(len)) {
+		int mergeable =  ll_new_mergeable(q, req, bio);
+
+		if (mergeable) {
+			if (req->nr_hw_segments == 1)
+				req->bio->bi_hw_front_size = len;
+			if (bio->bi_hw_segments == 1)
+				bio->bi_hw_back_size = len;
+		}
+		return mergeable;
+	}
 
 	return ll_new_hw_segment(q, req, bio);
 }
@@ -1027,14 +1054,31 @@
 static int ll_front_merge_fn(request_queue_t *q, struct request *req, 
 			     struct bio *bio)
 {
+	int len;
+
 	if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
 		req->flags |= REQ_NOMERGE;
-		q->last_merge = NULL;
+		if (req == q->last_merge)
+			q->last_merge = NULL;
 		return 0;
 	}
-
-	if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio)))
-		return ll_new_mergeable(q, req, bio);
+	len = bio->bi_hw_back_size + req->bio->bi_hw_front_size;
+	if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
+		blk_recount_segments(q, bio);
+	if (unlikely(!bio_flagged(req->bio, BIO_SEG_VALID)))
+		blk_recount_segments(q, req->bio);
+	if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio)) &&
+	    !BIOVEC_VIRT_OVERSIZE(len)) {
+		int mergeable =  ll_new_mergeable(q, req, bio);
+
+		if (mergeable) {
+			if (bio->bi_hw_segments == 1)
+				bio->bi_hw_front_size = len;
+			if (req->nr_hw_segments == 1)
+				req->biotail->bi_hw_back_size = len;
+		}
+		return mergeable;
+	}
 
 	return ll_new_hw_segment(q, req, bio);
 }
@@ -1066,8 +1110,17 @@
 		return 0;
 
 	total_hw_segments = req->nr_hw_segments + next->nr_hw_segments;
-	if (blk_hw_contig_segment(q, req->biotail, next->bio))
+	if (blk_hw_contig_segment(q, req->biotail, next->bio)) {
+		int len = req->biotail->bi_hw_back_size + next->bio->bi_hw_front_size;
+		/*
+		 * propagate the combined length to the end of the requests
+		 */
+		if (req->nr_hw_segments == 1)
+			req->bio->bi_hw_front_size = len;
+		if (next->nr_hw_segments == 1)
+			next->biotail->bi_hw_back_size = len;
 		total_hw_segments--;
+	}
 
 	if (total_hw_segments > q->max_hw_segments)
 		return 0;
@@ -1123,7 +1176,7 @@
 /*
  * remove the plug and let it rip..
  */
-static inline void __generic_unplug_device(request_queue_t *q)
+inline void __generic_unplug_device(request_queue_t *q)
 {
 	if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
 		return;
@@ -1137,6 +1190,7 @@
 	if (elv_next_request(q))
 		q->request_fn(q);
 }
+EXPORT_SYMBOL(__generic_unplug_device);
 
 /**
  * generic_unplug_device - fire a request queue
@@ -2280,13 +2334,9 @@
 out:
 	if (freereq)
 		__blk_put_request(q, freereq);
+	if (bio_sync(bio))
+		__generic_unplug_device(q);
 
-	if (blk_queue_plugged(q)) {
-		int nrq = q->rq.count[READ] + q->rq.count[WRITE] - q->in_flight;
-
-		if (nrq == q->unplug_thresh || bio_sync(bio))
-			__generic_unplug_device(q);
-	}
 	spin_unlock_irq(q->queue_lock);
 	return 0;
 
@@ -2535,7 +2585,7 @@
 
 void blk_recalc_rq_segments(struct request *rq)
 {
-	struct bio *bio;
+	struct bio *bio, *prevbio = NULL;
 	int nr_phys_segs, nr_hw_segs;
 
 	if (!rq->bio)
@@ -2548,6 +2598,13 @@
 
 		nr_phys_segs += bio_phys_segments(rq->q, bio);
 		nr_hw_segs += bio_hw_segments(rq->q, bio);
+		if (prevbio) {
+			if (blk_phys_contig_segment(rq->q, prevbio, bio))
+				nr_phys_segs--;
+			if (blk_hw_contig_segment(rq->q, prevbio, bio))
+				nr_hw_segs--;
+		}
+		prevbio = bio;
 	}
 
 	rq->nr_phys_segments = nr_phys_segs;
@@ -2610,7 +2667,7 @@
 	}
 
 	total_bytes = bio_nbytes = 0;
-	while ((bio = req->bio)) {
+	while ((bio = req->bio) != NULL) {
 		int nbytes;
 
 		if (nr_bytes >= bio->bi_size) {
diff -Nru a/drivers/block/sx8.c b/drivers/block/sx8.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/block/sx8.c	2004-06-23 19:04:28 -07:00
@@ -0,0 +1,1763 @@
+/*
+ *  sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware
+ *
+ *  Copyright 2004 Red Hat, Inc.
+ *
+ *  Author/maintainer:  Jeff Garzik <jgarzik@pobox.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file "COPYING" in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/blkdev.h>
+#include <linux/sched.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/interrupt.h>
+#include <linux/compiler.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/hdreg.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Promise SATA SX8 block driver");
+
+#if 0
+#define CARM_DEBUG
+#define CARM_VERBOSE_DEBUG
+#else
+#undef CARM_DEBUG
+#undef CARM_VERBOSE_DEBUG
+#endif
+#undef CARM_NDEBUG
+
+#define DRV_NAME "sx8"
+#define DRV_VERSION "0.8"
+#define PFX DRV_NAME ": "
+
+#define NEXT_RESP(idx)	((idx + 1) % RMSG_Q_LEN)
+
+/* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */
+#define TAG_ENCODE(tag)	(((tag) << 16) | 0xf)
+#define TAG_DECODE(tag)	(((tag) >> 16) & 0x1f)
+#define TAG_VALID(tag)	((((tag) & 0xf) == 0xf) && (TAG_DECODE(tag) < 32))
+
+/* note: prints function name for you */
+#ifdef CARM_DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#ifdef CARM_VERBOSE_DEBUG
+#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#else
+#define VPRINTK(fmt, args...)
+#endif	/* CARM_VERBOSE_DEBUG */
+#else
+#define DPRINTK(fmt, args...)
+#define VPRINTK(fmt, args...)
+#endif	/* CARM_DEBUG */
+
+#ifdef CARM_NDEBUG
+#define assert(expr)
+#else
+#define assert(expr) \
+        if(unlikely(!(expr))) {                                   \
+        printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
+        #expr,__FILE__,__FUNCTION__,__LINE__);          \
+        }
+#endif
+
+/* defines only for the constants which don't work well as enums */
+struct carm_host;
+
+enum {
+	/* adapter-wide limits */
+	CARM_MAX_PORTS		= 8,
+	CARM_SHM_SIZE		= (4096 << 7),
+	CARM_MINORS_PER_MAJOR	= 256 / CARM_MAX_PORTS,
+	CARM_MAX_WAIT_Q		= CARM_MAX_PORTS + 1,
+
+	/* command message queue limits */
+	CARM_MAX_REQ		= 64,	       /* max command msgs per host */
+	CARM_MAX_Q		= 1,		   /* one command at a time */
+	CARM_MSG_LOW_WATER	= (CARM_MAX_REQ / 4),	     /* refill mark */
+
+	/* S/G limits, host-wide and per-request */
+	CARM_MAX_REQ_SG		= 32,	     /* max s/g entries per request */
+	CARM_SG_BOUNDARY	= 0xffffUL,	    /* s/g segment boundary */
+	CARM_MAX_HOST_SG	= 600,		/* max s/g entries per host */
+	CARM_SG_LOW_WATER	= (CARM_MAX_HOST_SG / 4),   /* re-fill mark */
+
+	/* hardware registers */
+	CARM_IHQP		= 0x1c,
+	CARM_INT_STAT		= 0x10, /* interrupt status */
+	CARM_INT_MASK		= 0x14, /* interrupt mask */
+	CARM_HMUC		= 0x18, /* host message unit control */
+	RBUF_ADDR_LO		= 0x20, /* response msg DMA buf low 32 bits */
+	RBUF_ADDR_HI		= 0x24, /* response msg DMA buf high 32 bits */
+	RBUF_BYTE_SZ		= 0x28,
+	CARM_RESP_IDX		= 0x2c,
+	CARM_CMS0		= 0x30, /* command message size reg 0 */
+	CARM_LMUC		= 0x48,
+	CARM_HMPHA		= 0x6c,
+	CARM_INITC		= 0xb5,
+
+	/* bits in CARM_INT_{STAT,MASK} */
+	INT_RESERVED		= 0xfffffff0,
+	INT_WATCHDOG		= (1 << 3),	/* watchdog timer */
+	INT_Q_OVERFLOW		= (1 << 2),	/* cmd msg q overflow */
+	INT_Q_AVAILABLE		= (1 << 1),	/* cmd msg q has free space */
+	INT_RESPONSE		= (1 << 0),	/* response msg available */
+	INT_ACK_MASK		= INT_WATCHDOG | INT_Q_OVERFLOW,
+	INT_DEF_MASK		= INT_RESERVED | INT_Q_OVERFLOW |
+				  INT_RESPONSE,
+
+	/* command messages, and related register bits */
+	CARM_HAVE_RESP		= 0x01,
+	CARM_MSG_READ		= 1,
+	CARM_MSG_WRITE		= 2,
+	CARM_MSG_VERIFY		= 3,
+	CARM_MSG_GET_CAPACITY	= 4,
+	CARM_MSG_FLUSH		= 5,
+	CARM_MSG_IOCTL		= 6,
+	CARM_MSG_ARRAY		= 8,
+	CARM_MSG_MISC		= 9,
+	CARM_CME		= (1 << 2),
+	CARM_RME		= (1 << 1),
+	CARM_WZBC		= (1 << 0),
+	CARM_RMI		= (1 << 0),
+	CARM_Q_FULL		= (1 << 3),
+	CARM_MSG_SIZE		= 288,
+	CARM_Q_LEN		= 48,
+
+	/* CARM_MSG_IOCTL messages */
+	CARM_IOC_SCAN_CHAN	= 5,	/* scan channels for devices */
+	CARM_IOC_GET_TCQ	= 13,	/* get tcq/ncq depth */
+	CARM_IOC_SET_TCQ	= 14,	/* set tcq/ncq depth */
+
+	IOC_SCAN_CHAN_NODEV	= 0x1f,
+	IOC_SCAN_CHAN_OFFSET	= 0x40,
+
+	/* CARM_MSG_ARRAY messages */
+	CARM_ARRAY_INFO		= 0,
+
+	ARRAY_NO_EXIST		= (1 << 31),
+
+	/* response messages */
+	RMSG_SZ			= 8,	/* sizeof(struct carm_response) */
+	RMSG_Q_LEN		= 48,	/* resp. msg list length */
+	RMSG_OK			= 1,	/* bit indicating msg was successful */
+					/* length of entire resp. msg buffer */
+	RBUF_LEN		= RMSG_SZ * RMSG_Q_LEN,
+
+	PDC_SHM_SIZE		= (4096 << 7), /* length of entire h/w buffer */
+
+	/* CARM_MSG_MISC messages */
+	MISC_GET_FW_VER		= 2,
+	MISC_ALLOC_MEM		= 3,
+	MISC_SET_TIME		= 5,
+
+	/* MISC_GET_FW_VER feature bits */
+	FW_VER_4PORT		= (1 << 2), /* 1=4 ports, 0=8 ports */
+	FW_VER_NON_RAID		= (1 << 1), /* 1=non-RAID firmware, 0=RAID */
+	FW_VER_ZCR		= (1 << 0), /* zero channel RAID (whatever that is) */
+
+	/* carm_host flags */
+	FL_NON_RAID		= FW_VER_NON_RAID,
+	FL_4PORT		= FW_VER_4PORT,
+	FL_FW_VER_MASK		= (FW_VER_NON_RAID | FW_VER_4PORT),
+	FL_DAC			= (1 << 16),
+	FL_DYN_MAJOR		= (1 << 17),
+};
+
+enum scatter_gather_types {
+	SGT_32BIT		= 0,
+	SGT_64BIT		= 1,
+};
+
+enum host_states {
+	HST_INVALID,		/* invalid state; never used */
+	HST_ALLOC_BUF,		/* setting up master SHM area */
+	HST_ERROR,		/* we never leave here */
+	HST_PORT_SCAN,		/* start dev scan */
+	HST_DEV_SCAN_START,	/* start per-device probe */
+	HST_DEV_SCAN,		/* continue per-device probe */
+	HST_DEV_ACTIVATE,	/* activate devices we found */
+	HST_PROBE_FINISHED,	/* probe is complete */
+	HST_PROBE_START,	/* initiate probe */
+	HST_SYNC_TIME,		/* tell firmware what time it is */
+	HST_GET_FW_VER,		/* get firmware version, adapter port cnt */
+};
+
+#ifdef CARM_DEBUG
+static const char *state_name[] = {
+	"HST_INVALID",
+	"HST_ALLOC_BUF",
+	"HST_ERROR",
+	"HST_PORT_SCAN",
+	"HST_DEV_SCAN_START",
+	"HST_DEV_SCAN",
+	"HST_DEV_ACTIVATE",
+	"HST_PROBE_FINISHED",
+	"HST_PROBE_START",
+	"HST_SYNC_TIME",
+	"HST_GET_FW_VER",
+};
+#endif
+
+struct carm_port {
+	unsigned int			port_no;
+	unsigned int			n_queued;
+	struct gendisk			*disk;
+	struct carm_host		*host;
+
+	/* attached device characteristics */
+	u64				capacity;
+	char				name[41];
+	u16				dev_geom_head;
+	u16				dev_geom_sect;
+	u16				dev_geom_cyl;
+};
+
+struct carm_request {
+	unsigned int			tag;
+	int				n_elem;
+	unsigned int			msg_type;
+	unsigned int			msg_subtype;
+	unsigned int			msg_bucket;
+	struct request			*rq;
+	struct carm_port		*port;
+	struct scatterlist		sg[CARM_MAX_REQ_SG];
+};
+
+struct carm_host {
+	unsigned long			flags;
+	void				*mmio;
+	void				*shm;
+	dma_addr_t			shm_dma;
+
+	int				major;
+	int				id;
+	char				name[32];
+
+	spinlock_t			lock;
+	struct pci_dev			*pdev;
+	unsigned int			state;
+	u32				fw_ver;
+
+	request_queue_t			*oob_q;
+	unsigned int			n_oob;
+
+	unsigned int			hw_sg_used;
+
+	unsigned int			resp_idx;
+
+	unsigned int			wait_q_prod;
+	unsigned int			wait_q_cons;
+	request_queue_t			*wait_q[CARM_MAX_WAIT_Q];
+
+	unsigned int			n_msgs;
+	u64				msg_alloc;
+	struct carm_request		req[CARM_MAX_REQ];
+	void				*msg_base;
+	dma_addr_t			msg_dma;
+
+	int				cur_scan_dev;
+	unsigned long			dev_active;
+	unsigned long			dev_present;
+	struct carm_port		port[CARM_MAX_PORTS];
+
+	struct work_struct		fsm_task;
+
+	struct semaphore		probe_sem;
+};
+
+struct carm_response {
+	u32 ret_handle;
+	u32 status;
+}  __attribute__((packed));
+
+struct carm_msg_sg {
+	u32 start;
+	u32 len;
+}  __attribute__((packed));
+
+struct carm_msg_rw {
+	u8 type;
+	u8 id;
+	u8 sg_count;
+	u8 sg_type;
+	u32 handle;
+	u32 lba;
+	u16 lba_count;
+	u16 lba_high;
+	struct carm_msg_sg sg[32];
+}  __attribute__((packed));
+
+struct carm_msg_allocbuf {
+	u8 type;
+	u8 subtype;
+	u8 n_sg;
+	u8 sg_type;
+	u32 handle;
+	u32 addr;
+	u32 len;
+	u32 evt_pool;
+	u32 n_evt;
+	u32 rbuf_pool;
+	u32 n_rbuf;
+	u32 msg_pool;
+	u32 n_msg;
+	struct carm_msg_sg sg[8];
+}  __attribute__((packed));
+
+struct carm_msg_ioctl {
+	u8 type;
+	u8 subtype;
+	u8 array_id;
+	u8 reserved1;
+	u32 handle;
+	u32 data_addr;
+	u32 reserved2;
+}  __attribute__((packed));
+
+struct carm_msg_sync_time {
+	u8 type;
+	u8 subtype;
+	u16 reserved1;
+	u32 handle;
+	u32 reserved2;
+	u32 timestamp;
+}  __attribute__((packed));
+
+struct carm_msg_get_fw_ver {
+	u8 type;
+	u8 subtype;
+	u16 reserved1;
+	u32 handle;
+	u32 data_addr;
+	u32 reserved2;
+}  __attribute__((packed));
+
+struct carm_fw_ver {
+	u32 version;
+	u8 features;
+	u8 reserved1;
+	u16 reserved2;
+}  __attribute__((packed));
+
+struct carm_array_info {
+	u32 size;
+
+	u16 size_hi;
+	u16 stripe_size;
+
+	u32 mode;
+
+	u16 stripe_blk_sz;
+	u16 reserved1;
+
+	u16 cyl;
+	u16 head;
+
+	u16 sect;
+	u8 array_id;
+	u8 reserved2;
+
+	char name[40];
+
+	u32 array_status;
+
+	/* device list continues beyond this point? */
+}  __attribute__((packed));
+
+static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static void carm_remove_one (struct pci_dev *pdev);
+static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
+			   unsigned int cmd, unsigned long arg);
+
+static struct pci_device_id carm_pci_tbl[] = {
+	{ PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ PCI_VENDOR_ID_PROMISE, 0x8002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ }	/* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, carm_pci_tbl);
+
+static struct pci_driver carm_driver = {
+	.name		= DRV_NAME,
+	.id_table	= carm_pci_tbl,
+	.probe		= carm_init_one,
+	.remove		= carm_remove_one,
+};
+
+static struct block_device_operations carm_bd_ops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= carm_bdev_ioctl,
+};
+
+static unsigned int carm_host_id;
+static unsigned long carm_major_alloc;
+
+
+
+static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
+			   unsigned int cmd, unsigned long arg)
+{
+	void __user *usermem = (void __user *) arg;
+	struct carm_port *port = ino->i_bdev->bd_disk->private_data;
+	struct hd_geometry geom;
+
+	switch (cmd) {
+	case HDIO_GETGEO:
+		if (!usermem)
+			return -EINVAL;
+
+		geom.heads = (u8) port->dev_geom_head;
+		geom.sectors = (u8) port->dev_geom_sect;
+		geom.cylinders = port->dev_geom_cyl;
+		geom.start = get_start_sect(ino->i_bdev);
+
+		if (copy_to_user(usermem, &geom, sizeof(geom)))
+			return -EFAULT;
+		return 0;
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE };
+
+static inline int carm_lookup_bucket(u32 msg_size)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
+		if (msg_size <= msg_sizes[i])
+			return i;
+	
+	return -ENOENT;
+}
+
+static void carm_init_buckets(void *mmio)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
+		writel(msg_sizes[i], mmio + CARM_CMS0 + (4 * i));
+}
+
+static inline void *carm_ref_msg(struct carm_host *host,
+				 unsigned int msg_idx)
+{
+	return host->msg_base + (msg_idx * CARM_MSG_SIZE);
+}
+
+static inline dma_addr_t carm_ref_msg_dma(struct carm_host *host,
+					  unsigned int msg_idx)
+{
+	return host->msg_dma + (msg_idx * CARM_MSG_SIZE);
+}
+
+static int carm_send_msg(struct carm_host *host,
+			 struct carm_request *crq)
+{
+	void *mmio = host->mmio;
+	u32 msg = (u32) carm_ref_msg_dma(host, crq->tag);
+	u32 cm_bucket = crq->msg_bucket;
+	u32 tmp;
+	int rc = 0;
+
+	VPRINTK("ENTER\n");
+
+	tmp = readl(mmio + CARM_HMUC);
+	if (tmp & CARM_Q_FULL) {
+#if 0
+		tmp = readl(mmio + CARM_INT_MASK);
+		tmp |= INT_Q_AVAILABLE;
+		writel(tmp, mmio + CARM_INT_MASK);
+		readl(mmio + CARM_INT_MASK);	/* flush */
+#endif
+		DPRINTK("host msg queue full\n");
+		rc = -EBUSY;
+	} else {
+		writel(msg | (cm_bucket << 1), mmio + CARM_IHQP);
+		readl(mmio + CARM_IHQP);	/* flush */
+	}
+
+	return rc;
+}
+
+static struct carm_request *carm_get_request(struct carm_host *host)
+{
+	unsigned int i;
+
+	/* obey global hardware limit on S/G entries */
+	if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG))
+		return NULL;
+
+	for (i = 0; i < CARM_MAX_Q; i++)
+		if ((host->msg_alloc & (1ULL << i)) == 0) {
+			struct carm_request *crq = &host->req[i];
+			crq->port = NULL;
+			crq->n_elem = 0;
+
+			host->msg_alloc |= (1ULL << i);
+			host->n_msgs++;
+
+			assert(host->n_msgs <= CARM_MAX_REQ);
+			return crq;
+		}
+	
+	DPRINTK("no request available, returning NULL\n");
+	return NULL;
+}
+
+static int carm_put_request(struct carm_host *host, struct carm_request *crq)
+{
+	assert(crq->tag < CARM_MAX_Q);
+
+	if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0))
+		return -EINVAL; /* tried to clear a tag that was not active */
+
+	assert(host->hw_sg_used >= crq->n_elem);
+
+	host->msg_alloc &= ~(1ULL << crq->tag);
+	host->hw_sg_used -= crq->n_elem;
+	host->n_msgs--;
+
+	return 0;
+}
+
+static struct carm_request *carm_get_special(struct carm_host *host)
+{
+	unsigned long flags;
+	struct carm_request *crq = NULL;
+	struct request *rq;
+	int tries = 5000;
+
+	while (tries-- > 0) {
+		spin_lock_irqsave(&host->lock, flags);
+		crq = carm_get_request(host);
+		spin_unlock_irqrestore(&host->lock, flags);
+
+		if (crq)
+			break;
+		msleep(10);
+	}
+
+	if (!crq)
+		return NULL;
+
+	rq = blk_get_request(host->oob_q, WRITE /* bogus */, GFP_KERNEL);
+	if (!rq) {
+		spin_lock_irqsave(&host->lock, flags);
+		carm_put_request(host, crq);
+		spin_unlock_irqrestore(&host->lock, flags);
+		return NULL;
+	}
+
+	crq->rq = rq;
+	return crq;
+}
+
+static int carm_array_info (struct carm_host *host, unsigned int array_idx)
+{
+	struct carm_msg_ioctl *ioc;
+	unsigned int idx;
+	u32 msg_data;
+	dma_addr_t msg_dma;
+	struct carm_request *crq;
+	int rc;
+
+	crq = carm_get_special(host);
+	if (!crq) {
+		rc = -ENOMEM;
+		goto err_out;
+	}
+
+	idx = crq->tag;
+
+	ioc = carm_ref_msg(host, idx);
+	msg_dma = carm_ref_msg_dma(host, idx);
+	msg_data = (u32) (msg_dma + sizeof(struct carm_array_info));
+
+	crq->msg_type = CARM_MSG_ARRAY;
+	crq->msg_subtype = CARM_ARRAY_INFO;
+	rc = carm_lookup_bucket(sizeof(struct carm_msg_ioctl) +
+				sizeof(struct carm_array_info));
+	BUG_ON(rc < 0);
+	crq->msg_bucket = (u32) rc;
+
+	memset(ioc, 0, sizeof(*ioc));
+	ioc->type	= CARM_MSG_ARRAY;
+	ioc->subtype	= CARM_ARRAY_INFO;
+	ioc->array_id	= (u8) array_idx;
+	ioc->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	ioc->data_addr	= cpu_to_le32(msg_data);
+
+	spin_lock_irq(&host->lock);
+	assert(host->state == HST_DEV_SCAN_START ||
+	       host->state == HST_DEV_SCAN);
+	spin_unlock_irq(&host->lock);
+
+	DPRINTK("blk_insert_request, tag == %u\n", idx);
+	blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+
+	return 0;
+
+err_out:
+	spin_lock_irq(&host->lock);
+	host->state = HST_ERROR;
+	spin_unlock_irq(&host->lock);
+	return rc;
+}
+
+typedef unsigned int (*carm_sspc_t)(struct carm_host *, unsigned int, void *);
+
+static int carm_send_special (struct carm_host *host, carm_sspc_t func)
+{
+	struct carm_request *crq;
+	struct carm_msg_ioctl *ioc;
+	void *mem;
+	unsigned int idx, msg_size;
+	int rc;
+
+	crq = carm_get_special(host);
+	if (!crq)
+		return -ENOMEM;
+
+	idx = crq->tag;
+
+	mem = carm_ref_msg(host, idx);
+
+	msg_size = func(host, idx, mem);
+
+	ioc = mem;
+	crq->msg_type = ioc->type;
+	crq->msg_subtype = ioc->subtype;
+	rc = carm_lookup_bucket(msg_size);
+	BUG_ON(rc < 0);
+	crq->msg_bucket = (u32) rc;
+
+	DPRINTK("blk_insert_request, tag == %u\n", idx);
+	blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+
+	return 0;
+}
+
+static unsigned int carm_fill_sync_time(struct carm_host *host,
+					unsigned int idx, void *mem)
+{
+	struct timeval tv;
+	struct carm_msg_sync_time *st = mem;
+
+	do_gettimeofday(&tv);
+
+	memset(st, 0, sizeof(*st));
+	st->type	= CARM_MSG_MISC;
+	st->subtype	= MISC_SET_TIME;
+	st->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	st->timestamp	= cpu_to_le32(tv.tv_sec);
+
+	return sizeof(struct carm_msg_sync_time);
+}
+
+static unsigned int carm_fill_alloc_buf(struct carm_host *host,
+					unsigned int idx, void *mem)
+{
+	struct carm_msg_allocbuf *ab = mem;
+
+	memset(ab, 0, sizeof(*ab));
+	ab->type	= CARM_MSG_MISC;
+	ab->subtype	= MISC_ALLOC_MEM;
+	ab->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	ab->n_sg	= 1;
+	ab->sg_type	= SGT_32BIT;
+	ab->addr	= cpu_to_le32(host->shm_dma + (PDC_SHM_SIZE >> 1));
+	ab->len		= cpu_to_le32(PDC_SHM_SIZE >> 1);
+	ab->evt_pool	= cpu_to_le32(host->shm_dma + (16 * 1024));
+	ab->n_evt	= cpu_to_le32(1024);
+	ab->rbuf_pool	= cpu_to_le32(host->shm_dma);
+	ab->n_rbuf	= cpu_to_le32(RMSG_Q_LEN);
+	ab->msg_pool	= cpu_to_le32(host->shm_dma + RBUF_LEN);
+	ab->n_msg	= cpu_to_le32(CARM_Q_LEN);
+	ab->sg[0].start	= cpu_to_le32(host->shm_dma + (PDC_SHM_SIZE >> 1));
+	ab->sg[0].len	= cpu_to_le32(65536);
+
+	return sizeof(struct carm_msg_allocbuf);
+}
+
+static unsigned int carm_fill_scan_channels(struct carm_host *host,
+					    unsigned int idx, void *mem)
+{
+	struct carm_msg_ioctl *ioc = mem;
+	u32 msg_data = (u32) (carm_ref_msg_dma(host, idx) +
+			      IOC_SCAN_CHAN_OFFSET);
+
+	memset(ioc, 0, sizeof(*ioc));
+	ioc->type	= CARM_MSG_IOCTL;
+	ioc->subtype	= CARM_IOC_SCAN_CHAN;
+	ioc->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	ioc->data_addr	= cpu_to_le32(msg_data);
+
+	/* fill output data area with "no device" default values */
+	mem += IOC_SCAN_CHAN_OFFSET;
+	memset(mem, IOC_SCAN_CHAN_NODEV, CARM_MAX_PORTS);
+
+	return IOC_SCAN_CHAN_OFFSET + CARM_MAX_PORTS;
+}
+
+static unsigned int carm_fill_get_fw_ver(struct carm_host *host,
+					 unsigned int idx, void *mem)
+{
+	struct carm_msg_get_fw_ver *ioc = mem;
+	u32 msg_data = (u32) (carm_ref_msg_dma(host, idx) + sizeof(*ioc));
+
+	memset(ioc, 0, sizeof(*ioc));
+	ioc->type	= CARM_MSG_MISC;
+	ioc->subtype	= MISC_GET_FW_VER;
+	ioc->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	ioc->data_addr	= cpu_to_le32(msg_data);
+
+	return sizeof(struct carm_msg_get_fw_ver) +
+	       sizeof(struct carm_fw_ver);
+}
+
+static inline void carm_end_request_queued(struct carm_host *host,
+					   struct carm_request *crq,
+					   int uptodate)
+{
+	struct request *req = crq->rq;
+	int rc;
+
+	rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
+	assert(rc == 0);
+
+	end_that_request_last(req);
+
+	rc = carm_put_request(host, crq);
+	assert(rc == 0);
+}
+
+static inline void carm_push_q (struct carm_host *host, request_queue_t *q)
+{
+	unsigned int idx = host->wait_q_prod % CARM_MAX_WAIT_Q;
+
+	blk_stop_queue(q);
+	VPRINTK("STOPPED QUEUE %p\n", q);
+
+	host->wait_q[idx] = q;
+	host->wait_q_prod++;
+	BUG_ON(host->wait_q_prod == host->wait_q_cons); /* overrun */
+}
+
+static inline request_queue_t *carm_pop_q(struct carm_host *host)
+{
+	unsigned int idx;
+
+	if (host->wait_q_prod == host->wait_q_cons)
+		return NULL;
+
+	idx = host->wait_q_cons % CARM_MAX_WAIT_Q;
+	host->wait_q_cons++;
+
+	return host->wait_q[idx];
+}
+
+static inline void carm_round_robin(struct carm_host *host)
+{
+	request_queue_t *q = carm_pop_q(host);
+	if (q) {
+		blk_start_queue(q);
+		VPRINTK("STARTED QUEUE %p\n", q);
+	}
+}
+
+static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
+			int is_ok)
+{
+	carm_end_request_queued(host, crq, is_ok);
+	if (CARM_MAX_Q == 1)
+		carm_round_robin(host);
+	else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
+		 (host->hw_sg_used <= CARM_SG_LOW_WATER)) {
+		carm_round_robin(host);
+	}
+}
+
+static void carm_oob_rq_fn(request_queue_t *q)
+{
+	struct carm_host *host = q->queuedata;
+	struct carm_request *crq;
+	struct request *rq;
+	int rc;
+
+	while (1) {
+		DPRINTK("get req\n");
+		rq = elv_next_request(q);
+		if (!rq)
+			break;
+
+		blkdev_dequeue_request(rq);
+
+		crq = rq->special;
+		assert(crq != NULL);
+		assert(crq->rq == rq);
+
+		crq->n_elem = 0;
+
+		DPRINTK("send req\n");
+		rc = carm_send_msg(host, crq);
+		if (rc) {
+			blk_requeue_request(q, rq);
+			carm_push_q(host, q);
+			return;		/* call us again later, eventually */
+		}
+	}
+}
+
+static void carm_rq_fn(request_queue_t *q)
+{
+	struct carm_port *port = q->queuedata;
+	struct carm_host *host = port->host;
+	struct carm_msg_rw *msg;
+	struct carm_request *crq;
+	struct request *rq;
+	struct scatterlist *sg;
+	int writing = 0, pci_dir, i, n_elem, rc;
+	u32 tmp;
+	unsigned int msg_size;
+
+queue_one_request:
+	VPRINTK("get req\n");
+	rq = elv_next_request(q);
+	if (!rq)
+		return;
+
+	crq = carm_get_request(host);
+	if (!crq) {
+		carm_push_q(host, q);
+		return;		/* call us again later, eventually */
+	}
+	crq->rq = rq;
+
+	blkdev_dequeue_request(rq);
+
+	if (rq_data_dir(rq) == WRITE) {
+		writing = 1;
+		pci_dir = PCI_DMA_TODEVICE;
+	} else {
+		pci_dir = PCI_DMA_FROMDEVICE;
+	}
+
+	/* get scatterlist from block layer */
+	sg = &crq->sg[0];
+	n_elem = blk_rq_map_sg(q, rq, sg);
+	if (n_elem <= 0) {
+		carm_end_rq(host, crq, 0);
+		return;		/* request with no s/g entries? */
+	}
+
+	/* map scatterlist to PCI bus addresses */
+	n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir);
+	if (n_elem <= 0) {
+		carm_end_rq(host, crq, 0);
+		return;		/* request with no s/g entries? */
+	}
+	crq->n_elem = n_elem;
+	crq->port = port;
+	host->hw_sg_used += n_elem;
+
+	/*
+	 * build read/write message
+	 */
+
+	VPRINTK("build msg\n");
+	msg = (struct carm_msg_rw *) carm_ref_msg(host, crq->tag);
+
+	if (writing) {
+		msg->type = CARM_MSG_WRITE;
+		crq->msg_type = CARM_MSG_WRITE;
+	} else {
+		msg->type = CARM_MSG_READ;
+		crq->msg_type = CARM_MSG_READ;
+	}
+
+	msg->id		= port->port_no;
+	msg->sg_count	= n_elem;
+	msg->sg_type	= SGT_32BIT;
+	msg->handle	= cpu_to_le32(TAG_ENCODE(crq->tag));
+	msg->lba	= cpu_to_le32(rq->sector & 0xffffffff);
+	tmp		= (rq->sector >> 16) >> 16;
+	msg->lba_high	= cpu_to_le16( (u16) tmp );
+	msg->lba_count	= cpu_to_le16(rq->nr_sectors);
+
+	msg_size = sizeof(struct carm_msg_rw) - sizeof(msg->sg);
+	for (i = 0; i < n_elem; i++) {
+		struct carm_msg_sg *carm_sg = &msg->sg[i];
+		carm_sg->start = cpu_to_le32(sg_dma_address(&crq->sg[i]));
+		carm_sg->len = cpu_to_le32(sg_dma_len(&crq->sg[i]));
+		msg_size += sizeof(struct carm_msg_sg);
+	}
+
+	rc = carm_lookup_bucket(msg_size);
+	BUG_ON(rc < 0);
+	crq->msg_bucket = (u32) rc;
+
+	/*
+	 * queue read/write message to hardware
+	 */
+
+	VPRINTK("send msg, tag == %u\n", crq->tag);
+	rc = carm_send_msg(host, crq);
+	if (rc) {
+		carm_put_request(host, crq);
+		blk_requeue_request(q, rq);
+		carm_push_q(host, q);
+		return;		/* call us again later, eventually */
+	}
+
+	goto queue_one_request;
+}
+
+static void carm_handle_array_info(struct carm_host *host,
+				   struct carm_request *crq, u8 *mem,
+				   int is_ok)
+{
+	struct carm_port *port;
+	u8 *msg_data = mem + sizeof(struct carm_array_info);
+	struct carm_array_info *desc = (struct carm_array_info *) msg_data;
+	u64 lo, hi;
+	int cur_port;
+	size_t slen;
+
+	DPRINTK("ENTER\n");
+
+	carm_end_rq(host, crq, is_ok);
+
+	if (!is_ok)
+		goto out;
+	if (le32_to_cpu(desc->array_status) & ARRAY_NO_EXIST)
+		goto out;
+
+	cur_port = host->cur_scan_dev;
+
+	/* should never occur */
+	if ((cur_port < 0) || (cur_port >= CARM_MAX_PORTS)) {
+		printk(KERN_ERR PFX "BUG: cur_scan_dev==%d, array_id==%d\n",
+		       cur_port, (int) desc->array_id);
+		goto out;
+	}
+
+	port = &host->port[cur_port];
+
+	lo = (u64) le32_to_cpu(desc->size);
+	hi = (u64) le32_to_cpu(desc->size_hi);
+
+	port->capacity = lo | (hi << 32);
+	port->dev_geom_head = le16_to_cpu(desc->head);
+	port->dev_geom_sect = le16_to_cpu(desc->sect);
+	port->dev_geom_cyl = le16_to_cpu(desc->cyl);
+
+	host->dev_active |= (1 << cur_port);
+
+	strncpy(port->name, desc->name, sizeof(port->name));
+	port->name[sizeof(port->name) - 1] = 0;
+	slen = strlen(port->name);
+	while (slen && (port->name[slen - 1] == ' ')) {
+		port->name[slen - 1] = 0;
+		slen--;
+	}
+
+	printk(KERN_INFO DRV_NAME "(%s): port %u device %Lu sectors\n",
+	       pci_name(host->pdev), port->port_no,
+	       (unsigned long long) port->capacity);
+	printk(KERN_INFO DRV_NAME "(%s): port %u device \"%s\"\n",
+	       pci_name(host->pdev), port->port_no, port->name);
+
+out:
+	assert(host->state == HST_DEV_SCAN);
+	schedule_work(&host->fsm_task);
+}
+
+static void carm_handle_scan_chan(struct carm_host *host,
+				  struct carm_request *crq, u8 *mem,
+				  int is_ok)
+{
+	u8 *msg_data = mem + IOC_SCAN_CHAN_OFFSET;
+	unsigned int i, dev_count = 0;
+	int new_state = HST_DEV_SCAN_START;
+
+	DPRINTK("ENTER\n");
+
+	carm_end_rq(host, crq, is_ok);
+
+	if (!is_ok) {
+		new_state = HST_ERROR;
+		goto out;
+	}
+
+	/* TODO: scan and support non-disk devices */
+	for (i = 0; i < 8; i++)
+		if (msg_data[i] == 0) { /* direct-access device (disk) */
+			host->dev_present |= (1 << i);
+			dev_count++;
+		}
+
+	printk(KERN_INFO DRV_NAME "(%s): found %u interesting devices\n",
+	       pci_name(host->pdev), dev_count);
+
+out:
+	assert(host->state == HST_PORT_SCAN);
+	host->state = new_state;
+	schedule_work(&host->fsm_task);
+}
+
+static void carm_handle_generic(struct carm_host *host,
+				struct carm_request *crq, int is_ok,
+				int cur_state, int next_state)
+{
+	DPRINTK("ENTER\n");
+
+	carm_end_rq(host, crq, is_ok);
+
+	assert(host->state == cur_state);
+	if (is_ok)
+		host->state = next_state;
+	else
+		host->state = HST_ERROR;
+	schedule_work(&host->fsm_task);
+}
+
+static inline void carm_handle_rw(struct carm_host *host,
+				  struct carm_request *crq, int is_ok)
+{
+	int pci_dir;
+
+	VPRINTK("ENTER\n");
+
+	if (rq_data_dir(crq->rq) == WRITE)
+		pci_dir = PCI_DMA_TODEVICE;
+	else
+		pci_dir = PCI_DMA_FROMDEVICE;
+
+	pci_unmap_sg(host->pdev, &crq->sg[0], crq->n_elem, pci_dir);
+
+	carm_end_rq(host, crq, is_ok);
+}
+
+static inline void carm_handle_resp(struct carm_host *host,
+				    u32 ret_handle_le, u32 status)
+{
+	u32 handle = le32_to_cpu(ret_handle_le);
+	unsigned int msg_idx;
+	struct carm_request *crq;
+	int is_ok = (status == RMSG_OK);
+	u8 *mem;
+
+	VPRINTK("ENTER, handle == 0x%x\n", handle);
+
+	if (unlikely(!TAG_VALID(handle))) {
+		printk(KERN_ERR DRV_NAME "(%s): BUG: invalid tag 0x%x\n",
+		       pci_name(host->pdev), handle);
+		return;
+	}
+
+	msg_idx = TAG_DECODE(handle);
+	VPRINTK("tag == %u\n", msg_idx);
+
+	crq = &host->req[msg_idx];
+
+	/* fast path */
+	if (likely(crq->msg_type == CARM_MSG_READ ||
+		   crq->msg_type == CARM_MSG_WRITE)) {
+		carm_handle_rw(host, crq, is_ok);
+		return;
+	}
+
+	mem = carm_ref_msg(host, msg_idx);
+
+	switch (crq->msg_type) {
+	case CARM_MSG_IOCTL: {
+		switch (crq->msg_subtype) {
+		case CARM_IOC_SCAN_CHAN:
+			carm_handle_scan_chan(host, crq, mem, is_ok);
+			break;
+		default:
+			/* unknown / invalid response */
+			goto err_out;
+		}
+		break;
+	}
+
+	case CARM_MSG_MISC: {
+		switch (crq->msg_subtype) {
+		case MISC_ALLOC_MEM:
+			carm_handle_generic(host, crq, is_ok,
+					    HST_ALLOC_BUF, HST_SYNC_TIME);
+			break;
+		case MISC_SET_TIME:
+			carm_handle_generic(host, crq, is_ok,
+					    HST_SYNC_TIME, HST_GET_FW_VER);
+			break;
+		case MISC_GET_FW_VER: {
+			struct carm_fw_ver *ver = (struct carm_fw_ver *)
+				mem + sizeof(struct carm_msg_get_fw_ver);
+			if (is_ok) {
+				host->fw_ver = le32_to_cpu(ver->version);
+				host->flags |= (ver->features & FL_FW_VER_MASK);
+			}
+			carm_handle_generic(host, crq, is_ok,
+					    HST_GET_FW_VER, HST_PORT_SCAN);
+			break;
+		}
+		default:
+			/* unknown / invalid response */
+			goto err_out;
+		}
+		break;
+	}
+
+	case CARM_MSG_ARRAY: {
+		switch (crq->msg_subtype) {
+		case CARM_ARRAY_INFO:
+			carm_handle_array_info(host, crq, mem, is_ok);
+			break;
+		default:
+			/* unknown / invalid response */
+			goto err_out;
+		}
+		break;
+	}
+
+	default:
+		/* unknown / invalid response */
+		goto err_out;
+	}
+
+	return;
+
+err_out:
+	printk(KERN_WARNING DRV_NAME "(%s): BUG: unhandled message type %d/%d\n",
+	       pci_name(host->pdev), crq->msg_type, crq->msg_subtype);
+	carm_end_rq(host, crq, 0);
+}
+
+static inline void carm_handle_responses(struct carm_host *host)
+{
+	void *mmio = host->mmio;
+	struct carm_response *resp = (struct carm_response *) host->shm;
+	unsigned int work = 0;
+	unsigned int idx = host->resp_idx % RMSG_Q_LEN;
+
+	while (1) {
+		u32 status = le32_to_cpu(resp[idx].status);
+
+		if (status == 0xffffffff) {
+			VPRINTK("ending response on index %u\n", idx);
+			writel(idx << 3, mmio + CARM_RESP_IDX);
+			break;
+		}
+
+		/* response to a message we sent */
+		else if ((status & (1 << 31)) == 0) {
+			VPRINTK("handling msg response on index %u\n", idx);
+			carm_handle_resp(host, resp[idx].ret_handle, status);
+			resp[idx].status = 0xffffffff;
+		}
+
+		/* asynchronous events the hardware throws our way */
+		else if ((status & 0xff000000) == (1 << 31)) {
+			u8 *evt_type_ptr = (u8 *) &resp[idx];
+			u8 evt_type = *evt_type_ptr;
+			printk(KERN_WARNING DRV_NAME "(%s): unhandled event type %d\n",
+			       pci_name(host->pdev), (int) evt_type);
+			resp[idx].status = 0xffffffff;
+		}
+
+		idx = NEXT_RESP(idx);
+		work++;
+	}
+
+	VPRINTK("EXIT, work==%u\n", work);
+	host->resp_idx += work;
+}
+
+static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs)
+{
+	struct carm_host *host = __host;
+	void *mmio;
+	u32 mask;
+	int handled = 0;
+	unsigned long flags;
+
+	if (!host) {
+		VPRINTK("no host\n");
+		return IRQ_NONE;
+	}
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	mmio = host->mmio;
+
+	/* reading should also clear interrupts */
+	mask = readl(mmio + CARM_INT_STAT);
+
+	if (mask == 0 || mask == 0xffffffff) {
+		VPRINTK("no work, mask == 0x%x\n", mask);
+		goto out;
+	}
+
+	if (mask & INT_ACK_MASK)
+		writel(mask, mmio + CARM_INT_STAT);
+
+	if (unlikely(host->state == HST_INVALID)) {
+		VPRINTK("not initialized yet, mask = 0x%x\n", mask);
+		goto out;
+	}
+
+	if (mask & CARM_HAVE_RESP) {
+		handled = 1;
+		carm_handle_responses(host);
+	}
+
+out:
+	spin_unlock_irqrestore(&host->lock, flags);
+	VPRINTK("EXIT\n");
+	return IRQ_RETVAL(handled);
+}
+
+static void carm_fsm_task (void *_data)
+{
+	struct carm_host *host = _data;
+	unsigned long flags;
+	unsigned int state;
+	int rc, i, next_dev;
+	int reschedule = 0;
+	int new_state = HST_INVALID;
+
+	spin_lock_irqsave(&host->lock, flags);
+	state = host->state;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	DPRINTK("ENTER, state == %s\n", state_name[state]);
+
+	switch (state) {
+	case HST_PROBE_START:
+		new_state = HST_ALLOC_BUF;
+		reschedule = 1;
+		break;
+
+	case HST_ALLOC_BUF:
+		rc = carm_send_special(host, carm_fill_alloc_buf);
+		if (rc) {
+			new_state = HST_ERROR;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_SYNC_TIME:
+		rc = carm_send_special(host, carm_fill_sync_time);
+		if (rc) {
+			new_state = HST_ERROR;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_GET_FW_VER:
+		rc = carm_send_special(host, carm_fill_get_fw_ver);
+		if (rc) {
+			new_state = HST_ERROR;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_PORT_SCAN:
+		rc = carm_send_special(host, carm_fill_scan_channels);
+		if (rc) {
+			new_state = HST_ERROR;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_DEV_SCAN_START:
+		host->cur_scan_dev = -1;
+		new_state = HST_DEV_SCAN;
+		reschedule = 1;
+		break;
+
+	case HST_DEV_SCAN:
+		next_dev = -1;
+		for (i = host->cur_scan_dev + 1; i < CARM_MAX_PORTS; i++)
+			if (host->dev_present & (1 << i)) {
+				next_dev = i;
+				break;
+			}
+
+		if (next_dev >= 0) {
+			host->cur_scan_dev = next_dev;
+			rc = carm_array_info(host, next_dev);
+			if (rc) {
+				new_state = HST_ERROR;
+				reschedule = 1;
+			}
+		} else {
+			new_state = HST_DEV_ACTIVATE;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_DEV_ACTIVATE: {
+		int activated = 0;
+		for (i = 0; i < CARM_MAX_PORTS; i++)
+			if (host->dev_active & (1 << i)) {
+				struct carm_port *port = &host->port[i];
+				struct gendisk *disk = port->disk;
+
+				set_capacity(disk, port->capacity);
+				add_disk(disk);
+				activated++;
+			}
+
+		printk(KERN_INFO DRV_NAME "(%s): %d ports activated\n",
+		       pci_name(host->pdev), activated);
+
+		new_state = HST_PROBE_FINISHED;
+		reschedule = 1;
+		break;
+	}
+
+	case HST_PROBE_FINISHED:
+		up(&host->probe_sem);
+		break;
+
+	case HST_ERROR:
+		/* FIXME: TODO */
+		break;
+
+	default:
+		/* should never occur */
+		printk(KERN_ERR PFX "BUG: unknown state %d\n", state);
+		assert(0);
+		break;
+	}
+
+	if (new_state != HST_INVALID) {
+		spin_lock_irqsave(&host->lock, flags);
+		host->state = new_state;
+		spin_unlock_irqrestore(&host->lock, flags);
+	}
+	if (reschedule)
+		schedule_work(&host->fsm_task);
+}
+
+static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit)
+{
+	unsigned int i;
+
+	for (i = 0; i < 50000; i++) {
+		u32 tmp = readl(mmio + CARM_LMUC);
+		udelay(100);
+
+		if (test_bit) {
+			if ((tmp & bits) == bits)
+				return 0;
+		} else {
+			if ((tmp & bits) == 0)
+				return 0;
+		}
+
+		cond_resched();
+	}
+
+	printk(KERN_ERR PFX "carm_init_wait timeout, bits == 0x%x, test_bit == %s\n",
+	       bits, test_bit ? "yes" : "no");
+	return -EBUSY;
+}
+
+static void carm_init_responses(struct carm_host *host)
+{
+	void *mmio = host->mmio;
+	unsigned int i;
+	struct carm_response *resp = (struct carm_response *) host->shm;
+
+	for (i = 0; i < RMSG_Q_LEN; i++)
+		resp[i].status = 0xffffffff;
+
+	writel(0, mmio + CARM_RESP_IDX);
+}
+
+static int carm_init_host(struct carm_host *host)
+{
+	void *mmio = host->mmio;
+	u32 tmp;
+	u8 tmp8;
+	int rc;
+
+	DPRINTK("ENTER\n");
+
+	writel(0, mmio + CARM_INT_MASK);
+
+	tmp8 = readb(mmio + CARM_INITC);
+	if (tmp8 & 0x01) {
+		tmp8 &= ~0x01;
+		writeb(tmp8, CARM_INITC);
+		readb(mmio + CARM_INITC);	/* flush */
+
+		DPRINTK("snooze...\n");
+		msleep(5000);
+	}
+
+	tmp = readl(mmio + CARM_HMUC);
+	if (tmp & CARM_CME) {
+		DPRINTK("CME bit present, waiting\n");
+		rc = carm_init_wait(mmio, CARM_CME, 1);
+		if (rc) {
+			DPRINTK("EXIT, carm_init_wait 1 failed\n");
+			return rc;
+		}
+	}
+	if (tmp & CARM_RME) {
+		DPRINTK("RME bit present, waiting\n");
+		rc = carm_init_wait(mmio, CARM_RME, 1);
+		if (rc) {
+			DPRINTK("EXIT, carm_init_wait 2 failed\n");
+			return rc;
+		}
+	}
+
+	tmp &= ~(CARM_RME | CARM_CME);
+	writel(tmp, mmio + CARM_HMUC);
+	readl(mmio + CARM_HMUC);	/* flush */
+
+	rc = carm_init_wait(mmio, CARM_RME | CARM_CME, 0);
+	if (rc) {
+		DPRINTK("EXIT, carm_init_wait 3 failed\n");
+		return rc;
+	}
+
+	carm_init_buckets(mmio);
+
+	writel(host->shm_dma & 0xffffffff, mmio + RBUF_ADDR_LO);
+	writel((host->shm_dma >> 16) >> 16, mmio + RBUF_ADDR_HI);
+	writel(RBUF_LEN, mmio + RBUF_BYTE_SZ);
+
+	tmp = readl(mmio + CARM_HMUC);
+	tmp |= (CARM_RME | CARM_CME | CARM_WZBC);
+	writel(tmp, mmio + CARM_HMUC);
+	readl(mmio + CARM_HMUC);	/* flush */
+
+	rc = carm_init_wait(mmio, CARM_RME | CARM_CME, 1);
+	if (rc) {
+		DPRINTK("EXIT, carm_init_wait 4 failed\n");
+		return rc;
+	}
+
+	writel(0, mmio + CARM_HMPHA);
+	writel(INT_DEF_MASK, mmio + CARM_INT_MASK);
+
+	carm_init_responses(host);
+
+	/* start initialization, probing state machine */
+	spin_lock_irq(&host->lock);
+	assert(host->state == HST_INVALID);
+	host->state = HST_PROBE_START;
+	spin_unlock_irq(&host->lock);
+	schedule_work(&host->fsm_task);
+
+	DPRINTK("EXIT\n");
+	return 0;
+}
+
+static int carm_init_disks(struct carm_host *host)
+{
+	unsigned int i;
+	int rc = 0;
+
+	for (i = 0; i < CARM_MAX_PORTS; i++) {
+		struct gendisk *disk;
+		request_queue_t *q;
+		struct carm_port *port;
+
+		port = &host->port[i];
+		port->host = host;
+		port->port_no = i;
+
+		disk = alloc_disk(CARM_MINORS_PER_MAJOR);
+		if (!disk) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		port->disk = disk;
+		sprintf(disk->disk_name, DRV_NAME "%u_%u", host->id, i);
+		sprintf(disk->devfs_name, DRV_NAME "/%u_%u", host->id, i);
+		disk->major = host->major;
+		disk->first_minor = i * CARM_MINORS_PER_MAJOR;
+		disk->fops = &carm_bd_ops;
+		disk->private_data = port;
+
+		q = blk_init_queue(carm_rq_fn, &host->lock);
+		if (!q) {
+			rc = -ENOMEM;
+			break;
+		}
+		disk->queue = q;
+		blk_queue_max_hw_segments(q, CARM_MAX_REQ_SG);
+		blk_queue_max_phys_segments(q, CARM_MAX_REQ_SG);
+		blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
+
+		q->queuedata = port;
+	}
+
+	return rc;
+}
+
+static void carm_free_disks(struct carm_host *host)
+{
+	unsigned int i;
+
+	for (i = 0; i < CARM_MAX_PORTS; i++) {
+		struct gendisk *disk = host->port[i].disk;
+		if (disk) {
+			request_queue_t *q = disk->queue;
+
+			if (disk->flags & GENHD_FL_UP)
+				del_gendisk(disk);
+			if (q)
+				blk_cleanup_queue(q);
+			put_disk(disk);
+		}
+	}
+}
+
+static int carm_init_shm(struct carm_host *host)
+{
+	host->shm = pci_alloc_consistent(host->pdev, CARM_SHM_SIZE,
+					 &host->shm_dma);
+	if (!host->shm)
+		return -ENOMEM;
+
+	host->msg_base = host->shm + RBUF_LEN;
+	host->msg_dma = host->shm_dma + RBUF_LEN;
+
+	memset(host->shm, 0xff, RBUF_LEN);
+	memset(host->msg_base, 0, PDC_SHM_SIZE - RBUF_LEN);
+
+	return 0;
+}
+
+static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static unsigned int printed_version;
+	struct carm_host *host;
+	unsigned int pci_dac;
+	int rc;
+	request_queue_t *q;
+	unsigned int i;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+#if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */
+	rc = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+	if (!rc) {
+		rc = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+		if (rc) {
+			printk(KERN_ERR DRV_NAME "(%s): consistent DMA mask failure\n",
+				pci_name(pdev));
+			goto err_out_regions;
+		}
+		pci_dac = 1;
+	} else {
+#endif
+		rc = pci_set_dma_mask(pdev, 0xffffffffULL);
+		if (rc) {
+			printk(KERN_ERR DRV_NAME "(%s): DMA mask failure\n",
+				pci_name(pdev));
+			goto err_out_regions;
+		}
+		pci_dac = 0;
+#if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */
+	}
+#endif
+
+	host = kmalloc(sizeof(*host), GFP_KERNEL);
+	if (!host) {
+		printk(KERN_ERR DRV_NAME "(%s): memory alloc failure\n",
+		       pci_name(pdev));
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(host, 0, sizeof(*host));
+	host->pdev = pdev;
+	host->flags = pci_dac ? FL_DAC : 0;
+	spin_lock_init(&host->lock);
+	INIT_WORK(&host->fsm_task, carm_fsm_task, host);
+	init_MUTEX_LOCKED(&host->probe_sem);
+
+	for (i = 0; i < ARRAY_SIZE(host->req); i++)
+		host->req[i].tag = i;
+
+	host->mmio = ioremap(pci_resource_start(pdev, 0),
+			     pci_resource_len(pdev, 0));
+	if (!host->mmio) {
+		printk(KERN_ERR DRV_NAME "(%s): MMIO alloc failure\n",
+		       pci_name(pdev));
+		rc = -ENOMEM;
+		goto err_out_kfree;
+	}
+
+	rc = carm_init_shm(host);
+	if (rc) {
+		printk(KERN_ERR DRV_NAME "(%s): DMA SHM alloc failure\n",
+		       pci_name(pdev));
+		goto err_out_iounmap;
+	}
+
+	q = blk_init_queue(carm_oob_rq_fn, &host->lock);
+	if (!q) {
+		printk(KERN_ERR DRV_NAME "(%s): OOB queue alloc failure\n",
+		       pci_name(pdev));
+		rc = -ENOMEM;
+		goto err_out_pci_free;
+	}
+	host->oob_q = q;
+	q->queuedata = host;
+
+	/*
+	 * Figure out which major to use: 160, 161, or dynamic
+	 */
+	if (!test_and_set_bit(0, &carm_major_alloc))
+		host->major = 160;
+	else if (!test_and_set_bit(1, &carm_major_alloc))
+		host->major = 161;
+	else
+		host->flags |= FL_DYN_MAJOR;
+
+	host->id = carm_host_id;
+	sprintf(host->name, DRV_NAME "%d", carm_host_id);
+
+	rc = register_blkdev(host->major, host->name);
+	if (rc < 0)
+		goto err_out_free_majors;
+	if (host->flags & FL_DYN_MAJOR)
+		host->major = rc;
+
+	devfs_mk_dir(DRV_NAME);
+
+	rc = carm_init_disks(host);
+	if (rc)
+		goto err_out_blkdev_disks;
+
+	pci_set_master(pdev);
+
+	rc = request_irq(pdev->irq, carm_interrupt, SA_SHIRQ, DRV_NAME, host);
+	if (rc) {
+		printk(KERN_ERR DRV_NAME "(%s): irq alloc failure\n",
+		       pci_name(pdev));
+		goto err_out_blkdev_disks;
+	}
+
+	rc = carm_init_host(host);
+	if (rc)
+		goto err_out_free_irq;
+
+	DPRINTK("waiting for probe_sem\n");
+	down(&host->probe_sem);
+
+	printk(KERN_INFO "%s: pci %s, ports %d, io %lx, irq %u, major %d\n",
+	       host->name, pci_name(pdev), (int) CARM_MAX_PORTS,
+	       pci_resource_start(pdev, 0), pdev->irq, host->major);
+
+	carm_host_id++;
+	pci_set_drvdata(pdev, host);
+	return 0;
+
+err_out_free_irq:
+	free_irq(pdev->irq, host);
+err_out_blkdev_disks:
+	carm_free_disks(host);
+	unregister_blkdev(host->major, host->name);
+err_out_free_majors:
+	if (host->major == 160)
+		clear_bit(0, &carm_major_alloc);
+	else if (host->major == 161)
+		clear_bit(1, &carm_major_alloc);
+	blk_cleanup_queue(host->oob_q);
+err_out_pci_free:
+	pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma);
+err_out_iounmap:
+	iounmap(host->mmio);
+err_out_kfree:
+	kfree(host);
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static void carm_remove_one (struct pci_dev *pdev)
+{
+	struct carm_host *host = pci_get_drvdata(pdev);
+
+	if (!host) {
+		printk(KERN_ERR PFX "BUG: no host data for PCI(%s)\n",
+		       pci_name(pdev));
+		return;
+	}
+
+	free_irq(pdev->irq, host);
+	carm_free_disks(host);
+	devfs_remove(DRV_NAME);
+	unregister_blkdev(host->major, host->name);
+	if (host->major == 160)
+		clear_bit(0, &carm_major_alloc);
+	else if (host->major == 161)
+		clear_bit(1, &carm_major_alloc);
+	blk_cleanup_queue(host->oob_q);
+	pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma);
+	iounmap(host->mmio);
+	kfree(host);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+static int __init carm_init(void)
+{
+	return pci_module_init(&carm_driver);
+}
+
+static void __exit carm_exit(void)
+{
+	pci_unregister_driver(&carm_driver);
+}
+
+module_init(carm_init);
+module_exit(carm_exit);
+
+
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/cdrom/cdrom.c	2004-06-23 19:04:25 -07:00
@@ -508,6 +508,8 @@
 	unsigned char buffer[16];
 	int ret;
 
+	*write = 0;
+
 	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
 
 	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
@@ -521,8 +523,10 @@
 	mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
 	*write = mfd->write;
 
-	if ((ret = cdrom_mrw_probe_pc(cdi)))
+	if ((ret = cdrom_mrw_probe_pc(cdi))) {
+		*write = 0;
 		return ret;
+	}
 
 	return 0;
 }
@@ -822,8 +826,30 @@
  */
 static int cdrom_open_write(struct cdrom_device_info *cdi)
 {
+	int mrw, mrw_write, ram_write;
 	int ret = 1;
 
+	mrw = 0;
+	if (!cdrom_is_mrw(cdi, &mrw_write))
+		mrw = 1;
+
+	(void) cdrom_is_random_writable(cdi, &ram_write);
+
+	if (mrw)
+		cdi->mask &= ~CDC_MRW;
+	else
+		cdi->mask |= CDC_MRW;
+
+	if (mrw_write)
+		cdi->mask &= ~CDC_MRW_W;
+	else
+		cdi->mask |= CDC_MRW_W;
+
+	if (ram_write)
+		cdi->mask &= ~CDC_RAM;
+	else
+		cdi->mask |= CDC_RAM;
+
 	if (CDROM_CAN(CDC_MRW_W))
 		ret = cdrom_mrw_open_write(cdi);
 	else if (CDROM_CAN(CDC_DVD_RAM))
@@ -866,6 +892,9 @@
 	if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS)) {
 		ret = cdi->ops->open(cdi, 1);
 	} else {
+		ret = open_for_data(cdi);
+		if (ret)
+			goto err;
 		if (fp->f_mode & FMODE_WRITE) {
 			ret = -EROFS;
 			if (!CDROM_CAN(CDC_RAM))
@@ -873,7 +902,6 @@
 			if (cdrom_open_write(cdi))
 				goto err;
 		}
-		ret = open_for_data(cdi);
 	}
 
 	if (ret)
diff -Nru a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c
--- a/drivers/cdrom/isp16.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/cdrom/isp16.c	2004-06-23 19:04:28 -07:00
@@ -16,6 +16,10 @@
  *			   module_init & module_exit.
  *			   Torben Mathiasen <tmm@image.dk>
  *
+ *     19 June 2004     -- check_region() converted to request_region()
+ *                         and return statement cleanups.
+ *                         Jesper Juhl <juhl-lkml@dif.dk>
+ *
  *    Detect cdrom interface on ISP16 sound card.
  *    Configure cdrom interface.
  *
@@ -118,17 +122,17 @@
 
 	if (!strcmp(isp16_cdrom_type, "noisp16")) {
 		printk("ISP16: no cdrom interface configured.\n");
-		return (0);
+		return 0;
 	}
 
-	if (check_region(ISP16_IO_BASE, ISP16_IO_SIZE)) {
+	if (!request_region(ISP16_IO_BASE, ISP16_IO_SIZE, "isp16")) {
 		printk("ISP16: i/o ports already in use.\n");
-		return (-EIO);
+		goto out;
 	}
 
 	if ((isp16_type = isp16_detect()) < 0) {
 		printk("ISP16: no cdrom interface found.\n");
-		return (-EIO);
+		goto cleanup_out;
 	}
 
 	printk(KERN_INFO
@@ -148,27 +152,32 @@
 	else {
 		printk("ISP16: %s not supported by cdrom interface.\n",
 		       isp16_cdrom_type);
-		return (-EIO);
+		goto cleanup_out;
 	}
 
 	if (isp16_cdi_config(isp16_cdrom_base, expected_drive,
 			     isp16_cdrom_irq, isp16_cdrom_dma) < 0) {
 		printk
 		    ("ISP16: cdrom interface has not been properly configured.\n");
-		return (-EIO);
+		goto cleanup_out;
 	}
 	printk(KERN_INFO
 	       "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
 	       " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq,
 	       isp16_cdrom_dma, isp16_cdrom_type);
-	return (0);
+	return 0;
+
+cleanup_out:
+	release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
+out:
+	return -EIO;
 }
 
 static short __init isp16_detect(void)
 {
 
 	if (isp16_c929__detect() >= 0)
-		return (2);
+		return 2;
 	else
 		return (isp16_c928__detect());
 }
@@ -206,7 +215,7 @@
 			ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom);
 		} else {	/* bits are not the same */
 			ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-			return (i);	/* -> not detected: possibly incorrect conclusion */
+			return i;	/* -> not detected: possibly incorrect conclusion */
 		}
 	} else if (enable_cdrom == 0x20)
 		i = 0;
@@ -215,7 +224,7 @@
 
 	ISP16_OUT(ISP16_CTRL_PORT, ctrl);
 
-	return (i);
+	return i;
 }
 
 static short __init isp16_c929__detect(void)
@@ -236,12 +245,12 @@
 	tmp = ISP16_IN(ISP16_CTRL_PORT);
 
 	if (tmp != 2)		/* isp16 with 82C929 not detected */
-		return (-1);
+		return -1;
 
 	/* restore ctrl port value */
 	ISP16_OUT(ISP16_CTRL_PORT, ctrl);
 
-	return (2);
+	return 2;
 }
 
 static short __init
@@ -272,7 +281,7 @@
 		printk
 		    ("ISP16: base address 0x%03X not supported by cdrom interface.\n",
 		     base);
-		return (-1);
+		return -1;
 	}
 	switch (irq) {
 	case 0:
@@ -303,7 +312,7 @@
 	default:
 		printk("ISP16: irq %d not supported by cdrom interface.\n",
 		       irq);
-		return (-1);
+		return -1;
 	}
 	switch (dma) {
 	case 0:
@@ -312,7 +321,7 @@
 	case 1:
 		printk("ISP16: dma 1 cannot be used by cdrom interface,"
 		       " due to conflict with the sound card.\n");
-		return (-1);
+		return -1;
 		break;
 	case 3:
 		dma_code = ISP16_DMA_3;
@@ -329,7 +338,7 @@
 	default:
 		printk("ISP16: dma %d not supported by cdrom interface.\n",
 		       dma);
-		return (-1);
+		return -1;
 	}
 
 	if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
@@ -339,7 +348,7 @@
 		printk
 		    ("ISP16: drive type (code 0x%02X) not supported by cdrom"
 		     " interface.\n", drive_type);
-		return (-1);
+		return -1;
 	}
 
 	/* set type of interface */
@@ -354,7 +363,7 @@
 	i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;	/* keep some bits */
 	ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code);
 
-	return (0);
+	return 0;
 }
 
 void __exit isp16_exit(void)
diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig
--- a/drivers/char/Kconfig	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/Kconfig	2004-06-23 19:04:25 -07:00
@@ -586,17 +586,6 @@
 	  console. This driver allows each pSeries partition to have a console
 	  which is accessed via the HMC.
 
-config PC9800_OLDLP
-	tristate "NEC PC-9800 old-style printer port support"
-	depends on X86_PC9800 && !PARPORT
-	---help---
-	  If you intend to attach a printer to the parallel port of NEC PC-9801
-	  /PC-9821 with OLD compatibility mode, Say Y.
-
-config PC9800_OLDLP_CONSOLE
-	bool "Support for console on line printer"
-	depends on PC9800_OLDLP
-
 config QIC02_TAPE
 	tristate "QIC-02 tape support"
 	help
@@ -740,7 +729,7 @@
 
 config RTC
 	tristate "Enhanced Real Time Clock Support"
-	depends on !PPC32 && !PARISC && !IA64 && !X86_PC9800 && !M68K
+	depends on !PPC32 && !PARISC && !IA64 && !M68K
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -764,6 +753,28 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called rtc.
 
+config SGI_DS1286
+	tristate "SGI DS1286 RTC support"
+	depends on SGI_IP22
+	help
+	  If you say Y here and create a character special file /dev/rtc with
+	  major number 10 and minor number 135 using mknod ("man mknod"), you
+	  will get access to the real time clock built into your computer.
+	  Every SGI has such a clock built in. It reports status information
+	  via the file /proc/rtc and its behaviour is set by various ioctls on
+	  /dev/rtc.
+
+config SGI_IP27_RTC
+	bool "SGI M48T35 RTC support"
+	depends on SGI_IP27
+	help
+	  If you say Y here and create a character special file /dev/rtc with
+	  major number 10 and minor number 135 using mknod ("man mknod"), you
+	  will get access to the real time clock built into your computer.
+	  Every SGI has such a clock built in. It reports status information
+	  via the file /proc/rtc and its behaviour is set by various ioctls on
+	  /dev/rtc.
+
 config GEN_RTC
 	tristate "Generic /dev/rtc emulation"
 	depends on RTC!=y && !IA64
@@ -793,14 +804,12 @@
 	bool "EFI Real Time Clock Services"
 	depends on IA64
 
-config RTC98
-	tristate "NEC PC-9800 Real Time Clock Support"
-	depends on X86_PC9800
-	default y
-	---help---
-	  If you say Y here and create a character special file /dev/rtc with
-	  major number 10 and minor number 135 using mknod ("man mknod"), you
-	  will get access to the real time clock (or hardware clock) built
+config COBALT_LCD
+	bool "Support for Cobalt LCD"
+	depends on MIPS_COBALT
+	help
+	  This option enables support for the LCD display and buttons found
+	  on Cobalt systems through a misc device.
 
 config H8
 	bool "Tadpole ANA H8 Support (OBSOLETE)"
@@ -956,6 +965,33 @@
           The raw driver is deprecated and may be removed from 2.7
           kernels.  Applications should simply open the device (eg /dev/hda1)
           with the O_DIRECT flag.
+
+config HPET
+	bool "HPET - High Precision Event Timer" if (X86 || IA64)
+	default n
+	depends on ACPI
+	help
+	  If you say Y here, you will have a device named "/dev/hpet/XX" for
+	  each timer supported by the HPET.  The timers are
+	  non-periodioc and/or periodic.
+
+config HPET_RTC_IRQ
+	bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC
+	default n
+	depends on HPET
+	help
+	  If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It
+	  is assumed the platform called hpet_alloc with the RTC IRQ values for
+	  the HPET timers.
+
+config HPET_NOMMAP
+	bool "HPET - Control mmap capability."
+	default n
+	depends on HPET
+	help
+	  If you say Y here, then the mmap interface for the HPET driver returns ENOSYS.
+	  Some hardware implementations might not want all the memory in the page the
+	  HPET control registers reside to be exposed.
 
 config MAX_RAW_DEVS
 	int "Maximum number of RAW devices to support (1-8192)"
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/Makefile	2004-06-23 19:04:28 -07:00
@@ -47,15 +47,17 @@
 
 obj-$(CONFIG_PRINTER) += lp.o
 obj-$(CONFIG_TIPAR) += tipar.o
-obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o
 
 obj-$(CONFIG_DTLK) += dtlk.o
 obj-$(CONFIG_R3964) += n_r3964.o
 obj-$(CONFIG_APPLICOM) += applicom.o
 obj-$(CONFIG_SONYPI) += sonypi.o
 obj-$(CONFIG_RTC) += rtc.o
+obj-$(CONFIG_HPET) += hpet.o
 obj-$(CONFIG_GEN_RTC) += genrtc.o
 obj-$(CONFIG_EFI_RTC) += efirtc.o
+obj-$(CONFIG_SGI_DS1286) += ds1286.o
+obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
 ifeq ($(CONFIG_GENERIC_NVRAM),y)
   obj-$(CONFIG_NVRAM) += generic_nvram.o
 else
@@ -67,6 +69,7 @@
 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_H8) += h8.o
 obj-$(CONFIG_PPDEV) += ppdev.o
 obj-$(CONFIG_NWBUTTON) += nwbutton.o
diff -Nru a/drivers/char/applicom.c b/drivers/char/applicom.c
--- a/drivers/char/applicom.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/applicom.c	2004-06-23 19:04:28 -07:00
@@ -105,8 +105,8 @@
 static unsigned int ReadErrorCount;	/* number of read error       */
 static unsigned int DeviceErrorCount;	/* number of device error     */
 
-static ssize_t ac_read (struct file *, char *, size_t, loff_t *);
-static ssize_t ac_write (struct file *, const char *, size_t, loff_t *);
+static ssize_t ac_read (struct file *, char __user *, size_t, loff_t *);
+static ssize_t ac_write (struct file *, const char __user *, size_t, loff_t *);
 static int ac_ioctl(struct inode *, struct file *, unsigned int,
 		    unsigned long);
 static irqreturn_t ac_interrupt(int, void *, struct pt_regs *);
@@ -343,7 +343,7 @@
 __initcall(applicom_init);
 #endif
 
-static ssize_t ac_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
+static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
 {
 	unsigned int NumCard;	/* Board number 1 -> 8           */
 	unsigned int IndexCard;	/* Index board number 0 -> 7     */
@@ -467,7 +467,7 @@
 	return 0;
 }
 
-static int do_ac_read(int IndexCard, char *buf,
+static int do_ac_read(int IndexCard, char __user *buf,
 		struct st_ram_io *st_loc, struct mailbox *mailbox)
 {
 	unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC;
@@ -521,7 +521,7 @@
 	return (sizeof(struct st_ram_io) + sizeof(struct mailbox));
 }
 
-static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr)
+static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_t *ptr)
 {
 	unsigned long flags;
 	unsigned int i;
@@ -689,6 +689,7 @@
 	int ret = 0;
 	volatile unsigned char byte_reset_it;
 	struct st_ram_io *adgl;
+	void __user *argp = (void __user *)arg;
 
 	/* In general, the device is only openable by root anyway, so we're not
 	   particularly concerned that bogus ioctls can flood the console. */
@@ -697,7 +698,7 @@
 	if (!adgl)
 		return -ENOMEM;
 
-	if (copy_from_user(adgl, (void *)arg,sizeof(struct st_ram_io))) {
+	if (copy_from_user(adgl, argp, sizeof(struct st_ram_io))) {
 		kfree(adgl);
 		return -EFAULT;
 	}
@@ -721,7 +722,7 @@
 		pmem = apbs[IndexCard].RamIO;
 		for (i = 0; i < sizeof(struct st_ram_io); i++)
 			((unsigned char *)adgl)[i]=readb(pmem++);
-		if (copy_to_user((void *)arg, adgl, sizeof(struct st_ram_io)))
+		if (copy_to_user(argp, adgl, sizeof(struct st_ram_io)))
 			ret = -EFAULT;
 		break;
 	case 1:
@@ -742,7 +743,7 @@
 			(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + 
 			(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) );
 
-		if (copy_to_user((void *)arg, adgl, sizeof(struct st_ram_io)))
+		if (copy_to_user(argp, adgl, sizeof(struct st_ram_io)))
 			ret = -EFAULT;
 		break;
 	case 2:
@@ -768,7 +769,7 @@
 		pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC;
 		adgl->tic_owner_to_pc     = readb(pmem++);
 		adgl->numcard_owner_to_pc = readb(pmem);
-		if (copy_to_user((void *)arg, adgl,sizeof(struct st_ram_io)))
+		if (copy_to_user(argp, adgl,sizeof(struct st_ram_io)))
 			ret = -EFAULT;
 		break;
 	case 5:
diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c
--- a/drivers/char/cyclades.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/cyclades.c	2004-06-23 19:04:26 -07:00
@@ -676,8 +676,6 @@
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
-#define cy_put_user	put_user
-
 static void cy_throttle (struct tty_struct *tty);
 static void cy_send_xchar (struct tty_struct *tty, char ch);
 
@@ -3536,7 +3534,7 @@
 
 static int
 get_serial_info(struct cyclades_port * info,
-                           struct serial_struct * retinfo)
+                           struct serial_struct __user * retinfo)
 {
   struct serial_struct tmp;
   struct cyclades_card *cinfo = &cy_card[info->card];
@@ -3559,7 +3557,7 @@
 
 static int
 set_serial_info(struct cyclades_port * info,
-                           struct serial_struct * new_info)
+                           struct serial_struct __user * new_info)
 {
   struct serial_struct new_serial;
   struct cyclades_port old_info;
@@ -3613,7 +3611,7 @@
  *	    transmit holding register is empty.  This functionality
  *	    allows an RS485 driver to be written in user space.
  */
-static int get_lsr_info(struct cyclades_port *info, unsigned int *value)
+static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
 {
     int card, chip, channel, index;
     unsigned char status;
@@ -3638,7 +3636,7 @@
 	/* Not supported yet */
 	return -EINVAL;
     }
-    return cy_put_user(result, (unsigned long *) value);
+    return put_user(result, (unsigned long __user *) value);
 }
 
 static int
@@ -3916,7 +3914,7 @@
 } /* cy_break */
 
 static int
-get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
+get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon)
 {
 
     if(copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
@@ -3961,7 +3959,7 @@
 
 
 static int
-get_threshold(struct cyclades_port * info, unsigned long *value)
+get_threshold(struct cyclades_port * info, unsigned long __user *value)
 {
   unsigned char *base_addr;
   int card,channel,chip,index;
@@ -3978,7 +3976,7 @@
 		       + (cy_chip_offset[chip]<<index));
 
 	tmp = cy_readb(base_addr+(CyCOR3<<index)) & CyREC_FIFO;
-	return cy_put_user(tmp,value);
+	return put_user(tmp,value);
     } else {
 	// Nothing to do!
 	return 0;
@@ -3995,9 +3993,9 @@
 
 
 static int
-get_default_threshold(struct cyclades_port * info, unsigned long *value)
+get_default_threshold(struct cyclades_port * info, unsigned long __user *value)
 {
-    return cy_put_user(info->default_threshold,value);
+    return put_user(info->default_threshold,value);
 }/* get_default_threshold */
 
 
@@ -4029,7 +4027,7 @@
 
 
 static int
-get_timeout(struct cyclades_port * info, unsigned long *value)
+get_timeout(struct cyclades_port * info, unsigned long __user *value)
 {
   unsigned char *base_addr;
   int card,channel,chip,index;
@@ -4046,7 +4044,7 @@
 		       + (cy_chip_offset[chip]<<index));
 
 	tmp = cy_readb(base_addr+(CyRTPR<<index));
-	return cy_put_user(tmp,value);
+	return put_user(tmp,value);
     } else {
 	// Nothing to do!
 	return 0;
@@ -4063,9 +4061,9 @@
 
 
 static int
-get_default_timeout(struct cyclades_port * info, unsigned long *value)
+get_default_timeout(struct cyclades_port * info, unsigned long __user *value)
 {
-    return cy_put_user(info->default_timeout,value);
+    return put_user(info->default_timeout,value);
 }/* get_default_timeout */
 
 /*
@@ -4079,9 +4077,10 @@
 {
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   struct cyclades_icount cprev, cnow;		/* kernel counter temps */
-  struct serial_icounter_struct *p_cuser;	/* user space */
+  struct serial_icounter_struct __user *p_cuser;	/* user space */
   int ret_val = 0;
   unsigned long flags;
+  void __user *argp = (void __user *)arg;
 
     if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
 	return -ENODEV;
@@ -4093,31 +4092,31 @@
 
     switch (cmd) {
         case CYGETMON:
-            ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);
+            ret_val = get_mon_info(info, argp);
             break;
         case CYGETTHRESH:
-            ret_val = get_threshold(info, (unsigned long *)arg);
+            ret_val = get_threshold(info, argp);
             break;
         case CYSETTHRESH:
-            ret_val = set_threshold(info, (unsigned long)arg);
+            ret_val = set_threshold(info, arg);
             break;
         case CYGETDEFTHRESH:
-            ret_val = get_default_threshold(info, (unsigned long *)arg);
+            ret_val = get_default_threshold(info, argp);
             break;
         case CYSETDEFTHRESH:
-            ret_val = set_default_threshold(info, (unsigned long)arg);
+            ret_val = set_default_threshold(info, arg);
             break;
         case CYGETTIMEOUT:
-            ret_val = get_timeout(info, (unsigned long *)arg);
+            ret_val = get_timeout(info, argp);
             break;
         case CYSETTIMEOUT:
-            ret_val = set_timeout(info, (unsigned long)arg);
+            ret_val = set_timeout(info, arg);
             break;
         case CYGETDEFTIMEOUT:
-            ret_val = get_default_timeout(info, (unsigned long *)arg);
+            ret_val = get_default_timeout(info, argp);
             break;
         case CYSETDEFTIMEOUT:
-            ret_val = set_default_timeout(info, (unsigned long)arg);
+            ret_val = set_default_timeout(info, arg);
             break;
 	case CYSETRFLOW:
     	    info->rflow = (int)arg;
@@ -4134,7 +4133,7 @@
 	    ret_val = info->rtsdtr_inv;
 	    break;
 	case CYGETCARDINFO:
-            if (copy_to_user((void *)arg, (void *)&cy_card[info->card], 
+            if (copy_to_user(argp, &cy_card[info->card], 
 			sizeof (struct cyclades_card))) {
 		ret_val = -EFAULT;
 		break;
@@ -4161,13 +4160,13 @@
 	    ret_val = info->closing_wait / (HZ/100);
 	    break;
         case TIOCGSERIAL:
-            ret_val = get_serial_info(info, (struct serial_struct *) arg);
+            ret_val = get_serial_info(info, argp);
             break;
         case TIOCSSERIAL:
-            ret_val = set_serial_info(info, (struct serial_struct *) arg);
+            ret_val = set_serial_info(info, argp);
             break;
 	case TIOCSERGETLSR: /* Get line status register */
-	    ret_val = get_lsr_info(info, (unsigned int *) arg);
+	    ret_val = get_lsr_info(info, argp);
 	    break;
 	/*
 	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change 
@@ -4215,7 +4214,7 @@
 	    CY_LOCK(info, flags);
 	    cnow = info->icount;
 	    CY_UNLOCK(info, flags);
-	    p_cuser = (struct serial_icounter_struct *) arg;
+	    p_cuser = argp;
 	    ret_val = put_user(cnow.cts, &p_cuser->cts);
 	    if (ret_val) return ret_val;
 	    ret_val = put_user(cnow.dsr, &p_cuser->dsr);
diff -Nru a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
--- a/drivers/char/drm/sis_mm.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/drm/sis_mm.c	2004-06-23 19:04:27 -07:00
@@ -113,7 +113,7 @@
 
 	DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
 
-	DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
+	DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
 
 	return retval;
 }
@@ -130,7 +130,7 @@
 
 	if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
 		retval = DRM_ERR(EINVAL);
-	sis_free(fb.free);
+	sis_free((u32)fb.free);
 
 	DRM_DEBUG("free fb, offset = %lu\n", fb.free);
 
diff -Nru a/drivers/char/ds1286.c b/drivers/char/ds1286.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/ds1286.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,578 @@
+/*
+ * DS1286 Real Time Clock interface for Linux
+ *
+ * Copyright (C) 1998, 1999, 2000 Ralf Baechle
+ *
+ * Based on code written by Paul Gortmaker.
+ *
+ * This driver allows use of the real time clock (built into nearly all
+ * computers) from user space. It exports the /dev/rtc interface supporting
+ * various ioctl() and also the /proc/rtc pseudo-file for status
+ * information.
+ *
+ * The ioctls can be used to set the interrupt behaviour and generation rate
+ * from the RTC via IRQ 8. Then the /dev/rtc interface can be used to make
+ * use of these timer interrupts, be they interval or alarm based.
+ *
+ * The /dev/rtc interface will block on reads until an interrupt has been
+ * received. If a RTC interrupt has already happened, it will output an
+ * unsigned long and then block. The output value contains the interrupt
+ * status in the low byte and the number of interrupts since the last read
+ * in the remaining high bytes. The /dev/rtc interface can also be used with
+ * the select(2) call.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/ds1286.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/rtc.h>
+#include <linux/spinlock.h>
+#include <linux/bcd.h>
+#include <linux/proc_fs.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define DS1286_VERSION		"1.0"
+
+/*
+ *	We sponge a minor off of the misc major. No need slurping
+ *	up another valuable major dev number for this. If you add
+ *	an ioctl, make sure you don't conflict with SPARC's RTC
+ *	ioctls.
+ */
+
+static DECLARE_WAIT_QUEUE_HEAD(ds1286_wait);
+
+static ssize_t ds1286_read(struct file *file, char *buf,
+			size_t count, loff_t *ppos);
+
+static int ds1286_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg);
+
+static unsigned int ds1286_poll(struct file *file, poll_table *wait);
+
+static void ds1286_get_alm_time (struct rtc_time *alm_tm);
+static void ds1286_get_time(struct rtc_time *rtc_tm);
+static int ds1286_set_time(struct rtc_time *rtc_tm);
+
+static inline unsigned char ds1286_is_updating(void);
+
+static spinlock_t ds1286_lock = SPIN_LOCK_UNLOCKED;
+
+static int ds1286_read_proc(char *page, char **start, off_t off,
+                            int count, int *eof, void *data);
+
+/*
+ *	Bits in rtc_status. (7 bits of room for future expansion)
+ */
+
+#define RTC_IS_OPEN		0x01	/* means /dev/rtc is in use	*/
+#define RTC_TIMER_ON		0x02	/* missed irq timer active	*/
+
+static unsigned char ds1286_status;	/* bitmapped status byte.	*/
+
+static unsigned char days_in_mo[] = {
+	0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ *	Now all the various file operations that we export.
+ */
+
+static ssize_t ds1286_read(struct file *file, char *buf,
+                           size_t count, loff_t *ppos)
+{
+	return -EIO;
+}
+
+static int ds1286_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+	struct rtc_time wtime;
+
+	switch (cmd) {
+	case RTC_AIE_OFF:	/* Mask alarm int. enab. bit	*/
+	{
+		unsigned int flags;
+		unsigned char val;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		spin_lock_irqsave(&ds1286_lock, flags);
+		val = rtc_read(RTC_CMD);
+		val |=  RTC_TDM;
+		rtc_write(val, RTC_CMD);
+		spin_unlock_irqrestore(&ds1286_lock, flags);
+
+		return 0;
+	}
+	case RTC_AIE_ON:	/* Allow alarm interrupts.	*/
+	{
+		unsigned int flags;
+		unsigned char val;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		spin_lock_irqsave(&ds1286_lock, flags);
+		val = rtc_read(RTC_CMD);
+		val &=  ~RTC_TDM;
+		rtc_write(val, RTC_CMD);
+		spin_unlock_irqrestore(&ds1286_lock, flags);
+
+		return 0;
+	}
+	case RTC_WIE_OFF:	/* Mask watchdog int. enab. bit	*/
+	{
+		unsigned int flags;
+		unsigned char val;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		spin_lock_irqsave(&ds1286_lock, flags);
+		val = rtc_read(RTC_CMD);
+		val |= RTC_WAM;
+		rtc_write(val, RTC_CMD);
+		spin_unlock_irqrestore(&ds1286_lock, flags);
+
+		return 0;
+	}
+	case RTC_WIE_ON:	/* Allow watchdog interrupts.	*/
+	{
+		unsigned int flags;
+		unsigned char val;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		spin_lock_irqsave(&ds1286_lock, flags);
+		val = rtc_read(RTC_CMD);
+		val &= ~RTC_WAM;
+		rtc_write(val, RTC_CMD);
+		spin_unlock_irqrestore(&ds1286_lock, flags);
+
+		return 0;
+	}
+	case RTC_ALM_READ:	/* Read the present alarm time */
+	{
+		/*
+		 * This returns a struct rtc_time. Reading >= 0xc0
+		 * means "don't care" or "match all". Only the tm_hour,
+		 * tm_min, and tm_sec values are filled in.
+		 */
+
+		memset(&wtime, 0, sizeof(wtime));
+		ds1286_get_alm_time(&wtime);
+		break;
+	}
+	case RTC_ALM_SET:	/* Store a time into the alarm */
+	{
+		/*
+		 * This expects a struct rtc_time. Writing 0xff means
+		 * "don't care" or "match all". Only the tm_hour,
+		 * tm_min and tm_sec are used.
+		 */
+		unsigned char hrs, min, sec;
+		struct rtc_time alm_tm;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		if (copy_from_user(&alm_tm, (struct rtc_time*)arg,
+				   sizeof(struct rtc_time)))
+			return -EFAULT;
+
+		hrs = alm_tm.tm_hour;
+		min = alm_tm.tm_min;
+
+		if (hrs >= 24)
+			hrs = 0xff;
+
+		if (min >= 60)
+			min = 0xff;
+
+		BIN_TO_BCD(sec);
+		BIN_TO_BCD(min);
+		BIN_TO_BCD(hrs);
+
+		spin_lock(&ds1286_lock);
+		rtc_write(hrs, RTC_HOURS_ALARM);
+		rtc_write(min, RTC_MINUTES_ALARM);
+		spin_unlock(&ds1286_lock);
+
+		return 0;
+	}
+	case RTC_RD_TIME:	/* Read the time/date from RTC	*/
+	{
+		memset(&wtime, 0, sizeof(wtime));
+		ds1286_get_time(&wtime);
+		break;
+	}
+	case RTC_SET_TIME:	/* Set the RTC */
+	{
+		struct rtc_time rtc_tm;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
+				   sizeof(struct rtc_time)))
+			return -EFAULT;
+
+		return ds1286_set_time(&rtc_tm);
+	}
+	default:
+		return -EINVAL;
+	}
+	return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
+}
+
+/*
+ *	We enforce only one user at a time here with the open/close.
+ *	Also clear the previous interrupt data on an open, and clean
+ *	up things on a close.
+ */
+
+static int ds1286_open(struct inode *inode, struct file *file)
+{
+	spin_lock_irq(&ds1286_lock);
+
+	if (ds1286_status & RTC_IS_OPEN)
+		goto out_busy;
+
+	ds1286_status |= RTC_IS_OPEN;
+
+	spin_unlock_irq(&ds1286_lock);
+	return 0;
+
+out_busy:
+	spin_lock_irq(&ds1286_lock);
+	return -EBUSY;
+}
+
+static int ds1286_release(struct inode *inode, struct file *file)
+{
+	ds1286_status &= ~RTC_IS_OPEN;
+
+	return 0;
+}
+
+static unsigned int ds1286_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &ds1286_wait, wait);
+
+	return 0;
+}
+
+/*
+ *	The various file operations we support.
+ */
+
+static struct file_operations ds1286_fops = {
+	.llseek		= no_llseek,
+	.read		= ds1286_read,
+	.poll		= ds1286_poll,
+	.ioctl		= ds1286_ioctl,
+	.open		= ds1286_open,
+	.release	= ds1286_release,
+};
+
+static struct miscdevice ds1286_dev=
+{
+	.minor	= RTC_MINOR,
+	.name	= "rtc",
+	.fops	= &ds1286_fops,
+};
+
+static int __init ds1286_init(void)
+{
+	int err;
+
+	printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION);
+
+	err = misc_register(&ds1286_dev);
+	if (err)
+		goto out;
+
+	if (!create_proc_read_entry("driver/rtc", 0, 0, ds1286_read_proc, NULL)) {
+		err = -ENOMEM;
+
+		goto out_deregister;
+	}
+
+	return 0;
+
+out_deregister:
+	misc_deregister(&ds1286_dev);
+
+out:
+	return err;
+}
+
+static void __exit ds1286_exit(void)
+{
+	remove_proc_entry("driver/rtc", NULL);
+	misc_deregister(&ds1286_dev);
+}
+
+static char *days[] = {
+	"***", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+/*
+ *	Info exported via "/proc/rtc".
+ */
+static int ds1286_proc_output(char *buf)
+{
+	char *p, *s;
+	struct rtc_time tm;
+	unsigned char hundredth, month, cmd, amode;
+
+	p = buf;
+
+	ds1286_get_time(&tm);
+	hundredth = rtc_read(RTC_HUNDREDTH_SECOND);
+	BCD_TO_BIN(hundredth);
+
+	p += sprintf(p,
+	             "rtc_time\t: %02d:%02d:%02d.%02d\n"
+	             "rtc_date\t: %04d-%02d-%02d\n",
+		     tm.tm_hour, tm.tm_min, tm.tm_sec, hundredth,
+		     tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
+
+	/*
+	 * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will
+	 * match any value for that particular field. Values that are
+	 * greater than a valid time, but less than 0xc0 shouldn't appear.
+	 */
+	ds1286_get_alm_time(&tm);
+	p += sprintf(p, "alarm\t\t: %s ", days[tm.tm_wday]);
+	if (tm.tm_hour <= 24)
+		p += sprintf(p, "%02d:", tm.tm_hour);
+	else
+		p += sprintf(p, "**:");
+
+	if (tm.tm_min <= 59)
+		p += sprintf(p, "%02d\n", tm.tm_min);
+	else
+		p += sprintf(p, "**\n");
+
+	month = rtc_read(RTC_MONTH);
+	p += sprintf(p,
+	             "oscillator\t: %s\n"
+	             "square_wave\t: %s\n",
+	             (month & RTC_EOSC) ? "disabled" : "enabled",
+	             (month & RTC_ESQW) ? "disabled" : "enabled");
+
+	amode = ((rtc_read(RTC_MINUTES_ALARM) & 0x80) >> 5) |
+	        ((rtc_read(RTC_HOURS_ALARM) & 0x80) >> 6) |
+	        ((rtc_read(RTC_DAY_ALARM) & 0x80) >> 7);
+	if (amode == 7)      s = "each minute";
+	else if (amode == 3) s = "minutes match";
+	else if (amode == 1) s = "hours and minutes match";
+	else if (amode == 0) s = "days, hours and minutes match";
+	else                 s = "invalid";
+	p += sprintf(p, "alarm_mode\t: %s\n", s);
+
+	cmd = rtc_read(RTC_CMD);
+	p += sprintf(p,
+	             "alarm_enable\t: %s\n"
+	             "wdog_alarm\t: %s\n"
+	             "alarm_mask\t: %s\n"
+	             "wdog_alarm_mask\t: %s\n"
+	             "interrupt_mode\t: %s\n"
+	             "INTB_mode\t: %s_active\n"
+	             "interrupt_pins\t: %s\n",
+		     (cmd & RTC_TDF) ? "yes" : "no",
+		     (cmd & RTC_WAF) ? "yes" : "no",
+		     (cmd & RTC_TDM) ? "disabled" : "enabled",
+		     (cmd & RTC_WAM) ? "disabled" : "enabled",
+		     (cmd & RTC_PU_LVL) ? "pulse" : "level",
+		     (cmd & RTC_IBH_LO) ? "low" : "high",
+	             (cmd & RTC_IPSW) ? "unswapped" : "swapped");
+
+	return  p - buf;
+}
+
+static int ds1286_read_proc(char *page, char **start, off_t off,
+                         int count, int *eof, void *data)
+{
+	int len = ds1286_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;
+}
+
+/*
+ * Returns true if a clock update is in progress
+ */
+static inline unsigned char ds1286_is_updating(void)
+{
+	return rtc_read(RTC_CMD) & RTC_TE;
+}
+
+
+static void ds1286_get_time(struct rtc_time *rtc_tm)
+{
+	unsigned char save_control;
+	unsigned int flags;
+	unsigned long uip_watchdog = jiffies;
+
+	/*
+	 * read RTC once any update in progress is done. The update
+	 * can take just over 2ms. We wait 10 to 20ms. There is no need to
+	 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
+	 * If you need to know *exactly* when a second has started, enable
+	 * periodic update complete interrupts, (via ioctl) and then
+	 * immediately read /dev/rtc which will block until you get the IRQ.
+	 * Once the read clears, read the RTC time (again via ioctl). Easy.
+	 */
+
+	if (ds1286_is_updating() != 0)
+		while (jiffies - uip_watchdog < 2*HZ/100)
+			barrier();
+
+	/*
+	 * Only the values that we read from the RTC are set. We leave
+	 * tm_wday, tm_yday and tm_isdst untouched. Even though the
+	 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+	 * by the RTC when initially set to a non-zero value.
+	 */
+	spin_lock_irqsave(&ds1286_lock, flags);
+	save_control = rtc_read(RTC_CMD);
+	rtc_write((save_control|RTC_TE), RTC_CMD);
+
+	rtc_tm->tm_sec = rtc_read(RTC_SECONDS);
+	rtc_tm->tm_min = rtc_read(RTC_MINUTES);
+	rtc_tm->tm_hour = rtc_read(RTC_HOURS) & 0x3f;
+	rtc_tm->tm_mday = rtc_read(RTC_DATE);
+	rtc_tm->tm_mon = rtc_read(RTC_MONTH) & 0x1f;
+	rtc_tm->tm_year = rtc_read(RTC_YEAR);
+
+	rtc_write(save_control, RTC_CMD);
+	spin_unlock_irqrestore(&ds1286_lock, flags);
+
+	BCD_TO_BIN(rtc_tm->tm_sec);
+	BCD_TO_BIN(rtc_tm->tm_min);
+	BCD_TO_BIN(rtc_tm->tm_hour);
+	BCD_TO_BIN(rtc_tm->tm_mday);
+	BCD_TO_BIN(rtc_tm->tm_mon);
+	BCD_TO_BIN(rtc_tm->tm_year);
+
+	/*
+	 * Account for differences between how the RTC uses the values
+	 * and how they are defined in a struct rtc_time;
+	 */
+	if (rtc_tm->tm_year < 45)
+		rtc_tm->tm_year += 30;
+	if ((rtc_tm->tm_year += 40) < 70)
+		rtc_tm->tm_year += 100;
+
+	rtc_tm->tm_mon--;
+}
+
+static int ds1286_set_time(struct rtc_time *rtc_tm)
+{
+	unsigned char mon, day, hrs, min, sec, leap_yr;
+	unsigned char save_control;
+	unsigned int yrs, flags;
+
+
+	yrs = rtc_tm->tm_year + 1900;
+	mon = rtc_tm->tm_mon + 1;   /* tm_mon starts at zero */
+	day = rtc_tm->tm_mday;
+	hrs = rtc_tm->tm_hour;
+	min = rtc_tm->tm_min;
+	sec = 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 -= 1940) > 255)    /* They are unsigned */
+		return -EINVAL;
+
+	if (yrs >= 100)
+		yrs -= 100;
+
+	BIN_TO_BCD(sec);
+	BIN_TO_BCD(min);
+	BIN_TO_BCD(hrs);
+	BIN_TO_BCD(day);
+	BIN_TO_BCD(mon);
+	BIN_TO_BCD(yrs);
+
+	spin_lock_irqsave(&ds1286_lock, flags);
+	save_control = rtc_read(RTC_CMD);
+	rtc_write((save_control|RTC_TE), RTC_CMD);
+
+	rtc_write(yrs, RTC_YEAR);
+	rtc_write(mon, RTC_MONTH);
+	rtc_write(day, RTC_DATE);
+	rtc_write(hrs, RTC_HOURS);
+	rtc_write(min, RTC_MINUTES);
+	rtc_write(sec, RTC_SECONDS);
+	rtc_write(0, RTC_HUNDREDTH_SECOND);
+
+	rtc_write(save_control, RTC_CMD);
+	spin_unlock_irqrestore(&ds1286_lock, flags);
+
+	return 0;
+}
+
+static void ds1286_get_alm_time(struct rtc_time *alm_tm)
+{
+	unsigned char cmd;
+	unsigned int flags;
+
+	/*
+	 * Only the values that we read from the RTC are set. That
+	 * means only tm_wday, tm_hour, tm_min.
+	 */
+	spin_lock_irqsave(&ds1286_lock, flags);
+	alm_tm->tm_min = rtc_read(RTC_MINUTES_ALARM) & 0x7f;
+	alm_tm->tm_hour = rtc_read(RTC_HOURS_ALARM)  & 0x1f;
+	alm_tm->tm_wday = rtc_read(RTC_DAY_ALARM)    & 0x07;
+	cmd = rtc_read(RTC_CMD);
+	spin_unlock_irqrestore(&ds1286_lock, flags);
+
+	BCD_TO_BIN(alm_tm->tm_min);
+	BCD_TO_BIN(alm_tm->tm_hour);
+	alm_tm->tm_sec = 0;
+}
+
+module_init(ds1286_init);
+module_exit(ds1286_exit);
+
+MODULE_AUTHOR("Ralf Baechle");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(RTC_MINOR);
diff -Nru a/drivers/char/hpet.c b/drivers/char/hpet.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/hpet.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,1076 @@
+/*
+ * Intel & MS High Precision Event Timer Implementation.
+ * Contributors:
+ *	Venki Pallipadi
+ * 	Bob Picco
+ */
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/major.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/sysctl.h>
+#include <linux/wait.h>
+#include <linux/bcd.h>
+#include <linux/seq_file.h>
+
+#include <asm/current.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/div64.h>
+
+#include <linux/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <linux/hpet.h>
+
+/*
+ * The High Precision Event Timer driver.
+ * This driver is closely modelled after the rtc.c driver.
+ * http://www.intel.com/labs/platcomp/hpet/hpetspec.htm
+ */
+#define	HPET_USER_FREQ	(64)
+#define	HPET_DRIFT	(500)
+
+static u32 hpet_ntimer, hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
+
+/* A lock for concurrent access by app and isr hpet activity. */
+static spinlock_t hpet_lock = SPIN_LOCK_UNLOCKED;
+/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
+static spinlock_t hpet_task_lock = SPIN_LOCK_UNLOCKED;
+
+struct hpet_dev {
+	struct hpets *hd_hpets;
+	struct hpet *hd_hpet;
+	struct hpet_timer *hd_timer;
+	unsigned long hd_ireqfreq;
+	unsigned long hd_irqdata;
+	wait_queue_head_t hd_waitqueue;
+	struct fasync_struct *hd_async_queue;
+	struct hpet_task *hd_task;
+	unsigned int hd_flags;
+	unsigned int hd_irq;
+	unsigned int hd_hdwirq;
+};
+
+struct hpets {
+	struct hpets *hp_next;
+	struct hpet *hp_hpet;
+	unsigned long hp_period;
+	unsigned long hp_delta;
+	unsigned int hp_ntimer;
+	unsigned int hp_which;
+	struct hpet_dev hp_dev[1];
+};
+
+static struct hpets *hpets;
+
+#define	HPET_OPEN		0x0001
+#define	HPET_IE			0x0002	/* interrupt enabled */
+#define	HPET_PERIODIC		0x0004
+
+#if BITS_PER_LONG == 64
+#define	write_counter(V, MC)	writeq(V, MC)
+#define	read_counter(MC)	readq(MC)
+#else
+#define	write_counter(V, MC) 	writel(V, MC)
+#define	read_counter(MC)	readl(MC)
+#endif
+
+#ifndef readq
+static unsigned long long __inline readq(void *addr)
+{
+	return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL);
+}
+#endif
+
+#ifndef writeq
+static void __inline writeq(unsigned long long v, void *addr)
+{
+	writel(v & 0xffffffff, addr);
+	writel(v >> 32, addr + 4);
+}
+#endif
+
+static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs)
+{
+	struct hpet_dev *devp;
+	unsigned long isr;
+
+	devp = data;
+
+	spin_lock(&hpet_lock);
+	devp->hd_irqdata++;
+
+	/*
+	 * For non-periodic timers, increment the accumulator.
+	 * This has the effect of treating non-periodic like periodic.
+	 */
+	if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) {
+		unsigned long m, t;
+
+		t = devp->hd_ireqfreq;
+		m = read_counter(&devp->hd_hpet->hpet_mc);
+		write_counter(t + m + devp->hd_hpets->hp_delta,
+			      &devp->hd_timer->hpet_compare);
+	}
+
+	isr = (1 << (devp - devp->hd_hpets->hp_dev));
+	writeq(isr, &devp->hd_hpet->hpet_isr);
+	spin_unlock(&hpet_lock);
+
+	spin_lock(&hpet_task_lock);
+	if (devp->hd_task)
+		devp->hd_task->ht_func(devp->hd_task->ht_data);
+	spin_unlock(&hpet_task_lock);
+
+	wake_up_interruptible(&devp->hd_waitqueue);
+
+	kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN);
+
+	return IRQ_HANDLED;
+}
+
+static int hpet_open(struct inode *inode, struct file *file)
+{
+	struct hpet_dev *devp;
+	struct hpets *hpetp;
+	int i;
+
+	spin_lock_irq(&hpet_lock);
+
+	for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
+		for (i = 0; i < hpetp->hp_ntimer; i++)
+			if (hpetp->hp_dev[i].hd_flags & HPET_OPEN
+			    || hpetp->hp_dev[i].hd_task)
+				continue;
+			else {
+				devp = &hpetp->hp_dev[i];
+				break;
+			}
+
+	if (!devp) {
+		spin_unlock_irq(&hpet_lock);
+		return -EBUSY;
+	}
+
+	file->private_data = devp;
+	devp->hd_irqdata = 0;
+	devp->hd_flags |= HPET_OPEN;
+	spin_unlock_irq(&hpet_lock);
+
+	return 0;
+}
+
+static ssize_t
+hpet_read(struct file *file, char *buf, size_t count, loff_t * ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long data;
+	ssize_t retval;
+	struct hpet_dev *devp;
+
+	devp = file->private_data;
+	if (!devp->hd_ireqfreq)
+		return -EIO;
+
+	if (count < sizeof(unsigned long))
+		return -EINVAL;
+
+	add_wait_queue(&devp->hd_waitqueue, &wait);
+
+	do {
+		__set_current_state(TASK_INTERRUPTIBLE);
+
+		spin_lock_irq(&hpet_lock);
+		data = devp->hd_irqdata;
+		devp->hd_irqdata = 0;
+		spin_unlock_irq(&hpet_lock);
+
+		if (data)
+			break;
+		else if (file->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto out;
+		} else if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			goto out;
+		}
+
+		schedule();
+
+	} while (1);
+
+	retval = put_user(data, (unsigned long *)buf);
+	if (!retval)
+		retval = sizeof(unsigned long);
+      out:
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&devp->hd_waitqueue, &wait);
+
+	return retval;
+}
+
+static unsigned int hpet_poll(struct file *file, poll_table * wait)
+{
+	unsigned long v;
+	struct hpet_dev *devp;
+
+	devp = file->private_data;
+
+	if (!devp->hd_ireqfreq)
+		return 0;
+
+	poll_wait(file, &devp->hd_waitqueue, wait);
+
+	spin_lock_irq(&hpet_lock);
+	v = devp->hd_irqdata;
+	spin_unlock_irq(&hpet_lock);
+
+	if (v != 0)
+		return POLLIN | POLLRDNORM;
+
+	return 0;
+}
+
+static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
+{
+#ifdef	CONFIG_HPET_NOMMAP
+	return -ENOSYS;
+#else
+	struct hpet_dev *devp;
+	unsigned long addr;
+
+	if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
+		return -EINVAL;
+
+	if (vma->vm_flags & VM_WRITE)
+		return -EPERM;
+
+	devp = file->private_data;
+	addr = (unsigned long)devp->hd_hpet;
+
+	if (addr & (PAGE_SIZE - 1))
+		return -ENOSYS;
+
+	vma->vm_flags |= VM_IO;
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	addr = __pa(addr);
+
+	if (remap_page_range
+	    (vma, vma->vm_start, addr, PAGE_SIZE, vma->vm_page_prot)) {
+		printk(KERN_ERR "remap_page_range failed in hpet.c\n");
+		return -EAGAIN;
+	}
+
+	return 0;
+#endif
+}
+
+static int hpet_fasync(int fd, struct file *file, int on)
+{
+	struct hpet_dev *devp;
+
+	devp = file->private_data;
+
+	if (fasync_helper(fd, file, on, &devp->hd_async_queue) >= 0)
+		return 0;
+	else
+		return -EIO;
+}
+
+static int hpet_release(struct inode *inode, struct file *file)
+{
+	struct hpet_dev *devp;
+	struct hpet_timer *timer;
+	int irq = 0;
+
+	devp = file->private_data;
+	timer = devp->hd_timer;
+
+	spin_lock_irq(&hpet_lock);
+
+	writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
+	       &timer->hpet_config);
+
+	irq = devp->hd_irq;
+	devp->hd_irq = 0;
+
+	devp->hd_ireqfreq = 0;
+
+	if (devp->hd_flags & HPET_PERIODIC
+	    && readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) {
+		unsigned long v;
+
+		v = readq(&timer->hpet_config);
+		v ^= Tn_TYPE_CNF_MASK;
+		writeq(v, &timer->hpet_config);
+	}
+
+	devp->hd_flags &= ~(HPET_OPEN | HPET_IE | HPET_PERIODIC);
+	spin_unlock_irq(&hpet_lock);
+
+	if (irq)
+		free_irq(irq, devp);
+
+	if (file->f_flags & FASYNC)
+		hpet_fasync(-1, file, 0);
+
+	file->private_data = 0;
+	return 0;
+}
+
+static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int);
+
+static int
+hpet_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	   unsigned long arg)
+{
+	struct hpet_dev *devp;
+
+	devp = file->private_data;
+	return hpet_ioctl_common(devp, cmd, arg, 0);
+}
+
+static int hpet_ioctl_ieon(struct hpet_dev *devp)
+{
+	struct hpet_timer *timer;
+	struct hpet *hpet;
+	struct hpets *hpetp;
+	int irq;
+	unsigned long g, v, t, m;
+	unsigned long flags, isr;
+
+	timer = devp->hd_timer;
+	hpet = devp->hd_hpet;
+	hpetp = devp->hd_hpets;
+
+	v = readq(&timer->hpet_config);
+	spin_lock_irq(&hpet_lock);
+
+	if (devp->hd_flags & HPET_IE) {
+		spin_unlock_irq(&hpet_lock);
+		return -EBUSY;
+	}
+
+	devp->hd_flags |= HPET_IE;
+	spin_unlock_irq(&hpet_lock);
+
+	t = readq(&timer->hpet_config);
+	irq = devp->hd_hdwirq;
+
+	if (irq) {
+		char name[7];
+
+		sprintf(name, "hpet%d", (int)(devp - hpetp->hp_dev));
+
+		if (request_irq
+		    (irq, hpet_interrupt, SA_INTERRUPT, name, (void *)devp)) {
+			printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
+			irq = 0;
+		}
+	}
+
+	if (irq == 0) {
+		spin_lock_irq(&hpet_lock);
+		devp->hd_flags ^= HPET_IE;
+		spin_unlock_irq(&hpet_lock);
+		return -EIO;
+	}
+
+	devp->hd_irq = irq;
+	t = devp->hd_ireqfreq;
+	v = readq(&timer->hpet_config);
+	g = v | Tn_INT_ENB_CNF_MASK;
+
+	if (devp->hd_flags & HPET_PERIODIC) {
+		write_counter(t, &timer->hpet_compare);
+		g |= Tn_TYPE_CNF_MASK;
+		v |= Tn_TYPE_CNF_MASK;
+		writeq(v, &timer->hpet_config);
+		v |= Tn_VAL_SET_CNF_MASK;
+		writeq(v, &timer->hpet_config);
+		local_irq_save(flags);
+		m = read_counter(&hpet->hpet_mc);
+		write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
+	} else {
+		local_irq_save(flags);
+		m = read_counter(&hpet->hpet_mc);
+		write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
+	}
+
+	isr = (1 << (devp - hpets->hp_dev));
+	writeq(isr, &hpet->hpet_isr);
+	writeq(g, &timer->hpet_config);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static inline unsigned long hpet_time_div(unsigned long dis)
+{
+	unsigned long long m = 1000000000000000ULL;
+
+	do_div(m, dis);
+
+	return (unsigned long)m;
+}
+
+static int
+hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
+{
+	struct hpet_timer *timer;
+	struct hpet *hpet;
+	struct hpets *hpetp;
+	int err;
+	unsigned long v;
+
+	switch (cmd) {
+	case HPET_IE_OFF:
+	case HPET_INFO:
+	case HPET_EPI:
+	case HPET_DPI:
+	case HPET_IRQFREQ:
+		timer = devp->hd_timer;
+		hpet = devp->hd_hpet;
+		hpetp = devp->hd_hpets;
+		break;
+	case HPET_IE_ON:
+		return hpet_ioctl_ieon(devp);
+	default:
+		return -EINVAL;
+	}
+
+	err = 0;
+
+	switch (cmd) {
+	case HPET_IE_OFF:
+		if ((devp->hd_flags & HPET_IE) == 0)
+			break;
+		v = readq(&timer->hpet_config);
+		v &= ~Tn_INT_ENB_CNF_MASK;
+		writeq(v, &timer->hpet_config);
+		if (devp->hd_irq) {
+			free_irq(devp->hd_irq, devp);
+			devp->hd_irq = 0;
+		}
+		devp->hd_flags ^= HPET_IE;
+		break;
+	case HPET_INFO:
+		{
+			struct hpet_info info;
+
+			info.hi_ireqfreq = hpet_time_div(hpetp->hp_period *
+							 devp->hd_ireqfreq);
+			info.hi_flags =
+			    readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
+			info.hi_hpet = devp->hd_hpets->hp_which;
+			info.hi_timer = devp - devp->hd_hpets->hp_dev;
+			if (copy_to_user((void *)arg, &info, sizeof(info)))
+				err = -EFAULT;
+			break;
+		}
+	case HPET_EPI:
+		v = readq(&timer->hpet_config);
+		if ((v & Tn_PER_INT_CAP_MASK) == 0) {
+			err = -ENXIO;
+			break;
+		}
+		devp->hd_flags |= HPET_PERIODIC;
+		break;
+	case HPET_DPI:
+		v = readq(&timer->hpet_config);
+		if ((v & Tn_PER_INT_CAP_MASK) == 0) {
+			err = -ENXIO;
+			break;
+		}
+		if (devp->hd_flags & HPET_PERIODIC &&
+		    readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) {
+			v = readq(&timer->hpet_config);
+			v ^= Tn_TYPE_CNF_MASK;
+			writeq(v, &timer->hpet_config);
+		}
+		devp->hd_flags &= ~HPET_PERIODIC;
+		break;
+	case HPET_IRQFREQ:
+		if (!kernel && (arg > hpet_max_freq) &&
+		    !capable(CAP_SYS_RESOURCE)) {
+			err = -EACCES;
+			break;
+		}
+
+		if (arg & (arg - 1)) {
+			err = -EINVAL;
+			break;
+		}
+
+		devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg);
+	}
+
+	return err;
+}
+
+static struct file_operations hpet_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.read = hpet_read,
+	.poll = hpet_poll,
+	.ioctl = hpet_ioctl,
+	.open = hpet_open,
+	.release = hpet_release,
+	.fasync = hpet_fasync,
+	.mmap = hpet_mmap,
+};
+
+EXPORT_SYMBOL(hpet_alloc);
+EXPORT_SYMBOL(hpet_register);
+EXPORT_SYMBOL(hpet_unregister);
+EXPORT_SYMBOL(hpet_control);
+
+int hpet_register(struct hpet_task *tp, int periodic)
+{
+	unsigned int i;
+	u64 mask;
+	struct hpet_timer *timer;
+	struct hpet_dev *devp;
+	struct hpets *hpetp;
+
+	switch (periodic) {
+	case 1:
+		mask = Tn_PER_INT_CAP_MASK;
+		break;
+	case 0:
+		mask = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irq(&hpet_task_lock);
+	spin_lock(&hpet_lock);
+
+	for (devp = 0, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
+		for (timer = hpetp->hp_hpet->hpet_timers, i = 0;
+		     i < hpetp->hp_ntimer; i++, timer++) {
+			if ((readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK)
+			    != mask)
+				continue;
+
+			devp = &hpetp->hp_dev[i];
+
+			if (devp->hd_flags & HPET_OPEN || devp->hd_task) {
+				devp = 0;
+				continue;
+			}
+
+			tp->ht_opaque = devp;
+			devp->hd_task = tp;
+			break;
+		}
+
+	spin_unlock(&hpet_lock);
+	spin_unlock_irq(&hpet_task_lock);
+
+	if (tp->ht_opaque)
+		return 0;
+	else
+		return -EBUSY;
+}
+
+static inline int hpet_tpcheck(struct hpet_task *tp)
+{
+	struct hpet_dev *devp;
+	struct hpets *hpetp;
+
+	devp = tp->ht_opaque;
+
+	if (!devp)
+		return -ENXIO;
+
+	for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
+		if (devp >= hpetp->hp_dev
+		    && devp < (hpetp->hp_dev + hpetp->hp_ntimer)
+		    && devp->hd_hpet == hpetp->hp_hpet)
+			return 0;
+
+	return -ENXIO;
+}
+
+int hpet_unregister(struct hpet_task *tp)
+{
+	struct hpet_dev *devp;
+	struct hpet_timer *timer;
+	int err;
+
+	if ((err = hpet_tpcheck(tp)))
+		return err;
+
+	spin_lock_irq(&hpet_task_lock);
+	spin_lock(&hpet_lock);
+
+	devp = tp->ht_opaque;
+	if (devp->hd_task != tp) {
+		spin_unlock(&hpet_lock);
+		spin_unlock_irq(&hpet_task_lock);
+		return -ENXIO;
+	}
+
+	timer = devp->hd_timer;
+	writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
+	       &timer->hpet_config);
+	devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC);
+	devp->hd_task = 0;
+	spin_unlock(&hpet_lock);
+	spin_unlock_irq(&hpet_task_lock);
+
+	return 0;
+}
+
+int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
+{
+	struct hpet_dev *devp;
+	int err;
+
+	if ((err = hpet_tpcheck(tp)))
+		return err;
+
+	spin_lock_irq(&hpet_lock);
+	devp = tp->ht_opaque;
+	if (devp->hd_task != tp) {
+		spin_unlock_irq(&hpet_lock);
+		return -ENXIO;
+	}
+	spin_unlock_irq(&hpet_lock);
+	return hpet_ioctl_common(devp, cmd, arg, 1);
+}
+
+#ifdef	CONFIG_TIME_INTERPOLATION
+
+static unsigned long hpet_offset, last_wall_hpet;
+static long hpet_nsecs_per_cycle, hpet_cycles_per_sec;
+
+static unsigned long hpet_getoffset(void)
+{
+	return hpet_offset + (read_counter(&hpets->hp_hpet->hpet_mc) -
+			      last_wall_hpet) * hpet_nsecs_per_cycle;
+}
+
+static void hpet_update(long delta)
+{
+	unsigned long mc;
+	unsigned long offset;
+
+	mc = read_counter(&hpets->hp_hpet->hpet_mc);
+	offset = hpet_offset + (mc - last_wall_hpet) * hpet_nsecs_per_cycle;
+
+	if (delta < 0 || (unsigned long)delta < offset)
+		hpet_offset = offset - delta;
+	else
+		hpet_offset = 0;
+	last_wall_hpet = mc;
+}
+
+static void hpet_reset(void)
+{
+	hpet_offset = 0;
+	last_wall_hpet = read_counter(&hpets->hp_hpet->hpet_mc);
+}
+
+static struct time_interpolator hpet_interpolator = {
+	.get_offset = hpet_getoffset,
+	.update = hpet_update,
+	.reset = hpet_reset
+};
+
+#endif
+
+static ctl_table hpet_table[] = {
+	{
+	 .ctl_name = 1,
+	 .procname = "max-user-freq",
+	 .data = &hpet_max_freq,
+	 .maxlen = sizeof(int),
+	 .mode = 0644,
+	 .proc_handler = &proc_dointvec,
+	 },
+	{.ctl_name = 0}
+};
+
+static ctl_table hpet_root[] = {
+	{
+	 .ctl_name = 1,
+	 .procname = "hpet",
+	 .maxlen = 0,
+	 .mode = 0555,
+	 .child = hpet_table,
+	 },
+	{.ctl_name = 0}
+};
+
+static ctl_table dev_root[] = {
+	{
+	 .ctl_name = CTL_DEV,
+	 .procname = "dev",
+	 .maxlen = 0,
+	 .mode = 0555,
+	 .child = hpet_root,
+	 },
+	{.ctl_name = 0}
+};
+
+static struct ctl_table_header *sysctl_header;
+
+static void *hpet_start(struct seq_file *s, loff_t * pos)
+{
+	struct hpets *hpetp;
+	loff_t n;
+
+	for (n = *pos, hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
+		if (!n--)
+			return hpetp;
+
+	return 0;
+}
+
+static void *hpet_next(struct seq_file *s, void *v, loff_t * pos)
+{
+	struct hpets *hpetp;
+
+	hpetp = v;
+	++*pos;
+	return hpetp->hp_next;
+}
+
+static void hpet_stop(struct seq_file *s, void *v)
+{
+	return;
+}
+
+static int hpet_show(struct seq_file *s, void *v)
+{
+	struct hpets *hpetp;
+	struct hpet *hpet;
+	u64 cap, vendor, period;
+
+	hpetp = v;
+	hpet = hpetp->hp_hpet;
+
+	cap = readq(&hpet->hpet_cap);
+	period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
+	    HPET_COUNTER_CLK_PERIOD_SHIFT;
+	vendor = (cap & HPET_VENDOR_ID_MASK) >> HPET_VENDOR_ID_SHIFT;
+
+	seq_printf(s,
+		   "HPET%d period = %d 10**-15  vendor = 0x%x number timer = %d\n",
+		   hpetp->hp_which, (u32) period, (u32) vendor,
+		   hpetp->hp_ntimer);
+
+	return 0;
+}
+
+static struct seq_operations hpet_seq_ops = {
+	.start = hpet_start,
+	.next = hpet_next,
+	.stop = hpet_stop,
+	.show = hpet_show
+};
+
+static int hpet_proc_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &hpet_seq_ops);
+}
+
+static struct file_operations hpet_proc_fops = {
+	.open = hpet_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release
+};
+
+/*
+ * Adjustment for when arming the timer with
+ * initial conditions.  That is, main counter
+ * ticks expired before interrupts are enabled.
+ */
+#define	TICK_CALIBRATE	(1000UL)
+
+static unsigned long __init hpet_calibrate(struct hpets *hpetp)
+{
+	struct hpet_timer *timer;
+	unsigned long t, m, count, i, flags, start;
+	struct hpet_dev *devp;
+	int j;
+	struct hpet *hpet;
+
+	for (timer = 0, j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer;
+	     j++, devp++)
+		if ((devp->hd_flags & HPET_OPEN) == 0) {
+			timer = devp->hd_timer;
+			break;
+		}
+
+	if (!timer)
+		return 0;
+
+	hpet = hpets->hp_hpet;
+	t = read_counter(&timer->hpet_compare);
+
+	i = 0;
+	count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE);
+
+	local_irq_save(flags);
+
+	start = read_counter(&hpet->hpet_mc);
+
+	do {
+		m = read_counter(&hpet->hpet_mc);
+		write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
+	} while (i++, (m - start) < count);
+
+	local_irq_restore(flags);
+
+	return (m - start) / i;
+}
+
+int __init hpet_alloc(struct hpet_data *hdp)
+{
+	u64 cap, mcfg;
+	struct hpet_dev *devp;
+	u32 i, ntimer;
+	struct hpets *hpetp;
+	size_t siz;
+	struct hpet *hpet;
+	static struct hpets *last __initdata = (struct hpets *)0;
+
+	/*
+	 * hpet_alloc can be called by platform dependent code.
+	 * if platform dependent code has allocated the hpet
+	 * ACPI also reports hpet, then we catch it here.
+	 */
+	for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
+		if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
+			return 0;
+
+	siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
+				      sizeof(struct hpet_dev));
+
+	hpetp = kmalloc(siz, GFP_KERNEL);
+
+	if (!hpetp)
+		return -ENOMEM;
+
+	memset(hpetp, 0, siz);
+
+	hpetp->hp_which = hpet_nhpet++;
+	hpetp->hp_hpet = (struct hpet *)hdp->hd_address;
+
+	hpetp->hp_ntimer = hdp->hd_nirqs;
+
+	for (i = 0; i < hdp->hd_nirqs; i++)
+		hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i];
+
+	hpet = hpetp->hp_hpet;
+
+	cap = readq(&hpet->hpet_cap);
+
+	ntimer = ((cap & HPET_NUM_TIM_CAP_MASK) >> HPET_NUM_TIM_CAP_SHIFT) + 1;
+
+	if (hpetp->hp_ntimer != ntimer) {
+		printk(KERN_WARNING "hpet: number irqs doesn't agree"
+		       " with number of timers\n");
+		kfree(hpetp);
+		return -ENODEV;
+	}
+
+	if (last)
+		last->hp_next = hpetp;
+	else
+		hpets = hpetp;
+
+	last = hpetp;
+
+	hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
+	    HPET_COUNTER_CLK_PERIOD_SHIFT;
+
+	mcfg = readq(&hpet->hpet_config);
+	if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
+		write_counter(0L, &hpet->hpet_mc);
+		mcfg |= HPET_ENABLE_CNF_MASK;
+		writeq(mcfg, &hpet->hpet_config);
+	}
+
+	for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer;
+	     i++, hpet_ntimer++, devp++) {
+		unsigned long v;
+		struct hpet_timer *timer;
+
+		timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
+		v = readq(&timer->hpet_config);
+
+		devp->hd_hpets = hpetp;
+		devp->hd_hpet = hpet;
+		devp->hd_timer = timer;
+
+		/*
+		 * If the timer was reserved by platform code,
+		 * then make timer unavailable for opens.
+		 */
+		if (hdp->hd_state & (1 << i)) {
+			devp->hd_flags = HPET_OPEN;
+			continue;
+		}
+
+		init_waitqueue_head(&devp->hd_waitqueue);
+	}
+
+	hpetp->hp_delta = hpet_calibrate(hpetp);
+
+	return 0;
+}
+
+static acpi_status __init hpet_resources(struct acpi_resource *res, void *data)
+{
+	struct hpet_data *hdp;
+	acpi_status status;
+	struct acpi_resource_address64 addr;
+	struct hpets *hpetp;
+
+	hdp = data;
+
+	status = acpi_resource_to_address64(res, &addr);
+
+	if (ACPI_SUCCESS(status)) {
+		unsigned long size;
+
+		size = addr.max_address_range - addr.min_address_range + 1;
+		hdp->hd_address =
+		    (unsigned long)ioremap(addr.min_address_range, size);
+
+		for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
+			if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
+				return -EBUSY;
+	} else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
+		struct acpi_resource_ext_irq *irqp;
+		int i;
+
+		irqp = &res->data.extended_irq;
+
+		if (irqp->number_of_interrupts > 0) {
+			hdp->hd_nirqs = irqp->number_of_interrupts;
+
+			for (i = 0; i < hdp->hd_nirqs; i++)
+#ifdef	CONFIG_IA64
+				hdp->hd_irq[i] =
+				    acpi_register_gsi(irqp->interrupts[i],
+						      irqp->edge_level,
+						      irqp->active_high_low);
+#else
+				hdp->hd_irq[i] = irqp->interrupts[i];
+#endif
+		}
+	}
+
+	return AE_OK;
+}
+
+static int __init hpet_acpi_add(struct acpi_device *device)
+{
+	acpi_status result;
+	struct hpet_data data;
+
+	memset(&data, 0, sizeof(data));
+
+	result =
+	    acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+				hpet_resources, &data);
+
+	if (ACPI_FAILURE(result))
+		return -ENODEV;
+
+	if (!data.hd_address || !data.hd_nirqs) {
+		printk("%s: no address or irqs in _CRS\n", __FUNCTION__);
+		return -ENODEV;
+	}
+
+	return hpet_alloc(&data);
+}
+
+static int __init hpet_acpi_remove(struct acpi_device *device, int type)
+{
+	return 0;
+}
+
+static struct acpi_driver hpet_acpi_driver __initdata = {
+	.name = "hpet",
+	.class = "",
+	.ids = "PNP0103",
+	.ops = {
+		.add = hpet_acpi_add,
+		.remove = hpet_acpi_remove,
+		},
+};
+
+static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops };
+
+static int __init hpet_init(void)
+{
+	struct proc_dir_entry *entry;
+
+	(void)acpi_bus_register_driver(&hpet_acpi_driver);
+
+	if (hpets) {
+		if (misc_register(&hpet_misc))
+			return -ENODEV;
+
+		entry = create_proc_entry("driver/hpet", 0, 0);
+
+		if (entry)
+			entry->proc_fops = &hpet_proc_fops;
+
+		sysctl_header = register_sysctl_table(dev_root, 0);
+
+#ifdef	CONFIG_TIME_INTERPOLATION
+		{
+			struct hpet *hpet;
+
+			hpet = hpets->hp_hpet;
+			hpet_cycles_per_sec = hpet_time_div(hpets->hp_period);
+			hpet_interpolator.frequency = hpet_cycles_per_sec;
+			hpet_interpolator.drift = hpet_cycles_per_sec *
+			    HPET_DRIFT / 1000000;
+			hpet_nsecs_per_cycle = 1000000000 / hpet_cycles_per_sec;
+			register_time_interpolator(&hpet_interpolator);
+		}
+#endif
+		return 0;
+	} else
+		return -ENODEV;
+}
+
+static void __exit hpet_exit(void)
+{
+	acpi_bus_unregister_driver(&hpet_acpi_driver);
+
+	if (hpets) {
+		unregister_sysctl_table(sysctl_header);
+		remove_proc_entry("driver/hpet", NULL);
+	}
+
+	return;
+}
+
+module_init(hpet_init);
+module_exit(hpet_exit);
+MODULE_AUTHOR("Bob Picco <Robert.Picco@hp.com>");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/ip27-rtc.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,327 @@
+/*
+ *	Driver for the SGS-Thomson M48T35 Timekeeper RAM chip
+ *
+ *	Real Time Clock interface for Linux
+ *
+ *	TODO: Implement periodic interrupts.
+ *
+ *	Copyright (C) 2000 Silicon Graphics, Inc.
+ *	Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ *
+ *	Based on code written by Paul Gortmaker.
+ *
+ *	This driver allows use of the real time clock (built into
+ *	nearly all computers) from user space. It exports the /dev/rtc
+ *	interface supporting various ioctl() and also the /proc/rtc
+ *	pseudo-file for status information.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ */
+
+#define RTC_VERSION		"1.09b"
+
+#include <linux/bcd.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
+
+#include <asm/m48t35.h>
+#include <asm/sn/ioc3.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn0/ip27.h>
+#include <asm/sn/sn0/hub.h>
+#include <asm/sn/sn_private.h>
+
+static int rtc_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg);
+
+static int rtc_read_proc(char *page, char **start, off_t off,
+                         int count, int *eof, void *data);
+
+static void get_rtc_time(struct rtc_time *rtc_tm);
+
+/*
+ *	Bits in rtc_status. (6 bits of room for future expansion)
+ */
+
+#define RTC_IS_OPEN		0x01	/* means /dev/rtc is in use	*/
+#define RTC_TIMER_ON		0x02	/* missed irq timer active	*/
+
+static unsigned char rtc_status;	/* bitmapped status byte.	*/
+static unsigned long rtc_freq;	/* Current periodic IRQ rate	*/
+static struct m48t35_rtc *rtc;
+
+/*
+ *	If this driver ever becomes modularised, it will be really nice
+ *	to make the epoch retain its value across module reload...
+ */
+
+static unsigned long epoch = 1970;	/* year corresponding to 0x00	*/
+
+static const unsigned char days_in_mo[] =
+{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg)
+{
+
+	struct rtc_time wtime;
+
+	switch (cmd) {
+	case RTC_RD_TIME:	/* Read the time/date from RTC	*/
+	{
+		get_rtc_time(&wtime);
+		break;
+	}
+	case RTC_SET_TIME:	/* Set the RTC */
+	{
+		struct rtc_time 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(&rtc_tm, (struct rtc_time*)arg,
+				   sizeof(struct rtc_time)))
+			return -EFAULT;
+
+		yrs = rtc_tm.tm_year + 1900;
+		mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
+		day = rtc_tm.tm_mday;
+		hrs = rtc_tm.tm_hour;
+		min = rtc_tm.tm_min;
+		sec = 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 -= epoch) > 255)    /* They are unsigned */
+			return -EINVAL;
+
+		if (yrs > 169)
+			return -EINVAL;
+
+		if (yrs >= 100)
+			yrs -= 100;
+
+		sec = BIN2BCD(sec);
+		min = BIN2BCD(min);
+		hrs = BIN2BCD(hrs);
+		day = BIN2BCD(day);
+		mon = BIN2BCD(mon);
+		yrs = BIN2BCD(yrs);
+
+		spin_lock_irq(&rtc_lock);
+		rtc->control |= M48T35_RTC_SET;
+		rtc->year = yrs;
+		rtc->month = mon;
+		rtc->date = day;
+		rtc->hour = hrs;
+		rtc->min = min;
+		rtc->sec = sec;
+		rtc->control &= ~M48T35_RTC_SET;
+		spin_unlock_irq(&rtc_lock);
+
+		return 0;
+	}
+	default:
+		return -EINVAL;
+	}
+	return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
+}
+
+/*
+ *	We enforce only one user at a time here with the open/close.
+ *	Also clear the previous interrupt data on an open, and clean
+ *	up things on a close.
+ */
+
+static int rtc_open(struct inode *inode, struct file *file)
+{
+	spin_lock_irq(&rtc_lock);
+
+	if (rtc_status & RTC_IS_OPEN) {
+		spin_unlock_irq(&rtc_lock);
+		return -EBUSY;
+	}
+
+	rtc_status |= RTC_IS_OPEN;
+	spin_unlock_irq(&rtc_lock);
+
+	return 0;
+}
+
+static int rtc_release(struct inode *inode, struct file *file)
+{
+	/*
+	 * Turn off all interrupts once the device is no longer
+	 * in use, and clear the data.
+	 */
+
+	spin_lock_irq(&rtc_lock);
+	rtc_status &= ~RTC_IS_OPEN;
+	spin_unlock_irq(&rtc_lock);
+
+	return 0;
+}
+
+/*
+ *	The various file operations we support.
+ */
+
+static struct file_operations rtc_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= rtc_ioctl,
+	.open		= rtc_open,
+	.release	= rtc_release,
+};
+
+static struct miscdevice rtc_dev=
+{
+	RTC_MINOR,
+	"rtc",
+	&rtc_fops
+};
+
+static int __init rtc_init(void)
+{
+	rtc = (struct m48t35_rtc *)
+	(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + IOC3_BYTEBUS_DEV0);
+
+	printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION);
+	if (misc_register(&rtc_dev)) {
+		printk(KERN_ERR "rtc: cannot register misc device.\n");
+		return -ENODEV;
+	}
+	if (!create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL)) {
+		printk(KERN_ERR "rtc: cannot create /proc/rtc.\n");
+		misc_deregister(&rtc_dev);
+		return -ENOENT;
+	}
+
+	rtc_freq = 1024;
+
+	return 0;
+}
+
+static void __exit rtc_exit (void)
+{
+	/* interrupts and timer disabled at this point by rtc_release */
+
+	remove_proc_entry ("rtc", NULL);
+	misc_deregister(&rtc_dev);
+}
+
+module_init(rtc_init);
+module_exit(rtc_exit);
+
+/*
+ *	Info exported via "/proc/rtc".
+ */
+
+static int rtc_get_status(char *buf)
+{
+	char *p;
+	struct rtc_time tm;
+
+	/*
+	 * Just emulate the standard /proc/rtc
+	 */
+
+	p = buf;
+
+	get_rtc_time(&tm);
+
+	/*
+	 * 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"
+		     "24hr\t\t: yes\n",
+		     tm.tm_hour, tm.tm_min, tm.tm_sec,
+		     tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
+
+	return  p - buf;
+}
+
+static int rtc_read_proc(char *page, char **start, off_t off,
+                                 int count, int *eof, void *data)
+{
+        int len = rtc_get_status(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 void get_rtc_time(struct rtc_time *rtc_tm)
+{
+	/*
+	 * Do we need to wait for the last update to finish?
+	 */
+
+	/*
+	 * Only the values that we read from the RTC are set. We leave
+	 * tm_wday, tm_yday and tm_isdst untouched. Even though the
+	 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+	 * by the RTC when initially set to a non-zero value.
+	 */
+	spin_lock_irq(&rtc_lock);
+	rtc->control |= M48T35_RTC_READ;
+	rtc_tm->tm_sec = rtc->sec;
+	rtc_tm->tm_min = rtc->min;
+	rtc_tm->tm_hour = rtc->hour;
+	rtc_tm->tm_mday = rtc->date;
+	rtc_tm->tm_mon = rtc->month;
+	rtc_tm->tm_year = rtc->year;
+	rtc->control &= ~M48T35_RTC_READ;
+	spin_unlock_irq(&rtc_lock);
+
+	rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec);
+	rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min);
+	rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour);
+	rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday);
+	rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon);
+	rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year);
+
+	/*
+	 * Account for differences between how the RTC uses the values
+	 * and how they are defined in a struct rtc_time;
+	 */
+	if ((rtc_tm->tm_year += (epoch - 1900)) <= 69)
+		rtc_tm->tm_year += 100;
+
+	rtc_tm->tm_mon--;
+}
diff -Nru a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
--- a/drivers/char/ipmi/ipmi_bt_sm.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/ipmi/ipmi_bt_sm.c	2004-06-23 19:04:28 -07:00
@@ -31,7 +31,7 @@
 #include <linux/ipmi_msgdefs.h>		/* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_BT_VERSION "v31"
+#define IPMI_BT_VERSION "v32"
 
 static int bt_debug = 0x00;	/* Production value 0, see following flags */
 
diff -Nru a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
--- a/drivers/char/ipmi/ipmi_devintf.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/ipmi/ipmi_devintf.c	2004-06-23 19:04:28 -07:00
@@ -45,7 +45,7 @@
 #include <asm/semaphore.h>
 #include <linux/init.h>
 
-#define IPMI_DEVINTF_VERSION "v31"
+#define IPMI_DEVINTF_VERSION "v32"
 
 struct ipmi_file_private
 {
@@ -199,7 +199,7 @@
 			goto out;
 		}
 
-		if (copy_from_user(&msgdata,
+		if (copy_from_user(msgdata,
 				   req->msg.data,
 				   req->msg.data_len))
 		{
@@ -231,6 +231,7 @@
 {
 	int                      rv = -EINVAL;
 	struct ipmi_file_private *priv = file->private_data;
+	void __user *arg = (void __user *)data;
 
 	switch (cmd) 
 	{
@@ -238,7 +239,7 @@
 	{
 		struct ipmi_req req;
 
-		if (copy_from_user(&req, (void *) data, sizeof(req))) {
+		if (copy_from_user(&req, arg, sizeof(req))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -254,7 +255,7 @@
 	{
 		struct ipmi_req_settime req;
 
-		if (copy_from_user(&req, (void *) data, sizeof(req))) {
+		if (copy_from_user(&req, arg, sizeof(req))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -277,7 +278,7 @@
 		
 
 		rv = 0;
-		if (copy_from_user(&rsp, (void *) data, sizeof(rsp))) {
+		if (copy_from_user(&rsp, arg, sizeof(rsp))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -344,7 +345,7 @@
 			rsp.msg.data_len = 0;
 		}
 
-		if (copy_to_user((void *) data, &rsp, sizeof(rsp))) {
+		if (copy_to_user(arg, &rsp, sizeof(rsp))) {
 			rv = -EFAULT;
 			goto recv_putback_on_err;
 		}
@@ -371,7 +372,7 @@
 	{
 		struct ipmi_cmdspec val;
 
-		if (copy_from_user(&val, (void *) data, sizeof(val))) {
+		if (copy_from_user(&val, arg, sizeof(val))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -384,7 +385,7 @@
 	{
 		struct ipmi_cmdspec   val;
 
-		if (copy_from_user(&val, (void *) data, sizeof(val))) {
+		if (copy_from_user(&val, arg, sizeof(val))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -397,7 +398,7 @@
 	{
 		int val;
 
-		if (copy_from_user(&val, (void *) data, sizeof(val))) {
+		if (copy_from_user(&val, arg, sizeof(val))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -410,7 +411,7 @@
 	{
 		unsigned int val;
 
-		if (copy_from_user(&val, (void *) data, sizeof(val))) {
+		if (copy_from_user(&val, arg, sizeof(val))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -426,7 +427,7 @@
 
 		val = ipmi_get_my_address(priv->user);
 
-		if (copy_to_user((void *) data, &val, sizeof(val))) {
+		if (copy_to_user(arg, &val, sizeof(val))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -438,7 +439,7 @@
 	{
 		unsigned int val;
 
-		if (copy_from_user(&val, (void *) data, sizeof(val))) {
+		if (copy_from_user(&val, arg, sizeof(val))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -454,7 +455,7 @@
 
 		val = ipmi_get_my_LUN(priv->user);
 
-		if (copy_to_user((void *) data, &val, sizeof(val))) {
+		if (copy_to_user(arg, &val, sizeof(val))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -465,7 +466,7 @@
 	{
 		struct ipmi_timing_parms parms;
 
-		if (copy_from_user(&parms, (void *) data, sizeof(parms))) {
+		if (copy_from_user(&parms, arg, sizeof(parms))) {
 			rv = -EFAULT;
 			break;
 		}
@@ -483,7 +484,7 @@
 		parms.retries = priv->default_retries;
 		parms.retry_time_ms = priv->default_retry_time_ms;
 
-		if (copy_to_user((void *) data, &parms, sizeof(parms))) {
+		if (copy_to_user(arg, &parms, sizeof(parms))) {
 			rv = -EFAULT;
 			break;
 		}
diff -Nru a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
--- a/drivers/char/ipmi/ipmi_kcs_sm.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c	2004-06-23 19:04:25 -07:00
@@ -42,7 +42,7 @@
 #include <linux/ipmi_msgdefs.h>		/* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_KCS_VERSION "v31"
+#define IPMI_KCS_VERSION "v32"
 
 /* Set this if you want a printout of why the state machine was hosed
    when it gets hosed. */
diff -Nru a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
--- a/drivers/char/ipmi/ipmi_msghandler.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/ipmi/ipmi_msghandler.c	2004-06-23 19:04:27 -07:00
@@ -46,7 +46,7 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 
-#define IPMI_MSGHANDLER_VERSION "v31"
+#define IPMI_MSGHANDLER_VERSION "v32"
 
 struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
 static int ipmi_init_msghandler(void);
@@ -1648,6 +1648,22 @@
 		/* It's the one we want */
 		if (msg->rsp[2] != 0) {
 			/* Got an error from the channel, just go on. */
+
+			if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) {
+				/* If the MC does not support this
+				   command, that is legal.  We just
+				   assume it has one IPMB at channel
+				   zero. */
+				intf->channels[0].medium
+					= IPMI_CHANNEL_MEDIUM_IPMB;
+				intf->channels[0].protocol
+					= IPMI_CHANNEL_PROTOCOL_IPMB;
+				rv = -ENOSYS;
+
+				intf->curr_channel = IPMI_MAX_CHANNELS;
+				wake_up(&intf->waitq);
+				goto out;
+			}
 			goto next_channel;
 		}
 		if (msg->rsp_size < 6) {
@@ -1671,10 +1687,20 @@
 			wake_up(&intf->waitq);
 
 			printk(KERN_WARNING "ipmi_msghandler: Error sending"
-			       "channel information: 0x%x\n",
+			       "channel information: %d\n",
 			       rv);
 		}
 	}
+ out:
+	return;
+}
+
+void ipmi_poll_interface(ipmi_user_t user)
+{
+	ipmi_smi_t intf = user->intf;
+
+	if (intf->handlers->poll)
+		intf->handlers->poll(intf->send_info);
 }
 
 int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
@@ -3154,6 +3180,7 @@
 EXPORT_SYMBOL(ipmi_request_settime);
 EXPORT_SYMBOL(ipmi_request_supply_msgs);
 EXPORT_SYMBOL(ipmi_request_with_source);
+EXPORT_SYMBOL(ipmi_poll_interface);
 EXPORT_SYMBOL(ipmi_register_smi);
 EXPORT_SYMBOL(ipmi_unregister_smi);
 EXPORT_SYMBOL(ipmi_register_for_cmd);
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	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/ipmi/ipmi_si_intf.c	2004-06-23 19:04:25 -07:00
@@ -76,7 +76,7 @@
 #include "ipmi_si_sm.h"
 #include <linux/init.h>
 
-#define IPMI_SI_VERSION "v31"
+#define IPMI_SI_VERSION "v32"
 
 /* Measure times between events in the driver. */
 #undef DEBUG_TIMING
@@ -712,6 +712,13 @@
 	spin_unlock_irqrestore(&(smi_info->si_lock), flags);
 }
 
+static void poll(void *send_info)
+{
+	struct smi_info *smi_info = send_info;
+
+	smi_event_handler(smi_info, 0);
+}
+
 static void request_events(void *send_info)
 {
 	struct smi_info *smi_info = send_info;
@@ -851,7 +858,8 @@
 	.owner                  = THIS_MODULE,
 	.sender			= sender,
 	.request_events		= request_events,
-	.set_run_to_completion  = set_run_to_completion
+	.set_run_to_completion  = set_run_to_completion,
+	.poll			= poll,
 };
 
 /* There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
@@ -1848,6 +1856,21 @@
 	atomic_set(&new_smi->req_events, 0);
 	new_smi->run_to_completion = 0;
 
+	new_smi->interrupt_disabled = 0;
+	new_smi->timer_stopped = 0;
+	new_smi->stop_operation = 0;
+
+	/* The ipmi_register_smi() code does some operations to
+	   determine the channel information, so we must be ready to
+	   handle operations before it is called.  This means we have
+	   to stop the timer if we get an error after this point. */
+	init_timer(&(new_smi->si_timer));
+	new_smi->si_timer.data = (long) new_smi;
+	new_smi->si_timer.function = smi_timeout;
+	new_smi->last_timeout_jiffies = jiffies;
+	new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
+	add_timer(&(new_smi->si_timer));
+
 	rv = ipmi_register_smi(&handlers,
 			       new_smi,
 			       new_smi->ipmi_version_major,
@@ -1857,7 +1880,7 @@
 		printk(KERN_ERR
 		       "ipmi_si: Unable to register device: error %d\n",
 		       rv);
-		goto out_err;
+		goto out_err_stop_timer;
 	}
 
 	rv = ipmi_smi_add_proc_entry(new_smi->intf, "type",
@@ -1867,7 +1890,7 @@
 		printk(KERN_ERR
 		       "ipmi_si: Unable to create proc entry: %d\n",
 		       rv);
-		goto out_err;
+		goto out_err_stop_timer;
 	}
 
 	rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats",
@@ -1877,7 +1900,7 @@
 		printk(KERN_ERR
 		       "ipmi_si: Unable to create proc entry: %d\n",
 		       rv);
-		goto out_err;
+		goto out_err_stop_timer;
 	}
 
 	start_clear_flags(new_smi);
@@ -1886,34 +1909,40 @@
 	if (new_smi->irq)
 		new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
 
-	new_smi->interrupt_disabled = 0;
-	new_smi->timer_stopped = 0;
-	new_smi->stop_operation = 0;
-
-	init_timer(&(new_smi->si_timer));
-	new_smi->si_timer.data = (long) new_smi;
-	new_smi->si_timer.function = smi_timeout;
-	new_smi->last_timeout_jiffies = jiffies;
-	new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
-	add_timer(&(new_smi->si_timer));
-
 	*smi = new_smi;
 
 	printk(" IPMI %s interface initialized\n", si_type[intf_num]);
 
 	return 0;
 
+ out_err_stop_timer:
+	new_smi->stop_operation = 1;
+
+	/* Wait for the timer to stop.  This avoids problems with race
+	   conditions removing the timer here. */
+	while (!new_smi->timer_stopped) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+
  out_err:
 	if (new_smi->intf)
 		ipmi_unregister_smi(new_smi->intf);
 
 	new_smi->irq_cleanup(new_smi);
+
+	/* Wait until we know that we are out of any interrupt
+	   handlers might have been running before we freed the
+	   interrupt. */
+	synchronize_kernel();
+
 	if (new_smi->si_sm) {
 		if (new_smi->handlers)
 			new_smi->handlers->cleanup(new_smi->si_sm);
 		kfree(new_smi->si_sm);
 	}
 	new_smi->io_cleanup(new_smi);
+
 	return rv;
 }
 
diff -Nru a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c
--- a/drivers/char/ipmi/ipmi_smic_sm.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/ipmi/ipmi_smic_sm.c	2004-06-23 19:04:27 -07:00
@@ -46,7 +46,7 @@
 #include <linux/ipmi_msgdefs.h>		/* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_SMIC_VERSION "v31"
+#define IPMI_SMIC_VERSION "v32"
 
 /* smic_debug is a bit-field
  *	SMIC_DEBUG_ENABLE -	turned on for now
diff -Nru a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
--- a/drivers/char/ipmi/ipmi_watchdog.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/ipmi/ipmi_watchdog.c	2004-06-23 19:04:28 -07:00
@@ -51,7 +51,7 @@
 #include <asm/apic.h>
 #endif
 
-#define IPMI_WATCHDOG_VERSION "v31"
+#define IPMI_WATCHDOG_VERSION "v32"
 
 /*
  * The IPMI command/response information for the watchdog timer.
@@ -515,40 +515,37 @@
 static int ipmi_ioctl(struct inode *inode, struct file *file,
 		      unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
 	int i;
 	int val;
 
 	switch(cmd) {
 	case WDIOC_GETSUPPORT:
-		i = copy_to_user((void*)arg, &ident, sizeof(ident));
+		i = copy_to_user(argp, &ident, sizeof(ident));
 		return i ? -EFAULT : 0;
 
 	case WDIOC_SETTIMEOUT:
-		i = copy_from_user(&val, (void *) arg, sizeof(int));
+		i = copy_from_user(&val, argp, sizeof(int));
 		if (i)
 			return -EFAULT;
 		timeout = val;
 		return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
 
 	case WDIOC_GETTIMEOUT:
-		i = copy_to_user((void *) arg,
-				 &timeout,
-				 sizeof(timeout));
+		i = copy_to_user(argp, &timeout, sizeof(timeout));
 		if (i)
 			return -EFAULT;
 		return 0;
 
 	case WDIOC_SET_PRETIMEOUT:
-		i = copy_from_user(&val, (void *) arg, sizeof(int));
+		i = copy_from_user(&val, argp, sizeof(int));
 		if (i)
 			return -EFAULT;
 		pretimeout = val;
 		return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
 
 	case WDIOC_GET_PRETIMEOUT:
-		i = copy_to_user((void *) arg,
-				 &pretimeout,
-				 sizeof(pretimeout));
+		i = copy_to_user(argp, &pretimeout, sizeof(pretimeout));
 		if (i)
 			return -EFAULT;
 		return 0;
@@ -557,7 +554,7 @@
 		return ipmi_heartbeat();
 
 	case WDIOC_SETOPTIONS:
-		i = copy_from_user(&val, (void *) arg, sizeof(int));
+		i = copy_from_user(&val, argp, sizeof(int));
 		if (i)
 			return -EFAULT;
 		if (val & WDIOS_DISABLECARD)
@@ -576,7 +573,7 @@
 
 	case WDIOC_GETSTATUS:
 		val = 0;
-		i = copy_to_user((void *) arg, &val, sizeof(val));
+		i = copy_to_user(argp, &val, sizeof(val));
 		if (i)
 			return -EFAULT;
 		return 0;
@@ -587,7 +584,7 @@
 }
 
 static ssize_t ipmi_write(struct file *file,
-			  const char  *buf,
+			  const char  __user *buf,
 			  size_t      len,
 			  loff_t      *ppos)
 {
@@ -607,7 +604,7 @@
 }
 
 static ssize_t ipmi_read(struct file *file,
-			 char        *buf,
+			 char        __user *buf,
 			 size_t      count,
 			 loff_t      *ppos)
 {
@@ -883,14 +880,12 @@
 
 	/* On a panic, if we have a panic timeout, make sure that the thing
 	   reboots, even if it hangs during that panic. */
-	if (watchdog_user && !panic_event_handled && (panic_timeout > 0)) {
+	if (watchdog_user && !panic_event_handled) {
 		/* Make sure the panic doesn't hang, and make sure we
 		   do this only once. */
 		panic_event_handled = 1;
 	    
-		timeout = panic_timeout + 120;
-		if (timeout > 255)
-			timeout = 255;
+		timeout = 255;
 		pretimeout = 0;
 		ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
 		panic_halt_ipmi_set_timeout();
diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c
--- a/drivers/char/istallion.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/istallion.c	2004-06-23 19:04:27 -07:00
@@ -851,7 +851,7 @@
 	i = tty_unregister_driver(stli_serial);
 	if (i) {
 		printk("STALLION: failed to un-register tty driver, "
-			"errno=%d,%d\n", -i);
+			"errno=%d\n", -i);
 		restore_flags(flags);
 		return;
 	}
diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c
--- a/drivers/char/keyboard.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/char/keyboard.c	2004-06-23 19:04:29 -07:00
@@ -52,13 +52,12 @@
 
 /*
  * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
- * This seems a good reason to start with NumLock off. On PC9800 and HIL keyboards 
+ * This seems a good reason to start with NumLock off. On HIL keyboards
  * of PARISC machines however there is no NumLock key and everyone expects the keypad 
  * to be used for numbers.
  */
 
-#if defined(CONFIG_X86_PC9800) || \
-    defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
+#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD))
 #define KBD_DEFLEDS (1 << VC_NUMLOCK)
 #else
 #define KBD_DEFLEDS 0
diff -Nru a/drivers/char/lcd.c b/drivers/char/lcd.c
--- a/drivers/char/lcd.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/char/lcd.c	2004-06-23 19:04:26 -07:00
@@ -12,7 +12,7 @@
  *
  */
 
-#define RTC_IO_EXTENT	0x10    /*Only really two ports, but...	*/
+#define RTC_IO_EXTENT	0x10	/*Only really two ports, but... */
 
 #include <linux/config.h>
 #include <linux/types.h>
@@ -32,8 +32,8 @@
 
 #include "lcd.h"
 
-static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 
-                     unsigned long arg);
+static int lcd_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg);
 
 static int lcd_present = 1;
 
@@ -57,8 +57,8 @@
 }
 #endif
 
-static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 
-			unsigned long arg)
+static int lcd_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
 {
 	struct lcd_display button_display;
 	unsigned long address, a;
@@ -69,7 +69,7 @@
 		udelay(150);
 		BusyCheck();
 		LCDWriteInst(0x0F);
-		break;		
+		break;
 
 	case LCD_Off:
 		udelay(150);
@@ -95,7 +95,7 @@
 	case LCD_Clear:
 		udelay(150);
 		BusyCheck();
-       		LCDWriteInst(0x01);     
+		LCDWriteInst(0x01);
 		break;
 
 	case LCD_Cursor_Left:
@@ -108,86 +108,95 @@
 		udelay(150);
 		BusyCheck();
 		LCDWriteInst(0x14);
-		break;	
+		break;
 
 	case LCD_Cursor_Off:
 		udelay(150);
-                BusyCheck();
-                LCDWriteInst(0x0C);
-	        break;
-
-        case LCD_Cursor_On:
-                udelay(150);
-                BusyCheck();
-                LCDWriteInst(0x0F);
-                break;
-
-        case LCD_Blink_Off:
-                udelay(150);
-                BusyCheck();
-                LCDWriteInst(0x0E);
-                break;
-
-	case LCD_Get_Cursor_Pos:{
-                struct lcd_display display;
+		BusyCheck();
+		LCDWriteInst(0x0C);
+		break;
 
+	case LCD_Cursor_On:
 		udelay(150);
-                BusyCheck();
-		display.cursor_address = ( LCDReadInst ); 
-		display.cursor_address = ( display.cursor_address & 0x07F );
-		if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display)))
-		  return -EFAULT;
+		BusyCheck();
+		LCDWriteInst(0x0F);
+		break;
 
+	case LCD_Blink_Off:
+		udelay(150);
+		BusyCheck();
+		LCDWriteInst(0x0E);
 		break;
+
+	case LCD_Get_Cursor_Pos:{
+			struct lcd_display display;
+
+			udelay(150);
+			BusyCheck();
+			display.cursor_address = (LCDReadInst);
+			display.cursor_address =
+			    (display.cursor_address & 0x07F);
+			if (copy_to_user
+			    ((struct lcd_display *) arg, &display,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
+
+			break;
 		}
 
 
-	case LCD_Set_Cursor_Pos: {
-                struct lcd_display display;
+	case LCD_Set_Cursor_Pos:{
+			struct lcd_display display;
 
-                if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display)))
-		  return -EFAULT;
+			if (copy_from_user
+			    (&display, (struct lcd_display *) arg,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
 
-		a = (display.cursor_address | kLCD_Addr ); 
+			a = (display.cursor_address | kLCD_Addr);
 
-                udelay(150);
-                BusyCheck();    
-                LCDWriteInst( a );
+			udelay(150);
+			BusyCheck();
+			LCDWriteInst(a);
 
-                break;
+			break;
 		}
-	
-	case LCD_Get_Cursor: {
-                struct lcd_display display;
 
-                udelay(150);
-                BusyCheck();    
-		display.character = LCDReadData;	
+	case LCD_Get_Cursor:{
+			struct lcd_display display;
 
-		if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display)))
-		  return -EFAULT;
-                udelay(150);
-                BusyCheck();
-                LCDWriteInst(0x10);
+			udelay(150);
+			BusyCheck();
+			display.character = LCDReadData;
 
-		break;
+			if (copy_to_user
+			    ((struct lcd_display *) arg, &display,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
+			udelay(150);
+			BusyCheck();
+			LCDWriteInst(0x10);
+
+			break;
 		}
 
 	case LCD_Set_Cursor:{
-                struct lcd_display display;
-   
-                if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display)))
-		  return -EFAULT;
-
-                udelay(150);
-		BusyCheck();    
-                LCDWriteData( display.character );
-                udelay(150);
-                BusyCheck();
-                LCDWriteInst(0x10);
+			struct lcd_display display;
 
-                break;
-                }
+			if (copy_from_user
+			    (&display, (struct lcd_display *) arg,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
+
+			udelay(150);
+			BusyCheck();
+			LCDWriteData(display.character);
+			udelay(150);
+			BusyCheck();
+			LCDWriteInst(0x10);
+
+			break;
+		}
 
 
 	case LCD_Disp_Left:
@@ -208,294 +217,330 @@
 		LCDWriteInst(0x02);
 		break;
 
-	case LCD_Write: {
-		struct lcd_display display;
-   
+	case LCD_Write:{
+			struct lcd_display display;
+
+
+			if (copy_from_user
+			    (&display, (struct lcd_display *) arg,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
 
-                if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display)))
-		  return -EFAULT;
- 
-		udelay(150);
-                BusyCheck();    
-                LCDWriteInst(0x80);
-		udelay(150);
-		BusyCheck();
-	
-		for (index = 0; index < (display.size1); index++) {
 			udelay(150);
-			BusyCheck();	
-			LCDWriteData( display.line1[index]);
-			BusyCheck();	
-		}		
-		
-		udelay(150);
-		BusyCheck();	
-		LCDWriteInst(0xC0);	
-		udelay(150);
-		BusyCheck();	
-                for (index = 0; index < (display.size2); index++) {
-                        udelay(150);
-                        BusyCheck();    
-                        LCDWriteData( display.line2[index]);
-		}
- 
-		break;	
-	}
-	
-	case LCD_Read: {	
-        	struct lcd_display display;
+			BusyCheck();
+			LCDWriteInst(0x80);
+			udelay(150);
+			BusyCheck();
 
-		BusyCheck();
-		for (address = kDD_R00; address <= kDD_R01; address++) {
-			a = (address | kLCD_Addr );	
+			for (index = 0; index < (display.size1); index++) {
+				udelay(150);
+				BusyCheck();
+				LCDWriteData(display.line1[index]);
+				BusyCheck();
+			}
 
 			udelay(150);
 			BusyCheck();
-			LCDWriteInst( a );
+			LCDWriteInst(0xC0);
 			udelay(150);
 			BusyCheck();
-			display.line1[address] = LCDReadData;
+			for (index = 0; index < (display.size2); index++) {
+				udelay(150);
+				BusyCheck();
+				LCDWriteData(display.line2[index]);
+			}
+
+			break;
 		}
 
-		display.line1[ 0x27 ] = '\0';
-	
-		for (address = kDD_R10; address <= kDD_R11; address++) {
-			a = (address | kLCD_Addr );     
-        
-			udelay(150);
-	 		BusyCheck();
-        		LCDWriteInst( a );
-       
-        		udelay(150);
-	 		BusyCheck();
-        		display.line2[address - 0x40 ] = LCDReadData;
-		 }
-
-		display.line2[ 0x27 ] = '\0';
-
-		if(copy_to_user((struct lcd_display*)arg, &display,
-				sizeof(struct lcd_display)))
-		  return -EFAULT;
-		break;
-	}
+	case LCD_Read:{
+			struct lcd_display display;
+
+			BusyCheck();
+			for (address = kDD_R00; address <= kDD_R01;
+			     address++) {
+				a = (address | kLCD_Addr);
+
+				udelay(150);
+				BusyCheck();
+				LCDWriteInst(a);
+				udelay(150);
+				BusyCheck();
+				display.line1[address] = LCDReadData;
+			}
 
-//  set all GPIO leds to led_display.leds 
+			display.line1[0x27] = '\0';
 
-	case LED_Set: {	
-		struct lcd_display led_display;
-	
+			for (address = kDD_R10; address <= kDD_R11;
+			     address++) {
+				a = (address | kLCD_Addr);
+
+				udelay(150);
+				BusyCheck();
+				LCDWriteInst(a);
+
+				udelay(150);
+				BusyCheck();
+				display.line2[address - 0x40] =
+				    LCDReadData;
+			}
+
+			display.line2[0x27] = '\0';
 
-	        if(copy_from_user(&led_display, (struct lcd_display*)arg,
-				  sizeof(struct lcd_display)))
-		  return -EFAULT;
+			if (copy_to_user
+			    ((struct lcd_display *) arg, &display,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
+			break;
+		}
 
-		led_state = led_display.leds;
-		LEDSet(led_state);
+//  set all GPIO leds to led_display.leds
 
-        	break;
-	}
+	case LED_Set:{
+			struct lcd_display led_display;
+
+
+			if (copy_from_user
+			    (&led_display, (struct lcd_display *) arg,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
+
+			led_state = led_display.leds;
+			LEDSet(led_state);
+
+			break;
+		}
 
 
 //  set only bit led_display.leds
 
-        case LED_Bit_Set: {
-                int i;
-		int bit=1;
-                struct lcd_display led_display;
+	case LED_Bit_Set:{
+			int i;
+			int bit = 1;
+			struct lcd_display led_display;
 
 
-                if(copy_from_user(&led_display, (struct lcd_display*)arg,
-				  sizeof(struct lcd_display)))
-		  return -EFAULT;
+			if (copy_from_user
+			    (&led_display, (struct lcd_display *) arg,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
 
-		for (i=0;i<(int)led_display.leds;i++)
-			{
-				bit = 2*bit;	
+			for (i = 0; i < (int) led_display.leds; i++) {
+				bit = 2 * bit;
 			}
 
-		led_state = led_state | bit;
-                LEDSet(led_state);
-                break;
-        }
+			led_state = led_state | bit;
+			LEDSet(led_state);
+			break;
+		}
 
 //  clear only bit led_display.leds
 
-        case LED_Bit_Clear: {
-                int i;
-		int bit=1;
-                struct lcd_display led_display;
-
-
-                if(copy_from_user(&led_display, (struct lcd_display*)arg,
-				  sizeof(struct lcd_display)))
-		  return -EFAULT;
-
-                for (i=0;i<(int)led_display.leds;i++)
-                        {
-                                bit = 2*bit;
-                        }
-
-		led_state = led_state &  ~bit;
-                LEDSet(led_state);
-                break;
-        }
-
-
-	case BUTTON_Read: {
-		button_display.buttons = GPIRead;
-                if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display)))
-		  return -EFAULT;
-		break;
-	}
+	case LED_Bit_Clear:{
+			int i;
+			int bit = 1;
+			struct lcd_display led_display;
 
-        case LINK_Check: {
-                button_display.buttons = *((volatile unsigned long *) (0xB0100060) );
-                if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display)))
-		  return -EFAULT;
-                break;
-        }
-
-	case LINK_Check_2: {
-		int iface_num;
-
-		/* panel-utils should pass in the desired interface status is wanted for
-		 * in "buttons" of the structure.  We will set this to non-zero if the
-		 * link is in fact up for the requested interface.  --DaveM
-		 */
-		if(copy_from_user(&button_display, (struct lcd_display *)arg, sizeof(button_display)))
-		  return -EFAULT;
-		iface_num = button_display.buttons;
-#if defined(CONFIG_TULIP) && 0
-		if (iface_num >= 0 &&
-		    iface_num < MAX_INTERFACES &&
-		    linkcheck_callbacks[iface_num] != NULL) {
-			button_display.buttons =
-				linkcheck_callbacks[iface_num](linkcheck_cookies[iface_num]);
-		} else
-#endif
-			button_display.buttons = 0;
-
-                if(__copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display)))
-		  return -EFAULT;
-                break;
-	}
 
-//  Erase the flash
+			if (copy_from_user
+			    (&led_display, (struct lcd_display *) arg,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
 
-	case FLASH_Erase: {
+			for (i = 0; i < (int) led_display.leds; i++) {
+				bit = 2 * bit;
+			}
 
-		int ctr=0;
+			led_state = led_state & ~bit;
+			LEDSet(led_state);
+			break;
+		}
 
-		    // Chip Erase Sequence
-		WRITE_FLASH( kFlash_Addr1, kFlash_Data1 );
-		WRITE_FLASH( kFlash_Addr2, kFlash_Data2 );
-		WRITE_FLASH( kFlash_Addr1, kFlash_Erase3 );
-		WRITE_FLASH( kFlash_Addr1, kFlash_Data1 );
-		WRITE_FLASH( kFlash_Addr2, kFlash_Data2 );
-		WRITE_FLASH( kFlash_Addr1, kFlash_Erase6 );
 
-		printk( "Erasing Flash.\n");
+	case BUTTON_Read:{
+			button_display.buttons = GPIRead;
+			if (copy_to_user
+			    ((struct lcd_display *) arg, &button_display,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
+			break;
+		}
 
-		while ( (!dqpoll(0x00000000,0xFF)) && (!timeout(0x00000000)) ) {
-		    ctr++;
+	case LINK_Check:{
+			button_display.buttons =
+			    *((volatile unsigned long *) (0xB0100060));
+			if (copy_to_user
+			    ((struct lcd_display *) arg, &button_display,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
+			break;
 		}
 
-		printk("\n");
-		printk("\n");
-		printk("\n");
+	case LINK_Check_2:{
+			int iface_num;
 
-		if (READ_FLASH(0x07FFF0)==0xFF) { printk("Erase Successful\r\n"); }
-		else if (timeout) { printk("Erase Timed Out\r\n"); }
+			/* panel-utils should pass in the desired interface status is wanted for
+			 * in "buttons" of the structure.  We will set this to non-zero if the
+			 * link is in fact up for the requested interface.  --DaveM
+			 */
+			if (copy_from_user
+			    (&button_display, (struct lcd_display *) arg,
+			     sizeof(button_display)))
+				return -EFAULT;
+			iface_num = button_display.buttons;
+#if defined(CONFIG_TULIP) && 0
+			if (iface_num >= 0 &&
+			    iface_num < MAX_INTERFACES &&
+			    linkcheck_callbacks[iface_num] != NULL) {
+				button_display.buttons =
+				    linkcheck_callbacks[iface_num]
+				    (linkcheck_cookies[iface_num]);
+			} else
+#endif
+				button_display.buttons = 0;
 
-	break;
-	}
+			if (__copy_to_user
+			    ((struct lcd_display *) arg, &button_display,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
+			break;
+		}
 
-// burn the flash 
+//  Erase the flash
 
-	case FLASH_Burn: {
+	case FLASH_Erase:{
 
-		volatile unsigned long burn_addr;
-		unsigned long flags;
-		int i;
-		unsigned char *rom;
-		
-
-                struct lcd_display display;
-
-                if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display)))
-		  return -EFAULT;
-		rom = (unsigned char *) kmalloc((128),GFP_ATOMIC);
-                if ( rom == NULL ) {
-                       printk ("broken\n");
-                       return 1;
-                   }
-
-		printk("Churning and Burning -");
-		save_flags(flags);
-		for (i=0; i<FLASH_SIZE; i=i+128) {
-
-		        if(copy_from_user(rom, display.RomImage + i, 128))
-			   return -EFAULT;
-			burn_addr = kFlashBase + i;
-			cli();
-			for ( index = 0; index < ( 128 ) ; index++ ) 
-		  	  {
-
-				WRITE_FLASH( kFlash_Addr1, kFlash_Data1 );
-		 	    	WRITE_FLASH( kFlash_Addr2, kFlash_Data2 );
-		 	    	WRITE_FLASH( kFlash_Addr1, kFlash_Prog );
-		 	    	*((volatile unsigned char *)burn_addr) = (volatile unsigned char) rom[index];
-
-		   	 	 while ( (!dqpoll(burn_addr,(volatile unsigned char) rom[index])) && (!timeout(burn_addr)) ) {
-		  	   		}
-		  	   	burn_addr++;
-		  	  }
-			restore_flags(flags);
-                	if ( *((volatile unsigned char *)(burn_addr-1)) == (volatile unsigned char) rom[index-1]  ) {
-               		 } else if (timeout) {
-                	    printk("Program timed out\r\n");
-               		 }
+			int ctr = 0;
 
+			// Chip Erase Sequence
+			WRITE_FLASH(kFlash_Addr1, kFlash_Data1);
+			WRITE_FLASH(kFlash_Addr2, kFlash_Data2);
+			WRITE_FLASH(kFlash_Addr1, kFlash_Erase3);
+			WRITE_FLASH(kFlash_Addr1, kFlash_Data1);
+			WRITE_FLASH(kFlash_Addr2, kFlash_Data2);
+			WRITE_FLASH(kFlash_Addr1, kFlash_Erase6);
+
+			printk("Erasing Flash.\n");
+
+			while ((!dqpoll(0x00000000, 0xFF))
+			       && (!timeout(0x00000000))) {
+				ctr++;
+			}
+
+			printk("\n");
+			printk("\n");
+			printk("\n");
+
+			if (READ_FLASH(0x07FFF0) == 0xFF) {
+				printk("Erase Successful\r\n");
+			} else if (timeout) {
+				printk("Erase Timed Out\r\n");
+			}
 
+			break;
 		}
-		kfree(rom);
 
-	break;
-	}
+// burn the flash
 
-//  read the flash all at once 
-	
-	case FLASH_Read: {
+	case FLASH_Burn:{
 
-		unsigned char *user_bytes;
-                volatile unsigned long read_addr;
-                int i;
+			volatile unsigned long burn_addr;
+			unsigned long flags;
+			int i;
+			unsigned char *rom;
+
+
+			struct lcd_display display;
+
+			if (copy_from_user
+			    (&display, (struct lcd_display *) arg,
+			     sizeof(struct lcd_display)))
+				return -EFAULT;
+			rom = (unsigned char *) kmalloc((128), GFP_ATOMIC);
+			if (rom == NULL) {
+				printk("broken\n");
+				return 1;
+			}
 
-		user_bytes = &(((struct lcd_display *)arg)->RomImage[0]);
+			printk("Churning and Burning -");
+			save_flags(flags);
+			for (i = 0; i < FLASH_SIZE; i = i + 128) {
+
+				if (copy_from_user
+				    (rom, display.RomImage + i, 128))
+					return -EFAULT;
+				burn_addr = kFlashBase + i;
+				cli();
+				for (index = 0; index < (128); index++) {
+
+					WRITE_FLASH(kFlash_Addr1,
+						    kFlash_Data1);
+					WRITE_FLASH(kFlash_Addr2,
+						    kFlash_Data2);
+					WRITE_FLASH(kFlash_Addr1,
+						    kFlash_Prog);
+					*((volatile unsigned char *)
+					  burn_addr) =
+		 (volatile unsigned char) rom[index];
+
+					while ((!dqpoll
+						(burn_addr,
+						 (volatile unsigned char)
+						 rom[index]))
+					       && (!timeout(burn_addr))) {
+					}
+					burn_addr++;
+				}
+				restore_flags(flags);
+				if (*
+				    ((volatile unsigned char *) (burn_addr
+								 - 1)) ==
+				    (volatile unsigned char) rom[index -
+								 1]) {
+				} else if (timeout) {
+					printk("Program timed out\r\n");
+				}
 
-		if(!access_ok(VERIFY_WRITE, user_bytes, FLASH_SIZE))
-                         return -EFAULT;
 
-		printk("Reading Flash");
-		for (i=0; i<FLASH_SIZE; i++) {
-			unsigned char tmp_byte;
-			read_addr = kFlashBase + i;
-			tmp_byte = *((volatile unsigned char *)read_addr);
-			if(__put_user (tmp_byte, &user_bytes[i]))
-			  return -EFAULT;
-		}
+			}
+			kfree(rom);
 
+			break;
+		}
 
-	break;
-	}
+//  read the flash all at once
 
+	case FLASH_Read:{
 
+			unsigned char *user_bytes;
+			volatile unsigned long read_addr;
+			int i;
+
+			user_bytes =
+			    &(((struct lcd_display *) arg)->RomImage[0]);
+
+			if (!access_ok
+			    (VERIFY_WRITE, user_bytes, FLASH_SIZE))
+				return -EFAULT;
+
+			printk("Reading Flash");
+			for (i = 0; i < FLASH_SIZE; i++) {
+				unsigned char tmp_byte;
+				read_addr = kFlashBase + i;
+				tmp_byte =
+				    *((volatile unsigned char *)
+				      read_addr);
+				if (__put_user(tmp_byte, &user_bytes[i]))
+					return -EFAULT;
+			}
 
 
+			break;
+		}
 
 	default:
 		return 0;
-	break;
+		break;
 
 	}
 
@@ -517,7 +562,8 @@
 {
 	unsigned long buttons = GPIRead;
 
-	if ( (buttons == BUTTON_Next) || (buttons == BUTTON_Next_B) || (buttons == BUTTON_Reset_B) )
+	if ((buttons == BUTTON_Next) || (buttons == BUTTON_Next_B)
+	    || (buttons == BUTTON_Reset_B))
 		return buttons;
 	return 0;
 }
@@ -526,22 +572,23 @@
 
 static int lcd_waiters = 0;
 
-static long lcd_read(struct inode *inode, struct file *file, char *buf, unsigned long count)
+static long lcd_read(struct inode *inode, struct file *file, char *buf,
+		     unsigned long count)
 {
 	long buttons_now;
 
-	if(lcd_waiters > 0)
+	if (lcd_waiters > 0)
 		return -EINVAL;
 
 	lcd_waiters++;
-	while(((buttons_now = (long)button_pressed()) == 0) &&
-	      !(signal_pending(current))) {
+	while (((buttons_now = (long) button_pressed()) == 0) &&
+	       !(signal_pending(current))) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(2 * HZ);
 	}
 	lcd_waiters--;
 
-	if(signal_pending(current))
+	if (signal_pending(current))
 		return -ERESTARTSYS;
 	return buttons_now;
 }
@@ -551,21 +598,20 @@
  */
 
 static struct file_operations lcd_fops = {
-	.read		= lcd_read,
-	.ioctl		= lcd_ioctl,
-	.open		= lcd_open,
+	.read = lcd_read,
+	.ioctl = lcd_ioctl,
+	.open = lcd_open,
 };
 
-static struct miscdevice lcd_dev=
-{
-	LCD_MINOR,
+static struct miscdevice lcd_dev = {
+	MISC_DYNAMIC_MINOR,
 	"lcd",
 	&lcd_fops
 };
 
-int lcd_init(void)
+static int lcd_init(void)
 {
-unsigned long data;
+	unsigned long data;
 
 	printk("%s\n", LCD_DRIVER);
 	misc_register(&lcd_dev);
@@ -575,19 +621,22 @@
 
 	udelay(150);
 	data = LCDReadData;
-	if ( (data & 0x000000FF) == (0x00) ) {
+	if ((data & 0x000000FF) == (0x00)) {
 		lcd_present = 0;
 		printk("LCD Not Present\n");
-	        }
-	else {
+	} else {
 		lcd_present = 1;
-		WRITE_GAL( kGal_DevBank2PReg, kGal_DevBank2Cfg );
-		WRITE_GAL( kGal_DevBank3PReg, kGal_DevBank3Cfg );
-		}
+		WRITE_GAL(kGal_DevBank2PReg, kGal_DevBank2Cfg);
+		WRITE_GAL(kGal_DevBank3PReg, kGal_DevBank3Cfg);
+	}
 
 	return 0;
 }
 
+static void __exit lcd_exit(void)
+{
+	misc_deregister(&lcd_dev);
+}
 
 //
 // Function: dqpoll
@@ -600,17 +649,15 @@
 //
 //
 
-int dqpoll( volatile unsigned long address, volatile unsigned char data ) {
-
-volatile unsigned char dq7;
-
-dq7 = data & 0x80;
+static int dqpoll(volatile unsigned long address, volatile unsigned char data)
+{
+	volatile unsigned char dq7;
 
-return ( (READ_FLASH(address) & 0x80) == dq7  );
+	dq7 = data & 0x80;
 
+	return ((READ_FLASH(address) & 0x80) == dq7);
 }
 
-
 //
 // Function: timeout
 //
@@ -622,12 +669,13 @@
 //
 // Out: 0 = not timed out, 1 = timed out
 
-int timeout( volatile unsigned long address ) {
-
-
-return (  (READ_FLASH(address) & 0x20) ==  0x20 );
-
+static int timeout(volatile unsigned long address)
+{
+	return (READ_FLASH(address) & 0x20) == 0x20;
 }
 
+module_init(lcd_init);
+module_exit(lcd_exit);
 
-
+MODULE_AUTHOR("Andrew Bose");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/lcd.h b/drivers/char/lcd.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/lcd.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,184 @@
+/*
+ * LED, LCD and Button panel driver for Cobalt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997 by Andrew Bose
+ *
+ * Linux kernel version history:
+ *       March 2001: Ported from 2.0.34  by Liam Davies
+ *
+ */
+
+// function headers
+
+static int dqpoll(volatile unsigned long, volatile unsigned char );
+static int timeout(volatile unsigned long);
+
+#define LCD_CHARS_PER_LINE 40
+#define FLASH_SIZE 524288
+#define MAX_IDLE_TIME 120
+
+struct lcd_display {
+        unsigned long buttons;
+        int size1;
+        int size2;
+        unsigned char line1[LCD_CHARS_PER_LINE];
+        unsigned char line2[LCD_CHARS_PER_LINE];
+        unsigned char cursor_address;
+        unsigned char character;
+        unsigned char leds;
+        unsigned char *RomImage;
+};
+
+
+
+#define LCD_DRIVER	"Cobalt LCD Driver v2.10"
+
+#define kLCD_IR		0x0F000000
+#define kLCD_DR		0x0F000010
+#define kGPI		0x0D000000
+#define kLED		0x0C000000
+
+#define kDD_R00         0x00
+#define kDD_R01         0x27
+#define kDD_R10         0x40
+#define kDD_R11         0x67
+
+#define kLCD_Addr       0x00000080
+
+#define LCDTimeoutValue	0xfff
+
+
+// Flash definitions AMD 29F040
+#define kFlashBase	0x0FC00000
+
+#define kFlash_Addr1    0x5555
+#define kFlash_Addr2    0x2AAA
+#define kFlash_Data1    0xAA
+#define kFlash_Data2    0x55
+#define kFlash_Prog     0xA0
+#define kFlash_Erase3   0x80
+#define kFlash_Erase6   0x10
+#define kFlash_Read     0xF0
+
+#define kFlash_ID       0x90
+#define kFlash_VenAddr  0x00
+#define kFlash_DevAddr  0x01
+#define kFlash_VenID    0x01
+#define kFlash_DevID    0xA4    // 29F040
+//#define kFlash_DevID  0xAD    // 29F016
+
+
+// Macros
+
+#define LCDWriteData(x)	outl((x << 24), kLCD_DR)
+#define LCDWriteInst(x)	outl((x << 24), kLCD_IR)
+
+#define LCDReadData	(inl(kLCD_DR) >> 24)
+#define LCDReadInst	(inl(kLCD_IR) >> 24)
+
+#define GPIRead		(inl(kGPI) >> 24)
+
+#define LEDSet(x)	outb((char)x, kLED)
+
+#define WRITE_GAL(x,y)	outl(y, 0x04000000 | (x))
+#define BusyCheck()	while ((LCDReadInst & 0x80) == 0x80)
+
+#define WRITE_FLASH(x,y) outb((char)y, kFlashBase | (x))
+#define READ_FLASH(x)	(inb(kFlashBase | (x)))
+
+
+
+/*
+ * Function command codes for io_ctl.
+ */
+#define LCD_On			1
+#define LCD_Off			2
+#define LCD_Clear		3
+#define LCD_Reset		4
+#define LCD_Cursor_Left		5
+#define LCD_Cursor_Right	6
+#define LCD_Disp_Left		7
+#define LCD_Disp_Right		8
+#define LCD_Get_Cursor		9
+#define LCD_Set_Cursor		10
+#define LCD_Home		11
+#define LCD_Read		12
+#define LCD_Write		13
+#define LCD_Cursor_Off		14
+#define LCD_Cursor_On		15
+#define LCD_Get_Cursor_Pos	16
+#define LCD_Set_Cursor_Pos	17
+#define LCD_Blink_Off           18
+
+#define LED_Set			40
+#define LED_Bit_Set		41
+#define LED_Bit_Clear		42
+
+
+//  Button defs
+#define BUTTON_Read             50
+
+//  Flash command codes
+#define FLASH_Erase		60
+#define FLASH_Burn		61
+#define FLASH_Read		62
+
+
+// Ethernet LINK check hackaroo
+#define LINK_Check              90
+#define LINK_Check_2		91
+
+//  Button patterns  _B - single layer lcd boards
+
+#define BUTTON_NONE               0x3F
+#define BUTTON_NONE_B             0xFE
+
+#define BUTTON_Left               0x3B
+#define BUTTON_Left_B             0xFA
+
+#define BUTTON_Right              0x37
+#define BUTTON_Right_B            0xDE
+
+#define BUTTON_Up                 0x2F
+#define BUTTON_Up_B               0xF6
+
+#define BUTTON_Down               0x1F
+#define BUTTON_Down_B             0xEE
+
+#define BUTTON_Next               0x3D
+#define BUTTON_Next_B             0x7E
+
+#define BUTTON_Enter              0x3E
+#define BUTTON_Enter_B            0xBE
+
+#define BUTTON_Reset_B            0xFC
+
+
+// debounce constants
+
+#define BUTTON_SENSE            160000
+#define BUTTON_DEBOUNCE		5000
+
+
+//  Galileo register stuff
+
+#define kGal_DevBank2Cfg        0x1466DB33
+#define kGal_DevBank2PReg       0x464
+#define kGal_DevBank3Cfg        0x146FDFFB
+#define kGal_DevBank3PReg       0x468
+
+// Network
+
+#define kIPADDR			1
+#define kNETMASK		2
+#define kGATEWAY		3
+#define kDNS			4
+
+#define kClassA			5
+#define kClassB			6
+#define kClassC			7
+
diff -Nru a/drivers/char/lp_old98.c b/drivers/char/lp_old98.c
--- a/drivers/char/lp_old98.c	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,537 +0,0 @@
-/*
- *	linux/drivers/char/lp_old98.c
- *
- * printer port driver for ancient PC-9800s with no bidirectional port support
- *
- * Copyright (C)  1998,99  Kousuke Takai <tak@kmc.kyoto-u.ac.jp>,
- *			   Kyoto University Microcomputer Club
- *
- * This driver is based on and has compatibility with `lp.c',
- * generic PC printer port driver.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/console.h>
-#include <linux/fs.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/lp.h>
-
-/*
- *  I/O port numbers
- */
-#define	LP_PORT_DATA	0x40
-#define	LP_PORT_STATUS	(LP_PORT_DATA + 2)
-#define	LP_PORT_STROBE	(LP_PORT_DATA + 4)
-#define LP_PORT_CONTROL	(LP_PORT_DATA + 6)
-
-#define	LP_PORT_H98MODE	0x0448
-#define	LP_PORT_EXTMODE	0x0149
-
-/*
- *  bit mask for I/O
- */
-#define	LP_MASK_nBUSY	(1 << 2)
-#define	LP_MASK_nSTROBE	(1 << 7)
-
-#define LP_CONTROL_ASSERT_STROBE	(0x0e)
-#define LP_CONTROL_NEGATE_STROBE	(0x0f)
-
-/*
- *  Acceptable maximum value for non-privileged user for LPCHARS ioctl.
- */
-#define LP_CHARS_NOPRIV_MAX	65535
-
-#define	DC1	'\x11'
-#define	DC3	'\x13'
-
-/* PC-9800s have at least and at most one old-style printer port. */
-static struct lp_struct lp = {
-	.flags	= LP_EXIST | LP_ABORTOPEN,
-	.chars	= LP_INIT_CHAR,
-	.time	= LP_INIT_TIME,
-	.wait	= LP_INIT_WAIT,
-};
-
-static	int	dc1_check;
-static spinlock_t lp_old98_lock = SPIN_LOCK_UNLOCKED;
-
-
-#undef LP_OLD98_DEBUG
-
-#ifdef CONFIG_PC9800_OLDLP_CONSOLE
-static struct console lp_old98_console;		/* defined later */
-static short saved_console_flags;
-#endif
-
-static DECLARE_WAIT_QUEUE_HEAD (lp_old98_waitq);
-
-static void lp_old98_timer_function(unsigned long data)
-{
-	if (inb(LP_PORT_STATUS) & LP_MASK_nBUSY)
-		wake_up_interruptible(&lp_old98_waitq);
-	else {
-		struct timer_list *t = (struct timer_list *) data;
-
-		t->expires = jiffies + 1;
-		add_timer(t);
-	}
-}
-
-static inline int lp_old98_wait_ready(void)
-{
-	struct timer_list timer;
-
-	init_timer(&timer);
-	timer.function = lp_old98_timer_function;
-	timer.expires = jiffies + 1;
-	timer.data = (unsigned long)&timer;
-	add_timer(&timer);
-	interruptible_sleep_on(&lp_old98_waitq);
-	del_timer(&timer);
-	return signal_pending(current);
-}
-
-static inline int lp_old98_char(char lpchar)
-{
-	unsigned long count = 0;
-#ifdef LP_STATS
-	int tmp;
-#endif
-
-	while (!(inb(LP_PORT_STATUS) & LP_MASK_nBUSY)) {
-		count++;
-		if (count >= lp.chars)
-			return 0;
-	}
-
-	outb(lpchar, LP_PORT_DATA);
-
-#ifdef LP_STATS
-	/*
-	 *  Update lp statsistics here (and between next two outb()'s).
-	 *  Time to compute it is part of storobe delay.
-	 */
-	if (count > lp.stats.maxwait) {
-#ifdef LP_OLD98_DEBUG
-		printk(KERN_DEBUG "lp_old98: success after %d counts.\n",
-		       count);
-#endif
-		lp.stats.maxwait = count;
-	}
-	count *= 256;
-	tmp = count - lp.stats.meanwait;
-	if (tmp < 0)
-		tmp = -tmp;
-#endif
-	ndelay(lp.wait);
-    
-	/* negate PSTB# (activate strobe)	*/
-	outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
-
-#ifdef LP_STATS
-	lp.stats.meanwait = (255 * lp.stats.meanwait + count + 128) / 256;
-	lp.stats.mdev = (127 * lp.stats.mdev + tmp + 64) / 128;
-	lp.stats.chars ++;
-#endif
-
-	ndelay(lp.wait);
-
-	/* assert PSTB# (deactivate strobe)	*/
-	outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
-
-	return 1;
-}
-
-static ssize_t lp_old98_write(struct file * file,
-			      const char * buf, size_t count,
-			      loff_t *dummy)
-{
-	unsigned long total_bytes_written = 0;
-
-	if (!access_ok(VERIFY_READ, buf, count))
-		return -EFAULT;
-
-#ifdef LP_STATS
-	if (jiffies - lp.lastcall > lp.time)
-		lp.runchars = 0;
-	lp.lastcall = jiffies;
-#endif
-
-	do {
-		unsigned long bytes_written = 0;
-		unsigned long copy_size
-			= (count < LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
-
-		if (__copy_from_user(lp.lp_buffer, buf, copy_size))
-			return -EFAULT;
-
-		while (bytes_written < copy_size) {
-			if (lp_old98_char(lp.lp_buffer[bytes_written]))
-				bytes_written ++;
-			else {
-#ifdef LP_STATS
-				int rc = lp.runchars + bytes_written;
-
-				if (rc > lp.stats.maxrun)
-					lp.stats.maxrun = rc;
-
-				lp.stats.sleeps ++;
-#endif
-#ifdef LP_OLD98_DEBUG
-				printk(KERN_DEBUG
-				       "lp_old98: sleeping at %d characters"
-				       " for %d jiffies\n",
-				       lp.runchars, lp.time);
-				lp.runchars = 0;
-#endif
-				if (lp_old98_wait_ready())
-					return ((total_bytes_written
-						 + bytes_written)
-						? : -EINTR);
-			}
-		}
-		total_bytes_written += bytes_written;
-		buf += bytes_written;
-#ifdef LP_STATS
-		lp.runchars += bytes_written;
-#endif
-		count -= bytes_written;
-	} while (count > 0);
-
-	return total_bytes_written;
-}
-
-static int lp_old98_open(struct inode * inode, struct file * file)
-{
-	if (iminor(inode) != 0)
-		return -ENXIO;
-
-	if (lp.flags & LP_BUSY)
-		return -EBUSY;
-
-	if (dc1_check && (lp.flags & LP_ABORTOPEN)
-	    && !(file->f_flags & O_NONBLOCK)) {
-		/*
-		 *  Check whether printer is on-line.
-		 *  PC-9800's old style port have only BUSY# as status input,
-		 *  so that it is impossible to distinguish that the printer is
-		 *  ready and that the printer is off-line or not connected
-		 *  (in both case BUSY# is in the same state). So:
-		 *
-		 *    (1) output DC1 (0x11) to printer port and do strobe.
-		 *    (2) watch BUSY# line for a while. If BUSY# is pulled
-		 *	  down, the printer will be ready. Otherwise,
-		 *	  it will be off-line (or not connected, or power-off,
-		 *	   ...).
-		 *
-		 *  The source of this procedure:
-		 *	Terumasa KODAKA, Kazufumi SHIMIZU, Yu HAYAMI:
-		 *		`PC-9801 Super Technique', Ascii, 1992.
-		 */
-		int count;
-		unsigned long flags;
-
-		/* interrupts while check is fairly bad */
-		spin_lock_irqsave(&lp_old98_lock, flags);
-
-		if (!lp_old98_char(DC1)) {
-			spin_unlock_irqrestore(&lp_old98_lock, flags);
-			return -EBUSY;
-		}
-		count = (unsigned int)dc1_check > 10000 ? 10000 : dc1_check;
-		while (inb(LP_PORT_STATUS) & LP_MASK_nBUSY) {
-			if (--count == 0) {
-				spin_unlock_irqrestore(&lp_old98_lock, flags);
-				return -ENODEV;
-			}
-		}
-		spin_unlock_irqrestore(&lp_old98_lock, flags);
-	}
-
-	if ((lp.lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL)) == NULL)
-		return -ENOMEM;
-
-	lp.flags |= LP_BUSY;
-
-#ifdef CONFIG_PC9800_OLDLP_CONSOLE
-	saved_console_flags = lp_old98_console.flags;
-	lp_old98_console.flags &= ~CON_ENABLED;
-#endif
-	return 0;
-}
-
-static int lp_old98_release(struct inode * inode, struct file * file)
-{
-	kfree(lp.lp_buffer);
-	lp.lp_buffer = NULL;
-	lp.flags &= ~LP_BUSY;
-#ifdef CONFIG_PC9800_OLDLP_CONSOLE
-	lp_old98_console.flags = saved_console_flags;
-#endif
-	return 0;
-}
-
-static int lp_old98_init_device(void)
-{
-	unsigned char data;
-
-	if ((data = inb(LP_PORT_EXTMODE)) != 0xFF && (data & 0x10)) {
-		printk(KERN_INFO
-		       "lp_old98: shutting down extended parallel port mode...\n");
-		outb(data & ~0x10, LP_PORT_EXTMODE);
-	}
-#ifdef	PC98_HW_H98
-	if ((pc98_hw_flags & PC98_HW_H98)
-	    && ((data = inb(LP_PORT_H98MODE)) & 0x01)) {
-		printk(KERN_INFO
-		       "lp_old98: shutting down H98 full centronics mode...\n");
-		outb(data & ~0x01, LP_PORT_H98MODE);
-	}
-#endif
-	return 0;
-}
-
-static int lp_old98_ioctl(struct inode *inode, struct file *file,
-			  unsigned int command, unsigned long arg)
-{
-	int retval = 0;
-
-	switch (command) {
-	case LPTIME:
-		lp.time = arg * HZ/100;
-		break;
-	case LPCHAR:
-		lp.chars = arg;
-		break;
-	case LPABORT:
-		if (arg)
-			lp.flags |= LP_ABORT;
-		else
-			lp.flags &= ~LP_ABORT;
-		break;
-	case LPABORTOPEN:
-		if (arg)
-			lp.flags |= LP_ABORTOPEN;
-		else
-			lp.flags &= ~LP_ABORTOPEN;
-		break;
-	case LPCAREFUL:
-		/* do nothing */
-		break;
-	case LPWAIT:
-		lp.wait = arg;
-		break;
-	case LPGETIRQ:
-		retval = put_user(0, (int *)arg);
-		break;
-	case LPGETSTATUS:
-		/*
-		 * convert PC-9800's status to IBM PC's one, so that tunelp(8)
-		 * works in the same way on this driver.
-		 */
-		retval = put_user((inb(LP_PORT_STATUS) & LP_MASK_nBUSY)
-					? (LP_PBUSY | LP_PERRORP) : LP_PERRORP,
-					(int *)arg);
-		break;
-	case LPRESET:
-		retval = lp_old98_init_device();
-		break;
-#ifdef LP_STATS
-	case LPGETSTATS:
-		if (copy_to_user((struct lp_stats *)arg, &lp.stats,
-				 sizeof(struct lp_stats)))
-			retval = -EFAULT;
-		else if (suser())
-			memset(&lp.stats, 0, sizeof(struct lp_stats));
-		break;
-#endif
-	case LPGETFLAGS:
-		retval = put_user(lp.flags, (int *)arg);
-		break;
-	case LPSETIRQ: 
-	default:
-		retval = -EINVAL;
-	}
-	return retval;
-}
-
-static struct file_operations lp_old98_fops = {
-	.owner		= THIS_MODULE,
-	.write		= lp_old98_write,
-	.ioctl		= lp_old98_ioctl,
-	.open		= lp_old98_open,
-	.release	= lp_old98_release,
-};
-
-/*
- *  Support for console on lp_old98
- */
-#ifdef CONFIG_PC9800_OLDLP_CONSOLE
-
-static inline void io_delay(void)
-{
-	unsigned char dummy;	/* actually not output */
-
-	asm volatile ("out%B0 %0,%1" : "=a"(dummy) : "N"(0x5f));
-}
-
-static void lp_old98_console_write(struct console *console,
-				    const char *s, unsigned int count)
-{
-	int i;
-	static unsigned int timeout_run = 0;
-
-	while (count) {
-		/* wait approx 1.2 seconds */
-		for (i = 2000000; !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY);
-								io_delay())
-			if (!--i) {
-				if (++timeout_run >= 10)
-					/* disable forever... */
-					console->flags &= ~CON_ENABLED;
-				return;
-			}
-
-		timeout_run = 0;
-
-		if (*s == '\n') {
-			outb('\r', LP_PORT_DATA);
-			io_delay();
-			io_delay();
-			outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
-			io_delay();
-			io_delay();
-			outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
-			io_delay();
-			io_delay();
-			for (i = 1000000;
-					!(inb(LP_PORT_STATUS) & LP_MASK_nBUSY);
-					io_delay())
-				if (!--i)
-					return;
-		}
-
-		outb(*s++, LP_PORT_DATA);
-		io_delay();
-		io_delay();
-		outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
-		io_delay();
-		io_delay();
-		outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
-		io_delay();
-		io_delay();
-
-		--count;
-	}
-}
-
-static struct console lp_old98_console = {
-	.name	= "lp_old98",
-	.write	= lp_old98_console_write,
-	.flags	= CON_PRINTBUFFER,
-	.index	= -1,
-};
-
-#endif	/* console on lp_old98 */
-
-static int __init lp_old98_init(void)
-{
-	char *errmsg = "I/O ports already occupied, giving up.";
-
-#ifdef	PC98_HW_H98
-	if (pc98_hw_flags & PC98_HW_H98)
-	    if (!request_region(LP_PORT_H98MODE, 1, "lp_old98")
-		goto err1;
-#endif
-	if (!request_region(LP_PORT_DATA,   1, "lp_old98"))
-		goto err2;
-	if (!request_region(LP_PORT_STATUS, 1, "lp_old98"))
-		goto err3;
-	if (!request_region(LP_PORT_STROBE, 1, "lp_old98"))
-		goto err4;
-	if (!request_region(LP_PORT_EXTMODE, 1, "lp_old98"))
-		goto err5;
-	if (!register_chrdev(LP_MAJOR, "lp", &lp_old98_fops)) {
-#ifdef CONFIG_PC9800_OLDLP_CONSOLE
-		register_console(&lp_old98_console);
-		printk(KERN_INFO "lp_old98: console ready\n");
-#endif
-		/*
-		 * rest are not needed by this driver,
-		 * but for locking out other printer drivers...
-		 */
-		lp_old98_init_device();
-		return 0;
-	} else
-		errmsg = "unable to register device";
-
-	release_region(LP_PORT_EXTMODE, 1);
-err5:
-	release_region(LP_PORT_STROBE, 1);
-err4:
-	release_region(LP_PORT_STATUS, 1);
-err3:
-	release_region(LP_PORT_DATA, 1);
-err2:
-#ifdef	PC98_HW_H98
-	if (pc98_hw_flags & PC98_HW_H98)
-	    release_region(LP_PORT_H98MODE, 1);
-
-err1:
-#endif
-	printk(KERN_ERR "lp_old98: %s\n", errmsg);
-	return -EBUSY;
-}
-
-static void __exit lp_old98_exit(void)
-{
-#ifdef CONFIG_PC9800_OLDLP_CONSOLE
-	unregister_console(&lp_old98_console);
-#endif
-	unregister_chrdev(LP_MAJOR, "lp");
-
-	release_region(LP_PORT_DATA,   1);
-	release_region(LP_PORT_STATUS, 1);
-	release_region(LP_PORT_STROBE, 1);
-#ifdef	PC98_HW_H98
-	if (pc98_hw_flags & PC98_HW_H98)
-		release_region(LP_PORT_H98MODE, 1);
-#endif
-	release_region(LP_PORT_EXTMODE, 1);
-}
-
-#ifndef MODULE
-static int __init lp_old98_setup(char *str)
-{
-        int ints[4];
-
-        str = get_options(str, ARRAY_SIZE(ints), ints);
-        if (ints[0] > 0)
-		dc1_check = ints[1];
-        return 1;
-}
-__setup("lp_old98_dc1_check=", lp_old98_setup);
-#endif
-
-MODULE_PARM(dc1_check, "i");
-MODULE_AUTHOR("Kousuke Takai <tak@kmc.kyoto-u.ac.jp>");
-MODULE_DESCRIPTION("PC-9800 old printer port driver");
-MODULE_LICENSE("GPL");
-
-module_init(lp_old98_init);
-module_exit(lp_old98_exit);
diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/mem.c	2004-06-23 19:04:27 -07:00
@@ -26,7 +26,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/pgalloc.h>
 
 #ifdef CONFIG_IA64
 # include <linux/efi.h>
diff -Nru a/drivers/char/misc.c b/drivers/char/misc.c
--- a/drivers/char/misc.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/misc.c	2004-06-23 19:04:28 -07:00
@@ -63,13 +63,8 @@
 #define DYNAMIC_MINORS 64 /* like dynamic majors */
 static unsigned char misc_minors[DYNAMIC_MINORS / 8];
 
-#ifdef CONFIG_SGI_NEWPORT_GFX
-extern void gfx_register(void);
-#endif
-extern void streamable_init(void);
 extern int rtc_DP8570A_init(void);
 extern int rtc_MK48T08_init(void);
-extern int ds1286_init(void);
 extern int pmu_device_init(void);
 extern int tosh_init(void);
 extern int i8k_init(void);
@@ -318,20 +313,8 @@
 #ifdef CONFIG_BVME6000
 	rtc_DP8570A_init();
 #endif
-#ifdef CONFIG_SGI_DS1286
-	ds1286_init();
-#endif
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_device_init();
-#endif
-#ifdef CONFIG_SGI_NEWPORT_GFX
-	gfx_register ();
-#endif
-#ifdef CONFIG_SGI_IP22
-	streamable_init ();
-#endif
-#ifdef CONFIG_SGI_NEWPORT_GFX
-	gfx_register ();
 #endif
 #ifdef CONFIG_TOSHIBA
 	tosh_init();
diff -Nru a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
--- a/drivers/char/mwave/3780i.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/mwave/3780i.c	2004-06-23 19:04:28 -07:00
@@ -467,10 +467,10 @@
 }
 
 
-int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void *pvBuffer,
+int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr)
 {
-	unsigned short *pusBuffer = pvBuffer;
+	unsigned short __user *pusBuffer = pvBuffer;
 	unsigned short val;
 
 
@@ -508,10 +508,10 @@
 }
 
 int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
-                                void *pvBuffer, unsigned uCount,
+                                void __user *pvBuffer, unsigned uCount,
                                 unsigned long ulDSPAddr)
 {
-	unsigned short *pusBuffer = pvBuffer;
+	unsigned short __user *pusBuffer = pvBuffer;
 	unsigned short val;
 
 
@@ -549,10 +549,10 @@
 }
 
 
-int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void *pvBuffer,
+int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                          unsigned uCount, unsigned long ulDSPAddr)
 {
-	unsigned short *pusBuffer = pvBuffer;
+	unsigned short __user *pusBuffer = pvBuffer;
 
 
 	PRINTK_5(TRACE_3780I,
@@ -590,10 +590,10 @@
 }
 
 
-int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void *pvBuffer,
+int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr)
 {
-	unsigned short *pusBuffer = pvBuffer;
+	unsigned short __user *pusBuffer = pvBuffer;
 
 	PRINTK_5(TRACE_3780I,
 		"3780i::dsp3780I_ReadIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
@@ -637,10 +637,10 @@
 }
 
 
-int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void *pvBuffer,
+int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                          unsigned uCount, unsigned long ulDSPAddr)
 {
-	unsigned short *pusBuffer = pvBuffer;
+	unsigned short __user *pusBuffer = pvBuffer;
 
 	PRINTK_5(TRACE_3780I,
 		"3780i::dsp3780I_WriteIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
diff -Nru a/drivers/char/mwave/3780i.h b/drivers/char/mwave/3780i.h
--- a/drivers/char/mwave/3780i.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/mwave/3780i.h	2004-06-23 19:04:27 -07:00
@@ -323,16 +323,16 @@
 int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings);
 int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings);
 int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings);
-int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void *pvBuffer,
+int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr);
 int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
-                                void *pvBuffer, unsigned uCount,
+                                void __user *pvBuffer, unsigned uCount,
                                 unsigned long ulDSPAddr);
-int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void *pvBuffer,
+int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                          unsigned uCount, unsigned long ulDSPAddr);
-int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void *pvBuffer,
+int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr);
-int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void *pvBuffer,
+int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                          unsigned uCount, unsigned long ulDSPAddr);
 unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
                                    unsigned long ulMsaAddr);
diff -Nru a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
--- a/drivers/char/mwave/mwavedd.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/char/mwave/mwavedd.c	2004-06-23 19:04:26 -07:00
@@ -121,6 +121,7 @@
 {
 	unsigned int retval = 0;
 	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
+	void __user *arg = (void __user *)ioarg;
 
 	PRINTK_5(TRACE_MWAVE,
 		"mwavedd::mwave_ioctl, entry inode %x file %x cmd %x arg %x\n",
@@ -164,8 +165,7 @@
 				" retval %x from tp3780I_QueryAbilities\n",
 				retval);
 			if (retval == 0) {
-				if( copy_to_user((char *) ioarg,
-							(char *) &rAbilities,
+				if( copy_to_user(arg, &rAbilities,
 							sizeof(MW_ABILITIES)) )
 					return -EFAULT;
 			}
@@ -179,13 +179,12 @@
 		case IOCTL_MW_READ_DATA:
 		case IOCTL_MW_READCLEAR_DATA: {
 			MW_READWRITE rReadData;
-			unsigned short *pusBuffer = 0;
+			unsigned short __user *pusBuffer = 0;
 	
-			if( copy_from_user((char *) &rReadData,
-						(char *) ioarg,
+			if( copy_from_user(&rReadData, arg,
 						sizeof(MW_READWRITE)) )
 				return -EFAULT;
-			pusBuffer = (unsigned short *) (rReadData.pBuf);
+			pusBuffer = (unsigned short __user *) (rReadData.pBuf);
 	
 			PRINTK_4(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
@@ -193,7 +192,7 @@
 				rReadData.ulDataLength, ioarg, pusBuffer);
 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
 					iocmd,
-					(void *) pusBuffer,
+					pusBuffer,
 					rReadData.ulDataLength,
 					rReadData.usDspAddress);
 		}
@@ -201,12 +200,12 @@
 	
 		case IOCTL_MW_READ_INST: {
 			MW_READWRITE rReadData;
-			unsigned short *pusBuffer = 0;
+			unsigned short __user *pusBuffer = 0;
 	
-			if( copy_from_user((char *) &rReadData, (char *) ioarg,
+			if( copy_from_user(&rReadData, arg,
 						sizeof(MW_READWRITE)) )
 				return -EFAULT;
-			pusBuffer = (unsigned short *) (rReadData.pBuf);
+			pusBuffer = (unsigned short __user *) (rReadData.pBuf);
 	
 			PRINTK_4(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl IOCTL_MW_READ_INST,"
@@ -222,13 +221,12 @@
 	
 		case IOCTL_MW_WRITE_DATA: {
 			MW_READWRITE rWriteData;
-			unsigned short *pusBuffer = 0;
+			unsigned short __user *pusBuffer = 0;
 	
-			if( copy_from_user((char *) &rWriteData,
-						(char *) ioarg,
+			if( copy_from_user(&rWriteData, arg,
 						sizeof(MW_READWRITE)) )
 				return -EFAULT;
-			pusBuffer = (unsigned short *) (rWriteData.pBuf);
+			pusBuffer = (unsigned short __user *) (rWriteData.pBuf);
 	
 			PRINTK_4(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA,"
@@ -244,13 +242,12 @@
 	
 		case IOCTL_MW_WRITE_INST: {
 			MW_READWRITE rWriteData;
-			unsigned short *pusBuffer = 0;
+			unsigned short __user *pusBuffer = 0;
 	
-			if( copy_from_user((char *) &rWriteData,
-						(char *) ioarg,
+			if( copy_from_user(&rWriteData, arg,
 						sizeof(MW_READWRITE)) )
 				return -EFAULT;
-			pusBuffer = (unsigned short *) (rWriteData.pBuf);
+			pusBuffer = (unsigned short __user *)(rWriteData.pBuf);
 	
 			PRINTK_4(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST,"
@@ -388,7 +385,7 @@
 }
 
 
-static ssize_t mwave_read(struct file *file, char *buf, size_t count,
+static ssize_t mwave_read(struct file *file, char __user *buf, size_t count,
                           loff_t * ppos)
 {
 	PRINTK_5(TRACE_MWAVE,
@@ -399,7 +396,7 @@
 }
 
 
-static ssize_t mwave_write(struct file *file, const char *buf,
+static ssize_t mwave_write(struct file *file, const char __user *buf,
                            size_t count, loff_t * ppos)
 {
 	PRINTK_5(TRACE_MWAVE,
diff -Nru a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
--- a/drivers/char/mwave/tp3780i.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/mwave/tp3780i.c	2004-06-23 19:04:25 -07:00
@@ -522,7 +522,7 @@
 }
 
 int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
-                               void *pvBuffer, unsigned int uCount,
+                               void __user *pvBuffer, unsigned int uCount,
                                unsigned long ulDSPAddr)
 {
 	int retval = 0;
@@ -558,7 +558,7 @@
 
 
 int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
-                               void *pvBuffer, unsigned int uCount,
+                               void __user *pvBuffer, unsigned int uCount,
                                unsigned long ulDSPAddr)
 {
 	int retval = 0;
diff -Nru a/drivers/char/mwave/tp3780i.h b/drivers/char/mwave/tp3780i.h
--- a/drivers/char/mwave/tp3780i.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/mwave/tp3780i.h	2004-06-23 19:04:25 -07:00
@@ -93,10 +93,10 @@
 int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities);
 int tp3780I_Cleanup(THINKPAD_BD_DATA * pBDData);
 int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
-                               void *pvBuffer, unsigned int uCount,
+                               void __user *pvBuffer, unsigned int uCount,
                                unsigned long ulDSPAddr);
 int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
-                               void *pvBuffer, unsigned int uCount,
+                               void __user *pvBuffer, unsigned int uCount,
                                unsigned long ulDSPAddr);
 
 
diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c
--- a/drivers/char/raw.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/raw.c	2004-06-23 19:04:27 -07:00
@@ -18,6 +18,7 @@
 #include <linux/capability.h>
 #include <linux/uio.h>
 #include <linux/cdev.h>
+#include <linux/device.h>
 
 #include <asm/uaccess.h>
 
@@ -26,6 +27,7 @@
 	int inuse;
 };
 
+static struct class_simple *raw_class;
 static struct raw_device_data raw_devices[MAX_RAW_MINORS];
 static DECLARE_MUTEX(raw_mutex);
 static struct file_operations raw_ctl_fops;	     /* forward declaration */
@@ -123,6 +125,13 @@
 	return ioctl_by_bdev(bdev, command, arg);
 }
 
+static void bind_device(struct raw_config_request rq)
+{
+	class_simple_device_remove(MKDEV(RAW_MAJOR, rq.raw_minor));
+	class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq.raw_minor),
+				      NULL, "raw%d", rq.raw_minor);
+}
+
 /*
  * Deal with ioctls against the raw-device control interface, to bind
  * and unbind other raw devices.
@@ -191,12 +200,15 @@
 			if (rq.block_major == 0 && rq.block_minor == 0) {
 				/* unbind */
 				rawdev->binding = NULL;
+				class_simple_device_remove(MKDEV(RAW_MAJOR, rq.raw_minor));
 			} else {
 				rawdev->binding = bdget(dev);
 				if (rawdev->binding == NULL)
 					err = -ENOMEM;
-				else
+				else {
 					__module_get(THIS_MODULE);
+					bind_device(rq);
+					}
 			}
 			up(&raw_mutex);
 		} else {
@@ -287,6 +299,15 @@
 		goto error;
 	}
 
+	raw_class = class_simple_create(THIS_MODULE, "raw");
+	if (IS_ERR(raw_class)) {
+		printk(KERN_ERR "Error creating raw class.\n");
+		cdev_del(&raw_cdev);
+		unregister_chrdev_region(dev, MAX_RAW_MINORS);
+		goto error;
+	}
+	class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
+
 	devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
 		      S_IFCHR | S_IRUGO | S_IWUGO,
 		      "raw/rawctl");
@@ -309,6 +330,8 @@
 		devfs_remove("raw/raw%d", i);
 	devfs_remove("raw/rawctl");
 	devfs_remove("raw");
+	class_simple_device_remove(MKDEV(RAW_MAJOR, 0));
+	class_simple_destroy(raw_class);
 	cdev_del(&raw_cdev);
 	unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
 }
diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c
--- a/drivers/char/rtc.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/char/rtc.c	2004-06-23 19:04:29 -07:00
@@ -97,6 +97,11 @@
 static int rtc_irq = PCI_IRQ_NONE;
 #endif
 
+#ifdef	CONFIG_HPET_RTC_IRQ
+#undef	RTC_IRQ
+#define	RTC_IRQ	0
+#endif
+
 #ifdef RTC_IRQ
 static int rtc_has_irq = 1;
 #endif
diff -Nru a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
--- a/drivers/char/synclinkmp.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/synclinkmp.c	2004-06-23 19:04:25 -07:00
@@ -567,17 +567,17 @@
 
 /* ioctl handlers */
 
-static int  get_stats(SLMP_INFO *info, struct mgsl_icount *user_icount);
-static int  get_params(SLMP_INFO *info, MGSL_PARAMS *params);
-static int  set_params(SLMP_INFO *info, MGSL_PARAMS *params);
-static int  get_txidle(SLMP_INFO *info, int*idle_mode);
+static int  get_stats(SLMP_INFO *info, struct mgsl_icount __user *user_icount);
+static int  get_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
+static int  set_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
+static int  get_txidle(SLMP_INFO *info, int __user *idle_mode);
 static int  set_txidle(SLMP_INFO *info, int idle_mode);
 static int  tx_enable(SLMP_INFO *info, int enable);
 static int  tx_abort(SLMP_INFO *info);
 static int  rx_enable(SLMP_INFO *info, int enable);
 static int  map_status(int signals);
 static int  modem_input_wait(SLMP_INFO *info,int arg);
-static int  wait_mgsl_event(SLMP_INFO *info, int *mask_ptr);
+static int  wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
 static int  tiocmget(struct tty_struct *tty, struct file *file);
 static int  tiocmset(struct tty_struct *tty, struct file *file,
 		     unsigned int set, unsigned int clear);
@@ -692,7 +692,7 @@
  * This allows remote debugging of dynamically loadable modules.
  */
 static void* synclinkmp_get_text_ptr(void);
-static void* synclinkmp_get_text_ptr() {return synclinkmp_get_text_ptr;}
+static void* synclinkmp_get_text_ptr(void) {return synclinkmp_get_text_ptr;}
 
 static inline int sanity_check(SLMP_INFO *info,
 			       char *name, const char *routine)
@@ -1333,8 +1333,9 @@
 	SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
 	int error;
 	struct mgsl_icount cnow;	/* kernel counter temps */
-	struct serial_icounter_struct *p_cuser;	/* user space */
+	struct serial_icounter_struct __user *p_cuser;	/* user space */
 	unsigned long flags;
+	void __user *argp = (void __user *)arg;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):%s ioctl() cmd=%08X\n", __FILE__,__LINE__,
@@ -1351,23 +1352,23 @@
 
 	switch (cmd) {
 	case MGSL_IOCGPARAMS:
-		return get_params(info,(MGSL_PARAMS *)arg);
+		return get_params(info, argp);
 	case MGSL_IOCSPARAMS:
-		return set_params(info,(MGSL_PARAMS *)arg);
+		return set_params(info, argp);
 	case MGSL_IOCGTXIDLE:
-		return get_txidle(info,(int*)arg);
+		return get_txidle(info, argp);
 	case MGSL_IOCSTXIDLE:
-		return set_txidle(info,(int)arg);
+		return set_txidle(info, (int)arg);
 	case MGSL_IOCTXENABLE:
-		return tx_enable(info,(int)arg);
+		return tx_enable(info, (int)arg);
 	case MGSL_IOCRXENABLE:
-		return rx_enable(info,(int)arg);
+		return rx_enable(info, (int)arg);
 	case MGSL_IOCTXABORT:
 		return tx_abort(info);
 	case MGSL_IOCGSTATS:
-		return get_stats(info,(struct mgsl_icount*)arg);
+		return get_stats(info, argp);
 	case MGSL_IOCWAITEVENT:
-		return wait_mgsl_event(info,(int*)arg);
+		return wait_mgsl_event(info, argp);
 	case MGSL_IOCLOOPTXDONE:
 		return 0; // TODO: Not supported, need to document
 		/* Wait for modem input (DCD,RI,DSR,CTS) change
@@ -1386,7 +1387,7 @@
 		spin_lock_irqsave(&info->lock,flags);
 		cnow = info->icount;
 		spin_unlock_irqrestore(&info->lock,flags);
-		p_cuser = (struct serial_icounter_struct *) arg;
+		p_cuser = argp;
 		PUT_USER(error,cnow.cts, &p_cuser->cts);
 		if (error) return error;
 		PUT_USER(error,cnow.dsr, &p_cuser->dsr);
@@ -2762,7 +2763,7 @@
 	program_hw(info);
 }
 
-static int get_stats(SLMP_INFO * info, struct mgsl_icount *user_icount)
+static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)
 {
 	int err;
 
@@ -2781,7 +2782,7 @@
 	return 0;
 }
 
-static int get_params(SLMP_INFO * info, MGSL_PARAMS *user_params)
+static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params)
 {
 	int err;
 	if (debug_level >= DEBUG_LEVEL_INFO)
@@ -2799,7 +2800,7 @@
 	return 0;
 }
 
-static int set_params(SLMP_INFO * info, MGSL_PARAMS *new_params)
+static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params)
 {
  	unsigned long flags;
 	MGSL_PARAMS tmp_params;
@@ -2825,7 +2826,7 @@
 	return 0;
 }
 
-static int get_txidle(SLMP_INFO * info, int*idle_mode)
+static int get_txidle(SLMP_INFO * info, int __user *idle_mode)
 {
 	int err;
 
@@ -2938,7 +2939,7 @@
 
 /* wait for specified event to occur
  */
-static int wait_mgsl_event(SLMP_INFO * info, int * mask_ptr)
+static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
 {
  	unsigned long flags;
 	int s;
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/tty_io.c	2004-06-23 19:04:27 -07:00
@@ -91,6 +91,7 @@
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <linux/device.h>
+#include <linux/idr.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -128,6 +129,8 @@
 #ifdef CONFIG_UNIX98_PTYS
 extern struct tty_driver *ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
 extern int pty_limit;		/* Config limit on Unix98 ptys */
+static DEFINE_IDR(allocated_ptys);
+static DECLARE_MUTEX(allocated_ptys_lock);
 #endif
 
 extern void disable_early_printk(void);
@@ -1065,6 +1068,7 @@
 {
 	struct tty_struct *tty, *o_tty;
 	int	pty_master, tty_closing, o_tty_closing, do_sleep;
+	int	devpts_master;
 	int	idx;
 	char	buf[64];
 	
@@ -1079,6 +1083,7 @@
 	idx = tty->index;
 	pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 		      tty->driver->subtype == PTY_TYPE_MASTER);
+	devpts_master = pty_master && (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM);
 	o_tty = tty->link;
 
 #ifdef TTY_PARANOIA_CHECK
@@ -1295,11 +1300,21 @@
 		o_tty->ldisc = ldiscs[N_TTY];
 	}
 
-	/* 
+	/*
 	 * The release_mem function takes care of the details of clearing
 	 * the slots and preserving the termios structure.
 	 */
 	release_mem(tty, idx);
+
+#ifdef CONFIG_UNIX98_PTYS
+	/* Make this pty number available for reallocation */
+	if (devpts_master) {
+		down(&allocated_ptys_lock);
+		idr_remove(&allocated_ptys, idx);
+		up(&allocated_ptys_lock);
+	}
+#endif
+
 }
 
 /*
@@ -1322,8 +1337,12 @@
 	int index;
 	dev_t device = inode->i_rdev;
 	unsigned short saved_flags = filp->f_flags;
+
 retry_open:
 	noctty = filp->f_flags & O_NOCTTY;
+	index  = -1;
+	retval = 0;
+
 	if (device == MKDEV(TTYAUX_MAJOR,0)) {
 		if (!current->signal->tty)
 			return -ENXIO;
@@ -1361,24 +1380,40 @@
 
 #ifdef CONFIG_UNIX98_PTYS
 	if (device == MKDEV(TTYAUX_MAJOR,2)) {
+		int idr_ret;
+
 		/* find a device that is not in use. */
-		static int next_ptmx_dev = 0;
-		retval = -1;
+		down(&allocated_ptys_lock);
+		if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
+			up(&allocated_ptys_lock);
+			return -ENOMEM;
+		}
+		idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
+		if (idr_ret < 0) {
+			up(&allocated_ptys_lock);
+			if (idr_ret == -EAGAIN)
+				return -ENOMEM;
+			return -EIO;
+		}
+		if (index >= pty_limit) {
+			idr_remove(&allocated_ptys, index);
+			up(&allocated_ptys_lock);
+			return -EIO;
+		}
+		up(&allocated_ptys_lock);
+
 		driver = ptm_driver;
-		while (driver->refcount < pty_limit) {
-			index = next_ptmx_dev;
-			next_ptmx_dev = (next_ptmx_dev+1) % driver->num;
-			if (!init_dev(driver, index, &tty))
-				goto ptmx_found; /* ok! */
+		retval = init_dev(driver, index, &tty);
+		if (retval) {
+			down(&allocated_ptys_lock);
+			idr_remove(&allocated_ptys, index);
+			up(&allocated_ptys_lock);
+			return retval;
 		}
-		return -EIO; /* no free ptys */
-	ptmx_found:
+
 		set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
-		if (devpts_pty_new(tty->link)) {
-			/* BADNESS - need to destroy both ptm and pts! */
-			return -ENOMEM;
-		}
-		noctty = 1;
+		if (devpts_pty_new(tty->link))
+			retval = -ENOMEM;
 	} else
 #endif
 	{
@@ -1400,10 +1435,12 @@
 #ifdef TTY_DEBUG_HANGUP
 	printk(KERN_DEBUG "opening %s...", tty->name);
 #endif
-	if (tty->driver->open)
-		retval = tty->driver->open(tty, filp);
-	else
-		retval = -ENODEV;
+	if (!retval) {
+		if (tty->driver->open)
+			retval = tty->driver->open(tty, filp);
+		else
+			retval = -ENODEV;
+	}
 	filp->f_flags = saved_flags;
 
 	if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
@@ -1413,6 +1450,14 @@
 #ifdef TTY_DEBUG_HANGUP
 		printk(KERN_DEBUG "error %d in opening %s...", retval,
 		       tty->name);
+#endif
+
+#ifdef CONFIG_UNIX98_PTYS
+		if (index != -1) {
+			down(&allocated_ptys_lock);
+			idr_remove(&allocated_ptys, index);
+			up(&allocated_ptys_lock);
+		}
 #endif
 
 		release_dev(filp);
diff -Nru a/drivers/char/upd4990a.c b/drivers/char/upd4990a.c
--- a/drivers/char/upd4990a.c	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,432 +0,0 @@
-/*
- * NEC PC-9800 Real Time Clock interface for Linux	
- *
- * Copyright (C) 1997-2001  Linux/98 project,
- *			    Kyoto University Microcomputer Club.
- *
- * Based on:
- *	drivers/char/rtc.c by Paul Gortmaker
- *
- * Changes:
- *  2001-02-09	Call check_region on rtc_init and do not request I/O 0033h.
- *		Call del_timer and release_region on rtc_exit. -- tak
- *  2001-07-14	Rewrite <linux/upd4990a.h> and split to <linux/upd4990a.h>
- *		and <asm-i386/upd4990a.h>.
- *		Introduce a lot of spin_lock/unlock (&rtc_lock).
- */
-
-#define RTC98_VERSION	"1.2"
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
-#include <linux/upd4990a.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/*
- *	We sponge a minor off of the misc major. No need slurping
- *	up another valuable major dev number for this. If you add
- *	an ioctl, make sure you don't conflict with SPARC's RTC
- *	ioctls.
- */
-
-static struct fasync_struct *rtc_async_queue;
-
-static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
-
-static struct timer_list rtc_uie_timer;
-static u8 old_refclk;
-
-static int rtc_ioctl(struct inode *inode, struct file *file,
-			unsigned int cmd, unsigned long arg);
-
-static int rtc_read_proc(char *page, char **start, off_t off,
-			  int count, int *eof, void *data);
-
-/*
- *	Bits in rtc_status. (5 bits of room for future expansion)
- */
-
-#define RTC_IS_OPEN		0x01	/* means /dev/rtc is in use	*/
-#define RTC_TIMER_ON            0x02    /* not used */
-#define RTC_UIE_TIMER_ON        0x04	/* UIE emulation timer is active */
-
-/*
- * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is
- * protected by the big kernel lock. However, ioctl can still disable the timer
- * in rtc_status and then with del_timer after the interrupt has read
- * rtc_status but before mod_timer is called, which would then reenable the
- * timer (but you would need to have an awful timing before you'd trip on it)
- */
-static unsigned char rtc_status;	/* bitmapped status byte.	*/
-static unsigned long rtc_irq_data;	/* our output to the world	*/
-
-static const unsigned char days_in_mo[] = 
-{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-extern spinlock_t rtc_lock;	/* defined in arch/i386/kernel/time.c */
-
-static void rtc_uie_intr(unsigned long data)
-{
-	u8 refclk, tmp;
-
-	/* Kernel timer does del_timer internally before calling
-	   each timer entry, so this is unnecessary.
-	   del_timer(&rtc_uie_timer);  */
-	spin_lock(&rtc_lock);
-
-	/* Detect rising edge of 1Hz reference clock.  */
-	refclk = UPD4990A_READ_DATA();
-	tmp = old_refclk & refclk;
-	old_refclk = ~refclk;
-	if (!(tmp & 1))
-		rtc_irq_data += 0x100;
-
-	spin_unlock(&rtc_lock);
-
-	if (!(tmp & 1)) {
-		/* Now do the rest of the actions */
-		wake_up_interruptible(&rtc_wait);
-		kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
-	}
-
-	rtc_uie_timer.expires = jiffies + 1;
-	add_timer(&rtc_uie_timer);
-}
-
-/*
- *	Now all the various file operations that we export.
- */
-
-static ssize_t rtc_read(struct file *file, char *buf,
-			size_t count, loff_t *ppos)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long data;
-	ssize_t retval = 0;
-	
-	if (count < sizeof(unsigned long))
-		return -EINVAL;
-
-	add_wait_queue(&rtc_wait, &wait);
-
-	set_current_state(TASK_INTERRUPTIBLE);
-
-	do {
-		/* First make it right. Then make it fast. Putting this whole
-		 * block within the parentheses of a while would be too
-		 * confusing. And no, xchg() is not the answer. */
-		spin_lock_irq(&rtc_lock);
-		data = rtc_irq_data;
-		rtc_irq_data = 0;
-		spin_unlock_irq(&rtc_lock);
-
-		if (data != 0)
-			break;
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EAGAIN;
-			goto out;
-		}
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			goto out;
-		}
-		schedule();
-	} while (1);
-
-	retval = put_user(data, (unsigned long *)buf);
-	if (!retval)
-		retval = sizeof(unsigned long); 
- out:
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&rtc_wait, &wait);
-
-	return retval;
-}
-
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-		     unsigned long arg)
-{
-	struct rtc_time wtime; 
-	struct upd4990a_raw_data raw;
-
-	switch (cmd) {
-	case RTC_UIE_OFF:	/* Mask ints from RTC updates.	*/
-		spin_lock_irq(&rtc_lock);
-		if (rtc_status & RTC_UIE_TIMER_ON) {
-			rtc_status &= ~RTC_UIE_TIMER_ON;
-			del_timer(&rtc_uie_timer);
-		}
-		spin_unlock_irq(&rtc_lock);
-		return 0;
-
-	case RTC_UIE_ON:	/* Allow ints for RTC updates.	*/
-		spin_lock_irq(&rtc_lock);
-		rtc_irq_data = 0;
-		if (!(rtc_status & RTC_UIE_TIMER_ON)) {
-			rtc_status |= RTC_UIE_TIMER_ON;
-			rtc_uie_timer.expires = jiffies + 1;
-			add_timer(&rtc_uie_timer);
-		}
-		/* Just in case... */
-		upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
-		old_refclk = ~UPD4990A_READ_DATA();
-		spin_unlock_irq(&rtc_lock);
-		return 0;
-
-	case RTC_RD_TIME:	/* Read the time/date from RTC	*/
-		spin_lock_irq(&rtc_lock);
-		upd4990a_get_time(&raw, 0);
-		spin_unlock_irq(&rtc_lock);
-
-		wtime.tm_sec	= BCD2BIN(raw.sec);
-		wtime.tm_min	= BCD2BIN(raw.min);
-		wtime.tm_hour	= BCD2BIN(raw.hour);
-		wtime.tm_mday	= BCD2BIN(raw.mday);
-		wtime.tm_mon	= raw.mon - 1; /* convert to 0-base */
-		wtime.tm_wday	= raw.wday;
-
-		/*
-		 * Account for differences between how the RTC uses the values
-		 * and how they are defined in a struct rtc_time;
-		 */
-		if ((wtime.tm_year = BCD2BIN(raw.year)) < 95)
-			wtime.tm_year += 100;
-
-		wtime.tm_isdst = 0;
-		break;
-
-	case RTC_SET_TIME:	/* Set the RTC */
-	{
-		int leap_yr;
-
-		if (!capable(CAP_SYS_TIME))
-			return -EACCES;
-
-		if (copy_from_user(&wtime, (struct rtc_time *) arg,
-				    sizeof (struct rtc_time)))
-			return -EFAULT;
-
-		/* Valid year is 1995 - 2094, inclusive.  */
-		if (wtime.tm_year < 95 || wtime.tm_year > 194)
-			return -EINVAL;
-
-		if (wtime.tm_mon > 11 || wtime.tm_mday == 0)
-			return -EINVAL;
-
-		/* For acceptable year domain (1995 - 2094),
-		   this IS sufficient.  */
-		leap_yr = !(wtime.tm_year % 4);
-
-		if (wtime.tm_mday > (days_in_mo[wtime.tm_mon]
-				     + (wtime.tm_mon == 2 && leap_yr)))
-			return -EINVAL;
-			
-		if (wtime.tm_hour >= 24
-		    || wtime.tm_min >= 60 || wtime.tm_sec >= 60)
-			return -EINVAL;
-
-		if (wtime.tm_wday > 6)
-			return -EINVAL;
-
-		raw.sec  = BIN2BCD(wtime.tm_sec);
-		raw.min  = BIN2BCD(wtime.tm_min);
-		raw.hour = BIN2BCD(wtime.tm_hour);
-		raw.mday = BIN2BCD(wtime.tm_mday);
-		raw.mon  = wtime.tm_mon + 1;
-		raw.wday = wtime.tm_wday;
-		raw.year = BIN2BCD(wtime.tm_year % 100);
-
-		spin_lock_irq(&rtc_lock);
-		upd4990a_set_time(&raw, 0);
-		spin_unlock_irq(&rtc_lock);
-
-		return 0;
-	}
-	default:
-		return -EINVAL;
-	}
-	return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
-}
-
-/*
- *	We enforce only one user at a time here with the open/close.
- *	Also clear the previous interrupt data on an open, and clean
- *	up things on a close.
- */
-
-static int rtc_open(struct inode *inode, struct file *file)
-{
-	spin_lock_irq(&rtc_lock);
-
-	if(rtc_status & RTC_IS_OPEN)
-		goto out_busy;
-
-	rtc_status |= RTC_IS_OPEN;
-
-	rtc_irq_data = 0;
-	spin_unlock_irq(&rtc_lock);
-	return 0;
-
- out_busy:
-	spin_unlock_irq(&rtc_lock);
-	return -EBUSY;
-}
-
-static int rtc_fasync(int fd, struct file *filp, int on)
-{
-	return fasync_helper(fd, filp, on, &rtc_async_queue);
-}
-
-static int rtc_release(struct inode *inode, struct file *file)
-{
-	del_timer(&rtc_uie_timer);
-
-	if (file->f_flags & FASYNC)
-		rtc_fasync(-1, file, 0);
-
-	rtc_irq_data = 0;
-
-	/* No need for locking -- nobody else can do anything until this rmw is
-	 * committed, and no timer is running. */
-	rtc_status &= ~(RTC_IS_OPEN | RTC_UIE_TIMER_ON);
-	return 0;
-}
-
-static unsigned int rtc_poll(struct file *file, poll_table *wait)
-{
-	unsigned long l;
-
-	poll_wait(file, &rtc_wait, wait);
-
-	spin_lock_irq(&rtc_lock);
-	l = rtc_irq_data;
-	spin_unlock_irq(&rtc_lock);
-
-	if (l != 0)
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-/*
- *	The various file operations we support.
- */
-
-static struct file_operations rtc_fops = {
-	.owner		= THIS_MODULE,
-	.read		= rtc_read,
-	.poll		= rtc_poll,
-	.ioctl		= rtc_ioctl,
-	.open		= rtc_open,
-	.release	= rtc_release,
-	.fasync		= rtc_fasync,
-};
-
-static struct miscdevice rtc_dev=
-{
-	.minor	= RTC_MINOR,
-	.name	= "rtc",
-	.fops	= &rtc_fops,
-};
-
-static int __init rtc_init(void)
-{
-	int err = 0;
-
-	if (!request_region(UPD4990A_IO, 1, "rtc")) {
-		printk(KERN_ERR "upd4990a: could not acquire I/O port %#x\n",
-			UPD4990A_IO);
-		return -EBUSY;
-	}
-
-	err = misc_register(&rtc_dev);
-	if (err) {
-		printk(KERN_ERR "upd4990a: can't misc_register() on minor=%d\n",
-			RTC_MINOR);
-		release_region(UPD4990A_IO, 1);
-		return err;
-	}
-		
-#if 0
-	printk(KERN_INFO "\xB6\xDA\xDD\xC0\xDE \xC4\xDE\xB9\xB2 Driver\n");  /* Calender Clock Driver */
-#else
-	printk(KERN_INFO
-	       "Real Time Clock driver for NEC PC-9800 v" RTC98_VERSION "\n");
-#endif
-	create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL);
-
-	init_timer(&rtc_uie_timer);
-	rtc_uie_timer.function = rtc_uie_intr;
-
-	return 0;
-}
-
-module_init (rtc_init);
-
-static void __exit rtc_exit(void)
-{
-	del_timer(&rtc_uie_timer);
-	release_region(UPD4990A_IO, 1);
-	remove_proc_entry("driver/rtc", NULL);
-	misc_deregister(&rtc_dev);
-}
-
-module_exit (rtc_exit);
-
-/*
- *	Info exported via "/proc/driver/rtc".
- */
-
-static inline int rtc_get_status(char *buf)
-{
-	char *p;
-	unsigned int year;
-	struct upd4990a_raw_data data;
-
-	p = buf;
-
-	upd4990a_get_time(&data, 0);
-
-	/*
-	 * 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.
-	 */
-	if ((year = BCD2BIN(data.year) + 1900) < 1995)
-		year += 100;
-	p += sprintf(p,
-		     "rtc_time\t: %02d:%02d:%02d\n"
-		     "rtc_date\t: %04d-%02d-%02d\n",
-		     BCD2BIN(data.hour), BCD2BIN(data.min),
-		     BCD2BIN(data.sec),
-		     year, data.mon, BCD2BIN(data.mday));
-
-	return  p - buf;
-}
-
-static int rtc_read_proc(char *page, char **start, off_t off,
-			 int count, int *eof, void *data)
-{
-	int len = rtc_get_status(page);
-
-	if (len <= off + count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-	return len;
-}
diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
--- a/drivers/char/watchdog/Kconfig	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/Kconfig	2004-06-23 19:04:27 -07:00
@@ -96,12 +96,13 @@
 	  Say N if you are unsure.
 
 config SA1100_WATCHDOG
-	tristate "SA1100 watchdog"
-	depends on WATCHDOG && ARCH_SA1100
+	tristate "SA1100/PXA2xx watchdog"
+	depends on WATCHDOG && ( ARCH_SA1100 || ARCH_PXA )
 	help
-	  Watchdog timer embedded into SA11x0 chips. This will reboot your
-	  system when timeout is reached.
-	  NOTE, that once enabled, this timer cannot be disabled.
+	  Watchdog timer embedded into SA11x0 and PXA2xx chips. This will
+	  reboot your system when timeout is reached.
+
+	  NOTE: once enabled, this timer cannot be disabled.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called sa1100_wdt.
diff -Nru a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c
--- a/drivers/char/watchdog/acquirewdt.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/acquirewdt.c	2004-06-23 19:04:27 -07:00
@@ -111,7 +111,7 @@
  *	/dev/watchdog handling.
  */
 
-static ssize_t acq_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
@@ -146,6 +146,8 @@
 	unsigned long arg)
 {
 	int options, retval = -EINVAL;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident =
 	{
 		.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
@@ -156,22 +158,22 @@
 	switch(cmd)
 	{
 	case WDIOC_GETSUPPORT:
-	  return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)) ? -EFAULT : 0;
+	  return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
 
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETBOOTSTATUS:
-	  return put_user(0, (int *)arg);
+	  return put_user(0, p);
 
 	case WDIOC_KEEPALIVE:
 	  acq_keepalive();
 	  return 0;
 
 	case WDIOC_GETTIMEOUT:
-	  return put_user(WATCHDOG_HEARTBEAT, (int *)arg);
+	  return put_user(WATCHDOG_HEARTBEAT, p);
 
 	case WDIOC_SETOPTIONS:
 	{
-	    if (get_user(options, (int *)arg))
+	    if (get_user(options, p))
 	      return -EFAULT;
 
 	    if (options & WDIOS_DISABLECARD)
diff -Nru a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c
--- a/drivers/char/watchdog/advantechwdt.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/char/watchdog/advantechwdt.c	2004-06-23 19:04:26 -07:00
@@ -100,7 +100,7 @@
 }
 
 static ssize_t
-advwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
@@ -130,6 +130,8 @@
 	  unsigned long arg)
 {
 	int new_timeout;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
@@ -138,20 +140,20 @@
 
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
-	  if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+	  if (copy_to_user(argp, &ident, sizeof(ident)))
 	    return -EFAULT;
 	  break;
 
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETBOOTSTATUS:
-	  return put_user(0, (int *)arg);
+	  return put_user(0, p);
 
 	case WDIOC_KEEPALIVE:
 	  advwdt_ping();
 	  break;
 
 	case WDIOC_SETTIMEOUT:
-	  if (get_user(new_timeout, (int *)arg))
+	  if (get_user(new_timeout, p))
 		  return -EFAULT;
 	  if ((new_timeout < 1) || (new_timeout > 63))
 		  return -EINVAL;
@@ -160,13 +162,13 @@
 	  /* Fall */
 
 	case WDIOC_GETTIMEOUT:
-	  return put_user(timeout, (int *)arg);
+	  return put_user(timeout, p);
 
 	case WDIOC_SETOPTIONS:
 	{
 	  int options, retval = -EINVAL;
 
-	  if (get_user(options, (int *)arg))
+	  if (get_user(options, p))
 	    return -EFAULT;
 
 	  if (options & WDIOS_DISABLECARD) {
diff -Nru a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c
--- a/drivers/char/watchdog/alim1535_wdt.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/char/watchdog/alim1535_wdt.c	2004-06-23 19:04:26 -07:00
@@ -138,7 +138,7 @@
  *	the next close to turn off the watchdog.
  */
 
-static ssize_t ali_write(struct file *file, const char *data,
+static ssize_t ali_write(struct file *file, const char __user *data,
 			      size_t len, loff_t * ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
@@ -184,6 +184,8 @@
 static int ali_ioctl(struct inode *inode, struct file *file,
 			  unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.options =		WDIOF_KEEPALIVEPING |
 					WDIOF_SETTIMEOUT |
@@ -194,12 +196,12 @@
 
 	switch (cmd) {
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *) arg, &ident,
+			return copy_to_user(argp, &ident,
 				sizeof (ident)) ? -EFAULT : 0;
 
 		case WDIOC_GETSTATUS:
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0, (int *) arg);
+			return put_user(0, p);
 
 		case WDIOC_KEEPALIVE:
 			ali_keepalive();
@@ -209,7 +211,7 @@
 		{
 			int new_options, retval = -EINVAL;
 
-			if (get_user (new_options, (int *) arg))
+			if (get_user (new_options, p))
 				return -EFAULT;
 
 			if (new_options & WDIOS_DISABLECARD) {
@@ -229,7 +231,7 @@
 		{
 			int new_timeout;
 
-			if (get_user(new_timeout, (int *) arg))
+			if (get_user(new_timeout, p))
 				return -EFAULT;
 
 			if (ali_settimer(new_timeout))
@@ -240,7 +242,7 @@
 		}
 
 		case WDIOC_GETTIMEOUT:
-			return put_user(timeout, (int *)arg);
+			return put_user(timeout, p);
 
 		default:
 			return -ENOIOCTLCMD;
diff -Nru a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c
--- a/drivers/char/watchdog/alim7101_wdt.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/watchdog/alim7101_wdt.c	2004-06-23 19:04:28 -07:00
@@ -148,7 +148,7 @@
  * /dev/watchdog handling
  */
 
-static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos)
+static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
 {
 	/* We can't seek */
 	if(ppos != &file->f_pos)
@@ -203,6 +203,8 @@
 
 static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident =
 	{
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
@@ -213,10 +215,10 @@
 	switch(cmd)
 	{
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
 		case WDIOC_GETSTATUS:
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0, (int *)arg);
+			return put_user(0, p);
 		case WDIOC_KEEPALIVE:
 			wdt_keepalive();
 			return 0;
@@ -224,7 +226,7 @@
 		{
 			int new_options, retval = -EINVAL;
 
-			if(get_user(new_options, (int *)arg))
+			if(get_user(new_options, p))
 				return -EFAULT;
 
 			if(new_options & WDIOS_DISABLECARD) {
@@ -243,7 +245,7 @@
 		{
 			int new_timeout;
 
-			if(get_user(new_timeout, (int *)arg))
+			if(get_user(new_timeout, p))
 				return -EFAULT;
 
 			if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
@@ -254,7 +256,7 @@
 			/* Fall through */
 		}
 		case WDIOC_GETTIMEOUT:
-			return put_user(timeout, (int *)arg);
+			return put_user(timeout, p);
 		default:
 			return -ENOIOCTLCMD;
 	}
diff -Nru a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
--- a/drivers/char/watchdog/cpu5wdt.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/char/watchdog/cpu5wdt.c	2004-06-23 19:04:26 -07:00
@@ -145,6 +145,7 @@
 
 static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
 	unsigned int value;
 	static struct watchdog_info ident =
 	{
@@ -159,15 +160,15 @@
 		case WDIOC_GETSTATUS:
 			value = inb(port + CPU5WDT_STATUS_REG);
 			value = (value >> 2) & 1;
-			if ( copy_to_user((int *)arg, (int *)&value, sizeof(int)) )
+			if ( copy_to_user(argp, &value, sizeof(int)) )
 				return -EFAULT;
 			break;
 		case WDIOC_GETSUPPORT:
-			if ( copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)) )
+			if ( copy_to_user(argp, &ident, sizeof(ident)) )
 				return -EFAULT;
 			break;
 		case WDIOC_SETOPTIONS:
-			if ( copy_from_user(&value, (int *)arg, sizeof(int)) )
+			if ( copy_from_user(&value, argp, sizeof(int)) )
 				return -EFAULT;
 			switch(value) {
 				case WDIOS_ENABLECARD:
@@ -185,7 +186,7 @@
 	return 0;
 }
 
-static ssize_t cpu5wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	if ( !count )
 		return -EIO;
diff -Nru a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c
--- a/drivers/char/watchdog/eurotechwdt.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/watchdog/eurotechwdt.c	2004-06-23 19:04:25 -07:00
@@ -196,8 +196,8 @@
  * write of data will do, as we we don't define content meaning.
  */
 
-static ssize_t eurwdt_write(struct file *file, const char *buf, size_t count,
-loff_t *ppos)
+static ssize_t eurwdt_write(struct file *file, const char __user *buf,
+size_t count, loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
@@ -237,6 +237,8 @@
 static int eurwdt_ioctl(struct inode *inode, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.options	  = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
@@ -251,19 +253,18 @@
 		return -ENOIOCTLCMD;
 
 	case WDIOC_GETSUPPORT:
-		return copy_to_user((struct watchdog_info *)arg, &ident,
-			sizeof(ident)) ? -EFAULT : 0;
+		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
 
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETBOOTSTATUS:
-		return put_user(0, (int *) arg);
+		return put_user(0, p);
 
 	case WDIOC_KEEPALIVE:
 		eurwdt_ping();
 		return 0;
 
 	case WDIOC_SETTIMEOUT:
-		if (copy_from_user(&time, (int *) arg, sizeof(int)))
+		if (copy_from_user(&time, p, sizeof(int)))
 			return -EFAULT;
 
 		/* Sanity check */
@@ -275,10 +276,10 @@
 		/* Fall */
 
 	case WDIOC_GETTIMEOUT:
-		return put_user(eurwdt_timeout, (int *)arg);
+		return put_user(eurwdt_timeout, p);
 
 	case WDIOC_SETOPTIONS:
-		if (get_user(options, (int *)arg))
+		if (get_user(options, p))
 			return -EFAULT;
 		if (options & WDIOS_DISABLECARD) {
 			eurwdt_disable_timer();
diff -Nru a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
--- a/drivers/char/watchdog/i8xx_tco.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/watchdog/i8xx_tco.c	2004-06-23 19:04:25 -07:00
@@ -212,7 +212,7 @@
 	return 0;
 }
 
-static ssize_t i8xx_tco_write (struct file *file, const char *data,
+static ssize_t i8xx_tco_write (struct file *file, const char __user *data,
 			      size_t len, loff_t * ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
@@ -249,6 +249,8 @@
 {
 	int new_options, retval = -EINVAL;
 	int new_heartbeat;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.options =		WDIOF_SETTIMEOUT |
 					WDIOF_KEEPALIVEPING |
@@ -259,12 +261,12 @@
 
 	switch (cmd) {
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *) arg, &ident,
+			return copy_to_user(argp, &ident,
 				sizeof (ident)) ? -EFAULT : 0;
 
 		case WDIOC_GETSTATUS:
 		case WDIOC_GETBOOTSTATUS:
-			return put_user (0, (int *) arg);
+			return put_user (0, p);
 
 		case WDIOC_KEEPALIVE:
 			tco_timer_keepalive ();
@@ -272,7 +274,7 @@
 
 		case WDIOC_SETOPTIONS:
 		{
-			if (get_user (new_options, (int *) arg))
+			if (get_user (new_options, p))
 				return -EFAULT;
 
 			if (new_options & WDIOS_DISABLECARD) {
@@ -291,7 +293,7 @@
 
 		case WDIOC_SETTIMEOUT:
 		{
-			if (get_user(new_heartbeat, (int *) arg))
+			if (get_user(new_heartbeat, p))
 				return -EFAULT;
 
 			if (tco_timer_set_heartbeat(new_heartbeat))
@@ -302,7 +304,7 @@
 		}
 
 		case WDIOC_GETTIMEOUT:
-			return put_user(heartbeat, (int *)arg);
+			return put_user(heartbeat, p);
 
 		default:
 			return -ENOIOCTLCMD;
diff -Nru a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c
--- a/drivers/char/watchdog/ib700wdt.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/watchdog/ib700wdt.c	2004-06-23 19:04:28 -07:00
@@ -139,7 +139,7 @@
 }
 
 static ssize_t
-ibwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
@@ -170,6 +170,8 @@
 	  unsigned long arg)
 {
 	int i, new_margin;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 
 	static struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
@@ -179,19 +181,19 @@
 
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
-	  if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+	  if (copy_to_user(argp, &ident, sizeof(ident)))
 	    return -EFAULT;
 	  break;
 
 	case WDIOC_GETSTATUS:
-	  return put_user(0, (int *) arg);
+	  return put_user(0, p);
 
 	case WDIOC_KEEPALIVE:
 	  ibwdt_ping();
 	  break;
 
 	case WDIOC_SETTIMEOUT:
-	  if (get_user(new_margin, (int *)arg))
+	  if (get_user(new_margin, p))
 		  return -EFAULT;
 	  if ((new_margin < 0) || (new_margin > 30))
 		  return -EINVAL;
@@ -203,7 +205,7 @@
 	  /* Fall */
 
 	case WDIOC_GETTIMEOUT:
-	  return put_user(wd_times[wd_margin], (int *)arg);
+	  return put_user(wd_times[wd_margin], p);
 	  break;
 
 	default:
diff -Nru a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
--- a/drivers/char/watchdog/machzwd.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/watchdog/machzwd.c	2004-06-23 19:04:25 -07:00
@@ -302,7 +302,7 @@
 	}
 }
 
-static ssize_t zf_write(struct file *file, const char *buf, size_t count,
+static ssize_t zf_write(struct file *file, const char __user *buf, size_t count,
 								loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
@@ -352,15 +352,16 @@
 static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	switch(cmd){
 		case WDIOC_GETSUPPORT:
-			if (copy_to_user((struct watchdog_info *)arg,
-					 &zf_info, sizeof(zf_info)))
+			if (copy_to_user(argp, &zf_info, sizeof(zf_info)))
 				return -EFAULT;
 			break;
 
 		case WDIOC_GETSTATUS:
-			return put_user(0, (int *) arg);
+			return put_user(0, p);
 
 		case WDIOC_KEEPALIVE:
 			zf_ping(0);
diff -Nru a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
--- a/drivers/char/watchdog/mixcomwd.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/char/watchdog/mixcomwd.c	2004-06-23 19:04:26 -07:00
@@ -134,7 +134,7 @@
 }
 
 
-static ssize_t mixcomwd_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
 {
 	if (ppos != &file->f_pos) {
 		return -ESPIPE;
@@ -164,6 +164,8 @@
 static int mixcomwd_ioctl(struct inode *inode, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	int status;
 	static struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
@@ -178,13 +180,12 @@
 			if (!nowayout) {
 				status|=mixcomwd_timer_alive;
 			}
-			if (copy_to_user((int *)arg, &status, sizeof(int))) {
+			if (copy_to_user(p, &status, sizeof(int))) {
 				return -EFAULT;
 			}
 			break;
 		case WDIOC_GETSUPPORT:
-			if (copy_to_user((struct watchdog_info *)arg, &ident,
-			    sizeof(ident))) {
+			if (copy_to_user(argp, &ident, sizeof(ident))) {
 				return -EFAULT;
 			}
 			break;
diff -Nru a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
--- a/drivers/char/watchdog/pcwd_pci.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/watchdog/pcwd_pci.c	2004-06-23 19:04:25 -07:00
@@ -258,7 +258,7 @@
  *	/dev/watchdog handling
  */
 
-static ssize_t pcipcwd_write(struct file *file, const char *data,
+static ssize_t pcipcwd_write(struct file *file, const char __user *data,
 			      size_t len, loff_t *ppos)
 {
 	/* Can't seek (pwrite) on this device  */
@@ -293,6 +293,8 @@
 static int pcipcwd_ioctl(struct inode *inode, struct file *file,
 			  unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.options =		WDIOF_OVERHEAT |
 					WDIOF_CARDRESET |
@@ -305,7 +307,7 @@
 
 	switch (cmd) {
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *) arg, &ident,
+			return copy_to_user(argp, &ident,
 				sizeof (ident)) ? -EFAULT : 0;
 
 		case WDIOC_GETSTATUS:
@@ -314,11 +316,11 @@
 
 			pcipcwd_get_status(&status);
 
-			return put_user(status, (int *) arg);
+			return put_user(status, p);
 		}
 
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(pcipcwd_private.boot_status, (int *) arg);
+			return put_user(pcipcwd_private.boot_status, p);
 
 		case WDIOC_GETTEMP:
 		{
@@ -327,7 +329,7 @@
 			if (pcipcwd_get_temperature(&temperature))
 				return -EFAULT;
 
-			return put_user(temperature, (int *) arg);
+			return put_user(temperature, p);
 		}
 
 		case WDIOC_KEEPALIVE:
@@ -338,7 +340,7 @@
 		{
 			int new_options, retval = -EINVAL;
 
-			if (get_user (new_options, (int *) arg))
+			if (get_user (new_options, p))
 				return -EFAULT;
 
 			if (new_options & WDIOS_DISABLECARD) {
@@ -363,7 +365,7 @@
 		{
 			int new_heartbeat;
 
-			if (get_user(new_heartbeat, (int *) arg))
+			if (get_user(new_heartbeat, p))
 				return -EFAULT;
 
 			if (pcipcwd_set_heartbeat(new_heartbeat))
@@ -374,7 +376,7 @@
 		}
 
 		case WDIOC_GETTIMEOUT:
-			return put_user(heartbeat, (int *)arg);
+			return put_user(heartbeat, p);
 
 		default:
 			return -ENOIOCTLCMD;
@@ -413,7 +415,7 @@
  *	/dev/temperature handling
  */
 
-static ssize_t pcipcwd_temp_read(struct file *file, char *data,
+static ssize_t pcipcwd_temp_read(struct file *file, char __user *data,
 				size_t len, loff_t *ppos)
 {
 	int temperature;
diff -Nru a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
--- a/drivers/char/watchdog/pcwd_usb.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/char/watchdog/pcwd_usb.c	2004-06-23 19:04:26 -07:00
@@ -326,7 +326,7 @@
  *	/dev/watchdog handling
  */
 
-static ssize_t usb_pcwd_write(struct file *file, const char *data,
+static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
 			      size_t len, loff_t *ppos)
 {
 	/* Can't seek (pwrite) on this device  */
@@ -361,6 +361,8 @@
 static int usb_pcwd_ioctl(struct inode *inode, struct file *file,
 			  unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.options =		WDIOF_KEEPALIVEPING |
 					WDIOF_SETTIMEOUT |
@@ -371,12 +373,12 @@
 
 	switch (cmd) {
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *) arg, &ident,
+			return copy_to_user(argp, &ident,
 				sizeof (ident)) ? -EFAULT : 0;
 
 		case WDIOC_GETSTATUS:
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0, (int *) arg);
+			return put_user(0, p);
 
 		case WDIOC_GETTEMP:
 		{
@@ -385,7 +387,7 @@
 			if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
 				return -EFAULT;
 
-			return put_user(temperature, (int *) arg);
+			return put_user(temperature, p);
 		}
 
 		case WDIOC_KEEPALIVE:
@@ -396,7 +398,7 @@
 		{
 			int new_options, retval = -EINVAL;
 
-			if (get_user (new_options, (int *) arg))
+			if (get_user (new_options, p))
 				return -EFAULT;
 
 			if (new_options & WDIOS_DISABLECARD) {
@@ -416,7 +418,7 @@
 		{
 			int new_heartbeat;
 
-			if (get_user(new_heartbeat, (int *) arg))
+			if (get_user(new_heartbeat, p))
 				return -EFAULT;
 
 			if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))
@@ -427,7 +429,7 @@
 		}
 
 		case WDIOC_GETTIMEOUT:
-			return put_user(heartbeat, (int *)arg);
+			return put_user(heartbeat, p);
 
 		default:
 			return -ENOIOCTLCMD;
@@ -466,7 +468,7 @@
  *	/dev/temperature handling
  */
 
-static ssize_t usb_pcwd_temperature_read(struct file *file, char *data,
+static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data,
 				size_t len, loff_t *ppos)
 {
 	int temperature;
@@ -478,7 +480,7 @@
 	if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
 		return -EFAULT;
 
-	if (copy_to_user (data, &temperature, 1))
+	if (copy_to_user(data, &temperature, 1))
 		return -EFAULT;
 
 	return 1;
diff -Nru a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
--- a/drivers/char/watchdog/sa1100_wdt.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/sa1100_wdt.c	2004-06-23 19:04:27 -07:00
@@ -1,5 +1,5 @@
 /*
- *	Watchdog driver for the SA11x0
+ *	Watchdog driver for the SA11x0/PXA2xx
  *
  *      (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
  *          Based on SoftDog driver by Alan Cox <alan@redhat.com>
@@ -174,7 +174,7 @@
 static struct miscdevice sa1100dog_miscdev =
 {
 	.minor		= WATCHDOG_MINOR,
-	.name		= "SA1100 watchdog",
+	.name		= "SA1100/PXA2xx watchdog",
 	.fops		= &sa1100dog_fops,
 };
 
@@ -194,7 +194,7 @@
 
 	ret = misc_register(&sa1100dog_miscdev);
 	if (ret == 0)
-		printk("SA1100 Watchdog Timer: timer margin %d sec\n",
+		printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
 		       margin);
 
 	return ret;
@@ -209,7 +209,7 @@
 module_exit(sa1100dog_exit);
 
 MODULE_AUTHOR("Oleg Drokin <green@crimea.edu>");
-MODULE_DESCRIPTION("SA1100 Watchdog");
+MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
 
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
diff -Nru a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
--- a/drivers/char/watchdog/sbc60xxwdt.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/sbc60xxwdt.c	2004-06-23 19:04:27 -07:00
@@ -166,7 +166,7 @@
  * /dev/watchdog handling
  */
 
-static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos)
+static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
 {
 	/* We can't seek */
 	if(ppos != &file->f_pos)
@@ -230,6 +230,8 @@
 static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident=
 	{
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
@@ -242,10 +244,10 @@
 		default:
 			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
 		case WDIOC_GETSTATUS:
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0, (int *)arg);
+			return put_user(0, p);
 		case WDIOC_KEEPALIVE:
 			wdt_keepalive();
 			return 0;
@@ -253,7 +255,7 @@
 		{
 			int new_options, retval = -EINVAL;
 
-			if(get_user(new_options, (int *)arg))
+			if(get_user(new_options, p))
 				return -EFAULT;
 
 			if(new_options & WDIOS_DISABLECARD) {
@@ -272,7 +274,7 @@
 		{
 			int new_timeout;
 
-			if(get_user(new_timeout, (int *)arg))
+			if(get_user(new_timeout, p))
 				return -EFAULT;
 
 			if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
@@ -283,7 +285,7 @@
 			/* Fall through */
 		}
 		case WDIOC_GETTIMEOUT:
-			return put_user(timeout, (int *)arg);
+			return put_user(timeout, p);
 	}
 }
 
diff -Nru a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
--- a/drivers/char/watchdog/sc1200wdt.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/char/watchdog/sc1200wdt.c	2004-06-23 19:04:25 -07:00
@@ -174,6 +174,8 @@
 static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	int new_timeout;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
 		.firmware_version = 0,
@@ -185,22 +187,22 @@
 			return -ENOIOCTLCMD;	/* Keep Pavel Machek amused ;) */
 
 		case WDIOC_GETSUPPORT:
-			if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof ident))
+			if (copy_to_user(argp, &ident, sizeof ident))
 				return -EFAULT;
 			return 0;
 
 		case WDIOC_GETSTATUS:
-			return put_user(sc1200wdt_status(), (int *)arg);
+			return put_user(sc1200wdt_status(), p);
 
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0, (int *)arg);
+			return put_user(0, p);
 
 		case WDIOC_KEEPALIVE:
 			sc1200wdt_write_data(WDTO, timeout);
 			return 0;
 
 		case WDIOC_SETTIMEOUT:
-			if (get_user(new_timeout, (int *)arg))
+			if (get_user(new_timeout, p))
 				return -EFAULT;
 
 			/* the API states this is given in secs */
@@ -213,13 +215,13 @@
 			/* fall through and return the new timeout */
 
 		case WDIOC_GETTIMEOUT:
-			return put_user(timeout * 60, (int *)arg);
+			return put_user(timeout * 60, p);
 
 		case WDIOC_SETOPTIONS:
 		{
 			int options, retval = -EINVAL;
 
-			if (get_user(options, (int *)arg))
+			if (get_user(options, p))
 				return -EFAULT;
 
 			if (options & WDIOS_DISABLECARD) {
@@ -254,7 +256,7 @@
 }
 
 
-static ssize_t sc1200wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
 {
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
diff -Nru a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
--- a/drivers/char/watchdog/sc520_wdt.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/sc520_wdt.c	2004-06-23 19:04:27 -07:00
@@ -225,7 +225,7 @@
  *	/dev/watchdog handling
  */
 
-static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos)
+static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
 {
 	/* We can't seek */
 	if(ppos != &file->f_pos)
@@ -285,6 +285,8 @@
 static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
@@ -296,10 +298,10 @@
 		default:
 			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
 		case WDIOC_GETSTATUS:
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0, (int *)arg);
+			return put_user(0, p);
 		case WDIOC_KEEPALIVE:
 			wdt_keepalive();
 			return 0;
@@ -307,7 +309,7 @@
 		{
 			int new_options, retval = -EINVAL;
 
-			if(get_user(new_options, (int *)arg))
+			if(get_user(new_options, p))
 				return -EFAULT;
 
 			if(new_options & WDIOS_DISABLECARD) {
@@ -326,7 +328,7 @@
 		{
 			int new_timeout;
 
-			if(get_user(new_timeout, (int *)arg))
+			if(get_user(new_timeout, p))
 				return -EFAULT;
 
 			if(wdt_set_heartbeat(new_timeout))
@@ -336,7 +338,7 @@
 			/* Fall through */
 		}
 		case WDIOC_GETTIMEOUT:
-			return put_user(timeout, (int *)arg);
+			return put_user(timeout, p);
 	}
 }
 
diff -Nru a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
--- a/drivers/char/watchdog/scx200_wdt.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/scx200_wdt.c	2004-06-23 19:04:27 -07:00
@@ -132,7 +132,7 @@
 	.notifier_call = scx200_wdt_notify_sys,
 };
 
-static ssize_t scx200_wdt_write(struct file *file, const char *data,
+static ssize_t scx200_wdt_write(struct file *file, const char __user *data,
 				     size_t len, loff_t *ppos)
 {
 	if (ppos != &file->f_pos)
@@ -163,6 +163,8 @@
 static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.identity = "NatSemi SCx200 Watchdog",
 		.firmware_version = 1,
@@ -174,20 +176,19 @@
 	default:
 		return -ENOIOCTLCMD;
 	case WDIOC_GETSUPPORT:
-		if(copy_to_user((struct watchdog_info *)arg, &ident,
-				sizeof(ident)))
+		if(copy_to_user(argp, &ident, sizeof(ident)))
 			return -EFAULT;
 		return 0;
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETBOOTSTATUS:
-		if (put_user(0, (int *)arg))
+		if (put_user(0, p))
 			return -EFAULT;
 		return 0;
 	case WDIOC_KEEPALIVE:
 		scx200_wdt_ping();
 		return 0;
 	case WDIOC_SETTIMEOUT:
-		if (get_user(new_margin, (int *)arg))
+		if (get_user(new_margin, p))
 			return -EFAULT;
 		if (new_margin < 1)
 			return -EINVAL;
@@ -195,7 +196,7 @@
 		scx200_wdt_update_margin();
 		scx200_wdt_ping();
 	case WDIOC_GETTIMEOUT:
-		if (put_user(margin, (int *)arg))
+		if (put_user(margin, p))
 			return -EFAULT;
 		return 0;
 	}
diff -Nru a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c
--- a/drivers/char/watchdog/softdog.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/char/watchdog/softdog.c	2004-06-23 19:04:26 -07:00
@@ -161,7 +161,7 @@
 	return 0;
 }
 
-static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+static ssize_t softdog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
@@ -194,6 +194,8 @@
 static int softdog_ioctl(struct inode *inode, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	int new_margin;
 	static struct watchdog_info ident = {
 		.options =		WDIOF_SETTIMEOUT |
@@ -206,23 +208,23 @@
 		default:
 			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *)arg, &ident,
+			return copy_to_user(argp, &ident,
 				sizeof(ident)) ? -EFAULT : 0;
 		case WDIOC_GETSTATUS:
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0,(int *)arg);
+			return put_user(0, p);
 		case WDIOC_KEEPALIVE:
 			softdog_keepalive();
 			return 0;
 		case WDIOC_SETTIMEOUT:
-			if (get_user(new_margin, (int *)arg))
+			if (get_user(new_margin, p))
 				return -EFAULT;
 			if (softdog_set_heartbeat(new_margin))
 				return -EINVAL;
 			softdog_keepalive();
 			/* Fall */
 		case WDIOC_GETTIMEOUT:
-			return put_user(soft_margin, (int *)arg);
+			return put_user(soft_margin, p);
 	}
 }
 
diff -Nru a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
--- a/drivers/char/watchdog/w83627hf_wdt.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/w83627hf_wdt.c	2004-06-23 19:04:27 -07:00
@@ -142,7 +142,7 @@
 }
 
 static ssize_t
-wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
@@ -171,6 +171,8 @@
 wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	  unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	int new_timeout;
 	static struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
@@ -180,20 +182,20 @@
 
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
-	  if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+	  if (copy_to_user(argp, &ident, sizeof(ident)))
 	    return -EFAULT;
 	  break;
 
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETBOOTSTATUS:
-	  return put_user(0, (int *)arg);
+	  return put_user(0, p);
 
 	case WDIOC_KEEPALIVE:
 	  wdt_ping();
 	  break;
 
 	case WDIOC_SETTIMEOUT:
-	  if (get_user(new_timeout, (int *)arg))
+	  if (get_user(new_timeout, p))
 		  return -EFAULT;
 	  if (wdt_set_heartbeat(new_timeout))
 		  return -EINVAL;
@@ -201,13 +203,13 @@
 	  /* Fall */
 
 	case WDIOC_GETTIMEOUT:
-	  return put_user(timeout, (int *)arg);
+	  return put_user(timeout, p);
 
 	case WDIOC_SETOPTIONS:
 	{
 	  int options, retval = -EINVAL;
 
-	  if (get_user(options, (int *)arg))
+	  if (get_user(options, p))
 	    return -EFAULT;
 
 	  if (options & WDIOS_DISABLECARD) {
diff -Nru a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c
--- a/drivers/char/watchdog/w83877f_wdt.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/w83877f_wdt.c	2004-06-23 19:04:27 -07:00
@@ -188,7 +188,7 @@
  * /dev/watchdog handling
  */
 
-static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos)
+static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
 {
 	/* We can't seek */
 	if(ppos != &file->f_pos)
@@ -249,6 +249,8 @@
 static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident=
 	{
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
@@ -261,10 +263,10 @@
 		default:
 			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
 		case WDIOC_GETSTATUS:
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0, (int *)arg);
+			return put_user(0, p);
 		case WDIOC_KEEPALIVE:
 			wdt_keepalive();
 			return 0;
@@ -272,7 +274,7 @@
 		{
 			int new_options, retval = -EINVAL;
 
-			if(get_user(new_options, (int *)arg))
+			if(get_user(new_options, p))
 				return -EFAULT;
 
 			if(new_options & WDIOS_DISABLECARD) {
@@ -291,7 +293,7 @@
 		{
 			int new_timeout;
 
-			if(get_user(new_timeout, (int *)arg))
+			if(get_user(new_timeout, p))
 				return -EFAULT;
 
 			if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
@@ -302,7 +304,7 @@
 			/* Fall through */
 		}
 		case WDIOC_GETTIMEOUT:
-			return put_user(timeout, (int *)arg);
+			return put_user(timeout, p);
 	}
 }
 
diff -Nru a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c
--- a/drivers/char/watchdog/wafer5823wdt.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/char/watchdog/wafer5823wdt.c	2004-06-23 19:04:28 -07:00
@@ -95,7 +95,7 @@
 	inb_p(wdt_stop);
 }
 
-static ssize_t wafwdt_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
+static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
@@ -128,6 +128,8 @@
 	     unsigned long arg)
 {
 	int new_timeout;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	static struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
@@ -136,21 +138,20 @@
 
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
-		if (copy_to_user
-		    ((struct watchdog_info *) arg, &ident, sizeof (ident)))
+		if (copy_to_user(argp, &ident, sizeof (ident)))
 			return -EFAULT;
 		break;
 
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETBOOTSTATUS:
-		return put_user(0, (int *)arg);
+		return put_user(0, p);
 
 	case WDIOC_KEEPALIVE:
 		wafwdt_ping();
 		break;
 
 	case WDIOC_SETTIMEOUT:
-		if (get_user(new_timeout, (int *)arg))
+		if (get_user(new_timeout, p))
 			return -EFAULT;
 		if ((new_timeout < 1) || (new_timeout > 255))
 			return -EINVAL;
@@ -159,13 +160,13 @@
 		wafwdt_start();
 		/* Fall */
 	case WDIOC_GETTIMEOUT:
-		return put_user(timeout, (int *)arg);
+		return put_user(timeout, p);
 
 	case WDIOC_SETOPTIONS:
 	{
 		int options, retval = -EINVAL;
 
-		if (get_user(options, (int *)arg))
+		if (get_user(options, p))
 			return -EFAULT;
 
 		if (options & WDIOS_DISABLECARD) {
diff -Nru a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c
--- a/drivers/char/watchdog/wdt.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/wdt.c	2004-06-23 19:04:27 -07:00
@@ -286,7 +286,7 @@
  *	write of data will do, as we we don't define content meaning.
  */
 
-static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
@@ -327,6 +327,8 @@
 static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 	int new_heartbeat;
 	int status;
 
@@ -351,18 +353,18 @@
 		default:
 			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
 
 		case WDIOC_GETSTATUS:
 			wdt_get_status(&status);
-			return put_user(status,(int *)arg);
+			return put_user(status, p);
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0, (int *)arg);
+			return put_user(0, p);
 		case WDIOC_KEEPALIVE:
 			wdt_ping();
 			return 0;
 		case WDIOC_SETTIMEOUT:
-			if (get_user(new_heartbeat, (int *)arg))
+			if (get_user(new_heartbeat, p))
 				return -EFAULT;
 
 			if (wdt_set_heartbeat(new_heartbeat))
@@ -371,7 +373,7 @@
 			wdt_ping();
 			/* Fall */
 		case WDIOC_GETTIMEOUT:
-			return put_user(heartbeat, (int *)arg);
+			return put_user(heartbeat, p);
 	}
 }
 
@@ -435,7 +437,7 @@
  *	farenheit. It was designed by an imperial measurement luddite.
  */
 
-static ssize_t wdt_temp_read(struct file *file, char *buf, size_t count, loff_t *ptr)
+static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
 {
 	int temperature;
 
diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
--- a/drivers/char/watchdog/wdt_pci.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/char/watchdog/wdt_pci.c	2004-06-23 19:04:27 -07:00
@@ -331,7 +331,7 @@
  *	write of data will do, as we we don't define content meaning.
  */
 
-static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
@@ -374,6 +374,8 @@
 {
 	int new_heartbeat;
 	int status;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 
 	static struct watchdog_info ident = {
 		.options =		WDIOF_SETTIMEOUT|
@@ -396,18 +398,18 @@
 		default:
 			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
-			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
 
 		case WDIOC_GETSTATUS:
 			wdtpci_get_status(&status);
-			return put_user(status,(int *)arg);
+			return put_user(status, p);
 		case WDIOC_GETBOOTSTATUS:
-			return put_user(0, (int *)arg);
+			return put_user(0, p);
 		case WDIOC_KEEPALIVE:
 			wdtpci_ping();
 			return 0;
 		case WDIOC_SETTIMEOUT:
-			if (get_user(new_heartbeat, (int *)arg))
+			if (get_user(new_heartbeat, p))
 				return -EFAULT;
 
 			if (wdtpci_set_heartbeat(new_heartbeat))
@@ -416,7 +418,7 @@
 			wdtpci_ping();
 			/* Fall */
 		case WDIOC_GETTIMEOUT:
-			return put_user(heartbeat, (int *)arg);
+			return put_user(heartbeat, p);
 	}
 }
 
@@ -484,7 +486,7 @@
  *	fahrenheit. It was designed by an imperial measurement luddite.
  */
 
-static ssize_t wdtpci_temp_read(struct file *file, char *buf, size_t count, loff_t *ptr)
+static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
 {
 	int temperature;
 
diff -Nru a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
--- a/drivers/firmware/efivars.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/firmware/efivars.c	2004-06-23 19:04:28 -07:00
@@ -134,7 +134,7 @@
 
 #define EFI_ATTR(_name, _mode, _show, _store) \
 struct subsys_attribute efi_attr_##_name = { \
-	.attr {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
 	.show = _show, \
 	.store = _store, \
 };
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/i2c/busses/i2c-piix4.c	2004-06-23 19:04:26 -07:00
@@ -138,7 +138,7 @@
 
 	dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev));
 
-	if(ibm_dmi_probe()) {
+	if(ibm_dmi_probe() && PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) {
 		dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module "
 			"may corrupt your serial eeprom! Refusing to load "
 			"module!\n");
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/i2c/chips/asb100.c	2004-06-23 19:04:27 -07:00
@@ -272,7 +272,7 @@
 	return show_in(dev, buf, 0x##offset); \
 } \
 static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
-		show_in##offset, NULL) \
+		show_in##offset, NULL); \
 static ssize_t \
 	show_in##offset##_min (struct device *dev, char *buf) \
 { \
@@ -294,17 +294,17 @@
 	return set_in_max(dev, buf, count, 0x##offset); \
 } \
 static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
-		show_in##offset##_min, set_in##offset##_min) \
+		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##_max, set_in##offset##_max);
 
-sysfs_in(0)
-sysfs_in(1)
-sysfs_in(2)
-sysfs_in(3)
-sysfs_in(4)
-sysfs_in(5)
-sysfs_in(6)
+sysfs_in(0);
+sysfs_in(1);
+sysfs_in(2);
+sysfs_in(3);
+sysfs_in(4);
+sysfs_in(5);
+sysfs_in(6);
 
 #define device_create_file_in(client, offset) do { \
 	device_create_file(&client->dev, &dev_attr_in##offset##_input); \
@@ -410,15 +410,15 @@
 	return set_fan_div(dev, buf, count, offset - 1); \
 } \
 static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
-		show_fan##offset, NULL) \
+		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##_min, set_fan##offset##_min); \
 static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
-		show_fan##offset##_div, set_fan##offset##_div)
+		show_fan##offset##_div, set_fan##offset##_div);
 
-sysfs_fan(1)
-sysfs_fan(2)
-sysfs_fan(3)
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
 
 #define device_create_file_fan(client, offset) do { \
 	device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
@@ -449,9 +449,9 @@
 	return sprintf_temp_from_reg(data->reg[nr], buf, nr); \
 }
 
-show_temp_reg(temp)
-show_temp_reg(temp_max)
-show_temp_reg(temp_hyst)
+show_temp_reg(temp);
+show_temp_reg(temp_max);
+show_temp_reg(temp_hyst);
 
 #define set_temp_reg(REG, reg) \
 static ssize_t set_##reg(struct device *dev, const char *buf, \
@@ -473,15 +473,15 @@
 	return count; \
 }
 
-set_temp_reg(MAX, temp_max)
-set_temp_reg(HYST, temp_hyst)
+set_temp_reg(MAX, temp_max);
+set_temp_reg(HYST, temp_hyst);
 
 #define sysfs_temp(num) \
 static ssize_t show_temp##num(struct device *dev, char *buf) \
 { \
 	return show_temp(dev, buf, num-1); \
 } \
-static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL) \
+static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL); \
 static ssize_t show_temp_max##num(struct device *dev, char *buf) \
 { \
 	return show_temp_max(dev, buf, num-1); \
@@ -492,7 +492,7 @@
 	return set_temp_max(dev, buf, count, num-1); \
 } \
 static DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \
-		show_temp_max##num, set_temp_max##num) \
+		show_temp_max##num, set_temp_max##num); \
 static ssize_t show_temp_hyst##num(struct device *dev, char *buf) \
 { \
 	return show_temp_hyst(dev, buf, num-1); \
@@ -503,12 +503,12 @@
 	return set_temp_hyst(dev, buf, count, num-1); \
 } \
 static DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \
-		show_temp_hyst##num, set_temp_hyst##num)
+		show_temp_hyst##num, set_temp_hyst##num);
 
-sysfs_temp(1)
-sysfs_temp(2)
-sysfs_temp(3)
-sysfs_temp(4)
+sysfs_temp(1);
+sysfs_temp(2);
+sysfs_temp(3);
+sysfs_temp(4);
 
 /* VID */
 #define device_create_file_temp(client, num) do { \
@@ -523,7 +523,7 @@
 	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
 }
 
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL)
+static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL);
 #define device_create_file_vid(client) \
 device_create_file(&client->dev, &dev_attr_in0_ref)
 
@@ -544,7 +544,7 @@
 }
 
 /* Alarms */
-static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm)
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
 #define device_create_file_vrm(client) \
 device_create_file(&client->dev, &dev_attr_vrm);
 
@@ -554,7 +554,7 @@
 	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
 }
 
-static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL)
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 #define device_create_file_alarms(client) \
 device_create_file(&client->dev, &dev_attr_alarms)
 
@@ -594,9 +594,9 @@
 	return count;
 }
 
-static DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1)
+static DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1);
 static DEVICE_ATTR(fan1_pwm_enable, S_IRUGO | S_IWUSR,
-		show_pwm_enable1, set_pwm_enable1)
+		show_pwm_enable1, set_pwm_enable1);
 #define device_create_file_pwm1(client) do { \
 	device_create_file(&new_client->dev, &dev_attr_fan1_pwm); \
 	device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable); \
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/i2c/chips/it87.c	2004-06-23 19:04:28 -07:00
@@ -128,15 +128,15 @@
 
 #define IT87_REG_FAN(nr)       (0x0d + (nr))
 #define IT87_REG_FAN_MIN(nr)   (0x10 + (nr))
-#define IT87_REG_FAN_CTRL      0x13
+#define IT87_REG_FAN_MAIN_CTRL 0x13
 
 #define IT87_REG_VIN(nr)       (0x20 + (nr))
 #define IT87_REG_TEMP(nr)      (0x29 + (nr))
 
 #define IT87_REG_VIN_MAX(nr)   (0x30 + (nr) * 2)
 #define IT87_REG_VIN_MIN(nr)   (0x31 + (nr) * 2)
-#define IT87_REG_TEMP_HIGH(nr) (0x40 + ((nr) * 2))
-#define IT87_REG_TEMP_LOW(nr)  (0x41 + ((nr) * 2))
+#define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2)
+#define IT87_REG_TEMP_LOW(nr)  (0x41 + (nr) * 2)
 
 #define IT87_REG_I2C_ADDR      0x48
 
@@ -145,8 +145,8 @@
 
 #define IT87_REG_CHIPID        0x58
 
-#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
-#define IN_FROM_REG(val) (((val) *  16) / 10)
+#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) + 8)/16),0,255))
+#define IN_FROM_REG(val) ((val) * 16)
 
 static inline u8 FAN_TO_REG(long rpm, int div)
 {
@@ -159,9 +159,9 @@
 
 #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
 
-#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
-					((val)+5)/10),0,255))
-#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
+#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\
+					((val)+500)/1000),-128,127))
+#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000)
 
 #define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
 				205-(val)*5)
@@ -170,7 +170,7 @@
 static int DIV_TO_REG(int val)
 {
 	int answer = 0;
-	while ((val >>= 1))
+	while ((val >>= 1) != 0)
 		answer++;
 	return answer;
 }
@@ -231,19 +231,19 @@
 static ssize_t show_in(struct device *dev, char *buf, int nr)
 {
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])*10 );
+	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 it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])*10 );
+	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 it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])*10 );
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
 }
 
 static ssize_t set_in_min(struct device *dev, const char *buf, 
@@ -251,7 +251,7 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct it87_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10)/10;
+	unsigned long val = simple_strtoul(buf, NULL, 10);
 	data->in_min[nr] = IN_TO_REG(val);
 	it87_write_value(client, IT87_REG_VIN_MIN(nr), 
 			data->in_min[nr]);
@@ -262,7 +262,7 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct it87_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10)/10;
+	unsigned long val = simple_strtoul(buf, NULL, 10);
 	data->in_max[nr] = IN_TO_REG(val);
 	it87_write_value(client, IT87_REG_VIN_MAX(nr), 
 			data->in_max[nr]);
@@ -275,7 +275,7 @@
 {								\
 	return show_in(dev, buf, 0x##offset);			\
 }								\
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL)
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);
 
 #define limit_in_offset(offset)					\
 static ssize_t							\
@@ -299,9 +299,9 @@
 	return set_in_max(dev, buf, count, 0x##offset);		\
 }								\
 static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, 	\
-		show_in##offset##_min, set_in##offset##_min)	\
+		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##_max, set_in##offset##_max);
 
 show_in_offset(0);
 limit_in_offset(0);
@@ -325,24 +325,24 @@
 static ssize_t show_temp(struct device *dev, char *buf, int nr)
 {
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*100 );
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
 }
 static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
 {
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*100);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr]));
 }
 static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
 {
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])*100);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr]));
 }
 static ssize_t set_temp_max(struct device *dev, const char *buf, 
 		size_t count, int nr)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct it87_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10)/100;
+	int val = simple_strtol(buf, NULL, 10);
 	data->temp_high[nr] = TEMP_TO_REG(val);
 	it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]);
 	return count;
@@ -352,7 +352,7 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct it87_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10)/100;
+	int val = simple_strtol(buf, NULL, 10);
 	data->temp_low[nr] = TEMP_TO_REG(val);
 	it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]);
 	return count;
@@ -382,11 +382,11 @@
 {									\
 	return set_temp_min(dev, buf, count, 0x##offset - 1);		\
 }									\
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL) \
+static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \
 static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_max, set_temp_##offset##_max) 	\
+		show_temp_##offset##_max, set_temp_##offset##_max); 	\
 static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_min, set_temp_##offset##_min)	
+		show_temp_##offset##_min, set_temp_##offset##_min);	
 
 show_temp_offset(1);
 show_temp_offset(2);
@@ -430,8 +430,8 @@
 {									\
 	return set_sensor(dev, buf, count, 0x##offset - 1);		\
 }									\
-static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR,	 		\
-		show_sensor_##offset, set_sensor_##offset)
+static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, 		\
+		show_sensor_##offset, set_sensor_##offset);
 
 show_sensor_offset(1);
 show_sensor_offset(2);
@@ -525,11 +525,11 @@
 {									\
 	return set_fan_div(dev, buf, count, 0x##offset - 1);		\
 }									\
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \
+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##_min, set_fan_##offset##_min); 	\
 static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, 		\
-		show_fan_##offset##_div, set_fan_##offset##_div)
+		show_fan_##offset##_div, set_fan_##offset##_div);
 
 show_fan_offset(1);
 show_fan_offset(2);
@@ -773,9 +773,7 @@
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
-   would slow down the IT87 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 IT87 access and should not be necessary. */
 static int it87_read_value(struct i2c_client *client, u8 reg)
 {
 	struct it87_data *data = i2c_get_clientdata(client);
@@ -795,9 +793,7 @@
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
-   would slow down the IT87 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 IT87 access and should not be necessary. */
 static int it87_write_value(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct it87_data *data = i2c_get_clientdata(client);
@@ -840,11 +836,11 @@
 	}
 
 	/* Check if tachometers are reset manually or by some reason */
-	tmp = it87_read_value(client, IT87_REG_FAN_CTRL);
+	tmp = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL);
 	if ((tmp & 0x70) == 0) {
 		/* Enable all fan tachometers */
 		tmp = (tmp & 0x8f) | 0x70;
-		it87_write_value(client, IT87_REG_FAN_CTRL, tmp);
+		it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, tmp);
 	}
 
 	/* Start monitoring */
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
--- a/drivers/i2c/chips/lm78.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/i2c/chips/lm78.c	2004-06-23 19:04:28 -07:00
@@ -281,7 +281,7 @@
 	return show_in(dev, buf, 0x##offset);			\
 }								\
 static DEVICE_ATTR(in##offset##_input, S_IRUGO, 		\
-		show_in##offset, NULL)				\
+		show_in##offset, NULL);				\
 static ssize_t							\
 	show_in##offset##_min (struct device *dev, char *buf)   \
 {								\
@@ -303,9 +303,9 @@
 	return set_in_max(dev, buf, count, 0x##offset);		\
 }								\
 static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,		\
-		show_in##offset##_min, set_in##offset##_min)    \
+		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##_max, set_in##offset##_max);
 
 show_in_offset(0);
 show_in_offset(1);
@@ -354,11 +354,11 @@
 	return count;
 }
 
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL)
+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)
+		show_temp_over, set_temp_over);
 static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
-		show_temp_hyst, set_temp_hyst)
+		show_temp_hyst, set_temp_hyst);
 
 /* 3 Fans */
 static ssize_t show_fan(struct device *dev, char *buf, int nr)
@@ -439,9 +439,9 @@
 {									\
 	return set_fan_min(dev, buf, count, 0x##offset - 1);		\
 }									\
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \
+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##_min, set_fan_##offset##_min);
 
 static ssize_t set_fan_1_div(struct device *dev, const char *buf,
 		size_t count)
@@ -461,10 +461,10 @@
 
 /* Fan 3 divisor is locked in H/W */
 static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
-		show_fan_1_div, set_fan_1_div)
+		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)
-static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL)
+		show_fan_2_div, set_fan_2_div);
+static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
 
 /* VID */
 static ssize_t show_vid(struct device *dev, char *buf)
diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
--- a/drivers/i2c/chips/lm85.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/i2c/chips/lm85.c	2004-06-23 19:04:26 -07:00
@@ -451,9 +451,9 @@
 {									\
 	return set_fan_min(dev, buf, count, 0x##offset - 1);		\
 }									\
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \
+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##_min, set_fan_##offset##_min);
 
 show_fan_offset(1);
 show_fan_offset(2);
@@ -468,7 +468,7 @@
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
 
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL)
+static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
 
 static ssize_t show_vrm_reg(struct device *dev, char *buf)
 {
@@ -487,7 +487,7 @@
 	return count;
 }
 
-static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 
 static ssize_t show_alarms_reg(struct device *dev, char *buf)
 {
@@ -495,7 +495,7 @@
 	return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
 }
 
-static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
 
 /* pwm */
 
@@ -542,8 +542,8 @@
 	return show_pwm_enable(dev, buf, 0x##offset - 1);			\
 }									\
 static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, 			\
-		show_pwm_##offset, set_pwm_##offset)			\
-static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO, show_pwm_enable##offset, NULL)
+		show_pwm_##offset, set_pwm_##offset);			\
+static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO, show_pwm_enable##offset, NULL);
 
 show_pwm_reg(1);
 show_pwm_reg(2);
@@ -617,11 +617,11 @@
 {									\
 	return set_in_max(dev, buf, count, 0x##offset);			\
 }									\
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in_##offset, NULL)	\
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in_##offset, NULL);	\
 static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, 		\
-		show_in_##offset##_min, set_in_##offset##_min)		\
+		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##_max, set_in_##offset##_max);
 
 show_in_reg(0);
 show_in_reg(1);
@@ -697,11 +697,11 @@
 {									\
 	return set_temp_max(dev, buf, count, 0x##offset - 1);		\
 }									\
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL)	\
+static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);	\
 static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_min, set_temp_##offset##_min)	\
+		show_temp_##offset##_min, set_temp_##offset##_min);	\
 static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_max, set_temp_##offset##_max)
+		show_temp_##offset##_max, set_temp_##offset##_max);
 
 show_temp_reg(1);
 show_temp_reg(2);
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/i2c/chips/via686a.c	2004-06-23 19:04:25 -07:00
@@ -405,11 +405,11 @@
 {								\
 	return set_in_max(dev, buf, count, 0x##offset);		\
 }								\
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL) 	\
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);\
 static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, 	\
-		show_in##offset##_min, set_in##offset##_min)	\
+		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##_max, set_in##offset##_max);
 
 show_in_offset(0);
 show_in_offset(1);
@@ -473,11 +473,11 @@
 {									\
 	return set_temp_hyst(dev, buf, count, 0x##offset - 1);		\
 }									\
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL) \
+static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);\
 static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_over, set_temp_##offset##_over) 	\
+		show_temp_##offset##_over, set_temp_##offset##_over);	\
 static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_hyst, set_temp_##offset##_hyst)	
+		show_temp_##offset##_hyst, set_temp_##offset##_hyst);	
 
 show_temp_offset(1);
 show_temp_offset(2);
@@ -542,11 +542,11 @@
 {									\
 	return set_fan_div(dev, buf, count, 0x##offset - 1);		\
 }									\
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \
+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##_min, set_fan_##offset##_min);	\
 static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, 		\
-		show_fan_##offset##_div, set_fan_##offset##_div)
+		show_fan_##offset##_div, set_fan_##offset##_div);
 
 show_fan_offset(1);
 show_fan_offset(2);
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
--- a/drivers/i2c/chips/w83627hf.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/i2c/chips/w83627hf.c	2004-06-23 19:04:28 -07:00
@@ -199,7 +199,7 @@
 #define W83627THF_REG_PWM2		0x03	/* 697HF and 637HF too */
 #define W83627THF_REG_PWM3		0x11	/* 637HF too */
 
-#define W83627THF_REG_VRM_OVT_CFG 	0x18	/* 637HF too, unused yet */
+#define W83627THF_REG_VRM_OVT_CFG 	0x18	/* 637HF too */
 
 static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
 static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
@@ -222,7 +222,7 @@
    these macros are called: arguments may be evaluated more than once.
    Fixing this is just not worth it. */
 #define IN_TO_REG(val)  (SENSORS_LIMIT((((val) + 8)/16),0,255))
-#define IN_FROM_REG(val) ((val) * 16 + 5)
+#define IN_FROM_REG(val) ((val) * 16)
 
 static inline u8 FAN_TO_REG(long rpm, int div)
 {
@@ -312,6 +312,7 @@
 				   Default = 3435.
 				   Other Betas unimplemented */
 	u8 vrm;
+	u8 vrm_ovt;		/* Register value, 627thf & 637hf only */
 };
 
 
@@ -370,7 +371,7 @@
 { \
         return show_in(dev, buf, 0x##offset); \
 } \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL)
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL);
 
 #define sysfs_in_reg_offset(reg, offset) \
 static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
@@ -384,22 +385,104 @@
 	return store_in_##reg (dev, buf, count, 0x##offset); \
 } \
 static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, \
-		  show_regs_in_##reg##offset, store_regs_in_##reg##offset)
+		  show_regs_in_##reg##offset, store_regs_in_##reg##offset);
 
 #define sysfs_in_offsets(offset) \
 sysfs_in_offset(offset) \
 sysfs_in_reg_offset(min, offset) \
 sysfs_in_reg_offset(max, offset)
 
-sysfs_in_offsets(0)
-sysfs_in_offsets(1)
-sysfs_in_offsets(2)
-sysfs_in_offsets(3)
-sysfs_in_offsets(4)
-sysfs_in_offsets(5)
-sysfs_in_offsets(6)
-sysfs_in_offsets(7)
-sysfs_in_offsets(8)
+sysfs_in_offsets(1);
+sysfs_in_offsets(2);
+sysfs_in_offsets(3);
+sysfs_in_offsets(4);
+sysfs_in_offsets(5);
+sysfs_in_offsets(6);
+sysfs_in_offsets(7);
+sysfs_in_offsets(8);
+
+/* use a different set of functions for in0 */
+static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
+{
+	long in0;
+
+	if ((data->vrm_ovt & 0x01) &&
+		(w83627thf == data->type || w83637hf == data->type))
+
+		/* use VRM9 calculation */
+		in0 = (long)((reg * 488 + 70000 + 50) / 100);
+	else
+		/* use VRM8 (standard) calculation */
+		in0 = (long)IN_FROM_REG(reg);
+
+	return sprintf(buf,"%ld\n", in0);
+}
+
+static ssize_t show_regs_in_0(struct device *dev, char *buf)
+{
+	struct w83627hf_data *data = w83627hf_update_device(dev);
+	return show_in_0(data, buf, data->in[0]);
+}
+
+static ssize_t show_regs_in_min0(struct device *dev, char *buf)
+{
+	struct w83627hf_data *data = w83627hf_update_device(dev);
+	return show_in_0(data, buf, data->in_min[0]);
+}
+
+static ssize_t show_regs_in_max0(struct device *dev, char *buf)
+{
+	struct w83627hf_data *data = w83627hf_update_device(dev);
+	return show_in_0(data, buf, data->in_max[0]);
+}
+
+static ssize_t store_regs_in_min0(struct device *dev,
+	const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83627hf_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	if ((data->vrm_ovt & 0x01) &&
+		(w83627thf == data->type || w83637hf == data->type))
+
+		/* use VRM9 calculation */
+		data->in_min[0] = (u8)(((val * 100) - 70000 + 244) / 488);
+	else
+		/* use VRM8 (standard) calculation */
+		data->in_min[0] = IN_TO_REG(val);
+
+	w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]);
+	return count;
+}
+
+static ssize_t store_regs_in_max0(struct device *dev,
+	const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83627hf_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	if ((data->vrm_ovt & 0x01) &&
+		(w83627thf == data->type || w83637hf == data->type))
+		
+		/* use VRM9 calculation */
+		data->in_max[0] = (u8)(((val * 100) - 70000 + 244) / 488);
+	else
+		/* use VRM8 (standard) calculation */
+		data->in_max[0] = IN_TO_REG(val);
+
+	w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]);
+	return count;
+}
+
+static DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL);
+static DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
+	show_regs_in_min0, store_regs_in_min0);
+static DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
+	show_regs_in_max0, store_regs_in_max0);
 
 #define device_create_file_in(client, offset) \
 do { \
@@ -416,8 +499,8 @@
 		FAN_FROM_REG(data->reg[nr-1], \
 			    (long)DIV_FROM_REG(data->fan_div[nr-1]))); \
 }
-show_fan_reg(fan)
-show_fan_reg(fan_min)
+show_fan_reg(fan);
+show_fan_reg(fan_min);
 
 static ssize_t
 store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
@@ -440,7 +523,7 @@
 { \
 	return show_fan(dev, buf, 0x##offset); \
 } \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL)
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL);
 
 #define sysfs_fan_min_offset(offset) \
 static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
@@ -453,14 +536,14 @@
 	return store_fan_min(dev, buf, count, 0x##offset); \
 } \
 static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
-		  show_regs_fan_min##offset, store_regs_fan_min##offset)
+		  show_regs_fan_min##offset, store_regs_fan_min##offset);
 
-sysfs_fan_offset(1)
-sysfs_fan_min_offset(1)
-sysfs_fan_offset(2)
-sysfs_fan_min_offset(2)
-sysfs_fan_offset(3)
-sysfs_fan_min_offset(3)
+sysfs_fan_offset(1);
+sysfs_fan_min_offset(1);
+sysfs_fan_offset(2);
+sysfs_fan_min_offset(2);
+sysfs_fan_offset(3);
+sysfs_fan_min_offset(3);
 
 #define device_create_file_fan(client, offset) \
 do { \
@@ -479,9 +562,9 @@
 		return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
 	} \
 }
-show_temp_reg(temp)
-show_temp_reg(temp_max)
-show_temp_reg(temp_max_hyst)
+show_temp_reg(temp);
+show_temp_reg(temp_max);
+show_temp_reg(temp_max_hyst);
 
 #define store_temp_reg(REG, reg) \
 static ssize_t \
@@ -505,8 +588,8 @@
 	 \
 	return count; \
 }
-store_temp_reg(OVER, max)
-store_temp_reg(HYST, max_hyst)
+store_temp_reg(OVER, max);
+store_temp_reg(HYST, max_hyst);
 
 #define sysfs_temp_offset(offset) \
 static ssize_t \
@@ -514,7 +597,7 @@
 { \
 	return show_temp(dev, buf, 0x##offset); \
 } \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL)
+static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL);
 
 #define sysfs_temp_reg_offset(reg, offset) \
 static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
@@ -528,16 +611,16 @@
 	return store_temp_##reg (dev, buf, count, 0x##offset); \
 } \
 static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \
-		  show_regs_temp_##reg##offset, store_regs_temp_##reg##offset)
+		  show_regs_temp_##reg##offset, store_regs_temp_##reg##offset);
 
 #define sysfs_temp_offsets(offset) \
 sysfs_temp_offset(offset) \
 sysfs_temp_reg_offset(max, offset) \
 sysfs_temp_reg_offset(max_hyst, offset)
 
-sysfs_temp_offsets(1)
-sysfs_temp_offsets(2)
-sysfs_temp_offsets(3)
+sysfs_temp_offsets(1);
+sysfs_temp_offsets(2);
+sysfs_temp_offsets(3);
 
 #define device_create_file_temp(client, offset) \
 do { \
@@ -552,7 +635,7 @@
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL)
+static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
 #define device_create_file_vid(client) \
 device_create_file(&client->dev, &dev_attr_in0_ref)
 
@@ -574,7 +657,7 @@
 
 	return count;
 }
-static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 #define device_create_file_vrm(client) \
 device_create_file(&client->dev, &dev_attr_vrm)
 
@@ -584,7 +667,7 @@
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) data->alarms);
 }
-static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
 #define device_create_file_alarms(client) \
 device_create_file(&client->dev, &dev_attr_alarms)
 
@@ -641,10 +724,10 @@
 	return store_beep_reg(dev, buf, count, BEEP_##REG); \
 } \
 static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \
-		  show_regs_beep_##reg, store_regs_beep_##reg)
+		  show_regs_beep_##reg, store_regs_beep_##reg);
 
-sysfs_beep(ENABLE, enable)
-sysfs_beep(MASK, mask)
+sysfs_beep(ENABLE, enable);
+sysfs_beep(MASK, mask);
 
 #define device_create_file_beep(client) \
 do { \
@@ -707,11 +790,11 @@
 	return store_fan_div_reg(dev, buf, count, offset - 1); \
 } \
 static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
-		  show_regs_fan_div_##offset, store_regs_fan_div_##offset)
+		  show_regs_fan_div_##offset, store_regs_fan_div_##offset);
 
-sysfs_fan_div(1)
-sysfs_fan_div(2)
-sysfs_fan_div(3)
+sysfs_fan_div(1);
+sysfs_fan_div(2);
+sysfs_fan_div(3);
 
 #define device_create_file_fan_div(client, offset) \
 do { \
@@ -763,11 +846,11 @@
 	return store_pwm_reg(dev, buf, count, offset); \
 } \
 static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \
-		  show_regs_pwm_##offset, store_regs_pwm_##offset)
+		  show_regs_pwm_##offset, store_regs_pwm_##offset);
 
-sysfs_pwm(1)
-sysfs_pwm(2)
-sysfs_pwm(3)
+sysfs_pwm(1);
+sysfs_pwm(2);
+sysfs_pwm(3);
 
 #define device_create_file_pwm(client, offset) \
 do { \
@@ -836,11 +919,11 @@
     return store_sensor_reg(dev, buf, count, offset); \
 } \
 static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
-		  show_regs_sensor_##offset, store_regs_sensor_##offset)
+		  show_regs_sensor_##offset, store_regs_sensor_##offset);
 
-sysfs_sensor(1)
-sysfs_sensor(2)
-sysfs_sensor(3)
+sysfs_sensor(1);
+sysfs_sensor(2);
+sysfs_sensor(3);
 
 #define device_create_file_sensor(client, offset) \
 do { \
@@ -1157,7 +1240,7 @@
 static void w83627hf_init_client(struct i2c_client *client)
 {
 	struct w83627hf_data *data = i2c_get_clientdata(client);
-	int vid = 0, i;
+	int i;
 	int type = data->type;
 	u8 tmp;
 
@@ -1191,10 +1274,15 @@
 		data->vid = w83627thf_read_gpio5(client) & 0x1f;
 	}
 
-	/* Convert VID to voltage based on default VRM */
-	data->vrm = DEFAULT_VRM;
-	if (type != w83697hf)
-		vid = vid_from_reg(vid, data->vrm);
+	/* Read VRM & OVT Config only once */
+	if (w83627thf == data->type || w83637hf == data->type) {
+		data->vrm_ovt = 
+			w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG);
+		data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
+	} else {
+		/* Convert VID to voltage based on default VRM */
+		data->vrm = DEFAULT_VRM;
+	}
 
 	tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
 	for (i = 1; i <= 3; i++) {
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	2004-06-23 19:04:24 -07:00
+++ b/drivers/i2c/chips/w83781d.c	2004-06-23 19:04:24 -07:00
@@ -320,7 +320,7 @@
 { \
         return show_in(dev, buf, 0x##offset); \
 } \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL)
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL);
 
 #define sysfs_in_reg_offset(reg, offset) \
 static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
@@ -331,7 +331,7 @@
 { \
 	return store_in_##reg (dev, buf, count, 0x##offset); \
 } \
-static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset)
+static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset);
 
 #define sysfs_in_offsets(offset) \
 sysfs_in_offset(offset); \
@@ -386,7 +386,7 @@
 { \
 	return show_fan(dev, buf, 0x##offset); \
 } \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL)
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL);
 
 #define sysfs_fan_min_offset(offset) \
 static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
@@ -397,7 +397,7 @@
 { \
 	return store_fan_min(dev, buf, count, 0x##offset); \
 } \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset)
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset);
 
 sysfs_fan_offset(1);
 sysfs_fan_min_offset(1);
@@ -466,7 +466,7 @@
 { \
 	return show_temp(dev, buf, 0x##offset); \
 } \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL)
+static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL);
 
 #define sysfs_temp_reg_offset(reg, offset) \
 static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
@@ -477,7 +477,7 @@
 { \
 	return store_temp_##reg (dev, buf, count, 0x##offset); \
 } \
-static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset)
+static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset);
 
 #define sysfs_temp_offsets(offset) \
 sysfs_temp_offset(offset); \
@@ -503,7 +503,7 @@
 }
 
 static
-DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL)
+DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
 #define device_create_file_vid(client) \
 device_create_file(&client->dev, &dev_attr_in0_ref);
 static ssize_t
@@ -527,7 +527,7 @@
 }
 
 static
-DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
+DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 #define device_create_file_vrm(client) \
 device_create_file(&client->dev, &dev_attr_vrm);
 static ssize_t
@@ -538,7 +538,7 @@
 }
 
 static
-DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
+DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
 #define device_create_file_alarms(client) \
 device_create_file(&client->dev, &dev_attr_alarms);
 static ssize_t show_beep_mask (struct device *dev, char *buf)
@@ -598,7 +598,7 @@
 { \
 	return store_beep_reg(dev, buf, count, BEEP_##REG); \
 } \
-static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg)
+static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg);
 
 sysfs_beep(ENABLE, enable);
 sysfs_beep(MASK, mask);
@@ -665,7 +665,7 @@
 { \
 	return store_fan_div_reg(dev, buf, count, offset - 1); \
 } \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset)
+static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset);
 
 sysfs_fan_div(1);
 sysfs_fan_div(2);
@@ -744,7 +744,7 @@
 { \
 	return store_pwm_reg(dev, buf, count, offset); \
 } \
-static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset)
+static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset);
 
 #define sysfs_pwmenable(offset) \
 static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \
@@ -755,7 +755,7 @@
 { \
 	return store_pwmenable_reg(dev, buf, count, offset); \
 } \
-static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset)
+static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset);
 
 sysfs_pwm(1);
 sysfs_pwm(2);
@@ -833,7 +833,7 @@
 { \
     return store_sensor_reg(dev, buf, count, offset); \
 } \
-static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset)
+static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset);
 
 sysfs_sensor(1);
 sysfs_sensor(2);
@@ -891,7 +891,7 @@
 { \
     return store_rt_reg(dev, buf, count, offset); \
 } \
-static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset)
+static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset);
 
 sysfs_rt(1);
 sysfs_rt(2);
@@ -1491,7 +1491,7 @@
 w83781d_init_client(struct i2c_client *client)
 {
 	struct w83781d_data *data = i2c_get_clientdata(client);
-	int vid = 0, i, p;
+	int i, p;
 	int type = data->type;
 	u8 tmp;
 
@@ -1513,14 +1513,7 @@
 		w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
 	}
 
-	if (type != w83697hf) {
-		vid = w83781d_read_value(client, W83781D_REG_VID_FANDIV) & 0x0f;
-		vid |=
-		    (w83781d_read_value(client, W83781D_REG_CHIPID) & 0x01) <<
-		    4;
-		data->vrm = DEFAULT_VRM;
-		vid = vid_from_reg(vid, data->vrm);
-	}
+	data->vrm = 82;
 
 	if ((type != w83781d) && (type != as99127f)) {
 		tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
diff -Nru a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c
--- a/drivers/i2c/chips/w83l785ts.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/i2c/chips/w83l785ts.c	2004-06-23 19:04:26 -07:00
@@ -137,8 +137,8 @@
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
 }
 
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL)
-static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_over, NULL)
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_over, NULL);
 
 /*
  * Real code
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/i2c/i2c-core.c	2004-06-23 19:04:25 -07:00
@@ -126,7 +126,13 @@
 		goto out_unlock;
 	}
 
-	id = idr_get_new(&i2c_adapter_idr, NULL);
+	res = idr_get_new(&i2c_adapter_idr, NULL, &id);
+	if (res < 0) {
+		if (res == -EAGAIN)
+			res = -ENOMEM;
+		goto out_unlock;
+	}
+
 	adap->nr =  id & MAX_ID_MASK;
 	init_MUTEX(&adap->bus_lock);
 	init_MUTEX(&adap->clist_lock);
@@ -162,7 +168,7 @@
 
 	dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr);
 
- out_unlock:
+out_unlock:
 	up(&core_lists);
 	return res;
 }
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/i2c/i2c-dev.c	2004-06-23 19:04:28 -07:00
@@ -181,7 +181,7 @@
 	struct i2c_smbus_ioctl_data data_arg;
 	union i2c_smbus_data temp;
 	struct i2c_msg *rdwr_pa;
-	u8 **data_ptrs;
+	u8 __user **data_ptrs;
 	int i,datasize,res;
 	unsigned long funcs;
 
@@ -238,8 +238,7 @@
 			return -EFAULT;
 		}
 
-		data_ptrs = (u8 **) kmalloc(rdwr_arg.nmsgs * sizeof(u8 *),
-					    GFP_KERNEL);
+		data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
 		if (data_ptrs == NULL) {
 			kfree(rdwr_pa);
 			return -ENOMEM;
@@ -252,7 +251,7 @@
 				res = -EINVAL;
 				break;
 			}
-			data_ptrs[i] = rdwr_pa[i].buf;
+			data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
 			rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
 			if(rdwr_pa[i].buf == NULL) {
 				res = -ENOMEM;
diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig
--- a/drivers/ide/Kconfig	2004-06-23 19:04:26 -07:00
+++ b/drivers/ide/Kconfig	2004-06-23 19:04:26 -07:00
@@ -95,27 +95,29 @@
 
 comment "Please see Documentation/ide.txt for help/info on IDE drives"
 
-config BLK_DEV_HD_IDE
-	bool "Use old disk-only driver on primary interface"
-	depends on ((X86 && X86_PC9800!=y) || SH_MPC1211)
+config BLK_DEV_IDE_SATA
+	bool "Support for SATA (deprecated; conflicts with libata SATA driver)"
+	default n
 	---help---
-	  There are two drivers for MFM/RLL/IDE disks.  Most people use just
-	  the new enhanced driver by itself.  This option however installs the
-	  old hard disk driver to control the primary IDE/disk interface in
-	  the system, leaving the new enhanced IDE driver to take care of only
-	  the 2nd/3rd/4th IDE interfaces.  Doing this will prevent you from
-	  having an IDE/ATAPI CD-ROM or tape drive connected to the primary
-	  IDE interface.  Choosing this option may be useful for older systems
-	  which have MFM/RLL/ESDI controller+drives at the primary port
-	  address (0x1f0), along with IDE drives at the secondary/3rd/4th port
-	  addresses.
+	  There are two drivers for Serial ATA controllers.
+
+	  The main driver, "libata", exists inside the SCSI subsystem
+	  and supports most modern SATA controllers.
 
-	  Normally, just say N here; you will then use the new driver for all
-	  4 interfaces.
+	  The IDE driver (which you are currently configuring) supports
+	  a few first-generation SATA controllers.
 
-config BLK_DEV_HD_IDE98
+	  In order to eliminate conflicts between the two subsystems,
+	  this config option enables the IDE driver's SATA support.
+	  Normally this is disabled, as it is preferred that libata
+	  supports SATA controllers, and this (IDE) driver supports
+	  PATA controllers.
+
+	  If unsure, say N.
+
+config BLK_DEV_HD_IDE
 	bool "Use old disk-only driver on primary interface"
-	depends on X86 && X86_PC9800
+	depends on (X86 || SH_MPC1211)
 	---help---
 	  There are two drivers for MFM/RLL/IDE disks.  Most people use just
 	  the new enhanced driver by itself.  This option however installs the
diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile
--- a/drivers/ide/Makefile	2004-06-23 19:04:27 -07:00
+++ b/drivers/ide/Makefile	2004-06-23 19:04:27 -07:00
@@ -29,7 +29,6 @@
 ide-core-$(CONFIG_IDE_ARM)		+= arm/ide_arm.o
 
 # built-in only drivers from legacy/
-ide-core-$(CONFIG_BLK_DEV_IDE_PC9800)	+= legacy/pc9800.o
 ide-core-$(CONFIG_BLK_DEV_BUDDHA)	+= legacy/buddha.o
 ide-core-$(CONFIG_BLK_DEV_FALCON_IDE)	+= legacy/falconide.o
 ide-core-$(CONFIG_BLK_DEV_GAYLE)	+= legacy/gayle.o
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/ide/ide-cd.c	2004-06-23 19:04:26 -07:00
@@ -2816,7 +2816,6 @@
 	return 0;
 }
 
-
 /*
  * Close down the device.  Invalidate all cached blocks.
  */
@@ -2890,12 +2889,6 @@
 		devinfo->mask |= CDC_CLOSE_TRAY;
 	if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
 		devinfo->mask |= CDC_MO_DRIVE;
-	if (!CDROM_CONFIG_FLAGS(drive)->mrw)
-		devinfo->mask |= CDC_MRW;
-	if (!CDROM_CONFIG_FLAGS(drive)->mrw_w)
-		devinfo->mask |= CDC_MRW_W;
-	if (!CDROM_CONFIG_FLAGS(drive)->ram)
-		devinfo->mask |= CDC_RAM;
 
 	devinfo->disk = drive->disk;
 	return register_cdrom(devinfo);
@@ -2932,7 +2925,7 @@
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *cdi = &info->devinfo;
 	struct atapi_capabilities_page cap;
-	int nslots = 1, mrw_write = 0, ram_write = 0;
+	int nslots = 1;
 
 	if (drive->media == ide_optical) {
 		CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
@@ -2961,17 +2954,6 @@
 	if (ide_cdrom_get_capabilities(drive, &cap))
 		return 0;
 
-	if (!cdrom_is_mrw(cdi, &mrw_write)) {
-		CDROM_CONFIG_FLAGS(drive)->mrw = 1;
-		if (mrw_write) {
-			CDROM_CONFIG_FLAGS(drive)->mrw_w = 1;
-			CDROM_CONFIG_FLAGS(drive)->ram = 1;
-		}
-	}
-	if (!cdrom_is_random_writable(cdi, &ram_write))
-		if (ram_write)
-			CDROM_CONFIG_FLAGS(drive)->ram = 1;
-
 	if (cap.lock == 0)
 		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
 	if (cap.eject)
@@ -3050,9 +3032,6 @@
         	printk(" CD%s%s", 
         	(CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "", 
         	(CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : "");
-
-	if (CDROM_CONFIG_FLAGS(drive)->mrw || CDROM_CONFIG_FLAGS(drive)->mrw_w)
-		printk(" CD-MR%s", CDROM_CONFIG_FLAGS(drive)->mrw_w ? "W" : "");
 
         if (CDROM_CONFIG_FLAGS(drive)->is_changer) 
         	printk(" changer w/%d slots", nslots);
diff -Nru a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
--- a/drivers/ide/ide-cd.h	2004-06-23 19:04:29 -07:00
+++ b/drivers/ide/ide-cd.h	2004-06-23 19:04:29 -07:00
@@ -79,8 +79,6 @@
 	__u8 dvd		: 1; /* Drive is a DVD-ROM */
 	__u8 dvd_r		: 1; /* Drive can write DVD-R */
 	__u8 dvd_ram		: 1; /* Drive can write DVD-RAM */
-	__u8 mrw		: 1; /* drive can read mrw */
-	__u8 mrw_w		: 1; /* drive can write mrw */
 	__u8 ram		: 1; /* generic WRITE (dvd-ram/mrw) */
 	__u8 test_write		: 1; /* Drive can fake writes */
 	__u8 supp_disc_present	: 1; /* Changer can report exact contents
diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
--- a/drivers/ide/ide-proc.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/ide/ide-proc.c	2004-06-23 19:04:27 -07:00
@@ -321,7 +321,6 @@
 		case ide_cy82c693:	name = "cy82c693";	break;
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
-		case ide_pc9800:	name = "pc9800";	break;
 		default:		name = "(unknown)";	break;
 	}
 	len = sprintf(page, "%s\n", name);
diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
--- a/drivers/ide/ide-tape.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/ide/ide-tape.c	2004-06-23 19:04:26 -07:00
@@ -2674,7 +2674,7 @@
 	return __idetape_kmalloc_stage(tape, 0, 0);
 }
 
-static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char *buf, int n)
+static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
 {
 	struct idetape_bh *bh = tape->bh;
 	int count;
@@ -2701,7 +2701,7 @@
 	tape->bh = bh;
 }
 
-static void idetape_copy_stage_to_user (idetape_tape_t *tape, char *buf, idetape_stage_t *stage, int n)
+static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
 {
 	struct idetape_bh *bh = tape->bh;
 	int count;
@@ -3610,6 +3610,7 @@
 {
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_config_t config;
+	void __user *argp = (void __user *)arg;
 
 #if IDETAPE_DEBUG_LOG	
 	if (tape->debug_level >= 4)
@@ -3617,7 +3618,7 @@
 #endif /* IDETAPE_DEBUG_LOG */
 	switch (cmd) {
 		case 0x0340:
-			if (copy_from_user ((char *) &config, (char *) arg, sizeof (idetape_config_t)))
+			if (copy_from_user(&config, argp, sizeof (idetape_config_t)))
 				return -EFAULT;
 			tape->best_dsc_rw_frequency = config.dsc_rw_frequency;
 			tape->max_stages = config.nr_stages;
@@ -3625,7 +3626,7 @@
 		case 0x0350:
 			config.dsc_rw_frequency = (int) tape->best_dsc_rw_frequency;
 			config.nr_stages = tape->max_stages; 
-			if (copy_to_user((char *) arg, (char *) &config, sizeof (idetape_config_t)))
+			if (copy_to_user(argp, &config, sizeof (idetape_config_t)))
 				return -EFAULT;
 			break;
 		default:
@@ -3747,7 +3748,7 @@
  *	will no longer hit performance.
  *      This is not applicable to Onstream.
  */
-static ssize_t idetape_chrdev_read (struct file *file, char *buf,
+static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
 				    size_t count, loff_t *ppos)
 {
 	ide_drive_t *drive = file->private_data;
@@ -3810,7 +3811,7 @@
 	return actually_read;
 }
 
-static ssize_t idetape_chrdev_write (struct file *file, const char *buf,
+static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
 				     size_t count, loff_t *ppos)
 {
 	ide_drive_t *drive = file->private_data;
@@ -4127,6 +4128,7 @@
 	struct mtget mtget;
 	struct mtpos mtpos;
 	int block_offset = 0, position = tape->first_frame_position;
+	void __user *argp = (void __user *)arg;
 
 #if IDETAPE_DEBUG_LOG
 	if (tape->debug_level >= 3)
@@ -4146,7 +4148,7 @@
 	}
 	switch (cmd) {
 		case MTIOCTOP:
-			if (copy_from_user((char *) &mtop, (char *) arg, sizeof (struct mtop)))
+			if (copy_from_user(&mtop, argp, sizeof (struct mtop)))
 				return -EFAULT;
 			return (idetape_mtioctop(drive,mtop.mt_op,mtop.mt_count));
 		case MTIOCGET:
@@ -4157,12 +4159,12 @@
 			if (tape->drv_write_prot) {
 				mtget.mt_gstat |= GMT_WR_PROT(0xffffffff);
 			}
-			if (copy_to_user((char *) arg,(char *) &mtget, sizeof(struct mtget)))
+			if (copy_to_user(argp, &mtget, sizeof(struct mtget)))
 				return -EFAULT;
 			return 0;
 		case MTIOCPOS:
 			mtpos.mt_blkno = position / tape->user_bs_factor - block_offset;
-			if (copy_to_user((char *) arg,(char *) &mtpos, sizeof(struct mtpos)))
+			if (copy_to_user(argp, &mtpos, sizeof(struct mtpos)))
 				return -EFAULT;
 			return 0;
 		default:
diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
--- a/drivers/ide/legacy/hd.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/ide/legacy/hd.c	2004-06-23 19:04:25 -07:00
@@ -660,7 +660,7 @@
 	unsigned int cmd, unsigned long arg)
 {
 	struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data;
-	struct hd_geometry *loc = (struct hd_geometry *) arg;
+	struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
 	struct hd_geometry g; 
 
 	if (cmd != HDIO_GETGEO)
diff -Nru a/drivers/ide/legacy/hd98.c b/drivers/ide/legacy/hd98.c
--- a/drivers/ide/legacy/hd98.c	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,883 +0,0 @@
-/*
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- * This is the low-level hd interrupt support. It traverses the
- * request-list, using interrupts to jump between functions. As
- * all the functions are called within interrupts, we may not
- * sleep. Special care is recommended.
- *
- *  modified by Drew Eckhardt to check nr of hd's from the CMOS.
- *
- *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
- *  in the early extended-partition checks and added DM partitions
- *
- *  IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
- *  and general streamlining by Mark Lord.
- *
- *  Removed 99% of above. Use Mark's ide driver for those options.
- *  This is now a lightweight ST-506 driver. (Paul Gortmaker)
- *
- *  Modified 1995 Russell King for ARM processor.
- *
- *  Bugfix: max_sectors must be <= 255 or the wheels tend to come
- *  off in a hurry once you queue things up - Paul G. 02/2001
- */
-
-/* Uncomment the following if you want verbose error reports. */
-/* #define VERBOSE_ERRORS */
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/genhd.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/mc146818rtc.h> /* CMOS defines */
-#include <linux/init.h>
-#include <linux/blkpg.h>
-#include <linux/hdreg.h>
-
-#define REALLY_SLOW_IO
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include "io_ports.h"
-
-#ifdef __arm__
-#undef  HD_IRQ
-#endif
-#include <asm/irq.h>
-#ifdef __arm__
-#define HD_IRQ IRQ_HARDDISK
-#endif
-
-/* Hd controller regster ports */
-
-#define HD_DATA		0x640	/* _CTL when writing */
-#define HD_ERROR	0x642	/* see err-bits */
-#define HD_NSECTOR	0x644	/* nr of sectors to read/write */
-#define HD_SECTOR	0x646	/* starting sector */
-#define HD_LCYL		0x648	/* starting cylinder */
-#define HD_HCYL		0x64a	/* high byte of starting cyl */
-#define HD_CURRENT	0x64c	/* 101dhhhh , d=drive, hhhh=head */
-#define HD_STATUS	0x64e	/* see status-bits */
-#define HD_FEATURE	HD_ERROR	/* same io address, read=error, write=feature */
-#define HD_PRECOMP	HD_FEATURE	/* obsolete use of this port - predates IDE */
-#define HD_COMMAND	HD_STATUS	/* same io address, read=status, write=cmd */
-
-#define HD_CMD		0x74c	/* used for resets */
-#define HD_ALTSTATUS	0x74c	/* same as HD_STATUS but doesn't clear irq */
-
-/* Bits of HD_STATUS */
-#define ERR_STAT		0x01
-#define INDEX_STAT		0x02
-#define ECC_STAT		0x04	/* Corrected error */
-#define DRQ_STAT		0x08
-#define SEEK_STAT		0x10
-#define SERVICE_STAT		SEEK_STAT
-#define WRERR_STAT		0x20
-#define READY_STAT		0x40
-#define BUSY_STAT		0x80
-
-/* Bits for HD_ERROR */
-#define MARK_ERR		0x01	/* Bad address mark */
-#define TRK0_ERR		0x02	/* couldn't find track 0 */
-#define ABRT_ERR		0x04	/* Command aborted */
-#define MCR_ERR			0x08	/* media change request */
-#define ID_ERR			0x10	/* ID field not found */
-#define MC_ERR			0x20	/* media changed */
-#define ECC_ERR			0x40	/* Uncorrectable ECC error */
-#define BBD_ERR			0x80	/* pre-EIDE meaning:  block marked bad */
-#define ICRC_ERR		0x80	/* new meaning:  CRC error during transfer */
-
-static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED;
-static struct request_queue *hd_queue;
-
-#define CURRENT elv_next_request(hd_queue)
-
-#define TIMEOUT_VALUE	(6*HZ)
-#define	HD_DELAY	0
-
-#define MAX_ERRORS     16	/* Max read/write errors/sector */
-#define RESET_FREQ      8	/* Reset controller every 8th retry */
-#define RECAL_FREQ      4	/* Recalibrate every 4th retry */
-#define MAX_HD		2
-
-#define STAT_OK		(READY_STAT|SEEK_STAT)
-#define OK_STATUS(s)	(((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
-
-static void recal_intr(void);
-static void bad_rw_intr(void);
-
-static int reset;
-static int hd_error;
-
-/*
- *  This struct defines the HD's and their types.
- */
-struct hd_i_struct {
-	unsigned int head,sect,cyl,wpcom,lzone,ctl;
-	int unit;
-	int recalibrate;
-	int special_op;
-};
-	
-#ifdef HD_TYPE
-static struct hd_i_struct hd_info[] = { HD_TYPE };
-static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
-#else
-static struct hd_i_struct hd_info[MAX_HD];
-static int NR_HD;
-#endif
-
-static struct gendisk *hd_gendisk[MAX_HD];
-
-static struct timer_list device_timer;
-
-#define TIMEOUT_VALUE (6*HZ)
-
-#define SET_TIMER							\
-	do {								\
-		mod_timer(&device_timer, jiffies + TIMEOUT_VALUE);	\
-	} while (0)
-
-static void (*do_hd)(void) = NULL;
-#define SET_HANDLER(x) \
-if ((do_hd = (x)) != NULL) \
-	SET_TIMER; \
-else \
-	del_timer(&device_timer);
-
-
-#if (HD_DELAY > 0)
-unsigned long last_req;
-
-unsigned long read_timer(void)
-{
-        extern spinlock_t i8253_lock;
-	unsigned long t, flags;
-	int i;
-
-	spin_lock_irqsave(&i8253_lock, flags);
-	t = jiffies * 11932;
-    	outb_p(0, PIT_MODE);
-	i = inb_p(PIT_CH0);
-	i |= inb(PIT_CH0) << 8;
-	spin_unlock_irqrestore(&i8253_lock, flags);
-	return(t - i);
-}
-#endif
-
-void __init hd_setup(char *str, int *ints)
-{
-	int hdind = 0;
-
-	if (ints[0] != 3)
-		return;
-	if (hd_info[0].head != 0)
-		hdind=1;
-	hd_info[hdind].head = ints[2];
-	hd_info[hdind].sect = ints[3];
-	hd_info[hdind].cyl = ints[1];
-	hd_info[hdind].wpcom = 0;
-	hd_info[hdind].lzone = ints[1];
-	hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
-	NR_HD = hdind+1;
-}
-
-static void dump_status (const char *msg, unsigned int stat)
-{
-	char *name = CURRENT ?
-			CURRENT->rq_dev->bd_disk->disk_name :
-			"hd?";
-#ifdef VERBOSE_ERRORS
-	printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
-	if (stat & BUSY_STAT)	printk("Busy ");
-	if (stat & READY_STAT)	printk("DriveReady ");
-	if (stat & WRERR_STAT)	printk("WriteFault ");
-	if (stat & SEEK_STAT)	printk("SeekComplete ");
-	if (stat & DRQ_STAT)	printk("DataRequest ");
-	if (stat & ECC_STAT)	printk("CorrectedError ");
-	if (stat & INDEX_STAT)	printk("Index ");
-	if (stat & ERR_STAT)	printk("Error ");
-	printk("}\n");
-	if ((stat & ERR_STAT) == 0) {
-		hd_error = 0;
-	} else {
-		hd_error = inb(HD_ERROR);
-		printk("%s: %s: error=0x%02x { ", name, msg, hd_error & 0xff);
-		if (hd_error & BBD_ERR)		printk("BadSector ");
-		if (hd_error & ECC_ERR)		printk("UncorrectableError ");
-		if (hd_error & ID_ERR)		printk("SectorIdNotFound ");
-		if (hd_error & ABRT_ERR)	printk("DriveStatusError ");
-		if (hd_error & TRK0_ERR)	printk("TrackZeroNotFound ");
-		if (hd_error & MARK_ERR)	printk("AddrMarkNotFound ");
-		printk("}");
-		if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
-			printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
-				inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
-			if (CURRENT)
-				printk(", sector=%ld", CURRENT->sector);
-		}
-		printk("\n");
-	}
-#else
-	printk("%s: %s: status=0x%02x.\n", name, msg, stat & 0xff);
-	if ((stat & ERR_STAT) == 0) {
-		hd_error = 0;
-	} else {
-		hd_error = inb(HD_ERROR);
-		printk("%s: %s: error=0x%02x.\n", name, msg, hd_error & 0xff);
-	}
-#endif
-}
-
-void check_status(void)
-{
-	int i = inb(HD_STATUS);
-
-	if (!OK_STATUS(i)) {
-		dump_status("check_status", i);
-		bad_rw_intr();
-	}
-}
-
-static int controller_busy(void)
-{
-	int retries = 100000;
-	unsigned char status;
-
-	do {
-		status = inb(HD_STATUS);
-	} while ((status & BUSY_STAT) && --retries);
-	return status;
-}
-
-static int status_ok(void)
-{
-	unsigned char status = inb(HD_STATUS);
-
-	if (status & BUSY_STAT)
-		return 1;	/* Ancient, but does it make sense??? */
-	if (status & WRERR_STAT)
-		return 0;
-	if (!(status & READY_STAT))
-		return 0;
-	if (!(status & SEEK_STAT))
-		return 0;
-	return 1;
-}
-
-static int controller_ready(unsigned int drive, unsigned int head)
-{
-	int retry = 100;
-
-	do {
-		if (controller_busy() & BUSY_STAT)
-			return 0;
-		outb(0xA0 | (drive<<4) | head, HD_CURRENT);
-		if (status_ok())
-			return 1;
-	} while (--retry);
-	return 0;
-}
-
-static void hd_out(struct hd_i_struct *disk,
-		   unsigned int nsect,
-		   unsigned int sect,
-		   unsigned int head,
-		   unsigned int cyl,
-		   unsigned int cmd,
-		   void (*intr_addr)(void))
-{
-	unsigned short port;
-
-#if (HD_DELAY > 0)
-	while (read_timer() - last_req < HD_DELAY)
-		/* nothing */;
-#endif
-	if (reset)
-		return;
-	if (!controller_ready(disk->unit, head)) {
-		reset = 1;
-		return;
-	}
-	SET_HANDLER(intr_addr);
-	outb(disk->ctl,HD_CMD);
-	port=HD_DATA + 2;
-	outb(disk->wpcom>>2, port); port += 2;
-	outb(nsect, port); port += 2;
-	outb(sect, port); port += 2;
-	outb(cyl, port); port += 2;
-	outb(cyl>>8, port); port += 2;
-	outb(0xA0|(disk->unit<<4)|head, port); port += 2;
-	outb(cmd, port);
-}
-
-static void hd_request (void);
-
-static int drive_busy(void)
-{
-	unsigned int i;
-	unsigned char c;
-
-	for (i = 0; i < 500000 ; i++) {
-		c = inb(HD_STATUS);
-		if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
-			return 0;
-	}
-	dump_status("reset timed out", c);
-	return 1;
-}
-
-static void reset_controller(void)
-{
-	int	i;
-
-	outb(4,HD_CMD);
-	for(i = 0; i < 1000; i++) barrier();
-	outb(hd_info[0].ctl & 0x0f,HD_CMD);
-	for(i = 0; i < 1000; i++) barrier();
-	if (drive_busy())
-		printk("hd: controller still busy\n");
-	else if ((hd_error = inb(HD_ERROR)) != 1)
-		printk("hd: controller reset failed: %02x\n",hd_error);
-}
-
-static void reset_hd(void)
-{
-	static int i;
-
-repeat:
-	if (reset) {
-		reset = 0;
-		i = -1;
-		reset_controller();
-	} else {
-		check_status();
-		if (reset)
-			goto repeat;
-	}
-	if (++i < NR_HD) {
-		struct hd_i_struct *disk = &hd_info[i];
-		disk->special_op = disk->recalibrate = 1;
-		hd_out(disk, disk->sect, disk->sect, disk->head-1,
-			disk->cyl, WIN_SPECIFY, &reset_hd);
-		if (reset)
-			goto repeat;
-	} else
-		hd_request();
-}
-
-/*
- * Ok, don't know what to do with the unexpected interrupts: on some machines
- * doing a reset and a retry seems to result in an eternal loop. Right now I
- * ignore it, and just set the timeout.
- *
- * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
- * drive enters "idle", "standby", or "sleep" mode, so if the status looks
- * "good", we just ignore the interrupt completely.
- */
-void unexpected_hd_interrupt(void)
-{
-	unsigned int stat = inb(HD_STATUS);
-
-	if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
-		dump_status ("unexpected interrupt", stat);
-		SET_TIMER;
-	}
-}
-
-/*
- * bad_rw_intr() now tries to be a bit smarter and does things
- * according to the error returned by the controller.
- * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
- */
-static void bad_rw_intr(void)
-{
-	struct request *req = CURRENT;
-	struct hd_i_struct *disk;
-
-	if (!req)
-		return;
-	disk = req->rq_disk->private_data;
-	if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
-		end_request(req, 0);
-		disk->special_op = disk->recalibrate = 1;
-	} else if (req->errors % RESET_FREQ == 0)
-		reset = 1;
-	else if ((hd_error & TRK0_ERR) || req->errors % RECAL_FREQ == 0)
-		disk->special_op = disk->recalibrate = 1;
-	/* Otherwise just retry */
-}
-
-static inline int wait_DRQ(void)
-{
-	int retries = 100000, stat;
-
-	while (--retries > 0)
-		if ((stat = inb(HD_STATUS)) & DRQ_STAT)
-			return 0;
-	dump_status("wait_DRQ", stat);
-	return -1;
-}
-
-static void read_intr(void)
-{
-	int i, retries = 100000;
-	struct request *req;
-
-	do {
-		i = (unsigned) inb(HD_STATUS);
-		if (i & BUSY_STAT)
-			continue;
-		if (!OK_STATUS(i))
-			break;
-		if (i & DRQ_STAT)
-			goto ok_to_read;
-	} while (--retries > 0);
-	dump_status("read_intr", i);
-	bad_rw_intr();
-	hd_request();
-	return;
-ok_to_read:
-	req = CURRENT;
-	insw(HD_DATA,req->buffer,256);
-	req->sector++;
-	req->buffer += 512;
-	req->errors = 0;
-	i = --req->nr_sectors;
-	--req->current_nr_sectors;
-#ifdef DEBUG
-	printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n",
-		req->rq_disk->disk_name, req->sector, req->nr_sectors,
-		req->buffer+512);
-#endif
-	if (req->current_nr_sectors <= 0)
-		end_request(req, 1);
-	if (i > 0) {
-		SET_HANDLER(&read_intr);
-		return;
-	}
-	(void) inb(HD_STATUS);
-#if (HD_DELAY > 0)
-	last_req = read_timer();
-#endif
-	if (CURRENT)
-		hd_request();
-	return;
-}
-
-static void write_intr(void)
-{
-	int i;
-	int retries = 100000;
-	struct request *req = CURRENT;
-
-	do {
-		i = (unsigned) inb(HD_STATUS);
-		if (i & BUSY_STAT)
-			continue;
-		if (!OK_STATUS(i))
-			break;
-		if ((req->nr_sectors <= 1) || (i & DRQ_STAT))
-			goto ok_to_write;
-	} while (--retries > 0);
-	dump_status("write_intr", i);
-	bad_rw_intr();
-	hd_request();
-	return;
-ok_to_write:
-	req->sector++;
-	i = --req->nr_sectors;
-	--req->current_nr_sectors;
-	req->buffer += 512;
-	if (!i || (req->bio && req->current_nr_sectors < 1))
-		end_request(req, 1);
-	if (i > 0) {
-		SET_HANDLER(&write_intr);
-		outsw(HD_DATA,req->buffer,256);
-		local_irq_enable();
-	} else {
-#if (HD_DELAY > 0)
-		last_req = read_timer();
-#endif
-		hd_request();
-	}
-	return;
-}
-
-static void recal_intr(void)
-{
-	check_status();
-#if (HD_DELAY > 0)
-	last_req = read_timer();
-#endif
-	hd_request();
-}
-
-/*
- * This is another of the error-routines I don't know what to do with. The
- * best idea seems to just set reset, and start all over again.
- */
-static void hd_times_out(unsigned long dummy)
-{
-	do_hd = NULL;
-
-	if (!CURRENT)
-		return;
-
-	disable_irq(HD_IRQ);
-	local_irq_enable();
-	reset = 1;
-	printk("%s: timeout\n", CURRENT->rq_disk->disk_name);
-	if (++CURRENT->errors >= MAX_ERRORS) {
-#ifdef DEBUG
-		printk("%s: too many errors\n", CURRENT->rq_disk->disk_name);
-#endif
-		end_request(CURRENT, 0);
-	}
-	local_irq_disable();
-	hd_request();
-	enable_irq(HD_IRQ);
-}
-
-int do_special_op(struct hd_i_struct *disk, struct request *req)
-{
-	if (disk->recalibrate) {
-		disk->recalibrate = 0;
-		hd_out(disk, disk->sect,0,0,0,WIN_RESTORE,&recal_intr);
-		return reset;
-	}
-	if (disk->head > 16) {
-		printk ("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
-		end_request(req, 0);
-	}
-	disk->special_op = 0;
-	return 1;
-}
-
-/*
- * The driver enables interrupts as much as possible.  In order to do this,
- * (a) the device-interrupt is disabled before entering hd_request(),
- * and (b) the timeout-interrupt is disabled before the sti().
- *
- * Interrupts are still masked (by default) whenever we are exchanging
- * data/cmds with a drive, because some drives seem to have very poor
- * tolerance for latency during I/O. The IDE driver has support to unmask
- * interrupts for non-broken hardware, so use that driver if required.
- */
-static void hd_request(void)
-{
-	unsigned int block, nsect, sec, track, head, cyl;
-	struct hd_i_struct *disk;
-	struct request *req;
-
-	if (do_hd)
-		return;
-repeat:
-	del_timer(&device_timer);
-	local_irq_enable();
-
-	if (!CURRENT) {
-		do_hd = NULL;
-		return;
-	}
-	req = CURRENT;
-
-	if (reset) {
-		local_irq_disable();
-		reset_hd();
-		return;
-	}
-	disk = req->rq_disk->private_data;
-	block = req->sector;
-	nsect = req->nr_sectors;
-	if (block >= get_capacity(req->rq_disk) ||
-	    ((block+nsect) > get_capacity(req->rq_disk))) {
-		printk("%s: bad access: block=%d, count=%d\n",
-			req->rq_disk->disk_name, block, nsect);
-		end_request(req, 0);
-		goto repeat;
-	}
-
-	if (disk->special_op) {
-		if (do_special_op(disk, req))
-			goto repeat;
-		return;
-	}
-	sec   = block % disk->sect + 1;
-	track = block / disk->sect;
-	head  = track % disk->head;
-	cyl   = track / disk->head;
-#ifdef DEBUG
-	printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
-		req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
-		cyl, head, sec, nsect, req->buffer);
-#endif
-	if (req->flags & REQ_CMD) {
-		switch (rq_data_dir(req)) {
-		case READ:
-			hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr);
-			if (reset)
-				goto repeat;
-			break;
-		case WRITE:
-			hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
-			if (reset)
-				goto repeat;
-			if (wait_DRQ()) {
-				bad_rw_intr();
-				goto repeat;
-			}
-			outsw(HD_DATA,req->buffer,256);
-			break;
-		default:
-			printk("unknown hd-command\n");
-			end_request(req, 0);
-			break;
-		}
-	}
-}
-
-static void do_hd_request (request_queue_t * q)
-{
-	disable_irq(HD_IRQ);
-	hd_request();
-	enable_irq(HD_IRQ);
-}
-
-static int hd_ioctl(struct inode * inode, struct file * file,
-	unsigned int cmd, unsigned long arg)
-{
-	struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data;
-	struct hd_geometry *loc = (struct hd_geometry *) arg;
-	struct hd_geometry g; 
-
-	if (cmd != HDIO_GETGEO)
-		return -EINVAL;
-	if (!loc)
-		return -EINVAL;
-	g.heads = disk->head;
-	g.sectors = disk->sect;
-	g.cylinders = disk->cyl;
-	g.start = get_start_sect(inode->i_bdev);
-	return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-
-static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	void (*handler)(void) = do_hd;
-
-	do_hd = NULL;
-	del_timer(&device_timer);
-	if (!handler)
-		handler = unexpected_hd_interrupt;
-	handler();
-	local_irq_enable();
-}
-
-static struct block_device_operations hd_fops = {
-	.ioctl =	hd_ioctl,
-};
-
-/*
- * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags
- * means we run the IRQ-handler with interrupts disabled:  this is bad for
- * interrupt latency, but anything else has led to problems on some
- * machines.
- *
- * We enable interrupts in some of the routines after making sure it's
- * safe.
- */
-
-static int __init hd_init(void)
-{
-	int drive;
-	if (register_blkdev(HD_MAJOR,"hd")) {
-		printk("hd: unable to get major %d for hard disk\n",HD_MAJOR);
-		return -1;
-	}
-	hd_queue = blk_init_queue(do_hd_request, &hd_lock);
-	if (!hd_queue) {
-		unregister_blkdev(HD_MAJOR,"hd");
-		return -1;
-	}
-	blk_queue_max_sectors(hd_queue, 255);
-	init_timer(&device_timer);
-	device_timer.function = hd_times_out;
-	blk_queue_hardsect_size(hd_queue, 512);
-
-#ifdef __i386__
-	if (!NR_HD) {
-		extern struct drive_info drive_info;
-		unsigned char *BIOS = (unsigned char *) &drive_info;
-		unsigned long flags;
-#ifndef CONFIG_X86_PC9800
-		int cmos_disks;
-#endif
-
-		for (drive=0 ; drive<2 ; drive++) {
-			hd_info[drive].cyl = *(unsigned short *) BIOS;
-			hd_info[drive].head = *(3+BIOS);
-			hd_info[drive].sect = *(2+BIOS);
-			hd_info[drive].wpcom = 0;
-			hd_info[drive].ctl = *(3+BIOS) > 8 ? 8 : 0;
-			hd_info[drive].lzone = *(unsigned short *) BIOS;
-			if (hd_info[drive].cyl && NR_HD == drive)
-				NR_HD++;
-			BIOS += 6;
-		}
-
-	}
-#endif /* __i386__ */
-#ifdef __arm__
-	if (!NR_HD) {
-		/* We don't know anything about the drive.  This means
-		 * that you *MUST* specify the drive parameters to the
-		 * kernel yourself.
-		 */
-		printk("hd: no drives specified - use hd=cyl,head,sectors"
-			" on kernel command line\n");
-	}
-#endif
-	if (!NR_HD)
-		goto out;
-
-	for (drive=0 ; drive < NR_HD ; drive++) {
-		struct gendisk *disk = alloc_disk(64);
-		struct hd_i_struct *p = &hd_info[drive];
-		if (!disk)
-			goto Enomem;
-		disk->major = HD_MAJOR;
-		disk->first_minor = drive << 6;
-		disk->fops = &hd_fops;
-		sprintf(disk->disk_name, "hd%c", 'a'+drive);
-		disk->private_data = p;
-		set_capacity(disk, p->head * p->sect * p->cyl);
-		disk->queue = hd_queue;
-		p->unit = drive;
-		hd_gendisk[drive] = disk;
-		printk ("%s: %luMB, CHS=%d/%d/%d\n",
-			disk->disk_name, (unsigned long)get_capacity(disk)/2048,
-			p->cyl, p->head, p->sect);
-	}
-
-	if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
-		printk("hd: unable to get IRQ%d for the hard disk driver\n",
-			HD_IRQ);
-		goto out1;
-	}
-
-	if (!request_region(HD_DATA, 2, "hd(data)")) {
-		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
-		NR_HD = 0;
-		free_irq(HD_IRQ, NULL);
-		return;
-	}
-
-	if (!request_region(HD_DATA + 2, 1, "hd"))
-	{
-		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
-		goto out2;
-	}
-
-	if (!request_region(HD_DATA + 4, 1, "hd"))
-	{
-		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
-		goto out3;
-	}
-
-	if (!request_region(HD_DATA + 6, 1, "hd"))
-	{
-		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
-		goto out4;
-	}
-
-	if (!request_region(HD_DATA + 8, 1, "hd"))
-	{
-		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
-		goto out5;
-	}
-
-	if (!request_region(HD_DATA + 10, 1, "hd"))
-	{
-		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
-		goto out6;
-	}
-
-	if (!request_region(HD_DATA + 12, 1, "hd"))
-	{
-		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
-		goto out7;
-	}
-
-	if (!request_region(HD_CMD, 1, "hd(cmd)"))
-	{
-		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
-		goto out8;
-	}
-
-	if (!request_region(HD_CMD + 2, 1, "hd(cmd)"))
-	{
-		printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
-		goto out9;
-	}
-
-	for(drive=0; drive < NR_HD; drive++)
-		add_disk(hd_gendisk[drive]);
-	return 0;
-
-out9:
-	release_region(HD_CMD, 1);
-out8:
-	release_region(HD_DATA + 12, 1);
-out7:
-	release_region(HD_DATA + 10, 1);
-out6:
-	release_region(HD_DATA + 8, 1);
-out5:
-	release_region(HD_DATA + 6, 1);
-out4:
-	release_region(HD_DATA + 4, 1);
-out3:
-	release_region(HD_DATA + 2, 1);
-out2:
-	release_region(HD_DATA, 2);
-	free_irq(HD_IRQ, NULL);
-out1:
-	for (drive = 0; drive < NR_HD; drive++)
-		put_disk(hd_gendisk[drive]);
-	NR_HD = 0;
-out:
-	del_timer(&device_timer);
-	unregister_blkdev(HD_MAJOR,"hd");
-	blk_cleanup_queue(hd_queue);
-	return -1;
-Enomem:
-	while (drive--)
-		put_disk(hd_gendisk[drive]);
-	goto out;
-}
-
-static int parse_hd_setup (char *line) {
-	int ints[6];
-
-	(void) get_options(line, ARRAY_SIZE(ints), ints);
-	hd_setup(NULL, ints);
-
-	return 1;
-}
-__setup("hd=", parse_hd_setup);
-
-module_init(hd_init);
diff -Nru a/drivers/ide/legacy/pc9800.c b/drivers/ide/legacy/pc9800.c
--- a/drivers/ide/legacy/pc9800.c	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,84 +0,0 @@
-/*
- *  ide_pc9800.c
- *
- *  Copyright (C) 1997-2000  Linux/98 project,
- *			     Kyoto University Microcomputer Club.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pc9800.h>
-
-#define PC9800_IDE_BANKSELECT	0x432
-
-#undef PC9800_IDE_DEBUG
-
-static void pc9800_select(ide_drive_t *drive)
-{
-#ifdef PC9800_IDE_DEBUG
-	byte old;
-
-	/* Too noisy: */
-	/* printk(KERN_DEBUG "pc9800_select(%s)\n", drive->name); */
-
-	outb(0x80, PC9800_IDE_BANKSELECT);
-	old = inb(PC9800_IDE_BANKSELECT);
-	if (old != HWIF(drive)->index)
-		printk(KERN_DEBUG "ide-pc9800: switching bank #%d -> #%d\n",
-			old, HWIF(drive)->index);
-#endif
-	outb(HWIF(drive)->index, PC9800_IDE_BANKSELECT);
-}
-
-void __init ide_probe_for_pc9800(void)
-{
-	u8 saved_bank;
-
-	if (!PC9800_9821_P() /* || !PC9821_IDEIF_DOUBLE_P() */)
-		return;
-
-	if (!request_region(PC9800_IDE_BANKSELECT, 1, "ide0/1 bank")) {
-		printk(KERN_ERR
-			"ide: bank select port (%#x) is already occupied!\n",
-			PC9800_IDE_BANKSELECT);
-		return;
-	}
-
-	/* Do actual probing. */
-	if ((saved_bank = inb(PC9800_IDE_BANKSELECT)) == (u8) ~0
-	    || (outb(saved_bank ^ 1, PC9800_IDE_BANKSELECT),
-		/* Next outb is dummy for reading status. */
-		outb(0x80, PC9800_IDE_BANKSELECT),
-		inb(PC9800_IDE_BANKSELECT) != (saved_bank ^ 1))) {
-		printk(KERN_INFO
-			"ide: pc9800 type bank selecting port not found\n");
-		release_region(PC9800_IDE_BANKSELECT, 1);
-		return;
-	}
-
-	/* Restore original value, just in case. */
-	outb(saved_bank, PC9800_IDE_BANKSELECT);
-
-	/* These ports are reseved by IDE I/F.  */
-	if (!request_region(0x430, 1, "ide") ||
-	    !request_region(0x435, 1, "ide")) {
-		printk(KERN_WARNING
-			"ide: IO port 0x430 and 0x435 are reserved for IDE"
-			" the card using these ports may not work\n");
-	}
-
-	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET] == HD_DATA &&
-	    ide_hwifs[1].io_ports[IDE_DATA_OFFSET] == HD_DATA) {
-		ide_hwifs[0].chipset = ide_pc9800;
-		ide_hwifs[0].mate = &ide_hwifs[1];
-		ide_hwifs[0].selectproc = pc9800_select;
-		ide_hwifs[1].chipset = ide_pc9800;
-		ide_hwifs[1].mate = &ide_hwifs[0];
-		ide_hwifs[1].selectproc = pc9800_select;
-	}
-}
diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
--- a/drivers/ide/pci/amd74xx.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/ide/pci/amd74xx.c	2004-06-23 19:04:29 -07:00
@@ -71,11 +71,7 @@
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,	0x50, AMD_UDMA_133 },
 	{ 0 }
 };
 
@@ -487,11 +483,7 @@
 	/* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA"),
 	/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"),
 	/* 13 */ DECLARE_NV_DEV("NFORCE-CK804"),
-	/* 14 */ DECLARE_NV_DEV("NFORCE-CK804-SATA"),
-	/* 15 */ DECLARE_NV_DEV("NFORCE-CK804-SATA2"),
-	/* 16 */ DECLARE_NV_DEV("NFORCE-MCP04"),
-	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP04-SATA"),
-	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP04-SATA2")
+	/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
 };
 
 static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -512,17 +504,17 @@
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  5 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  6 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  7 },
+#ifdef CONFIG_BLK_DEV_IDE_SATA
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  8 },
+#endif
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  9 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
+#ifdef CONFIG_BLK_DEV_IDE_SATA
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
+#endif
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
diff -Nru a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
--- a/drivers/ide/pci/generic.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/ide/pci/generic.c	2004-06-23 19:04:27 -07:00
@@ -127,7 +127,9 @@
 	{ PCI_VENDOR_ID_HINT,   PCI_DEVICE_ID_HINT_VXPROII_IDE,    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
 	{ PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C561,          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
 	{ PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558,         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
+#ifdef CONFIG_BLK_DEV_IDE_SATA
 	{ PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237_SATA,	   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+#endif
 	{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10},
 	{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11},
 	{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
--- a/drivers/ide/pci/piix.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/ide/pci/piix.c	2004-06-23 19:04:25 -07:00
@@ -793,9 +793,9 @@
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},
-#ifndef CONFIG_SCSI_SATA
+#ifdef CONFIG_BLK_DEV_IDE_SATA
  	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18},
-#endif /* !CONFIG_SCSI_SATA */
+#endif
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_19, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20},
 	{ 0, },
diff -Nru a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
--- a/drivers/ide/pci/siimage.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/ide/pci/siimage.c	2004-06-23 19:04:26 -07:00
@@ -21,6 +21,7 @@
  *	if neccessary
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -1127,8 +1128,10 @@
 
 static struct pci_device_id siimage_pci_tbl[] = {
 	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#ifdef CONFIG_BLK_DEV_IDE_SATA
 	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
 	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+#endif
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
--- a/drivers/ieee1394/amdtp.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/ieee1394/amdtp.c	2004-06-23 19:04:27 -07:00
@@ -1095,7 +1095,7 @@
 
 /* File operations */
 
-static ssize_t amdtp_write(struct file *file, const char *buffer, size_t count,
+static ssize_t amdtp_write(struct file *file, const char __user *buffer, size_t count,
 			   loff_t *offset_is_ignored)
 {
 	struct stream *s = file->private_data;
@@ -1150,7 +1150,7 @@
 	{
 	case AMDTP_IOC_PLUG:
 	case AMDTP_IOC_CHANNEL:
-		if (copy_from_user(&cfg, (struct amdtp_ioctl *) arg, sizeof cfg))
+		if (copy_from_user(&cfg, (struct amdtp_ioctl __user *) arg, sizeof cfg))
 			return -EFAULT;
 		else
 			return stream_configure(s, cmd, &cfg);
diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
--- a/drivers/ieee1394/dv1394.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/ieee1394/dv1394.c	2004-06-23 19:04:28 -07:00
@@ -1333,7 +1333,7 @@
         return 0;
 }
 
-static ssize_t dv1394_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct video_card *video = file_to_video_card(file);
 	DECLARE_WAITQUEUE(wait, current);
@@ -1430,7 +1430,7 @@
 }
 
 
-static ssize_t dv1394_read(struct file *file,  char *buffer, size_t count, loff_t *ppos)
+static ssize_t dv1394_read(struct file *file,  char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct video_card *video = file_to_video_card(file);
 	DECLARE_WAITQUEUE(wait, current);
@@ -1549,6 +1549,7 @@
 	struct video_card *video = file_to_video_card(file);
 	unsigned long flags;
 	int ret = -EINVAL;
+	void __user *argp = (void __user *)arg;
 
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -1718,10 +1719,10 @@
 
 	case DV1394_IOC_INIT: {
 		struct dv1394_init init;
-		if (arg == (unsigned long) NULL) {
+		if (!argp) {
 			ret = do_dv1394_init_default(video);
 		} else {
-			if (copy_from_user(&init, (void*)arg, sizeof(init))) {
+			if (copy_from_user(&init, argp, sizeof(init))) {
 				ret = -EFAULT;
 				goto out;
 			}
@@ -1767,7 +1768,7 @@
 
 		spin_unlock_irqrestore(&video->spinlock, flags);
 
-		if (copy_to_user((void*)arg, &status, sizeof(status))) {
+		if (copy_to_user(argp, &status, sizeof(status))) {
 			ret = -EFAULT;
 			goto out;
 		}
diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
--- a/drivers/ieee1394/eth1394.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/ieee1394/eth1394.c	2004-06-23 19:04:27 -07:00
@@ -431,9 +431,12 @@
 		if (!node)
 			return -ENOMEM;
 
-
 		node_info = kmalloc(sizeof(struct eth1394_node_info),
 				    in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+		if (!node_info) {
+			kfree(node);
+			return -ENOMEM;
+                }
 
 		spin_lock_init(&node_info->pdg.lock);
 		INIT_LIST_HEAD(&node_info->pdg.list);
diff -Nru a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
--- a/drivers/ieee1394/raw1394-private.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/ieee1394/raw1394-private.h	2004-06-23 19:04:28 -07:00
@@ -35,11 +35,11 @@
 
         struct list_head addr_list;
 
-        u8 *fcp_buffer;
+        u8 __user *fcp_buffer;
 
 	/* old ISO API */
         u64 listen_channels;
-        quadlet_t *iso_buffer;
+        quadlet_t __user *iso_buffer;
         size_t iso_buffer_length;
 
         u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
--- a/drivers/ieee1394/raw1394.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/ieee1394/raw1394.c	2004-06-23 19:04:25 -07:00
@@ -56,11 +56,11 @@
 #include "raw1394-private.h"
 
 #if BITS_PER_LONG == 64
-#define int2ptr(x) ((void *)x)
-#define ptr2int(x) ((u64)x)
+#define int2ptr(x) ((void __user *)x)
+#define ptr2int(x) ((u64)(unsigned long)(void __user *)x)
 #else
-#define int2ptr(x) ((void *)(u32)x)
-#define ptr2int(x) ((u64)(u32)x)
+#define int2ptr(x) ((void __user *)(u32)x)
+#define ptr2int(x) ((u64)(unsigned long)(void __user *)x)
 #endif
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
@@ -410,7 +410,7 @@
 }
 
 
-static ssize_t raw1394_read(struct file *file, char *buffer, size_t count,
+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;
@@ -602,7 +602,7 @@
                 if (fi->fcp_buffer) {
                         req->req.error = RAW1394_ERROR_ALREADY;
                 } else {
-                        fi->fcp_buffer = (u8 *)int2ptr(req->req.recvb);
+                        fi->fcp_buffer = int2ptr(req->req.recvb);
                 }
         } else {
                 if (!fi->fcp_buffer) {
@@ -826,7 +826,7 @@
                 return sizeof(struct raw1394_request);
         }
 
-        if (copy_from_user(packet->data, ((u8*) int2ptr(req->req.sendb)) + header_length,
+        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;
@@ -964,9 +964,8 @@
                 arm_req->buffer  = NULL;
                 arm_resp->buffer = NULL;
                 if (rcode == RCODE_COMPLETE) {
-                        arm_resp->buffer = ((byte_t *)(arm_resp) +
-                                (sizeof(struct arm_response)));
-                        memcpy (arm_resp->buffer,
+                        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) +
@@ -1091,10 +1090,9 @@
                         (sizeof (struct arm_request_response)));
                 arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
                         (sizeof(struct arm_request)));
-                arm_req->buffer = ((byte_t *)(arm_resp) +
-                        (sizeof(struct arm_response)));
                 arm_resp->buffer = NULL;
-                memcpy (arm_req->buffer, data, length);
+                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) +
@@ -1233,6 +1231,7 @@
                 }
         }
         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) {
@@ -1258,26 +1257,22 @@
                         (sizeof (struct arm_request_response)));
                 arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
                         (sizeof(struct arm_request)));
-                arm_req->buffer = ((byte_t *)(arm_resp) +
-                        (sizeof(struct arm_response)));
-                arm_resp->buffer = ((byte_t *)(arm_req->buffer) +
-                        (2* sizeof(*store)));
+                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 (arm_req->buffer, &data, sizeof(*store));
+                        memcpy (buf1, &data, sizeof(*store));
 
                 } else {
                         arm_req->buffer_length = 2 * sizeof(*store);
-                        memcpy (arm_req->buffer, &arg,  sizeof(*store));
-                        memcpy (((arm_req->buffer) + sizeof(*store)),
-                                &data, 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 (arm_resp->buffer, &old, sizeof(*store));
+                        memcpy (buf2, &old, sizeof(*store));
                 } else {
-                        arm_resp->buffer = NULL;
                         arm_resp->buffer_length = 0;
                 }
                 req->file_info = fi;
@@ -1438,6 +1433,7 @@
                 }
         }
         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) {
@@ -1463,26 +1459,22 @@
                         (sizeof (struct arm_request_response)));
                 arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
                         (sizeof(struct arm_request)));
-                arm_req->buffer = ((byte_t *)(arm_resp) +
-                        (sizeof(struct arm_response)));
-                arm_resp->buffer = ((byte_t *)(arm_req->buffer) +
-                        (2* sizeof(*store)));
+                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 (arm_req->buffer, &data, sizeof(*store));
+                        memcpy (buf1, &data, sizeof(*store));
 
                 } else {
                         arm_req->buffer_length = 2 * sizeof(*store);
-                        memcpy (arm_req->buffer, &arg,  sizeof(*store));
-                        memcpy (((arm_req->buffer) + sizeof(*store)),
-                                &data, 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 (arm_resp->buffer, &old, sizeof(*store));
+                        memcpy (buf2, &old, sizeof(*store));
                 } else {
-                        arm_resp->buffer = NULL;
                         arm_resp->buffer_length = 0;
                 }
                 req->file_info = fi;
@@ -2146,7 +2138,7 @@
 }
 
 
-static ssize_t raw1394_write(struct file *file, const char *buffer, size_t count,
+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;
@@ -2262,7 +2254,7 @@
 	stat->xmit_cycle = iso->xmit_cycle;
 }
 
-static int raw1394_iso_xmit_init(struct file_info *fi, void *uaddr)
+static int raw1394_iso_xmit_init(struct file_info *fi, void __user *uaddr)
 {
 	struct raw1394_iso_status stat;
 
@@ -2294,7 +2286,7 @@
 	return 0;
 }
 
-static int raw1394_iso_recv_init(struct file_info *fi, void *uaddr)
+static int raw1394_iso_recv_init(struct file_info *fi, void __user *uaddr)
 {
 	struct raw1394_iso_status stat;
 
@@ -2322,7 +2314,7 @@
 	return 0;
 }
 
-static int raw1394_iso_get_status(struct file_info *fi, void *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;
@@ -2338,7 +2330,7 @@
 }
 
 /* copy N packet_infos out of the ringbuffer into user-supplied array */
-static int raw1394_iso_recv_packets(struct file_info *fi, void *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;
@@ -2369,7 +2361,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 *uaddr)
+static int raw1394_iso_send_packets(struct file_info *fi, void __user *uaddr)
 {
 	struct raw1394_iso_packets upackets;
 	int i, rv;
@@ -2426,14 +2418,15 @@
 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) {
 	case RAW1394_ISO_INACTIVE:
 		switch(cmd) {
 		case RAW1394_IOC_ISO_XMIT_INIT:
-			return raw1394_iso_xmit_init(fi, (void*) arg);
+			return raw1394_iso_xmit_init(fi, argp);
 		case RAW1394_IOC_ISO_RECV_INIT:
-			return raw1394_iso_recv_init(fi, (void*) arg);
+			return raw1394_iso_recv_init(fi, argp);
 		default:
 			break;
 		}
@@ -2443,7 +2436,7 @@
 		case RAW1394_IOC_ISO_RECV_START: {
 			/* copy args from user-space */
 			int args[3];
-			if (copy_from_user(&args[0], (void*) arg, sizeof(args)))
+			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]);
 		}
@@ -2457,14 +2450,14 @@
 		case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: {
 			/* copy the u64 from user-space */
 			u64 mask;
-			if (copy_from_user(&mask, (void*) arg, sizeof(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, (void*) arg);
+			return raw1394_iso_get_status(fi, argp);
 		case RAW1394_IOC_ISO_RECV_PACKETS:
-			return raw1394_iso_recv_packets(fi, (void*) arg);
+			return raw1394_iso_recv_packets(fi, argp);
 		case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
 			return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
 		case RAW1394_IOC_ISO_RECV_FLUSH:
@@ -2482,7 +2475,7 @@
 		case RAW1394_IOC_ISO_XMIT_START: {
 			/* copy two ints from user-space */
 			int args[2];
-			if (copy_from_user(&args[0], (void*) arg, sizeof(args)))
+			if (copy_from_user(&args[0], argp, sizeof(args)))
 				return -EFAULT;
 			return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]);
 		}
@@ -2492,9 +2485,9 @@
 			hpsb_iso_stop(fi->iso_handle);
 			return 0;
 		case RAW1394_IOC_ISO_GET_STATUS:
-			return raw1394_iso_get_status(fi, (void*) arg);
+			return raw1394_iso_get_status(fi, argp);
 		case RAW1394_IOC_ISO_XMIT_PACKETS:
-			return raw1394_iso_send_packets(fi, (void*) arg);
+			return raw1394_iso_send_packets(fi, argp);
 		case RAW1394_IOC_ISO_SHUTDOWN:
 			raw1394_iso_shutdown(fi);
 			return 0;
diff -Nru a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
--- a/drivers/ieee1394/raw1394.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/ieee1394/raw1394.h	2004-06-23 19:04:25 -07:00
@@ -105,18 +105,18 @@
         __u8            extended_transaction_code;
         __u32           generation;
         __u16           buffer_length;
-        __u8            *buffer;
+        __u8            __user *buffer;
 } *arm_request_t;
 
 typedef struct arm_response {
         __s32           response_code;
         __u16           buffer_length;
-        __u8            *buffer;
+        __u8            __user *buffer;
 } *arm_response_t;
 
 typedef struct arm_request_response {
-        struct arm_request  *request;
-        struct arm_response *response;
+        struct arm_request  __user *request;
+        struct arm_response __user *response;
 } *arm_request_response_t;
 
 /* rawiso API */
@@ -136,7 +136,7 @@
 /* argument for RAW1394_ISO_RECV/XMIT_PACKETS ioctls */
 struct raw1394_iso_packets {
 	__u32 n_packets;
-	struct raw1394_iso_packet_info *infos;
+	struct raw1394_iso_packet_info __user *infos;
 };
 
 struct raw1394_iso_config {
diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
--- a/drivers/ieee1394/video1394.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/ieee1394/video1394.c	2004-06-23 19:04:25 -07:00
@@ -705,6 +705,7 @@
 	struct file_ctx *ctx = (struct file_ctx *)file->private_data;
 	struct ti_ohci *ohci = ctx->ohci;
 	unsigned long flags;
+	void __user *argp = (void __user *)arg;
 
 	switch(cmd)
 	{
@@ -716,7 +717,7 @@
 		struct dma_iso_ctx *d;
 		int i;
 
-		if (copy_from_user(&v, (void *)arg, sizeof(v)))
+		if (copy_from_user(&v, argp, sizeof(v)))
 			return -EFAULT;
 
 		/* if channel < 0, find lowest available one */
@@ -813,7 +814,7 @@
 			      v.channel);
 		}
 
-		if (copy_to_user((void *)arg, &v, sizeof(v)))
+		if (copy_to_user(argp, &v, sizeof(v)))
 			return -EFAULT;
 
 		return 0;
@@ -825,7 +826,7 @@
 		u64 mask;
 		struct dma_iso_ctx *d;
 
-		if (copy_from_user(&channel, (void *)arg, sizeof(int)))
+		if (copy_from_user(&channel, argp, sizeof(int)))
 			return -EFAULT;
 
 		if (channel<0 || channel>(ISO_CHANNELS-1)) {
@@ -860,7 +861,7 @@
 		struct video1394_wait v;
 		struct dma_iso_ctx *d;
 
-		if (copy_from_user(&v, (void *)arg, sizeof(v)))
+		if (copy_from_user(&v, argp, sizeof(v)))
 			return -EFAULT;
 
 		d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
@@ -923,7 +924,7 @@
 		struct dma_iso_ctx *d;
 		int i;
 
-		if (copy_from_user(&v, (void *)arg, sizeof(v)))
+		if (copy_from_user(&v, argp, sizeof(v)))
 			return -EFAULT;
 
 		d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
@@ -994,7 +995,7 @@
 		spin_unlock_irqrestore(&d->lock, flags);
 
 		v.buffer=i;
-		if (copy_to_user((void *)arg, &v, sizeof(v)))
+		if (copy_to_user(argp, &v, sizeof(v)))
 			return -EFAULT;
 
 		return 0;
@@ -1007,7 +1008,7 @@
 
 		qv.packet_sizes = NULL;
 
-		if (copy_from_user(&v, (void *)arg, sizeof(v)))
+		if (copy_from_user(&v, argp, sizeof(v)))
 			return -EFAULT;
 
 		d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
@@ -1023,7 +1024,7 @@
 			unsigned int *psizes;
 			int buf_size = d->nb_cmd * sizeof(unsigned int);
 
-			if (copy_from_user(&qv, (void *)arg, sizeof(qv)))
+			if (copy_from_user(&qv, argp, sizeof(qv)))
 				return -EFAULT;
 
 			psizes = kmalloc(buf_size, GFP_KERNEL);
@@ -1111,7 +1112,7 @@
 		struct video1394_wait v;
 		struct dma_iso_ctx *d;
 
-		if (copy_from_user(&v, (void *)arg, sizeof(v)))
+		if (copy_from_user(&v, argp, sizeof(v)))
 			return -EFAULT;
 
 		d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c
--- a/drivers/input/joydev.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/input/joydev.c	2004-06-23 19:04:27 -07:00
@@ -191,12 +191,12 @@
 	return 0;
 }
 
-static ssize_t joydev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos)
+static ssize_t joydev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
 {
 	return -EINVAL;
 }
 
-static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
 	struct joydev_list *list = file->private_data;
 	struct joydev *joydev = list->joydev;
@@ -291,6 +291,7 @@
 	struct joydev_list *list = file->private_data;
 	struct joydev *joydev = list->joydev;
 	struct input_dev *dev = joydev->handle.dev;
+	void __user *argp = (void __user *)arg;
 	int i, j;
 
 	if (!joydev->exist) return -ENODEV;
@@ -298,34 +299,34 @@
 	switch (cmd) {
 
 		case JS_SET_CAL:
-			return copy_from_user(&joydev->glue.JS_CORR, (struct JS_DATA_TYPE *) arg,
+			return copy_from_user(&joydev->glue.JS_CORR, argp,
 				sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
 		case JS_GET_CAL:
-			return copy_to_user((struct JS_DATA_TYPE *) arg, &joydev->glue.JS_CORR,
+			return copy_to_user(argp, &joydev->glue.JS_CORR,
 				sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
 		case JS_SET_TIMEOUT:
-			return get_user(joydev->glue.JS_TIMEOUT, (int *) arg);
+			return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
 		case JS_GET_TIMEOUT:
-			return put_user(joydev->glue.JS_TIMEOUT, (int *) arg);
+			return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
 		case JS_SET_TIMELIMIT:
-			return get_user(joydev->glue.JS_TIMELIMIT, (long *) arg);
+			return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
 		case JS_GET_TIMELIMIT:
-			return put_user(joydev->glue.JS_TIMELIMIT, (long *) arg);
+			return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
 		case JS_SET_ALL:
-			return copy_from_user(&joydev->glue, (struct JS_DATA_SAVE_TYPE *) arg,
+			return copy_from_user(&joydev->glue, argp,
 						sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
 		case JS_GET_ALL:
-			return copy_to_user((struct JS_DATA_SAVE_TYPE *) arg, &joydev->glue,
+			return copy_to_user(argp, &joydev->glue,
 						sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
 
 		case JSIOCGVERSION:
-			return put_user(JS_VERSION, (__u32 *) arg);
+			return put_user(JS_VERSION, (__u32 __user *) arg);
 		case JSIOCGAXES:
-			return put_user(joydev->nabs, (__u8 *) arg);
+			return put_user(joydev->nabs, (__u8 __user *) arg);
 		case JSIOCGBUTTONS:
-			return put_user(joydev->nkey, (__u8 *) arg);
+			return put_user(joydev->nkey, (__u8 __user *) arg);
 		case JSIOCSCORR:
-			if (copy_from_user(joydev->corr, (struct js_corr *)arg,
+			if (copy_from_user(joydev->corr, argp,
 				      sizeof(struct js_corr) * joydev->nabs))
 			    return -EFAULT;
 			for (i = 0; i < joydev->nabs; i++) {
@@ -334,10 +335,10 @@
 			}
 			return 0;
 		case JSIOCGCORR:
-			return copy_to_user((struct js_corr *) arg, joydev->corr,
+			return copy_to_user(argp, joydev->corr,
 						sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
 		case JSIOCSAXMAP:
-			if (copy_from_user(joydev->abspam, (__u8 *) arg, sizeof(__u8) * ABS_MAX))
+			if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * ABS_MAX))
 				return -EFAULT;
 			for (i = 0; i < joydev->nabs; i++) {
 				if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
@@ -345,10 +346,10 @@
 			}
 			return 0;
 		case JSIOCGAXMAP:
-			return copy_to_user((__u8 *) arg, joydev->abspam,
+			return copy_to_user(argp, joydev->abspam,
 						sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
 		case JSIOCSBTNMAP:
-			if (copy_from_user(joydev->keypam, (__u16 *) arg, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
+			if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
 				return -EFAULT;
 			for (i = 0; i < joydev->nkey; i++) {
 				if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
@@ -356,7 +357,7 @@
 			}
 			return 0;
 		case JSIOCGBTNMAP:
-			return copy_to_user((__u16 *) arg, joydev->keypam,
+			return copy_to_user(argp, joydev->keypam,
 						sizeof(__u16) * (KEY_MAX - BTN_MISC)) ? -EFAULT : 0;
 		default:
 			if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
@@ -364,7 +365,7 @@
 				if (!dev->name) return 0;
 				len = strlen(dev->name) + 1;
 				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-				if (copy_to_user((char *) arg, dev->name, len)) return -EFAULT;
+				if (copy_to_user(argp, dev->name, len)) return -EFAULT;
 				return len;
 			}
 	}
diff -Nru a/drivers/input/keyboard/98kbd.c b/drivers/input/keyboard/98kbd.c
--- a/drivers/input/keyboard/98kbd.c	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,391 +0,0 @@
-/*
- *  drivers/input/keyboard/98kbd.c
- *
- *  PC-9801 keyboard driver for Linux
- *
- *    Based on atkbd.c and xtkbd.c written by Vojtech Pavlik
- *
- *  Copyright (c) 2002 Osamu Tomita
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/delay.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/init.h>
-#include <linux/serio.h>
-
-#include <asm/io.h>
-#include <asm/pc9800.h>
-
-MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
-MODULE_DESCRIPTION("PC-9801 keyboard driver");
-MODULE_LICENSE("GPL");
-
-#define KBD98_KEY	0x7f
-#define KBD98_RELEASE	0x80
-
-static unsigned char kbd98_keycode[256] = {
-	  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 43, 14, 15,
-	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 41, 26, 28, 30, 31, 32,
-	 33, 34, 35, 36, 37, 38, 39, 40, 27, 44, 45, 46, 47, 48, 49, 50,
-	 51, 52, 53, 12, 57, 92,109,104,110,111,103,105,106,108,102,107,
-	 74, 98, 71, 72, 73, 55, 75, 76, 77, 78, 79, 80, 81,117, 82,121,
-	 83, 94, 87, 88,183,184,185,  0,  0,  0,  0,  0,  0,  0,102,  0,
-	 99,133, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,  0,  0,  0,  0,
-	 54, 58, 42, 56, 29
-};
-
-struct jis_kbd_conv {
-	unsigned char scancode;
-	struct {
-		unsigned char shift;
-		unsigned char keycode;
-	} emul[2];
-};
-
-static struct jis_kbd_conv kbd98_jis[] = {
-	{0x02, {{0,   3}, {1,  40}}},
-	{0x06, {{0,   7}, {1,   8}}},
-	{0x07, {{0,   8}, {0,  40}}},
-	{0x08, {{0,   9}, {1,  10}}},
-	{0x09, {{0,  10}, {1,  11}}},
-	{0x0a, {{0,  11}, {1, 255}}},
-	{0x0b, {{0,  12}, {0,  13}}},
-	{0x0c, {{1,   7}, {0,  41}}},
-	{0x1a, {{1,   3}, {1,  41}}},
-	{0x26, {{0,  39}, {1,  13}}},
-	{0x27, {{1,  39}, {1,   9}}},
-	{0x33, {{0, 255}, {1,  12}}},
-	{0xff, {{0, 255}, {1, 255}}}	/* terminater */
-};
-
-#define KBD98_CMD_SETEXKEY	0x1095	/* Enable/Disable Windows, Appli key */
-#define KBD98_CMD_SETRATE	0x109c	/* Set typematic rate */
-#define KBD98_CMD_SETLEDS	0x109d	/* Set keyboard leds */
-#define KBD98_CMD_GETLEDS	0x119d	/* Get keyboard leds */
-#define KBD98_CMD_GETID		0x019f
-
-#define KBD98_RET_ACK		0xfa
-#define KBD98_RET_NAK		0xfc	/* Command NACK, send the cmd again */
-
-#define KBD98_KEY_JIS_EMUL	253
-#define KBD98_KEY_UNKNOWN	254
-#define KBD98_KEY_NULL		255
-
-static char *kbd98_name = "PC-9801 Keyboard";
-
-struct kbd98 {
-	unsigned char keycode[256];
-	struct input_dev dev;
-	struct serio *serio;
-	char phys[32];
-	unsigned char cmdbuf[4];
-	unsigned char cmdcnt;
-	signed char ack;
-	unsigned char shift;
-	struct {
-		unsigned char scancode;
-		unsigned char keycode;
-	} emul;
-	struct jis_kbd_conv jis[16];
-};
-
-irqreturn_t kbd98_interrupt(struct serio *serio, unsigned char data,
-			    unsigned int flags, struct pt_regs *regs)
-{
-	struct kbd98 *kbd98 = serio->private;
-	unsigned char scancode, keycode;
-	int press, i;
-
-	switch (data) {
-		case KBD98_RET_ACK:
-			kbd98->ack = 1;
-			goto out;
-		case KBD98_RET_NAK:
-			kbd98->ack = -1;
-			goto out;
-	}
-
-	if (kbd98->cmdcnt) {
-		kbd98->cmdbuf[--kbd98->cmdcnt] = data;
-		goto out;
-	}
-
-	scancode = data & KBD98_KEY;
-	keycode = kbd98->keycode[scancode];
-	press = !(data & KBD98_RELEASE);
-	if (kbd98->emul.scancode != KBD98_KEY_UNKNOWN
-	    && scancode != kbd98->emul.scancode) {
-		input_report_key(&kbd98->dev, kbd98->emul.keycode, 0);
-		kbd98->emul.scancode = KBD98_KEY_UNKNOWN;
-	}
-
-	if (keycode == KEY_RIGHTSHIFT)
-		kbd98->shift = press;
-
-	switch (keycode) {
-		case KEY_2:
-		case KEY_6:
-		case KEY_7:
-		case KEY_8:
-		case KEY_9:
-		case KEY_0:
-		case KEY_MINUS:
-		case KEY_EQUAL:
-		case KEY_GRAVE:
-		case KEY_SEMICOLON:
-		case KEY_APOSTROPHE:
-			/* emulation: JIS keyboard to US101 keyboard */
-			i = 0;
-			while (kbd98->jis[i].scancode != 0xff) {
-				if (scancode == kbd98->jis[i].scancode)
-					break;
-				i ++;
-			}
-
-			keycode = kbd98->jis[i].emul[kbd98->shift].keycode;
-			if (keycode == KBD98_KEY_NULL)
-				break;
-
-			if (press) {
-				kbd98->emul.scancode = scancode;
-				kbd98->emul.keycode = keycode;
-				if (kbd98->jis[i].emul[kbd98->shift].shift
-								!= kbd98->shift)
-					input_report_key(&kbd98->dev,
-							KEY_RIGHTSHIFT,
-							!(kbd98->shift));
-			}
-
-			input_report_key(&kbd98->dev, keycode, press);
-			if (!press) {
-				if (kbd98->jis[i].emul[kbd98->shift].shift
-								!= kbd98->shift)
-					input_report_key(&kbd98->dev,
-							KEY_RIGHTSHIFT,
-							kbd98->shift);
-				kbd98->emul.scancode = KBD98_KEY_UNKNOWN;
-			}
-
-			input_sync(&kbd98->dev);
-			break;
-
-		case KEY_CAPSLOCK:
-			input_report_key(&kbd98->dev, keycode, 1);
-			input_sync(&kbd98->dev);
-			input_report_key(&kbd98->dev, keycode, 0);
-			input_sync(&kbd98->dev);
-			break;
-
-		case KBD98_KEY_NULL:
-			break;
-
-		case 0:
-			printk(KERN_WARNING "kbd98.c: Unknown key (scancode %#x) %s.\n",
-				data & KBD98_KEY, data & KBD98_RELEASE ? "released" : "pressed");
-			break;
-
-		default:
-			input_report_key(&kbd98->dev, keycode, press);
-			input_sync(&kbd98->dev);
-			break;
-	}
-
-out:
-	return IRQ_HANDLED;
-}
-
-/*
- * kbd98_sendbyte() sends a byte to the keyboard, and waits for
- * acknowledge. It doesn't handle resends according to the keyboard
- * protocol specs, because if these are needed, the keyboard needs
- * replacement anyway, and they only make a mess in the protocol.
- */
-
-static int kbd98_sendbyte(struct kbd98 *kbd98, unsigned char byte)
-{
-	int timeout = 10000; /* 100 msec */
-	kbd98->ack = 0;
-
-	if (serio_write(kbd98->serio, byte))
-		return -1;
-
-	while (!kbd98->ack && timeout--) udelay(10);
-
-	return -(kbd98->ack <= 0);
-}
-
-/*
- * kbd98_command() sends a command, and its parameters to the keyboard,
- * then waits for the response and puts it in the param array.
- */
-
-static int kbd98_command(struct kbd98 *kbd98, unsigned char *param, int command)
-{
-	int timeout = 50000; /* 500 msec */
-	int send = (command >> 12) & 0xf;
-	int receive = (command >> 8) & 0xf;
-	int i;
-
-	kbd98->cmdcnt = receive;
-
-	if (command & 0xff)
-		if (kbd98_sendbyte(kbd98, command & 0xff))
-			return (kbd98->cmdcnt = 0) - 1;
-
-	for (i = 0; i < send; i++)
-		if (kbd98_sendbyte(kbd98, param[i]))
-			return (kbd98->cmdcnt = 0) - 1;
-
-	while (kbd98->cmdcnt && timeout--) udelay(10);
-
-	if (param)
-		for (i = 0; i < receive; i++)
-			param[i] = kbd98->cmdbuf[(receive - 1) - i];
-
-	if (kbd98->cmdcnt)
-		return (kbd98->cmdcnt = 0) - 1;
-
-	return 0;
-}
-
-/*
- * Event callback from the input module. Events that change the state of
- * the hardware are processed here.
- */
-
-static int kbd98_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-	struct kbd98 *kbd98 = dev->private;
-	char param[2];
-
-	switch (type) {
-
-		case EV_LED:
-
-			if (__PC9800SCA_TEST_BIT(0x481, 3)) {
-				/* 98note with Num Lock key */
-				/* keep Num Lock status     */
-				*param = 0x60;
-				if (kbd98_command(kbd98, param,
-							KBD98_CMD_GETLEDS))
-					printk(KERN_DEBUG
-						"kbd98: Get keyboard LED"
-						" status Error\n");
-
-				*param &= 1;
-			} else {
-				/* desktop PC-9801 */
-				*param = 1;	/* Always set Num Lock */
-			}
-
-			*param |= 0x70
-			       | (test_bit(LED_CAPSL,   dev->led) ? 4 : 0)
-			       | (test_bit(LED_KANA,    dev->led) ? 8 : 0);
-		        kbd98_command(kbd98, param, KBD98_CMD_SETLEDS);
-
-			return 0;
-	}
-
-	return -1;
-}
-
-void kbd98_connect(struct serio *serio, struct serio_dev *dev)
-{
-	struct kbd98 *kbd98;
-	int i;
-
-	if ((serio->type & SERIO_TYPE) != SERIO_PC9800)
-		return;
-
-	if (!(kbd98 = kmalloc(sizeof(struct kbd98), GFP_KERNEL)))
-		return;
-
-	memset(kbd98, 0, sizeof(struct kbd98));
-	kbd98->emul.scancode = KBD98_KEY_UNKNOWN;
-
-	kbd98->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
-	kbd98->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_KANA);
-
-	kbd98->serio = serio;
-
-	init_input_dev(&kbd98->dev);
-	kbd98->dev.keycode = kbd98->keycode;
-	kbd98->dev.keycodesize = sizeof(unsigned char);
-	kbd98->dev.keycodemax = ARRAY_SIZE(kbd98_keycode);
-	kbd98->dev.event = kbd98_event;
-	kbd98->dev.private = kbd98;
-
-	serio->private = kbd98;
-
-	if (serio_open(serio, dev)) {
-		kfree(kbd98);
-		return;
-	}
-
-	memcpy(kbd98->jis, kbd98_jis, sizeof(kbd98_jis));
-	memcpy(kbd98->keycode, kbd98_keycode, sizeof(kbd98->keycode));
-	for (i = 0; i < 255; i++)
-		set_bit(kbd98->keycode[i], kbd98->dev.keybit);
-	clear_bit(0, kbd98->dev.keybit);
-
-	sprintf(kbd98->phys, "%s/input0", serio->phys);
-
-	kbd98->dev.name = kbd98_name;
-	kbd98->dev.phys = kbd98->phys;
-	kbd98->dev.id.bustype = BUS_XTKBD;
-	kbd98->dev.id.vendor = 0x0002;
-	kbd98->dev.id.product = 0x0001;
-	kbd98->dev.id.version = 0x0100;
-
-	input_register_device(&kbd98->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", kbd98_name, serio->phys);
-}
-
-void kbd98_disconnect(struct serio *serio)
-{
-	struct kbd98 *kbd98 = serio->private;
-	input_unregister_device(&kbd98->dev);
-	serio_close(serio);
-	kfree(kbd98);
-}
-
-struct serio_dev kbd98_dev = {
-	.interrupt =	kbd98_interrupt,
-	.connect =	kbd98_connect,
-	.disconnect =	kbd98_disconnect
-};
-
-int __init kbd98_init(void)
-{
-	serio_register_device(&kbd98_dev);
-	return 0;
-}
-
-void __exit kbd98_exit(void)
-{
-	serio_unregister_device(&kbd98_dev);
-}
-
-module_init(kbd98_init);
-module_exit(kbd98_exit);
diff -Nru a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
--- a/drivers/input/keyboard/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/input/keyboard/Kconfig	2004-06-23 19:04:28 -07:00
@@ -96,15 +96,3 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called amikbd.
-
-config KEYBOARD_98KBD
-	tristate "NEC PC-9800 Keyboard support"
-	depends on X86_PC9800 && INPUT && INPUT_KEYBOARD
-	select SERIO
-	help
-	  Say Y here if you want to use the NEC PC-9801/PC-9821 keyboard (or
-	  compatible) on your system.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called 98kbd.
-
diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
--- a/drivers/input/keyboard/atkbd.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/input/keyboard/atkbd.c	2004-06-23 19:04:28 -07:00
@@ -288,7 +288,7 @@
 			atkbd_report_key(&atkbd->dev, regs, KEY_HANJA, 3);
 			goto out;
 		case ATKBD_RET_ERR:
-			printk(KERN_WARNING "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
+			printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
 			goto out;
 	}
 
diff -Nru a/drivers/input/misc/98spkr.c b/drivers/input/misc/98spkr.c
--- a/drivers/input/misc/98spkr.c	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,96 +0,0 @@
-/*
- *  PC-9800 Speaker beeper driver for Linux
- *
- *  Copyright (c) 2002 Osamu Tomita
- *  Copyright (c) 2002 Vojtech Pavlik
- *  Copyright (c) 1992 Orest Zborowski
- *
- */
-
-/*
- * 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/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <asm/8253pit.h>
-#include <asm/io.h>
-
-MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
-MODULE_DESCRIPTION("PC-9800 Speaker beeper driver");
-MODULE_LICENSE("GPL");
-
-static char spkr98_name[] = "PC-9801 Speaker";
-static char spkr98_phys[] = "isa3fdb/input0";
-static struct input_dev spkr98_dev;
-
-spinlock_t i8253_beep_lock = SPIN_LOCK_UNLOCKED;
-
-static int spkr98_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-	unsigned int count = 0;
-	unsigned long flags;
-
-	if (type != EV_SND)
-		return -1;
-
-	switch (code) {
-		case SND_BELL: if (value) value = 1000;
-		case SND_TONE: break;
-		default: return -1;
-	}
-
-	if (value > 20 && value < 32767)
-		count = PIT_TICK_RATE / value;
-
-	spin_lock_irqsave(&i8253_beep_lock, flags);
-
-	if (count) {
-		outb(0x76, 0x3fdf);
-		outb(0, 0x5f);
-		outb(count & 0xff, 0x3fdb);
-		outb(0, 0x5f);
-		outb((count >> 8) & 0xff, 0x3fdb);
-		/* beep on */
-		outb(6, 0x37);
-	} else {
-		/* beep off */
-		outb(7, 0x37);
-	}
-
-	spin_unlock_irqrestore(&i8253_beep_lock, flags);
-
-	return 0;
-}
-
-static int __init spkr98_init(void)
-{
-	spkr98_dev.evbit[0] = BIT(EV_SND);
-	spkr98_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
-	spkr98_dev.event = spkr98_event;
-
-	spkr98_dev.name = spkr98_name;
-	spkr98_dev.phys = spkr98_phys;
-	spkr98_dev.id.bustype = BUS_ISA;
-	spkr98_dev.id.vendor = 0x001f;
-	spkr98_dev.id.product = 0x0001;
-	spkr98_dev.id.version = 0x0100;
-
-	input_register_device(&spkr98_dev);
-
-        printk(KERN_INFO "input: %s\n", spkr98_name);
-
-	return 0;
-}
-
-static void __exit spkr98_exit(void)
-{
-        input_unregister_device(&spkr98_dev);
-}
-
-module_init(spkr98_init);
-module_exit(spkr98_exit);
diff -Nru a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
--- a/drivers/input/misc/Kconfig	2004-06-23 19:04:26 -07:00
+++ b/drivers/input/misc/Kconfig	2004-06-23 19:04:26 -07:00
@@ -40,10 +40,6 @@
 	tristate "M68k Beeper support"
 	depends on M68K && INPUT && INPUT_MISC
 
-config INPUT_98SPKR
-	tristate "PC-9800 Speaker support"
-	depends on X86_PC9800 && INPUT && INPUT_MISC
-
 config INPUT_UINPUT
 	tristate "User level driver support"
 	depends on INPUT && INPUT_MISC
diff -Nru a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
--- a/drivers/input/misc/uinput.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/input/misc/uinput.c	2004-06-23 19:04:28 -07:00
@@ -166,7 +166,7 @@
 	return retval;
 }
 
-static int uinput_alloc_device(struct file *file, const char *buffer, size_t count)
+static int uinput_alloc_device(struct file *file, const char __user *buffer, size_t count)
 {
 	struct uinput_user_dev	*user_dev;
 	struct input_dev	*dev;
@@ -226,7 +226,7 @@
 	return retval;
 }
 
-static ssize_t uinput_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+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;
 
@@ -243,7 +243,7 @@
 	return count;
 }
 
-static ssize_t uinput_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct uinput_device *udev = file->private_data;
 	int retval = 0;
diff -Nru a/drivers/input/mouse/98busmouse.c b/drivers/input/mouse/98busmouse.c
--- a/drivers/input/mouse/98busmouse.c	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,197 +0,0 @@
-/*
- *
- *  Copyright (c) 2002 Osamu Tomita
- *
- *  Based on the work of:
- *	James Banks		Matthew Dillon
- *	David Giller		Nathan Laredo
- *	Linus Torvalds		Johan Myreen
- *	Cliff Matthews		Philip Blundell
- *	Russell King		Vojtech Pavlik
- */
-
-/*
- * NEC PC-9801 Bus Mouse 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 as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
-MODULE_DESCRIPTION("PC-9801 busmouse driver");
-MODULE_LICENSE("GPL");
-
-#define	PC98BM_BASE		0x7fd9
-#define	PC98BM_DATA_PORT	PC98BM_BASE + 0
-/*	PC98BM_SIGNATURE_PORT	does not exist */
-#define	PC98BM_CONTROL_PORT	PC98BM_BASE + 4
-/*	PC98BM_INTERRUPT_PORT	does not exist */
-#define	PC98BM_CONFIG_PORT	PC98BM_BASE + 6
-
-#define	PC98BM_ENABLE_IRQ	0x00
-#define	PC98BM_DISABLE_IRQ	0x10
-#define	PC98BM_READ_X_LOW	0x80
-#define	PC98BM_READ_X_HIGH	0xa0
-#define	PC98BM_READ_Y_LOW	0xc0
-#define	PC98BM_READ_Y_HIGH	0xe0
-
-#define PC98BM_DEFAULT_MODE	0x93
-/*	PC98BM_CONFIG_BYTE	is not used */
-/*	PC98BM_SIGNATURE_BYTE	is not used */
-
-#define PC98BM_TIMER_PORT	0xbfdb
-#define PC98BM_DEFAULT_TIMER_VAL	0x00
-
-#define PC98BM_IRQ		13
-
-static int pc98bm_irq = PC98BM_IRQ;
-module_param_named(irq, pc98bm_irq, uint, 0);
-MODULE_PARM_DESC(irq, "IRQ number (13=default)");
-
-__obsolete_setup("pc98bm_irq=");
-
-static int pc98bm_used = 0;
-
-static irqreturn_t pc98bm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
-static int pc98bm_open(struct input_dev *dev)
-{
-	if (pc98bm_used++)
-		return 0;
-	if (request_irq(pc98bm_irq, pc98bm_interrupt, 0, "98busmouse", NULL)) {
-		pc98bm_used--;
-		printk(KERN_ERR "98busmouse.c: Can't allocate irq %d\n", pc98bm_irq);
-		return -EBUSY;
-	}
-	outb(PC98BM_ENABLE_IRQ, PC98BM_CONTROL_PORT);
-	return 0;
-}
-
-static void pc98bm_close(struct input_dev *dev)
-{
-	if (--pc98bm_used)
-		return;
-	outb(PC98BM_DISABLE_IRQ, PC98BM_CONTROL_PORT);
-	free_irq(pc98bm_irq, NULL);
-}
-
-static struct input_dev pc98bm_dev = {
-	.evbit	= { BIT(EV_KEY) | BIT(EV_REL) },
-	.keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
-	.relbit	= { BIT(REL_X) | BIT(REL_Y) },
-	.open	= pc98bm_open,
-	.close	= pc98bm_close,
-	.name	= "PC-9801 bus mouse",
-	.phys	= "isa7fd9/input0",
-	.id	= {
-		.bustype = BUS_ISA,
-		.vendor  = 0x0004,
-		.product = 0x0001,
-		.version = 0x0100,
-	},
-};
-
-static irqreturn_t pc98bm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	char dx, dy;
-	unsigned char buttons;
-
-	outb(PC98BM_READ_X_LOW, PC98BM_CONTROL_PORT);
-	dx = (inb(PC98BM_DATA_PORT) & 0xf);
-	outb(PC98BM_READ_X_HIGH, PC98BM_CONTROL_PORT);
-	dx |= (inb(PC98BM_DATA_PORT) & 0xf) << 4;
-	outb(PC98BM_READ_Y_LOW, PC98BM_CONTROL_PORT);
-	dy = (inb(PC98BM_DATA_PORT) & 0xf);
-	outb(PC98BM_READ_Y_HIGH, PC98BM_CONTROL_PORT);
-	buttons = inb(PC98BM_DATA_PORT);
-	dy |= (buttons & 0xf) << 4;
-	buttons = ~buttons >> 5;
-
-	input_report_rel(&pc98bm_dev, REL_X, dx);
-	input_report_rel(&pc98bm_dev, REL_Y, dy);
-	input_report_key(&pc98bm_dev, BTN_RIGHT,  buttons & 1);
-	input_report_key(&pc98bm_dev, BTN_MIDDLE, buttons & 2);
-	input_report_key(&pc98bm_dev, BTN_LEFT,   buttons & 4);
-	input_sync(&pc98bm_dev);
-
-	outb(PC98BM_ENABLE_IRQ, PC98BM_CONTROL_PORT);
-
-	return IRQ_HANDLED;
-}
-
-static int __init pc98bm_init(void)
-{
-	int i;
-
-	for (i = 0; i <= 6; i += 2) {
-		if (!request_region(PC98BM_BASE + i, 1, "98busmouse")) {
-			printk(KERN_ERR "98busmouse.c: Can't allocate ports at %#x\n", PC98BM_BASE + i);
-			while (i > 0) {
-				i -= 2;
-				release_region(PC98BM_BASE + i, 1);
-			}
-
-			return -EBUSY;
-		}
-
-	}
-
-	if (!request_region(PC98BM_TIMER_PORT, 1, "98busmouse")) {
-		printk(KERN_ERR "98busmouse.c: Can't allocate ports at %#x\n", PC98BM_TIMER_PORT);
-		for (i = 0; i <= 6; i += 2)
-			release_region(PC98BM_BASE + i, 1);
-
-		return -EBUSY;
-	}
-
-	outb(PC98BM_DEFAULT_MODE, PC98BM_CONFIG_PORT);
-	outb(PC98BM_DISABLE_IRQ, PC98BM_CONTROL_PORT);
-
-	outb(PC98BM_DEFAULT_TIMER_VAL, PC98BM_TIMER_PORT);
-
-	input_register_device(&pc98bm_dev);
-	
-	printk(KERN_INFO "input: PC-9801 bus mouse at %#x irq %d\n", PC98BM_BASE, pc98bm_irq);
-
-	return 0;
-}
-
-static void __exit pc98bm_exit(void)
-{
-	int i;
-
-	input_unregister_device(&pc98bm_dev);
-	for (i = 0; i <= 6; i += 2)
-		release_region(PC98BM_BASE + i, 1);
-
-	release_region(PC98BM_TIMER_PORT, 1);
-}
-
-module_init(pc98bm_init);
-module_exit(pc98bm_exit);
diff -Nru a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
--- a/drivers/input/mouse/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/input/mouse/Kconfig	2004-06-23 19:04:28 -07:00
@@ -130,14 +130,3 @@
 	  described in the source file). This driver should, in theory,
 	  also work with the digitizer DEC produced, but it isn't tested
 	  with that (I don't have the hardware yet).
-
-config MOUSE_PC9800
-	tristate "NEC PC-9800 busmouse"
-	depends on X86_PC9800 && INPUT && INPUT_MOUSE && ISA
-	help
-	  Say Y here if you have NEC PC-9801/PC-9821 computer and want its
-	  native mouse supported.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called 98busmouse.
-
diff -Nru a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
--- a/drivers/input/mouse/Makefile	2004-06-23 19:04:25 -07:00
+++ b/drivers/input/mouse/Makefile	2004-06-23 19:04:25 -07:00
@@ -10,7 +10,6 @@
 obj-$(CONFIG_MOUSE_LOGIBM)	+= logibm.o
 obj-$(CONFIG_MOUSE_MAPLE)	+= maplemouse.o
 obj-$(CONFIG_MOUSE_PC110PAD)	+= pc110pad.o
-obj-$(CONFIG_MOUSE_PC9800)	+= 98busmouse.o
 obj-$(CONFIG_MOUSE_PS2)		+= psmouse.o
 obj-$(CONFIG_MOUSE_SERIAL)	+= sermouse.o
 obj-$(CONFIG_MOUSE_VSXXXAA)	+= vsxxxaa.o
diff -Nru a/drivers/input/serio/98kbd-io.c b/drivers/input/serio/98kbd-io.c
--- a/drivers/input/serio/98kbd-io.c	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,179 +0,0 @@
-/*
- *  NEC PC-9801 keyboard controller driver for Linux
- *
- *  Copyright (c) 1999-2002 Osamu Tomita <tomita@cinet.co.jp>
- *    Based on i8042.c written by 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.
- */
-
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/serio.h>
-#include <linux/sched.h>
-
-#include <asm/io.h>
-
-MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
-MODULE_DESCRIPTION("NEC PC-9801 keyboard controller driver");
-MODULE_LICENSE("GPL");
-
-/*
- * Names.
- */
-
-#define KBD98_PHYS_DESC "isa0041/serio0"
-
-/*
- * IRQs.
- */
-
-#define KBD98_IRQ	1
-
-/*
- * Register numbers.
- */
-
-#define KBD98_COMMAND_REG	0x43
-#define KBD98_STATUS_REG	0x43
-#define KBD98_DATA_REG		0x41
-
-spinlock_t kbd98io_lock = SPIN_LOCK_UNLOCKED;
-
-static struct serio kbd98_port;
-extern struct pt_regs *kbd_pt_regs;
-
-static irqreturn_t kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
-/*
- * kbd98_flush() flushes all data that may be in the keyboard buffers
- */
-
-static int kbd98_flush(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&kbd98io_lock, flags);
-
-	while (inb(KBD98_STATUS_REG) & 0x02) /* RxRDY */
-		inb(KBD98_DATA_REG);
-
-	if (inb(KBD98_STATUS_REG) & 0x38)
-		printk("98kbd-io: Keyboard error!\n");
-
-	spin_unlock_irqrestore(&kbd98io_lock, flags);
-
-	return 0;
-}
-
-/*
- * kbd98_write() sends a byte out through the keyboard interface.
- */
-
-static int kbd98_write(struct serio *port, unsigned char c)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&kbd98io_lock, flags);
-
-	outb(0, 0x5f);			/* wait */
-	outb(0x17, KBD98_COMMAND_REG);	/* enable send command */
-	outb(0, 0x5f);			/* wait */
-	outb(c, KBD98_DATA_REG);
-	outb(0, 0x5f);			/* wait */
-	outb(0x16, KBD98_COMMAND_REG);	/* disable send command */
-	outb(0, 0x5f);			/* wait */
-
-	spin_unlock_irqrestore(&kbd98io_lock, flags);
-
-	return 0;
-}
-
-/*
- * kbd98_open() is called when a port is open by the higher layer.
- * It allocates the interrupt and enables in in the chip.
- */
-
-static int kbd98_open(struct serio *port)
-{
-	kbd98_flush();
-
-	if (request_irq(KBD98_IRQ, kbd98io_interrupt, 0, "kbd98", NULL)) {
-		printk(KERN_ERR "98kbd-io.c: Can't get irq %d for %s, unregistering the port.\n", KBD98_IRQ, "KBD");
-		serio_unregister_port(port);
-		return -1;
-	}
-
-	return 0;
-}
-
-static void kbd98_close(struct serio *port)
-{
-	free_irq(KBD98_IRQ, NULL);
-
-	kbd98_flush();
-}
-
-/*
- * Structures for registering the devices in the serio.c module.
- */
-
-static struct serio kbd98_port =
-{
-	.type =		SERIO_PC9800,
-	.write =	kbd98_write,
-	.open =		kbd98_open,
-	.close =	kbd98_close,
-	.driver =	NULL,
-	.name =		"PC-9801 Kbd Port",
-	.phys =		KBD98_PHYS_DESC,
-};
-
-/*
- * kbd98io_interrupt() is the most important function in this driver -
- * it handles the interrupts from keyboard, and sends incoming bytes
- * to the upper layers.
- */
-
-static irqreturn_t kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	unsigned char data;
-
-	spin_lock_irqsave(&kbd98io_lock, flags);
-
-	data = inb(KBD98_DATA_REG);
-	spin_unlock_irqrestore(&kbd98io_lock, flags);
-	serio_interrupt(&kbd98_port, data, 0, regs);
-
-	return IRQ_HANDLED;
-}
-
-int __init kbd98io_init(void)
-{
-	serio_register_port(&kbd98_port);
-
-	printk(KERN_INFO "serio: PC-9801 %s port at %#lx,%#lx irq %d\n",
-	       "KBD",
-	       (unsigned long) KBD98_DATA_REG,
-	       (unsigned long) KBD98_COMMAND_REG,
-	       KBD98_IRQ);
-
-	return 0;
-}
-
-void __exit kbd98io_exit(void)
-{
-	serio_unregister_port(&kbd98_port);
-}
-
-module_init(kbd98io_init);
-module_exit(kbd98io_exit);
diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
--- a/drivers/input/serio/Kconfig	2004-06-23 19:04:27 -07:00
+++ b/drivers/input/serio/Kconfig	2004-06-23 19:04:27 -07:00
@@ -97,16 +97,6 @@
 	tristate "Intel SA1111 keyboard controller"
 	depends on SA1111 && SERIO
 
-config SERIO_98KBD
-	tristate "NEC PC-9800 keyboard controller"
-	depends on X86_PC9800 && SERIO
-	help
-	  Say Y here if you have the NEC PC-9801/PC-9821 and want to use its
-	  standard keyboard connected to its keyboard controller.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called 98kbd-io.
-
 config SERIO_GSCPS2
 	tristate "HP GSC PS/2 keyboard and PS/2 mouse controller"
 	depends on GSC && SERIO
diff -Nru a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
--- a/drivers/input/serio/ambakmi.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/input/serio/ambakmi.c	2004-06-23 19:04:27 -07:00
@@ -18,17 +18,19 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba_kmi.h>
+#include <asm/hardware/clock.h>
 
 #define KMI_BASE	(kmi->base)
 
 struct amba_kmi_port {
 	struct serio		io;
-	struct amba_kmi_port	*next;
+	struct clk		*clk;
 	unsigned char		*base;
 	unsigned int		irq;
 	unsigned int		divisor;
@@ -67,21 +69,38 @@
 static int amba_kmi_open(struct serio *io)
 {
 	struct amba_kmi_port *kmi = io->driver;
+	unsigned int divisor;
 	int ret;
 
-	writeb(kmi->divisor, KMICLKDIV);
+	ret = clk_use(kmi->clk);
+	if (ret)
+		goto out;
+
+	ret = clk_enable(kmi->clk);
+	if (ret)
+		goto clk_unuse;
+
+	divisor = clk_get_rate(kmi->clk) / 8000000 - 1;
+	writeb(divisor, KMICLKDIV);
 	writeb(KMICR_EN, KMICR);
 
 	ret = request_irq(kmi->irq, amba_kmi_int, 0, "kmi-pl050", kmi);
 	if (ret) {
 		printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq);
 		writeb(0, KMICR);
-		return ret;
+		goto clk_disable;
 	}
 
 	writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
 
 	return 0;
+
+ clk_disable:
+	clk_disable(kmi->clk);
+ clk_unuse:
+	clk_unuse(kmi->clk);
+ out:
+	return ret;
 }
 
 static void amba_kmi_close(struct serio *io)
@@ -91,6 +110,8 @@
 	writeb(0, KMICR);
 
 	free_irq(kmi->irq, kmi);
+	clk_disable(kmi->clk);
+	clk_unuse(kmi->clk);
 }
 
 static int amba_kmi_probe(struct amba_device *dev, void *id)
@@ -124,14 +145,20 @@
 		goto out;
 	}
 
-	kmi->irq	= dev->irq[0];
-	kmi->divisor	= 24 / 8 - 1;
+	kmi->clk = clk_get(&dev->dev, "KMIREFCLK");
+	if (IS_ERR(kmi->clk)) {
+		ret = PTR_ERR(kmi->clk);
+		goto unmap;
+	}
 
+	kmi->irq = dev->irq[0];
 	amba_set_drvdata(dev, kmi);
 
 	serio_register_port(&kmi->io);
 	return 0;
 
+ unmap:
+	iounmap(kmi->base);
  out:
 	kfree(kmi);
 	amba_release_regions(dev);
@@ -145,6 +172,7 @@
 	amba_set_drvdata(dev, NULL);
 
 	serio_unregister_port(&kmi->io);
+	clk_put(kmi->clk);
 	iounmap(kmi->base);
 	kfree(kmi);
 	amba_release_regions(dev);
diff -Nru a/drivers/input/tsdev.c b/drivers/input/tsdev.c
--- a/drivers/input/tsdev.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/input/tsdev.c	2004-06-23 19:04:28 -07:00
@@ -151,7 +151,7 @@
 	return 0;
 }
 
-static ssize_t tsdev_read(struct file *file, char *buffer, size_t count,
+static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
 			  loff_t * ppos)
 {
 	struct tsdev_list *list = file->private_data;
diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
--- a/drivers/isdn/i4l/isdn_ppp.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/isdn/i4l/isdn_ppp.c	2004-06-23 19:04:27 -07:00
@@ -320,8 +320,8 @@
 	is->slcomp = slhc_init(16, 16);	/* not necessary for 2. link in bundle */
 #endif
 #ifdef CONFIG_IPPP_FILTER
-	is->pass_filter.filter = NULL;
-	is->active_filter.filter = NULL;
+	is->pass_filter = NULL;
+	is->active_filter = NULL;
 #endif
 	is->state = IPPP_OPEN;
 
@@ -378,13 +378,13 @@
 	is->slcomp = NULL;
 #endif
 #ifdef CONFIG_IPPP_FILTER
-	if (is->pass_filter.filter) {
-		kfree(is->pass_filter.filter);
-		is->pass_filter.filter = NULL;
-	}
-	if (is->active_filter.filter) {
-		kfree(is->active_filter.filter);
-		is->active_filter.filter = NULL;
+	if (is->pass_filter) {
+		kfree(is->pass_filter);
+		is->pass_filter = NULL;
+	}
+	if (is->active_filter) {
+		kfree(is->active_filter);
+		is->active_filter = NULL;
 	}
 #endif
 
@@ -414,11 +414,11 @@
  * get_arg .. ioctl helper
  */
 static int
-get_arg(void *b, void *val, int len)
+get_arg(void __user *b, void *val, int len)
 {
 	if (len <= 0)
 		len = sizeof(void *);
-	if (copy_from_user((void *) val, b, len))
+	if (copy_from_user(val, b, len))
 		return -EFAULT;
 	return 0;
 }
@@ -427,15 +427,50 @@
  * set arg .. ioctl helper
  */
 static int
-set_arg(void *b, void *val,int len)
+set_arg(void __user *b, void *val,int len)
 {
 	if(len <= 0)
 		len = sizeof(void *);
-	if (copy_to_user(b, (void *) val, len))
+	if (copy_to_user(b, val, len))
 		return -EFAULT;
 	return 0;
 }
 
+static int get_filter(void __user *arg, struct sock_filter **p)
+{
+	struct sock_fprog uprog;
+	struct sock_filter *code = NULL;
+	int len, err;
+
+	if (copy_from_user(&uprog, arg, sizeof(uprog)))
+		return -EFAULT;
+
+	if (!uprog.len) {
+		*p = NULL;
+		return 0;
+	}
+
+	/* uprog.len is unsigned short, so no overflow here */
+	len = uprog.len * sizeof(struct sock_filter);
+	code = kmalloc(len, GFP_KERNEL);
+	if (code == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(code, uprog.filter, len)) {
+		kfree(code);
+		return -EFAULT;
+	}
+
+	err = sk_chk_filter(code, uprog.len);
+	if (err) {
+		kfree(code);
+		return err;
+	}
+
+	*p = code;
+	return uprog.len;
+}
+
 /*
  * ippp device ioctl
  */
@@ -447,6 +482,7 @@
 	struct ippp_struct *is;
 	isdn_net_local *lp;
 	struct isdn_ppp_comp_data data;
+	void __user *argp = (void __user *)arg;
 
 	is = (struct ippp_struct *) file->private_data;
 	lp = is->lp;
@@ -462,7 +498,7 @@
 #ifdef CONFIG_ISDN_MPP
 			if (!(is->state & IPPP_CONNECT))
 				return -EINVAL;
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+			if ((r = get_arg(argp, &val, sizeof(val) )))
 				return r;
 			printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
 			       (int) min, (int) is->unit, (int) val);
@@ -472,30 +508,30 @@
 #endif
 			break;
 		case PPPIOCGUNIT:	/* get ppp/isdn unit number */
-			if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) )))
+			if ((r = set_arg(argp, &is->unit, sizeof(is->unit) )))
 				return r;
 			break;
 		case PPPIOCGIFNAME:
 			if(!lp)
 				return -EINVAL;
-			if ((r = set_arg((void *) arg, lp->name, strlen(lp->name))))
+			if ((r = set_arg(argp, lp->name, strlen(lp->name))))
 				return r;
 			break;
 		case PPPIOCGMPFLAGS:	/* get configuration flags */
-			if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) )))
+			if ((r = set_arg(argp, &is->mpppcfg, sizeof(is->mpppcfg) )))
 				return r;
 			break;
 		case PPPIOCSMPFLAGS:	/* set configuration flags */
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+			if ((r = get_arg(argp, &val, sizeof(val) )))
 				return r;
 			is->mpppcfg = val;
 			break;
 		case PPPIOCGFLAGS:	/* get configuration flags */
-			if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) )))
+			if ((r = set_arg(argp, &is->pppcfg,sizeof(is->pppcfg) )))
 				return r;
 			break;
 		case PPPIOCSFLAGS:	/* set configuration flags */
-			if ((r = get_arg((void *) arg, &val, sizeof(val) ))) {
+			if ((r = get_arg(argp, &val, sizeof(val) ))) {
 				return r;
 			}
 			if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
@@ -512,12 +548,12 @@
 			if (lp) {
 				struct ppp_idle pidle;
 				pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
-				if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle))))
+				if ((r = set_arg(argp, &pidle,sizeof(struct ppp_idle))))
 					 return r;
 			}
 			break;
 		case PPPIOCSMRU:	/* set receive unit size for PPP */
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+			if ((r = get_arg(argp, &val, sizeof(val) )))
 				return r;
 			is->mru = val;
 			break;
@@ -526,7 +562,7 @@
 		case PPPIOCSMPMTU:
 			break;
 		case PPPIOCSMAXCID:	/* set the maximum compression slot id */
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+			if ((r = get_arg(argp, &val, sizeof(val) )))
 				return r;
 			val++;
 			if (is->maxcid != val) {
@@ -549,11 +585,11 @@
 			}
 			break;
 		case PPPIOCGDEBUG:
-			if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) )))
+			if ((r = set_arg(argp, &is->debug, sizeof(is->debug) )))
 				return r;
 			break;
 		case PPPIOCSDEBUG:
-			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+			if ((r = get_arg(argp, &val, sizeof(val) )))
 				return r;
 			is->debug = val;
 			break;
@@ -568,12 +604,12 @@
 						protos[j] |= (0x1<<i);
 					ipc = ipc->next;
 				}
-				if ((r = set_arg((void *) arg,protos,8*sizeof(long) )))
+				if ((r = set_arg(argp,protos,8*sizeof(long) )))
 					return r;
 			}
 			break;
 		case PPPIOCSCOMPRESSOR:
-			if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data))))
+			if ((r = get_arg(argp, &data, sizeof(struct isdn_ppp_comp_data))))
 				return r;
 			return isdn_ppp_set_compressor(is, &data);
 		case PPPIOCGCALLINFO:
@@ -594,38 +630,29 @@
 					if(lp->flags & ISDN_NET_CALLBACK)
 						pci.calltype |= CALLTYPE_CALLBACK;
 				}
-				return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
+				return set_arg(argp,&pci,sizeof(struct pppcallinfo));
 			}
 #ifdef CONFIG_IPPP_FILTER
 		case PPPIOCSPASS:
+			{
+				struct sock_filter *code;
+				int len = get_filter(argp, &code);
+				if (len < 0)
+					return len;
+				kfree(is->pass_filter);
+				is->pass_filter = code;
+				is->pass_len = len;
+				break;
+			}
 		case PPPIOCSACTIVE:
 			{
-				struct sock_fprog uprog, *filtp;
-				struct sock_filter *code = NULL;
-				int len, err;
-
-				if (copy_from_user(&uprog, (void *) arg, sizeof(uprog)))
-					return -EFAULT;
-				if (uprog.len > 0) {
-					len = uprog.len * sizeof(struct sock_filter);
-					code = kmalloc(len, GFP_KERNEL);
-					if (code == NULL)
-						return -ENOMEM;
-					if (copy_from_user(code, uprog.filter, len)) {
-						kfree(code);
-						return -EFAULT;
-					}
-					err = sk_chk_filter(code, uprog.len);
-					if (err) {
-						kfree(code);
-						return err;
-					}
-				}
-				filtp = (cmd == PPPIOCSPASS) ? &is->pass_filter : &is->active_filter;
-				if (filtp->filter)
-					kfree(filtp->filter);
-				filtp->filter = code;
-				filtp->len = uprog.len;
+				struct sock_filter *code;
+				int len = get_filter(argp, &code);
+				if (len < 0)
+					return len;
+				kfree(is->active_filter);
+				is->active_filter = code;
+				is->active_len = len;
 				break;
 			}
 #endif /* CONFIG_IPPP_FILTER */
@@ -733,7 +760,7 @@
  */
 
 int
-isdn_ppp_read(int min, struct file *file, char *buf, int count)
+isdn_ppp_read(int min, struct file *file, char __user *buf, int count)
 {
 	struct ippp_struct *is;
 	struct ippp_buf_queue *b;
@@ -746,7 +773,7 @@
 	if (!(is->state & IPPP_OPEN))
 		return 0;
 
-	if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
+	if ((r = verify_area(VERIFY_WRITE, buf, count)))
 		return r;
 
 	spin_lock_irqsave(&is->buflock, flags);
@@ -773,7 +800,7 @@
  */
 
 int
-isdn_ppp_write(int min, struct file *file, const char *buf, int count)
+isdn_ppp_write(int min, struct file *file, const char __user *buf, int count)
 {
 	isdn_net_local *lp;
 	struct ippp_struct *is;
@@ -1128,17 +1155,16 @@
 		*p = 0;	/* indicate inbound in DLT_LINUX_SLL */
 	}
 
-	if (is->pass_filter.filter
-	    && sk_run_filter(skb, is->pass_filter.filter,
-	                    is->pass_filter.len) == 0) {
+	if (is->pass_filter
+	    && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0) {
 		if (is->debug & 0x2)
 			printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
 		kfree_skb(skb);
 		return;
 	}
-	if (!(is->active_filter.filter
-	      && sk_run_filter(skb, is->active_filter.filter,
-	                       is->active_filter.len) == 0)) {
+	if (!(is->active_filter
+	      && sk_run_filter(skb, is->active_filter,
+	                       is->active_len) == 0)) {
 		if (is->debug & 0x2)
 			printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
 		lp->huptimer = 0;
@@ -1276,17 +1302,16 @@
 		*p   = htons(proto);
 	}
 
-	if (ipt->pass_filter.filter 
-	    && sk_run_filter(skb, ipt->pass_filter.filter,
-		             ipt->pass_filter.len) == 0) {
+	if (ipt->pass_filter
+	    && sk_run_filter(skb, ipt->pass_filter, ipt->pass_len) == 0) {
 		if (ipt->debug & 0x4)
 			printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
 		kfree_skb(skb);
 		goto unlock;
 	}
-	if (!(ipt->active_filter.filter
-	      && sk_run_filter(skb, ipt->active_filter.filter,
-		               ipt->active_filter.len) == 0)) {
+	if (!(ipt->active_filter
+	      && sk_run_filter(skb, ipt->active_filter,
+		               ipt->active_len) == 0)) {
 		if (ipt->debug & 0x4)
 			printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
 		lp->huptimer = 0;
@@ -1475,12 +1500,10 @@
 		*p   = htons(proto);
 	}
 	
-	drop |= is->pass_filter.filter
-	        && sk_run_filter(skb, is->pass_filter.filter,
-	                         is->pass_filter.len) == 0;
-	drop |= is->active_filter.filter
-	        && sk_run_filter(skb, is->active_filter.filter,
-	                         is->active_filter.len) == 0;
+	drop |= is->pass_filter
+	        && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0;
+	drop |= is->active_filter
+	        && sk_run_filter(skb, is->active_filter, is->active_len) == 0;
 	
 	skb_push(skb, IPPP_MAX_HEADER - 4);
 	return drop;
@@ -1969,12 +1992,11 @@
 static int
 isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
 {
-	struct ppp_stats *res,
-	 t;
+	struct ppp_stats __user *res = ifr->ifr_data;
+	struct ppp_stats t;
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
 	int err;
 
-	res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
 	err = verify_area(VERIFY_WRITE, res, sizeof(struct ppp_stats));
 
 	if (err)
@@ -2004,7 +2026,8 @@
 		}
 #endif
 	}
-	if( copy_to_user(res, &t, sizeof(struct ppp_stats))) return -EFAULT;
+	if (copy_to_user(res, &t, sizeof(struct ppp_stats)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -2012,7 +2035,6 @@
 isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	int error=0;
-	char *r;
 	int len;
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
 
@@ -2023,9 +2045,8 @@
 	switch (cmd) {
 #define PPP_VERSION "2.3.7"
 		case SIOCGPPPVER:
-			r = (char *) ifr->ifr_ifru.ifru_data;
 			len = strlen(PPP_VERSION) + 1;
-			if (copy_to_user(r, PPP_VERSION, len))
+			if (copy_to_user(ifr->ifr_data, PPP_VERSION, len))
 				error = -EFAULT;
 			break;
 
diff -Nru a/drivers/isdn/i4l/isdn_ppp.h b/drivers/isdn/i4l/isdn_ppp.h
--- a/drivers/isdn/i4l/isdn_ppp.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/isdn/i4l/isdn_ppp.h	2004-06-23 19:04:26 -07:00
@@ -12,8 +12,8 @@
 #include <linux/ppp_defs.h>     /* for PPP_PROTOCOL */
 #include <linux/isdn_ppp.h>	/* for isdn_ppp info */
 
-extern int isdn_ppp_read(int, struct file *, char *, int);
-extern int isdn_ppp_write(int, struct file *, const char *, int);
+extern int isdn_ppp_read(int, struct file *, char __user *, int);
+extern int isdn_ppp_write(int, struct file *, const char __user *, int);
 extern int isdn_ppp_open(int, struct file *);
 extern int isdn_ppp_init(void);
 extern void isdn_ppp_cleanup(void);
diff -Nru a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c
--- a/drivers/isdn/sc/message.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/isdn/sc/message.c	2004-06-23 19:04:28 -07:00
@@ -30,7 +30,6 @@
  */
 extern int indicate_status(int,ulong,char*);
 extern int scm_command(isdn_ctrl *);
-extern void *memcpy_fromshmem(int, void *, const void *, size_t);
 
 
 /*
diff -Nru a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
--- a/drivers/isdn/sc/packet.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/isdn/sc/packet.c	2004-06-23 19:04:29 -07:00
@@ -25,8 +25,8 @@
 
 extern int get_card_from_id(int);
 extern int indicate_status(int, int,ulong, char*);
-extern void *memcpy_toshmem(int, void *, const void *, size_t);
-extern void *memcpy_fromshmem(int, void *, const void *, size_t);
+extern void memcpy_toshmem(int, void *, const void *, size_t);
+extern void memcpy_fromshmem(int, void *, const void *, size_t);
 extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
                 unsigned int, unsigned int, unsigned int, unsigned int *);
 
diff -Nru a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
--- a/drivers/isdn/sc/shmem.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/isdn/sc/shmem.c	2004-06-23 19:04:26 -07:00
@@ -30,19 +30,18 @@
 /*
  *
  */
-void *memcpy_toshmem(int card, void *dest, const void *src, size_t n)
+void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
 {
 	unsigned long flags;
-	void *ret;
 	unsigned char ch;
 
 	if(!IS_VALID_CARD(card)) {
 		pr_debug("Invalid param: %d is not a valid card id\n", card);
-		return NULL;
+		return;
 	}
 
 	if(n > SRAM_PAGESIZE) {
-		return NULL;
+		return;
 	}
 
 	/*
@@ -57,7 +56,7 @@
 
 	outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
 		sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
-	ret = memcpy_toio(sc_adapter[card]->rambase +
+	memcpy_toio(sc_adapter[card]->rambase +
 		((unsigned long) dest % 0x4000), src, n);
 	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 	pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
@@ -66,26 +65,23 @@
 		sc_adapter[card]->devicename, n,
 		(unsigned long) src,
 		sc_adapter[card]->rambase + ((unsigned long) dest %0x4000));
-
-	return ret;
 }
 
 /*
  * Reverse of above
  */
-void *memcpy_fromshmem(int card, void *dest, const void *src, size_t n)
+void memcpy_fromshmem(int card, void *dest, const void *src, size_t n)
 {
 	unsigned long flags;
-	void *ret;
 	unsigned char ch;
 
 	if(!IS_VALID_CARD(card)) {
 		pr_debug("Invalid param: %d is not a valid card id\n", card);
-		return NULL;
+		return;
 	}
 
 	if(n > SRAM_PAGESIZE) {
-		return NULL;
+		return;
 	}
 
 	/*
@@ -102,7 +98,7 @@
 
 	outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
 		sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
-	ret = memcpy_fromio(dest,(void *)(sc_adapter[card]->rambase +
+	memcpy_fromio(dest,(void *)(sc_adapter[card]->rambase +
 		((unsigned long) src % 0x4000)), n);
 	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 	pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
@@ -110,23 +106,20 @@
 /*	pr_debug("%s: copying %d bytes from %#x to %#x\n",
 		sc_adapter[card]->devicename, n,
 		sc_adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */
-
-	return ret;
 }
 
-void *memset_shmem(int card, void *dest, int c, size_t n)
+void memset_shmem(int card, void *dest, int c, size_t n)
 {
 	unsigned long flags;
 	unsigned char ch;
-	void *ret;
 
 	if(!IS_VALID_CARD(card)) {
 		pr_debug("Invalid param: %d is not a valid card id\n", card);
-		return NULL;
+		return;
 	}
 
 	if(n > SRAM_PAGESIZE) {
-		return NULL;
+		return;
 	}
 
 	/*
@@ -142,11 +135,9 @@
 
 	outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
 		sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
-	ret = memset_io(sc_adapter[card]->rambase +
+	memset_io(sc_adapter[card]->rambase +
 		((unsigned long) dest % 0x4000), c, n);
 	pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
 		((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
 	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
-
-	return ret;
 }
diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig
--- a/drivers/md/Kconfig	2004-06-23 19:04:25 -07:00
+++ b/drivers/md/Kconfig	2004-06-23 19:04:25 -07:00
@@ -180,5 +180,25 @@
 
 	  If unsure, say N.
 
+config DM_SNAPSHOT
+       tristate "Snapshot target (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+         Allow volume managers to take writeable snapshots of a device.
+
+config DM_MIRROR
+       tristate "Mirror target (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+         Allow volume managers to mirror logical volumes, also
+         needed for live data migration tools such as 'pvmove'.
+
+config DM_ZERO
+	tristate "Zero target (EXPERIMENTAL)"
+	depends on BLK_DEV_DM && EXPERIMENTAL
+	---help---
+	  A target that discards writes, and returns all zeroes for
+	  reads.  Useful in some recovery situations.
+
 endmenu
 
diff -Nru a/drivers/md/Makefile b/drivers/md/Makefile
--- a/drivers/md/Makefile	2004-06-23 19:04:27 -07:00
+++ b/drivers/md/Makefile	2004-06-23 19:04:27 -07:00
@@ -3,7 +3,9 @@
 #
 
 dm-mod-objs	:= dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
-		   dm-ioctl.o
+		   dm-ioctl.o dm-io.o kcopyd.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 \
 		   raid6int1.o raid6int2.o raid6int4.o \
 		   raid6int8.o raid6int16.o raid6int32.o \
@@ -24,6 +26,9 @@
 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_SNAPSHOT)	+= dm-snapshot.o
+obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o
+obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
 
 quiet_cmd_unroll = UNROLL  $@
       cmd_unroll = $(PERL) $(srctree)/$(src)/unroll.pl $(UNROLL) \
diff -Nru a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-exception-store.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,648 @@
+/*
+ * dm-snapshot.c
+ *
+ * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+#include "dm-snap.h"
+#include "dm-io.h"
+#include "kcopyd.h"
+
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+/*-----------------------------------------------------------------
+ * Persistent snapshots, by persistent we mean that the snapshot
+ * will survive a reboot.
+ *---------------------------------------------------------------*/
+
+/*
+ * We need to store a record of which parts of the origin have
+ * been copied to the snapshot device.  The snapshot code
+ * requires that we copy exception chunks to chunk aligned areas
+ * of the COW store.  It makes sense therefore, to store the
+ * metadata in chunk size blocks.
+ *
+ * There is no backward or forward compatibility implemented,
+ * snapshots with different disk versions than the kernel will
+ * not be usable.  It is expected that "lvcreate" will blank out
+ * the start of a fresh COW device before calling the snapshot
+ * constructor.
+ *
+ * The first chunk of the COW device just contains the header.
+ * After this there is a chunk filled with exception metadata,
+ * followed by as many exception chunks as can fit in the
+ * metadata areas.
+ *
+ * All on disk structures are in little-endian format.  The end
+ * of the exceptions info is indicated by an exception with a
+ * new_chunk of 0, which is invalid since it would point to the
+ * header chunk.
+ */
+
+/*
+ * Magic for persistent snapshots: "SnAp" - Feeble isn't it.
+ */
+#define SNAP_MAGIC 0x70416e53
+
+/*
+ * The on-disk version of the metadata.
+ */
+#define SNAPSHOT_DISK_VERSION 1
+
+struct disk_header {
+	uint32_t magic;
+
+	/*
+	 * Is this snapshot valid.  There is no way of recovering
+	 * an invalid snapshot.
+	 */
+	uint32_t valid;
+
+	/*
+	 * Simple, incrementing version. no backward
+	 * compatibility.
+	 */
+	uint32_t version;
+
+	/* In sectors */
+	uint32_t chunk_size;
+};
+
+struct disk_exception {
+	uint64_t old_chunk;
+	uint64_t new_chunk;
+};
+
+struct commit_callback {
+	void (*callback)(void *, int success);
+	void *context;
+};
+
+/*
+ * The top level structure for a persistent exception store.
+ */
+struct pstore {
+	struct dm_snapshot *snap;	/* up pointer to my snapshot */
+	int version;
+	int valid;
+	uint32_t chunk_size;
+	uint32_t exceptions_per_area;
+
+	/*
+	 * Now that we have an asynchronous kcopyd there is no
+	 * need for large chunk sizes, so it wont hurt to have a
+	 * whole chunks worth of metadata in memory at once.
+	 */
+	void *area;
+
+	/*
+	 * Used to keep track of which metadata area the data in
+	 * 'chunk' refers to.
+	 */
+	uint32_t current_area;
+
+	/*
+	 * The next free chunk for an exception.
+	 */
+	uint32_t next_free;
+
+	/*
+	 * The index of next free exception in the current
+	 * metadata area.
+	 */
+	uint32_t current_committed;
+
+	atomic_t pending_count;
+	uint32_t callback_count;
+	struct commit_callback *callbacks;
+};
+
+static inline unsigned int sectors_to_pages(unsigned int sectors)
+{
+	return sectors / (PAGE_SIZE >> 9);
+}
+
+static int alloc_area(struct pstore *ps)
+{
+	int r = -ENOMEM;
+	size_t len;
+
+	len = ps->chunk_size << SECTOR_SHIFT;
+
+	/*
+	 * Allocate the chunk_size block of memory that will hold
+	 * a single metadata area.
+	 */
+	ps->area = vmalloc(len);
+	if (!ps->area)
+		return r;
+
+	return 0;
+}
+
+static void free_area(struct pstore *ps)
+{
+	vfree(ps->area);
+}
+
+/*
+ * Read or write a chunk aligned and sized block of data from a device.
+ */
+static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
+{
+	struct io_region where;
+	unsigned long bits;
+
+	where.bdev = ps->snap->cow->bdev;
+	where.sector = ps->chunk_size * chunk;
+	where.count = ps->chunk_size;
+
+	return dm_io_sync_vm(1, &where, rw, ps->area, &bits);
+}
+
+/*
+ * Read or write a metadata area.  Remembering to skip the first
+ * chunk which holds the header.
+ */
+static int area_io(struct pstore *ps, uint32_t area, int rw)
+{
+	int r;
+	uint32_t chunk;
+
+	/* convert a metadata area index to a chunk index */
+	chunk = 1 + ((ps->exceptions_per_area + 1) * area);
+
+	r = chunk_io(ps, chunk, rw);
+	if (r)
+		return r;
+
+	ps->current_area = area;
+	return 0;
+}
+
+static int zero_area(struct pstore *ps, uint32_t area)
+{
+	memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT);
+	return area_io(ps, area, WRITE);
+}
+
+static int read_header(struct pstore *ps, int *new_snapshot)
+{
+	int r;
+	struct disk_header *dh;
+
+	r = chunk_io(ps, 0, READ);
+	if (r)
+		return r;
+
+	dh = (struct disk_header *) ps->area;
+
+	if (le32_to_cpu(dh->magic) == 0) {
+		*new_snapshot = 1;
+
+	} else if (le32_to_cpu(dh->magic) == SNAP_MAGIC) {
+		*new_snapshot = 0;
+		ps->valid = le32_to_cpu(dh->valid);
+		ps->version = le32_to_cpu(dh->version);
+		ps->chunk_size = le32_to_cpu(dh->chunk_size);
+
+	} else {
+		DMWARN("Invalid/corrupt snapshot");
+		r = -ENXIO;
+	}
+
+	return r;
+}
+
+static int write_header(struct pstore *ps)
+{
+	struct disk_header *dh;
+
+	memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT);
+
+	dh = (struct disk_header *) ps->area;
+	dh->magic = cpu_to_le32(SNAP_MAGIC);
+	dh->valid = cpu_to_le32(ps->valid);
+	dh->version = cpu_to_le32(ps->version);
+	dh->chunk_size = cpu_to_le32(ps->chunk_size);
+
+	return chunk_io(ps, 0, WRITE);
+}
+
+/*
+ * Access functions for the disk exceptions, these do the endian conversions.
+ */
+static struct disk_exception *get_exception(struct pstore *ps, uint32_t index)
+{
+	if (index >= ps->exceptions_per_area)
+		return NULL;
+
+	return ((struct disk_exception *) ps->area) + index;
+}
+
+static int read_exception(struct pstore *ps,
+			  uint32_t index, struct disk_exception *result)
+{
+	struct disk_exception *e;
+
+	e = get_exception(ps, index);
+	if (!e)
+		return -EINVAL;
+
+	/* copy it */
+	result->old_chunk = le64_to_cpu(e->old_chunk);
+	result->new_chunk = le64_to_cpu(e->new_chunk);
+
+	return 0;
+}
+
+static int write_exception(struct pstore *ps,
+			   uint32_t index, struct disk_exception *de)
+{
+	struct disk_exception *e;
+
+	e = get_exception(ps, index);
+	if (!e)
+		return -EINVAL;
+
+	/* copy it */
+	e->old_chunk = cpu_to_le64(de->old_chunk);
+	e->new_chunk = cpu_to_le64(de->new_chunk);
+
+	return 0;
+}
+
+/*
+ * Registers the exceptions that are present in the current area.
+ * 'full' is filled in to indicate if the area has been
+ * filled.
+ */
+static int insert_exceptions(struct pstore *ps, int *full)
+{
+	int r;
+	unsigned int i;
+	struct disk_exception de;
+
+	/* presume the area is full */
+	*full = 1;
+
+	for (i = 0; i < ps->exceptions_per_area; i++) {
+		r = read_exception(ps, i, &de);
+
+		if (r)
+			return r;
+
+		/*
+		 * If the new_chunk is pointing at the start of
+		 * the COW device, where the first metadata area
+		 * is we know that we've hit the end of the
+		 * exceptions.  Therefore the area is not full.
+		 */
+		if (de.new_chunk == 0LL) {
+			ps->current_committed = i;
+			*full = 0;
+			break;
+		}
+
+		/*
+		 * Keep track of the start of the free chunks.
+		 */
+		if (ps->next_free <= de.new_chunk)
+			ps->next_free = de.new_chunk + 1;
+
+		/*
+		 * Otherwise we add the exception to the snapshot.
+		 */
+		r = dm_add_exception(ps->snap, de.old_chunk, de.new_chunk);
+		if (r)
+			return r;
+	}
+
+	return 0;
+}
+
+static int read_exceptions(struct pstore *ps)
+{
+	uint32_t area;
+	int r, full = 1;
+
+	/*
+	 * Keeping reading chunks and inserting exceptions until
+	 * we find a partially full area.
+	 */
+	for (area = 0; full; area++) {
+		r = area_io(ps, area, READ);
+		if (r)
+			return r;
+
+		r = insert_exceptions(ps, &full);
+		if (r)
+			return r;
+	}
+
+	return 0;
+}
+
+static inline struct pstore *get_info(struct exception_store *store)
+{
+	return (struct pstore *) store->context;
+}
+
+static void persistent_fraction_full(struct exception_store *store,
+				     sector_t *numerator, sector_t *denominator)
+{
+	*numerator = get_info(store)->next_free * store->snap->chunk_size;
+	*denominator = get_dev_size(store->snap->cow->bdev);
+}
+
+static void persistent_destroy(struct exception_store *store)
+{
+	struct pstore *ps = get_info(store);
+
+	dm_io_put(sectors_to_pages(ps->chunk_size));
+	vfree(ps->callbacks);
+	free_area(ps);
+	kfree(ps);
+}
+
+static int persistent_read_metadata(struct exception_store *store)
+{
+	int r, new_snapshot;
+	struct pstore *ps = get_info(store);
+
+	/*
+	 * Read the snapshot header.
+	 */
+	r = read_header(ps, &new_snapshot);
+	if (r)
+		return r;
+
+	/*
+	 * Do we need to setup a new snapshot ?
+	 */
+	if (new_snapshot) {
+		r = write_header(ps);
+		if (r) {
+			DMWARN("write_header failed");
+			return r;
+		}
+
+		r = zero_area(ps, 0);
+		if (r) {
+			DMWARN("zero_area(0) failed");
+			return r;
+		}
+
+	} else {
+		/*
+		 * Sanity checks.
+		 */
+		if (!ps->valid) {
+			DMWARN("snapshot is marked invalid");
+			return -EINVAL;
+		}
+
+		if (ps->version != SNAPSHOT_DISK_VERSION) {
+			DMWARN("unable to handle snapshot disk version %d",
+			       ps->version);
+			return -EINVAL;
+		}
+
+		/*
+		 * Read the metadata.
+		 */
+		r = read_exceptions(ps);
+		if (r)
+			return r;
+	}
+
+	return 0;
+}
+
+static int persistent_prepare(struct exception_store *store,
+			      struct exception *e)
+{
+	struct pstore *ps = get_info(store);
+	uint32_t stride;
+	sector_t size = get_dev_size(store->snap->cow->bdev);
+
+	/* Is there enough room ? */
+	if (size < ((ps->next_free + 1) * store->snap->chunk_size))
+		return -ENOSPC;
+
+	e->new_chunk = ps->next_free;
+
+	/*
+	 * Move onto the next free pending, making sure to take
+	 * into account the location of the metadata chunks.
+	 */
+	stride = (ps->exceptions_per_area + 1);
+	if ((++ps->next_free % stride) == 1)
+		ps->next_free++;
+
+	atomic_inc(&ps->pending_count);
+	return 0;
+}
+
+static void persistent_commit(struct exception_store *store,
+			      struct exception *e,
+			      void (*callback) (void *, int success),
+			      void *callback_context)
+{
+	int r;
+	unsigned int i;
+	struct pstore *ps = get_info(store);
+	struct disk_exception de;
+	struct commit_callback *cb;
+
+	de.old_chunk = e->old_chunk;
+	de.new_chunk = e->new_chunk;
+	write_exception(ps, ps->current_committed++, &de);
+
+	/*
+	 * Add the callback to the back of the array.  This code
+	 * is the only place where the callback array is
+	 * manipulated, and we know that it will never be called
+	 * multiple times concurrently.
+	 */
+	cb = ps->callbacks + ps->callback_count++;
+	cb->callback = callback;
+	cb->context = callback_context;
+
+	/*
+	 * If there are no more exceptions in flight, or we have
+	 * filled this metadata area we commit the exceptions to
+	 * disk.
+	 */
+	if (atomic_dec_and_test(&ps->pending_count) ||
+	    (ps->current_committed == ps->exceptions_per_area)) {
+		r = area_io(ps, ps->current_area, WRITE);
+		if (r)
+			ps->valid = 0;
+
+		for (i = 0; i < ps->callback_count; i++) {
+			cb = ps->callbacks + i;
+			cb->callback(cb->context, r == 0 ? 1 : 0);
+		}
+
+		ps->callback_count = 0;
+	}
+
+	/*
+	 * Have we completely filled the current area ?
+	 */
+	if (ps->current_committed == ps->exceptions_per_area) {
+		ps->current_committed = 0;
+		r = zero_area(ps, ps->current_area + 1);
+		if (r)
+			ps->valid = 0;
+	}
+}
+
+static void persistent_drop(struct exception_store *store)
+{
+	struct pstore *ps = get_info(store);
+
+	ps->valid = 0;
+	if (write_header(ps))
+		DMWARN("write header failed");
+}
+
+int dm_create_persistent(struct exception_store *store, uint32_t chunk_size)
+{
+	int r;
+	struct pstore *ps;
+
+	r = dm_io_get(sectors_to_pages(chunk_size));
+	if (r)
+		return r;
+
+	/* allocate the pstore */
+	ps = kmalloc(sizeof(*ps), GFP_KERNEL);
+	if (!ps) {
+		r = -ENOMEM;
+		goto bad;
+	}
+
+	ps->snap = store->snap;
+	ps->valid = 1;
+	ps->version = SNAPSHOT_DISK_VERSION;
+	ps->chunk_size = chunk_size;
+	ps->exceptions_per_area = (chunk_size << SECTOR_SHIFT) /
+	    sizeof(struct disk_exception);
+	ps->next_free = 2;	/* skipping the header and first area */
+	ps->current_committed = 0;
+
+	r = alloc_area(ps);
+	if (r)
+		goto bad;
+
+	/*
+	 * Allocate space for all the callbacks.
+	 */
+	ps->callback_count = 0;
+	atomic_set(&ps->pending_count, 0);
+	ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
+				   sizeof(*ps->callbacks));
+
+	if (!ps->callbacks) {
+		r = -ENOMEM;
+		goto bad;
+	}
+
+	store->destroy = persistent_destroy;
+	store->read_metadata = persistent_read_metadata;
+	store->prepare_exception = persistent_prepare;
+	store->commit_exception = persistent_commit;
+	store->drop_snapshot = persistent_drop;
+	store->fraction_full = persistent_fraction_full;
+	store->context = ps;
+
+	return 0;
+
+      bad:
+	dm_io_put(sectors_to_pages(chunk_size));
+	if (ps) {
+		if (ps->area)
+			free_area(ps);
+
+		kfree(ps);
+	}
+	return r;
+}
+
+/*-----------------------------------------------------------------
+ * Implementation of the store for non-persistent snapshots.
+ *---------------------------------------------------------------*/
+struct transient_c {
+	sector_t next_free;
+};
+
+static void transient_destroy(struct exception_store *store)
+{
+	kfree(store->context);
+}
+
+static int transient_read_metadata(struct exception_store *store)
+{
+	return 0;
+}
+
+static int transient_prepare(struct exception_store *store, struct exception *e)
+{
+	struct transient_c *tc = (struct transient_c *) store->context;
+	sector_t size = get_dev_size(store->snap->cow->bdev);
+
+	if (size < (tc->next_free + store->snap->chunk_size))
+		return -1;
+
+	e->new_chunk = sector_to_chunk(store->snap, tc->next_free);
+	tc->next_free += store->snap->chunk_size;
+
+	return 0;
+}
+
+static void transient_commit(struct exception_store *store,
+		      struct exception *e,
+		      void (*callback) (void *, int success),
+		      void *callback_context)
+{
+	/* Just succeed */
+	callback(callback_context, 1);
+}
+
+static void transient_fraction_full(struct exception_store *store,
+				    sector_t *numerator, sector_t *denominator)
+{
+	*numerator = ((struct transient_c *) store->context)->next_free;
+	*denominator = get_dev_size(store->snap->cow->bdev);
+}
+
+int dm_create_transient(struct exception_store *store,
+			struct dm_snapshot *s, int blocksize)
+{
+	struct transient_c *tc;
+
+	memset(store, 0, sizeof(*store));
+	store->destroy = transient_destroy;
+	store->read_metadata = transient_read_metadata;
+	store->prepare_exception = transient_prepare;
+	store->commit_exception = transient_commit;
+	store->fraction_full = transient_fraction_full;
+	store->snap = s;
+
+	tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
+	if (!tc)
+		return -ENOMEM;
+
+	tc->next_free = 0;
+	store->context = tc;
+
+	return 0;
+}
diff -Nru a/drivers/md/dm-io.c b/drivers/md/dm-io.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-io.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,647 @@
+/*
+ * Copyright (C) 2003 Sistina Software
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-io.h"
+
+#include <linux/bio.h>
+#include <linux/mempool.h>
+#include <linux/module.h>
+#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 inline void bs_bio_init(struct bio *bio)
+{
+	bio->bi_next = NULL;
+	bio->bi_flags = 1 << BIO_UPTODATE;
+	bio->bi_rw = 0;
+	bio->bi_vcnt = 0;
+	bio->bi_idx = 0;
+	bio->bi_phys_segments = 0;
+	bio->bi_hw_segments = 0;
+	bio->bi_size = 0;
+	bio->bi_max_vecs = 0;
+	bio->bi_end_io = NULL;
+	atomic_set(&bio->bi_cnt, 1);
+	bio->bi_private = NULL;
+}
+
+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;
+
+/* FIXME: can we shrink this ? */
+struct io {
+	unsigned long error;
+	atomic_t count;
+	struct task_struct *sleeper;
+	io_notify_fn callback;
+	void *context;
+};
+
+/*
+ * io contexts are only dynamically allocated for asynchronous
+ * io.  Since async io is likely to be the majority of io we'll
+ * have the same number of io contexts as buffer heads ! (FIXME:
+ * must reduce this).
+ */
+static unsigned _num_ios;
+static mempool_t *_io_pool;
+
+static void *alloc_io(int gfp_mask, void *pool_data)
+{
+	return kmalloc(sizeof(struct io), gfp_mask);
+}
+
+static void free_io(void *element, void *pool_data)
+{
+	kfree(element);
+}
+
+static unsigned int pages_to_ios(unsigned int pages)
+{
+	return 4 * pages;	/* too many ? */
+}
+
+static int resize_pool(unsigned int new_ios)
+{
+	int r = 0;
+
+	if (_io_pool) {
+		if (new_ios == 0) {
+			/* free off the pool */
+			mempool_destroy(_io_pool);
+			_io_pool = NULL;
+			bio_set_exit(&_bios);
+
+		} else {
+			/* resize the pool */
+			r = mempool_resize(_io_pool, new_ios, GFP_KERNEL);
+		}
+
+	} else {
+		/* create new pool */
+		_io_pool = mempool_create(new_ios, alloc_io, free_io, NULL);
+		if (!_io_pool)
+			r = -ENOMEM;
+
+		r = bio_set_init(&_bios, "dm-io", 512, 1);
+		if (r) {
+			mempool_destroy(_io_pool);
+			_io_pool = NULL;
+		}
+	}
+
+	if (!r)
+		_num_ios = new_ios;
+
+	return r;
+}
+
+int dm_io_get(unsigned int num_pages)
+{
+	return resize_pool(_num_ios + pages_to_ios(num_pages));
+}
+
+void dm_io_put(unsigned int num_pages)
+{
+	resize_pool(_num_ios - pages_to_ios(num_pages));
+}
+
+/*-----------------------------------------------------------------
+ * 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).
+ *---------------------------------------------------------------*/
+static inline void bio_set_region(struct bio *bio, unsigned region)
+{
+	bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len = region;
+}
+
+static inline unsigned bio_get_region(struct bio *bio)
+{
+	return bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len;
+}
+
+/*-----------------------------------------------------------------
+ * We need an io object to keep track of the number of bios that
+ * have been dispatched for a particular io.
+ *---------------------------------------------------------------*/
+static void dec_count(struct io *io, unsigned int region, int error)
+{
+	if (error)
+		set_bit(region, &io->error);
+
+	if (atomic_dec_and_test(&io->count)) {
+		if (io->sleeper)
+			wake_up_process(io->sleeper);
+
+		else {
+			int r = io->error;
+			io_notify_fn fn = io->callback;
+			void *context = io->context;
+
+			mempool_free(io, _io_pool);
+			fn(r, context);
+		}
+	}
+}
+
+/* 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;
+
+	/* keep going until we've finished */
+	if (bio->bi_size)
+		return 1;
+
+	if (error && bio_data_dir(bio) == READ)
+		zero_fill_bio(bio);
+
+	dec_count(io, bio_get_region(bio), error);
+	bio_put(bio);
+
+	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.
+ *---------------------------------------------------------------*/
+struct dpages {
+	void (*get_page)(struct dpages *dp,
+			 struct page **p, unsigned long *len, unsigned *offset);
+	void (*next_page)(struct dpages *dp);
+
+	unsigned context_u;
+	void *context_ptr;
+};
+
+/*
+ * Functions for getting the pages from a list.
+ */
+static void list_get_page(struct dpages *dp,
+		  struct page **p, unsigned long *len, unsigned *offset)
+{
+	unsigned o = dp->context_u;
+	struct page_list *pl = (struct page_list *) dp->context_ptr;
+
+	*p = pl->page;
+	*len = PAGE_SIZE - o;
+	*offset = o;
+}
+
+static void list_next_page(struct dpages *dp)
+{
+	struct page_list *pl = (struct page_list *) dp->context_ptr;
+	dp->context_ptr = pl->next;
+	dp->context_u = 0;
+}
+
+static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offset)
+{
+	dp->get_page = list_get_page;
+	dp->next_page = list_next_page;
+	dp->context_u = offset;
+	dp->context_ptr = pl;
+}
+
+/*
+ * Functions for getting the pages from a bvec.
+ */
+static void bvec_get_page(struct dpages *dp,
+		  struct page **p, unsigned long *len, unsigned *offset)
+{
+	struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr;
+	*p = bvec->bv_page;
+	*len = bvec->bv_len;
+	*offset = bvec->bv_offset;
+}
+
+static void bvec_next_page(struct dpages *dp)
+{
+	struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr;
+	dp->context_ptr = bvec + 1;
+}
+
+static void bvec_dp_init(struct dpages *dp, struct bio_vec *bvec)
+{
+	dp->get_page = bvec_get_page;
+	dp->next_page = bvec_next_page;
+	dp->context_ptr = bvec;
+}
+
+static void vm_get_page(struct dpages *dp,
+		 struct page **p, unsigned long *len, unsigned *offset)
+{
+	*p = vmalloc_to_page(dp->context_ptr);
+	*offset = dp->context_u;
+	*len = PAGE_SIZE - dp->context_u;
+}
+
+static void vm_next_page(struct dpages *dp)
+{
+	dp->context_ptr += PAGE_SIZE - dp->context_u;
+	dp->context_u = 0;
+}
+
+static void vm_dp_init(struct dpages *dp, void *data)
+{
+	dp->get_page = vm_get_page;
+	dp->next_page = vm_next_page;
+	dp->context_u = ((unsigned long) data) & (PAGE_SIZE - 1);
+	dp->context_ptr = data;
+}
+
+/*-----------------------------------------------------------------
+ * IO routines that accept a list of pages.
+ *---------------------------------------------------------------*/
+static void do_region(int rw, unsigned int region, struct io_region *where,
+		      struct dpages *dp, struct io *io)
+{
+	struct bio *bio;
+	struct page *page;
+	unsigned long len;
+	unsigned offset;
+	unsigned num_bvecs;
+	sector_t remaining = where->count;
+
+	while (remaining) {
+		/*
+		 * Allocate a suitably sized bio, we add an extra
+		 * 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->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);
+
+		/*
+		 * Try and add as many pages as possible.
+		 */
+		while (remaining) {
+			dp->get_page(dp, &page, &len, &offset);
+			len = min(len, to_bytes(remaining));
+			if (!bio_add_page(bio, page, len, offset))
+				break;
+
+			offset = 0;
+			remaining -= to_sector(len);
+			dp->next_page(dp);
+		}
+
+		atomic_inc(&io->count);
+		submit_bio(rw, bio);
+	}
+}
+
+static void dispatch_io(int rw, unsigned int num_regions,
+			struct io_region *where, struct dpages *dp,
+			struct io *io, int sync)
+{
+	int i;
+	struct dpages old_pages = *dp;
+
+	if (sync)
+		rw |= (1 << BIO_RW_SYNC);
+
+	/*
+	 * For multiple regions we need to be careful to rewind
+	 * the dp object for each call to do_region.
+	 */
+	for (i = 0; i < num_regions; i++) {
+		*dp = old_pages;
+		if (where[i].count)
+			do_region(rw, i, where + i, dp, io);
+	}
+
+	/*
+	 * Drop the extra refence that we were holding to avoid
+	 * the io being completed too early.
+	 */
+	dec_count(io, 0, 0);
+}
+
+static int sync_io(unsigned int num_regions, struct io_region *where,
+	    int rw, struct dpages *dp, unsigned long *error_bits)
+{
+	struct io io;
+
+	if (num_regions > 1 && rw != WRITE) {
+		WARN_ON(1);
+		return -EIO;
+	}
+
+	io.error = 0;
+	atomic_set(&io.count, 1); /* see dispatch_io() */
+	io.sleeper = current;
+
+	dispatch_io(rw, num_regions, where, dp, &io, 1);
+
+	while (1) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+
+		if (!atomic_read(&io.count) || signal_pending(current))
+			break;
+
+		io_schedule();
+	}
+	set_current_state(TASK_RUNNING);
+
+	if (atomic_read(&io.count))
+		return -EINTR;
+
+	*error_bits = io.error;
+	return io.error ? -EIO : 0;
+}
+
+static int async_io(unsigned int num_regions, struct io_region *where, int rw,
+	     struct dpages *dp, io_notify_fn fn, void *context)
+{
+	struct io *io;
+
+	if (num_regions > 1 && rw != WRITE) {
+		WARN_ON(1);
+		fn(1, context);
+		return -EIO;
+	}
+
+	io = mempool_alloc(_io_pool, GFP_NOIO);
+	io->error = 0;
+	atomic_set(&io->count, 1); /* see dispatch_io() */
+	io->sleeper = NULL;
+	io->callback = fn;
+	io->context = context;
+
+	dispatch_io(rw, num_regions, where, dp, io, 0);
+	return 0;
+}
+
+int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
+	       struct page_list *pl, unsigned int offset,
+	       unsigned long *error_bits)
+{
+	struct dpages dp;
+	list_dp_init(&dp, pl, offset);
+	return sync_io(num_regions, where, rw, &dp, error_bits);
+}
+
+int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw,
+		    struct bio_vec *bvec, unsigned long *error_bits)
+{
+	struct dpages dp;
+	bvec_dp_init(&dp, bvec);
+	return sync_io(num_regions, where, rw, &dp, error_bits);
+}
+
+int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
+		  void *data, unsigned long *error_bits)
+{
+	struct dpages dp;
+	vm_dp_init(&dp, data);
+	return sync_io(num_regions, where, rw, &dp, error_bits);
+}
+
+int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
+		struct page_list *pl, unsigned int offset,
+		io_notify_fn fn, void *context)
+{
+	struct dpages dp;
+	list_dp_init(&dp, pl, offset);
+	return async_io(num_regions, where, rw, &dp, fn, context);
+}
+
+int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw,
+		     struct bio_vec *bvec, io_notify_fn fn, void *context)
+{
+	struct dpages dp;
+	bvec_dp_init(&dp, bvec);
+	return async_io(num_regions, where, rw, &dp, fn, context);
+}
+
+int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
+		   void *data, io_notify_fn fn, void *context)
+{
+	struct dpages dp;
+	vm_dp_init(&dp, data);
+	return async_io(num_regions, where, rw, &dp, fn, context);
+}
+
+EXPORT_SYMBOL(dm_io_get);
+EXPORT_SYMBOL(dm_io_put);
+EXPORT_SYMBOL(dm_io_sync);
+EXPORT_SYMBOL(dm_io_async);
+EXPORT_SYMBOL(dm_io_sync_bvec);
+EXPORT_SYMBOL(dm_io_async_bvec);
+EXPORT_SYMBOL(dm_io_sync_vm);
+EXPORT_SYMBOL(dm_io_async_vm);
diff -Nru a/drivers/md/dm-io.h b/drivers/md/dm-io.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-io.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2003 Sistina Software
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _DM_IO_H
+#define _DM_IO_H
+
+#include "dm.h"
+
+/* FIXME make this configurable */
+#define DM_MAX_IO_REGIONS 8
+
+struct io_region {
+	struct block_device *bdev;
+	sector_t sector;
+	sector_t count;
+};
+
+struct page_list {
+	struct page_list *next;
+	struct page *page;
+};
+
+
+/*
+ * 'error' is a bitset, with each bit indicating whether an error
+ * occurred doing io to the corresponding region.
+ */
+typedef void (*io_notify_fn)(unsigned long error, void *context);
+
+
+/*
+ * Before anyone uses the IO interface they should call
+ * dm_io_get(), specifying roughly how many pages they are
+ * expecting to perform io on concurrently.
+ *
+ * This function may block.
+ */
+int dm_io_get(unsigned int num_pages);
+void dm_io_put(unsigned int num_pages);
+
+/*
+ * Synchronous IO.
+ *
+ * Please ensure that the rw flag in the next two functions is
+ * either READ or WRITE, ie. we don't take READA.  Any
+ * regions with a zero count field will be ignored.
+ */
+int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
+	       struct page_list *pl, unsigned int offset,
+	       unsigned long *error_bits);
+
+int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw,
+		    struct bio_vec *bvec, unsigned long *error_bits);
+
+int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
+		  void *data, unsigned long *error_bits);
+
+/*
+ * Aynchronous IO.
+ *
+ * The 'where' array may be safely allocated on the stack since
+ * the function takes a copy.
+ */
+int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
+		struct page_list *pl, unsigned int offset,
+		io_notify_fn fn, void *context);
+
+int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw,
+		     struct bio_vec *bvec, io_notify_fn fn, void *context);
+
+int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
+		   void *data, io_notify_fn fn, void *context);
+
+#endif
diff -Nru a/drivers/md/dm-log.c b/drivers/md/dm-log.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-log.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,629 @@
+/*
+ * Copyright (C) 2003 Sistina Software
+ *
+ * This file is released under the LGPL.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include "dm-log.h"
+#include "dm-io.h"
+
+static LIST_HEAD(_log_types);
+static spinlock_t _lock = SPIN_LOCK_UNLOCKED;
+
+int dm_register_dirty_log_type(struct dirty_log_type *type)
+{
+	if (!try_module_get(type->module))
+		return -EINVAL;
+
+	spin_lock(&_lock);
+	type->use_count = 0;
+	list_add(&type->list, &_log_types);
+	spin_unlock(&_lock);
+
+	return 0;
+}
+
+int dm_unregister_dirty_log_type(struct dirty_log_type *type)
+{
+	spin_lock(&_lock);
+
+	if (type->use_count)
+		DMWARN("Attempt to unregister a log type that is still in use");
+	else {
+		list_del(&type->list);
+		module_put(type->module);
+	}
+
+	spin_unlock(&_lock);
+
+	return 0;
+}
+
+static struct dirty_log_type *get_type(const char *type_name)
+{
+	struct dirty_log_type *type;
+
+	spin_lock(&_lock);
+	list_for_each_entry (type, &_log_types, list)
+		if (!strcmp(type_name, type->name)) {
+			type->use_count++;
+			spin_unlock(&_lock);
+			return type;
+		}
+
+	spin_unlock(&_lock);
+	return NULL;
+}
+
+static void put_type(struct dirty_log_type *type)
+{
+	spin_lock(&_lock);
+	type->use_count--;
+	spin_unlock(&_lock);
+}
+
+struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
+				      unsigned int argc, char **argv)
+{
+	struct dirty_log_type *type;
+	struct dirty_log *log;
+
+	log = kmalloc(sizeof(*log), GFP_KERNEL);
+	if (!log)
+		return NULL;
+
+	type = get_type(type_name);
+	if (!type) {
+		kfree(log);
+		return NULL;
+	}
+
+	log->type = type;
+	if (type->ctr(log, ti, argc, argv)) {
+		kfree(log);
+		put_type(type);
+		return NULL;
+	}
+
+	return log;
+}
+
+void dm_destroy_dirty_log(struct dirty_log *log)
+{
+	log->type->dtr(log);
+	put_type(log->type);
+	kfree(log);
+}
+
+/*-----------------------------------------------------------------
+ * Persistent and core logs share a lot of their implementation.
+ * FIXME: need a reload method to be called from a resume
+ *---------------------------------------------------------------*/
+/*
+ * Magic for persistent mirrors: "MiRr"
+ */
+#define MIRROR_MAGIC 0x4D695272
+
+/*
+ * The on-disk version of the metadata.
+ */
+#define MIRROR_DISK_VERSION 1
+#define LOG_OFFSET 2
+
+struct log_header {
+	uint32_t magic;
+
+	/*
+	 * Simple, incrementing version. no backward
+	 * compatibility.
+	 */
+	uint32_t version;
+	sector_t nr_regions;
+};
+
+struct log_c {
+	struct dm_target *ti;
+	int touched;
+	sector_t region_size;
+	unsigned int region_count;
+	region_t sync_count;
+
+	unsigned bitset_uint32_count;
+	uint32_t *clean_bits;
+	uint32_t *sync_bits;
+	uint32_t *recovering_bits;	/* FIXME: this seems excessive */
+
+	int sync_search;
+
+	/*
+	 * Disk log fields
+	 */
+	struct dm_dev *log_dev;
+	struct log_header header;
+
+	struct io_region header_location;
+	struct log_header *disk_header;
+
+	struct io_region bits_location;
+	uint32_t *disk_bits;
+};
+
+/*
+ * The touched member needs to be updated every time we access
+ * one of the bitsets.
+ */
+static  inline int log_test_bit(uint32_t *bs, unsigned bit)
+{
+	return test_bit(bit, (unsigned long *) bs) ? 1 : 0;
+}
+
+static inline void log_set_bit(struct log_c *l,
+			       uint32_t *bs, unsigned bit)
+{
+	set_bit(bit, (unsigned long *) bs);
+	l->touched = 1;
+}
+
+static inline void log_clear_bit(struct log_c *l,
+				 uint32_t *bs, unsigned bit)
+{
+	clear_bit(bit, (unsigned long *) bs);
+	l->touched = 1;
+}
+
+/*----------------------------------------------------------------
+ * Header IO
+ *--------------------------------------------------------------*/
+static void header_to_disk(struct log_header *core, struct log_header *disk)
+{
+	disk->magic = cpu_to_le32(core->magic);
+	disk->version = cpu_to_le32(core->version);
+	disk->nr_regions = cpu_to_le64(core->nr_regions);
+}
+
+static void header_from_disk(struct log_header *core, struct log_header *disk)
+{
+	core->magic = le32_to_cpu(disk->magic);
+	core->version = le32_to_cpu(disk->version);
+	core->nr_regions = le64_to_cpu(disk->nr_regions);
+}
+
+static int read_header(struct log_c *log)
+{
+	int r;
+	unsigned long ebits;
+
+	r = dm_io_sync_vm(1, &log->header_location, READ,
+			  log->disk_header, &ebits);
+	if (r)
+		return r;
+
+	header_from_disk(&log->header, log->disk_header);
+
+	if (log->header.magic != MIRROR_MAGIC) {
+		log->header.magic = MIRROR_MAGIC;
+		log->header.version = MIRROR_DISK_VERSION;
+		log->header.nr_regions = 0;
+	}
+
+	if (log->header.version != MIRROR_DISK_VERSION) {
+		DMWARN("incompatible disk log version");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static inline int write_header(struct log_c *log)
+{
+	unsigned long ebits;
+
+	header_to_disk(&log->header, log->disk_header);
+	return dm_io_sync_vm(1, &log->header_location, WRITE,
+			     log->disk_header, &ebits);
+}
+
+/*----------------------------------------------------------------
+ * Bits IO
+ *--------------------------------------------------------------*/
+static inline void bits_to_core(uint32_t *core, uint32_t *disk, unsigned count)
+{
+	unsigned i;
+
+	for (i = 0; i < count; i++)
+		core[i] = le32_to_cpu(disk[i]);
+}
+
+static inline void bits_to_disk(uint32_t *core, uint32_t *disk, unsigned count)
+{
+	unsigned i;
+
+	/* copy across the clean/dirty bitset */
+	for (i = 0; i < count; i++)
+		disk[i] = cpu_to_le32(core[i]);
+}
+
+static int read_bits(struct log_c *log)
+{
+	int r;
+	unsigned long ebits;
+
+	r = dm_io_sync_vm(1, &log->bits_location, READ,
+			  log->disk_bits, &ebits);
+	if (r)
+		return r;
+
+	bits_to_core(log->clean_bits, log->disk_bits,
+		     log->bitset_uint32_count);
+	return 0;
+}
+
+static int write_bits(struct log_c *log)
+{
+	unsigned long ebits;
+	bits_to_disk(log->clean_bits, log->disk_bits,
+		     log->bitset_uint32_count);
+	return dm_io_sync_vm(1, &log->bits_location, WRITE,
+			     log->disk_bits, &ebits);
+}
+
+/*----------------------------------------------------------------
+ * constructor/destructor
+ *--------------------------------------------------------------*/
+#define BYTE_SHIFT 3
+static int core_ctr(struct dirty_log *log, struct dm_target *ti,
+		    unsigned int argc, char **argv)
+{
+	struct log_c *lc;
+	sector_t region_size;
+	unsigned int region_count;
+	size_t bitset_size;
+
+	if (argc != 1) {
+		DMWARN("wrong number of arguments to log_c");
+		return -EINVAL;
+	}
+
+	if (sscanf(argv[0], SECTOR_FORMAT, &region_size) != 1) {
+		DMWARN("invalid region size string");
+		return -EINVAL;
+	}
+
+	region_count = dm_div_up(ti->len, region_size);
+
+	lc = kmalloc(sizeof(*lc), GFP_KERNEL);
+	if (!lc) {
+		DMWARN("couldn't allocate core log");
+		return -ENOMEM;
+	}
+
+	lc->ti = ti;
+	lc->touched = 0;
+	lc->region_size = region_size;
+	lc->region_count = region_count;
+
+	/*
+	 * Work out how many words we need to hold the bitset.
+	 */
+	bitset_size = dm_round_up(region_count,
+				  sizeof(*lc->clean_bits) << BYTE_SHIFT);
+	bitset_size >>= BYTE_SHIFT;
+
+	lc->bitset_uint32_count = bitset_size / 4;
+	lc->clean_bits = vmalloc(bitset_size);
+	if (!lc->clean_bits) {
+		DMWARN("couldn't allocate clean bitset");
+		kfree(lc);
+		return -ENOMEM;
+	}
+	memset(lc->clean_bits, -1, bitset_size);
+
+	lc->sync_bits = vmalloc(bitset_size);
+	if (!lc->sync_bits) {
+		DMWARN("couldn't allocate sync bitset");
+		vfree(lc->clean_bits);
+		kfree(lc);
+		return -ENOMEM;
+	}
+	memset(lc->sync_bits, 0, bitset_size);
+        lc->sync_count = 0;
+
+	lc->recovering_bits = vmalloc(bitset_size);
+	if (!lc->recovering_bits) {
+		DMWARN("couldn't allocate sync bitset");
+		vfree(lc->sync_bits);
+		vfree(lc->clean_bits);
+		kfree(lc);
+		return -ENOMEM;
+	}
+	memset(lc->recovering_bits, 0, bitset_size);
+	lc->sync_search = 0;
+	log->context = lc;
+	return 0;
+}
+
+static void core_dtr(struct dirty_log *log)
+{
+	struct log_c *lc = (struct log_c *) log->context;
+	vfree(lc->clean_bits);
+	vfree(lc->sync_bits);
+	vfree(lc->recovering_bits);
+	kfree(lc);
+}
+
+static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
+		    unsigned int argc, char **argv)
+{
+	int r;
+	size_t size;
+	struct log_c *lc;
+	struct dm_dev *dev;
+
+	if (argc != 2) {
+		DMWARN("wrong number of arguments to log_d");
+		return -EINVAL;
+	}
+
+	r = dm_get_device(ti, argv[0], 0, 0 /* FIXME */,
+			  FMODE_READ | FMODE_WRITE, &dev);
+	if (r)
+		return r;
+
+	r = core_ctr(log, ti, argc - 1, argv + 1);
+	if (r) {
+		dm_put_device(ti, dev);
+		return r;
+	}
+
+	lc = (struct log_c *) log->context;
+	lc->log_dev = dev;
+
+	/* setup the disk header fields */
+	lc->header_location.bdev = lc->log_dev->bdev;
+	lc->header_location.sector = 0;
+	lc->header_location.count = 1;
+
+	/*
+	 * We can't read less than this amount, even though we'll
+	 * not be using most of this space.
+	 */
+	lc->disk_header = vmalloc(1 << SECTOR_SHIFT);
+	if (!lc->disk_header)
+		goto bad;
+
+	/* setup the disk bitset fields */
+	lc->bits_location.bdev = lc->log_dev->bdev;
+	lc->bits_location.sector = LOG_OFFSET;
+
+	size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t),
+			   1 << SECTOR_SHIFT);
+	lc->bits_location.count = size >> SECTOR_SHIFT;
+	lc->disk_bits = vmalloc(size);
+	if (!lc->disk_bits) {
+		vfree(lc->disk_header);
+		goto bad;
+	}
+	return 0;
+
+ bad:
+	dm_put_device(ti, lc->log_dev);
+	core_dtr(log);
+	return -ENOMEM;
+}
+
+static void disk_dtr(struct dirty_log *log)
+{
+	struct log_c *lc = (struct log_c *) log->context;
+	dm_put_device(lc->ti, lc->log_dev);
+	vfree(lc->disk_header);
+	vfree(lc->disk_bits);
+	core_dtr(log);
+}
+
+static int count_bits32(uint32_t *addr, unsigned size)
+{
+	int count = 0, i;
+
+	for (i = 0; i < size; i++) {
+		count += hweight32(*(addr+i));
+	}
+	return count;
+}
+
+static int disk_resume(struct dirty_log *log)
+{
+	int r;
+	unsigned i;
+	struct log_c *lc = (struct log_c *) log->context;
+	size_t size = lc->bitset_uint32_count * sizeof(uint32_t);
+
+	/* read the disk header */
+	r = read_header(lc);
+	if (r)
+		return r;
+
+	/* read the bits */
+	r = read_bits(lc);
+	if (r)
+		return r;
+
+	/* zero any new bits if the mirror has grown */
+	for (i = lc->header.nr_regions; i < lc->region_count; i++)
+		/* FIXME: amazingly inefficient */
+		log_clear_bit(lc, lc->clean_bits, i);
+
+	/* copy clean across to sync */
+	memcpy(lc->sync_bits, lc->clean_bits, size);
+	lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count);
+
+	/* write the bits */
+	r = write_bits(lc);
+	if (r)
+		return r;
+
+	/* set the correct number of regions in the header */
+	lc->header.nr_regions = lc->region_count;
+
+	/* write the new header */
+	return write_header(lc);
+}
+
+static sector_t core_get_region_size(struct dirty_log *log)
+{
+	struct log_c *lc = (struct log_c *) log->context;
+	return lc->region_size;
+}
+
+static int core_is_clean(struct dirty_log *log, region_t region)
+{
+	struct log_c *lc = (struct log_c *) log->context;
+	return log_test_bit(lc->clean_bits, region);
+}
+
+static int core_in_sync(struct dirty_log *log, region_t region, int block)
+{
+	struct log_c *lc = (struct log_c *) log->context;
+	return log_test_bit(lc->sync_bits, region);
+}
+
+static int core_flush(struct dirty_log *log)
+{
+	/* no op */
+	return 0;
+}
+
+static int disk_flush(struct dirty_log *log)
+{
+	int r;
+	struct log_c *lc = (struct log_c *) log->context;
+
+	/* only write if the log has changed */
+	if (!lc->touched)
+		return 0;
+
+	r = write_bits(lc);
+	if (!r)
+		lc->touched = 0;
+
+	return r;
+}
+
+static void core_mark_region(struct dirty_log *log, region_t region)
+{
+	struct log_c *lc = (struct log_c *) log->context;
+	log_clear_bit(lc, lc->clean_bits, region);
+}
+
+static void core_clear_region(struct dirty_log *log, region_t region)
+{
+	struct log_c *lc = (struct log_c *) log->context;
+	log_set_bit(lc, lc->clean_bits, region);
+}
+
+static int core_get_resync_work(struct dirty_log *log, region_t *region)
+{
+	struct log_c *lc = (struct log_c *) log->context;
+
+	if (lc->sync_search >= lc->region_count)
+		return 0;
+
+	do {
+		*region = find_next_zero_bit((unsigned long *) lc->sync_bits,
+					     lc->region_count,
+					     lc->sync_search);
+		lc->sync_search = *region + 1;
+
+		if (*region == lc->region_count)
+			return 0;
+
+	} while (log_test_bit(lc->recovering_bits, *region));
+
+	log_set_bit(lc, lc->recovering_bits, *region);
+	return 1;
+}
+
+static void core_complete_resync_work(struct dirty_log *log, region_t region,
+				      int success)
+{
+	struct log_c *lc = (struct log_c *) log->context;
+
+	log_clear_bit(lc, lc->recovering_bits, region);
+	if (success) {
+		log_set_bit(lc, lc->sync_bits, region);
+                lc->sync_count++;
+        }
+}
+
+static region_t core_get_sync_count(struct dirty_log *log)
+{
+        struct log_c *lc = (struct log_c *) log->context;
+
+        return lc->sync_count;
+}
+
+static struct dirty_log_type _core_type = {
+	.name = "core",
+	.module = THIS_MODULE,
+	.ctr = core_ctr,
+	.dtr = core_dtr,
+	.get_region_size = core_get_region_size,
+	.is_clean = core_is_clean,
+	.in_sync = core_in_sync,
+	.flush = core_flush,
+	.mark_region = core_mark_region,
+	.clear_region = core_clear_region,
+	.get_resync_work = core_get_resync_work,
+	.complete_resync_work = core_complete_resync_work,
+        .get_sync_count = core_get_sync_count
+};
+
+static struct dirty_log_type _disk_type = {
+	.name = "disk",
+	.module = THIS_MODULE,
+	.ctr = disk_ctr,
+	.dtr = disk_dtr,
+	.suspend = disk_flush,
+	.resume = disk_resume,
+	.get_region_size = core_get_region_size,
+	.is_clean = core_is_clean,
+	.in_sync = core_in_sync,
+	.flush = disk_flush,
+	.mark_region = core_mark_region,
+	.clear_region = core_clear_region,
+	.get_resync_work = core_get_resync_work,
+	.complete_resync_work = core_complete_resync_work,
+        .get_sync_count = core_get_sync_count
+};
+
+int __init dm_dirty_log_init(void)
+{
+	int r;
+
+	r = dm_register_dirty_log_type(&_core_type);
+	if (r)
+		DMWARN("couldn't register core log");
+
+	r = dm_register_dirty_log_type(&_disk_type);
+	if (r) {
+		DMWARN("couldn't register disk type");
+		dm_unregister_dirty_log_type(&_core_type);
+	}
+
+	return r;
+}
+
+void dm_dirty_log_exit(void)
+{
+	dm_unregister_dirty_log_type(&_disk_type);
+	dm_unregister_dirty_log_type(&_core_type);
+}
+
+EXPORT_SYMBOL(dm_register_dirty_log_type);
+EXPORT_SYMBOL(dm_unregister_dirty_log_type);
+EXPORT_SYMBOL(dm_create_dirty_log);
+EXPORT_SYMBOL(dm_destroy_dirty_log);
diff -Nru a/drivers/md/dm-log.h b/drivers/md/dm-log.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-log.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2003 Sistina Software
+ *
+ * This file is released under the LGPL.
+ */
+
+#ifndef DM_DIRTY_LOG
+#define DM_DIRTY_LOG
+
+#include "dm.h"
+
+typedef sector_t region_t;
+
+struct dirty_log_type;
+
+struct dirty_log {
+	struct dirty_log_type *type;
+	void *context;
+};
+
+struct dirty_log_type {
+	struct list_head list;
+	const char *name;
+	struct module *module;
+	unsigned int use_count;
+
+	int (*ctr)(struct dirty_log *log, struct dm_target *ti,
+		   unsigned int argc, char **argv);
+	void (*dtr)(struct dirty_log *log);
+
+	/*
+	 * There are times when we don't want the log to touch
+	 * the disk.
+	 */
+	int (*suspend)(struct dirty_log *log);
+	int (*resume)(struct dirty_log *log);
+
+	/*
+	 * Retrieves the smallest size of region that the log can
+	 * deal with.
+	 */
+	sector_t (*get_region_size)(struct dirty_log *log);
+
+        /*
+	 * A predicate to say whether a region is clean or not.
+	 * May block.
+	 */
+	int (*is_clean)(struct dirty_log *log, region_t region);
+
+	/*
+	 *  Returns: 0, 1, -EWOULDBLOCK, < 0
+	 *
+	 * A predicate function to check the area given by
+	 * [sector, sector + len) is in sync.
+	 *
+	 * If -EWOULDBLOCK is returned the state of the region is
+	 * unknown, typically this will result in a read being
+	 * passed to a daemon to deal with, since a daemon is
+	 * allowed to block.
+	 */
+	int (*in_sync)(struct dirty_log *log, region_t region, int can_block);
+
+	/*
+	 * Flush the current log state (eg, to disk).  This
+	 * function may block.
+	 */
+	int (*flush)(struct dirty_log *log);
+
+	/*
+	 * Mark an area as clean or dirty.  These functions may
+	 * block, though for performance reasons blocking should
+	 * be extremely rare (eg, allocating another chunk of
+	 * memory for some reason).
+	 */
+	void (*mark_region)(struct dirty_log *log, region_t region);
+	void (*clear_region)(struct dirty_log *log, region_t region);
+
+	/*
+	 * Returns: <0 (error), 0 (no region), 1 (region)
+	 *
+	 * The mirrord will need perform recovery on regions of
+	 * the mirror that are in the NOSYNC state.  This
+	 * function asks the log to tell the caller about the
+	 * next region that this machine should recover.
+	 *
+	 * Do not confuse this function with 'in_sync()', one
+	 * tells you if an area is synchronised, the other
+	 * assigns recovery work.
+	*/
+	int (*get_resync_work)(struct dirty_log *log, region_t *region);
+
+	/*
+	 * This notifies the log that the resync of an area has
+	 * been completed.  The log should then mark this region
+	 * as CLEAN.
+	 */
+	void (*complete_resync_work)(struct dirty_log *log,
+				     region_t region, int success);
+
+        /*
+	 * Returns the number of regions that are in sync.
+         */
+        region_t (*get_sync_count)(struct dirty_log *log);
+};
+
+int dm_register_dirty_log_type(struct dirty_log_type *type);
+int dm_unregister_dirty_log_type(struct dirty_log_type *type);
+
+
+/*
+ * Make sure you use these two functions, rather than calling
+ * type->constructor/destructor() directly.
+ */
+struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
+				      unsigned int argc, char **argv);
+void dm_destroy_dirty_log(struct dirty_log *log);
+
+/*
+ * init/exit functions.
+ */
+int dm_dirty_log_init(void);
+void dm_dirty_log_exit(void);
+
+#endif
diff -Nru a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-raid1.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,1278 @@
+/*
+ * Copyright (C) 2003 Sistina Software Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+#include "dm-bio-list.h"
+#include "dm-io.h"
+#include "dm-log.h"
+#include "kcopyd.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/vmalloc.h>
+#include <linux/workqueue.h>
+
+static struct workqueue_struct *_kmirrord_wq;
+static struct work_struct _kmirrord_work;
+
+static inline void wake(void)
+{
+	queue_work(_kmirrord_wq, &_kmirrord_work);
+}
+
+/*-----------------------------------------------------------------
+ * Region hash
+ *
+ * The mirror splits itself up into discrete regions.  Each
+ * region can be in one of three states: clean, dirty,
+ * nosync.  There is no need to put clean regions in the hash.
+ *
+ * In addition to being present in the hash table a region _may_
+ * be present on one of three lists.
+ *
+ *   clean_regions: Regions on this list have no io pending to
+ *   them, they are in sync, we are no longer interested in them,
+ *   they are dull.  rh_update_states() will remove them from the
+ *   hash table.
+ *
+ *   quiesced_regions: These regions have been spun down, ready
+ *   for recovery.  rh_recovery_start() will remove regions from
+ *   this list and hand them to kmirrord, which will schedule the
+ *   recovery io with kcopyd.
+ *
+ *   recovered_regions: Regions that kcopyd has successfully
+ *   recovered.  rh_update_states() will now schedule any delayed
+ *   io, up the recovery_count, and remove the region from the
+ *   hash.
+ *
+ * There are 2 locks:
+ *   A rw spin lock 'hash_lock' protects just the hash table,
+ *   this is never held in write mode from interrupt context,
+ *   which I believe means that we only have to disable irqs when
+ *   doing a write lock.
+ *
+ *   An ordinary spin lock 'region_lock' that protects the three
+ *   lists in the region_hash, with the 'state', 'list' and
+ *   'bhs_delayed' fields of the regions.  This is used from irq
+ *   context, so all other uses will have to suspend local irqs.
+ *---------------------------------------------------------------*/
+struct mirror_set;
+struct region_hash {
+	struct mirror_set *ms;
+	sector_t region_size;
+	unsigned region_shift;
+
+	/* holds persistent region state */
+	struct dirty_log *log;
+
+	/* hash table */
+	rwlock_t hash_lock;
+	mempool_t *region_pool;
+	unsigned int mask;
+	unsigned int nr_buckets;
+	struct list_head *buckets;
+
+	spinlock_t region_lock;
+	struct semaphore recovery_count;
+	struct list_head clean_regions;
+	struct list_head quiesced_regions;
+	struct list_head recovered_regions;
+};
+
+enum {
+	RH_CLEAN,
+	RH_DIRTY,
+	RH_NOSYNC,
+	RH_RECOVERING
+};
+
+struct region {
+	struct region_hash *rh;	/* FIXME: can we get rid of this ? */
+	region_t key;
+	int state;
+
+	struct list_head hash_list;
+	struct list_head list;
+
+	atomic_t pending;
+	struct bio_list delayed_bios;
+};
+
+/*
+ * Conversion fns
+ */
+static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio)
+{
+	return bio->bi_sector >> rh->region_shift;
+}
+
+static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
+{
+	return region << rh->region_shift;
+}
+
+/* FIXME move this */
+static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
+
+static void *region_alloc(int gfp_mask, void *pool_data)
+{
+	return kmalloc(sizeof(struct region), gfp_mask);
+}
+
+static void region_free(void *element, void *pool_data)
+{
+	kfree(element);
+}
+
+#define MIN_REGIONS 64
+#define MAX_RECOVERY 1
+static int rh_init(struct region_hash *rh, struct mirror_set *ms,
+		   struct dirty_log *log, sector_t region_size,
+		   region_t nr_regions)
+{
+	unsigned int nr_buckets, max_buckets;
+	size_t i;
+
+	/*
+	 * Calculate a suitable number of buckets for our hash
+	 * table.
+	 */
+	max_buckets = nr_regions >> 6;
+	for (nr_buckets = 128u; nr_buckets < max_buckets; nr_buckets <<= 1)
+		;
+	nr_buckets >>= 1;
+
+	rh->ms = ms;
+	rh->log = log;
+	rh->region_size = region_size;
+	rh->region_shift = ffs(region_size) - 1;
+	rwlock_init(&rh->hash_lock);
+	rh->mask = nr_buckets - 1;
+	rh->nr_buckets = nr_buckets;
+
+	rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets));
+	if (!rh->buckets) {
+		DMERR("unable to allocate region hash memory");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < nr_buckets; i++)
+		INIT_LIST_HEAD(rh->buckets + i);
+
+	spin_lock_init(&rh->region_lock);
+	sema_init(&rh->recovery_count, 0);
+	INIT_LIST_HEAD(&rh->clean_regions);
+	INIT_LIST_HEAD(&rh->quiesced_regions);
+	INIT_LIST_HEAD(&rh->recovered_regions);
+
+	rh->region_pool = mempool_create(MIN_REGIONS, region_alloc,
+					 region_free, NULL);
+	if (!rh->region_pool) {
+		vfree(rh->buckets);
+		rh->buckets = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void rh_exit(struct region_hash *rh)
+{
+	unsigned int h;
+	struct region *reg, *nreg;
+
+	BUG_ON(!list_empty(&rh->quiesced_regions));
+	for (h = 0; h < rh->nr_buckets; h++) {
+		list_for_each_entry_safe(reg, nreg, rh->buckets + h, hash_list) {
+			BUG_ON(atomic_read(&reg->pending));
+			mempool_free(reg, rh->region_pool);
+		}
+	}
+
+	if (rh->log)
+		dm_destroy_dirty_log(rh->log);
+	if (rh->region_pool)
+		mempool_destroy(rh->region_pool);
+	vfree(rh->buckets);
+}
+
+#define RH_HASH_MULT 2654435387U
+
+static inline unsigned int rh_hash(struct region_hash *rh, region_t region)
+{
+	return (unsigned int) ((region * RH_HASH_MULT) >> 12) & rh->mask;
+}
+
+static struct region *__rh_lookup(struct region_hash *rh, region_t region)
+{
+	struct region *reg;
+
+	list_for_each_entry (reg, rh->buckets + rh_hash(rh, region), hash_list)
+		if (reg->key == region)
+			return reg;
+
+	return NULL;
+}
+
+static void __rh_insert(struct region_hash *rh, struct region *reg)
+{
+	unsigned int h = rh_hash(rh, reg->key);
+	list_add(&reg->hash_list, rh->buckets + h);
+}
+
+static struct region *__rh_alloc(struct region_hash *rh, region_t region)
+{
+	struct region *reg, *nreg;
+
+	read_unlock(&rh->hash_lock);
+	nreg = mempool_alloc(rh->region_pool, GFP_NOIO);
+	nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
+		RH_CLEAN : RH_NOSYNC;
+	nreg->rh = rh;
+	nreg->key = region;
+
+	INIT_LIST_HEAD(&nreg->list);
+
+	atomic_set(&nreg->pending, 0);
+	bio_list_init(&nreg->delayed_bios);
+	write_lock_irq(&rh->hash_lock);
+
+	reg = __rh_lookup(rh, region);
+	if (reg)
+		/* we lost the race */
+		mempool_free(nreg, rh->region_pool);
+
+	else {
+		__rh_insert(rh, nreg);
+		if (nreg->state == RH_CLEAN) {
+			spin_lock_irq(&rh->region_lock);
+			list_add(&nreg->list, &rh->clean_regions);
+			spin_unlock_irq(&rh->region_lock);
+		}
+		reg = nreg;
+	}
+	write_unlock_irq(&rh->hash_lock);
+	read_lock(&rh->hash_lock);
+
+	return reg;
+}
+
+static inline struct region *__rh_find(struct region_hash *rh, region_t region)
+{
+	struct region *reg;
+
+	reg = __rh_lookup(rh, region);
+	if (!reg)
+		reg = __rh_alloc(rh, region);
+
+	return reg;
+}
+
+static int rh_state(struct region_hash *rh, region_t region, int may_block)
+{
+	int r;
+	struct region *reg;
+
+	read_lock(&rh->hash_lock);
+	reg = __rh_lookup(rh, region);
+	read_unlock(&rh->hash_lock);
+
+	if (reg)
+		return reg->state;
+
+	/*
+	 * The region wasn't in the hash, so we fall back to the
+	 * dirty log.
+	 */
+	r = rh->log->type->in_sync(rh->log, region, may_block);
+
+	/*
+	 * Any error from the dirty log (eg. -EWOULDBLOCK) gets
+	 * taken as a RH_NOSYNC
+	 */
+	return r == 1 ? RH_CLEAN : RH_NOSYNC;
+}
+
+static inline int rh_in_sync(struct region_hash *rh,
+			     region_t region, int may_block)
+{
+	int state = rh_state(rh, region, may_block);
+	return state == RH_CLEAN || state == RH_DIRTY;
+}
+
+static void dispatch_bios(struct mirror_set *ms, struct bio_list *bio_list)
+{
+	struct bio *bio;
+
+	while ((bio = bio_list_pop(bio_list))) {
+		queue_bio(ms, bio, WRITE);
+	}
+}
+
+static void rh_update_states(struct region_hash *rh)
+{
+	struct region *reg, *next;
+
+	LIST_HEAD(clean);
+	LIST_HEAD(recovered);
+
+	/*
+	 * Quickly grab the lists.
+	 */
+	write_lock_irq(&rh->hash_lock);
+	spin_lock(&rh->region_lock);
+	if (!list_empty(&rh->clean_regions)) {
+		list_splice(&rh->clean_regions, &clean);
+		INIT_LIST_HEAD(&rh->clean_regions);
+
+		list_for_each_entry (reg, &clean, list) {
+			rh->log->type->clear_region(rh->log, reg->key);
+			list_del(&reg->hash_list);
+		}
+	}
+
+	if (!list_empty(&rh->recovered_regions)) {
+		list_splice(&rh->recovered_regions, &recovered);
+		INIT_LIST_HEAD(&rh->recovered_regions);
+
+		list_for_each_entry (reg, &recovered, list)
+			list_del(&reg->hash_list);
+	}
+	spin_unlock(&rh->region_lock);
+	write_unlock_irq(&rh->hash_lock);
+
+	/*
+	 * All the regions on the recovered and clean lists have
+	 * now been pulled out of the system, so no need to do
+	 * any more locking.
+	 */
+	list_for_each_entry_safe (reg, next, &recovered, list) {
+		rh->log->type->clear_region(rh->log, reg->key);
+		rh->log->type->complete_resync_work(rh->log, reg->key, 1);
+		dispatch_bios(rh->ms, &reg->delayed_bios);
+		up(&rh->recovery_count);
+		mempool_free(reg, rh->region_pool);
+	}
+
+	if (!list_empty(&recovered))
+		rh->log->type->flush(rh->log);
+
+	list_for_each_entry_safe (reg, next, &clean, list)
+		mempool_free(reg, rh->region_pool);
+}
+
+static void rh_inc(struct region_hash *rh, region_t region)
+{
+	struct region *reg;
+
+	read_lock(&rh->hash_lock);
+	reg = __rh_find(rh, region);
+	if (reg->state == RH_CLEAN) {
+		rh->log->type->mark_region(rh->log, reg->key);
+
+		spin_lock_irq(&rh->region_lock);
+		reg->state = RH_DIRTY;
+		list_del_init(&reg->list);	/* take off the clean list */
+		spin_unlock_irq(&rh->region_lock);
+	}
+
+	atomic_inc(&reg->pending);
+	read_unlock(&rh->hash_lock);
+}
+
+static void rh_inc_pending(struct region_hash *rh, struct bio_list *bios)
+{
+	struct bio *bio;
+
+	for (bio = bios->head; bio; bio = bio->bi_next)
+		rh_inc(rh, bio_to_region(rh, bio));
+}
+
+static void rh_dec(struct region_hash *rh, region_t region)
+{
+	unsigned long flags;
+	struct region *reg;
+	int should_wake = 0;
+
+	read_lock(&rh->hash_lock);
+	reg = __rh_lookup(rh, region);
+	read_unlock(&rh->hash_lock);
+
+	if (atomic_dec_and_test(&reg->pending)) {
+		spin_lock_irqsave(&rh->region_lock, flags);
+		if (reg->state == RH_RECOVERING) {
+			list_add_tail(&reg->list, &rh->quiesced_regions);
+		} else {
+			reg->state = RH_CLEAN;
+			list_add(&reg->list, &rh->clean_regions);
+		}
+		spin_unlock_irqrestore(&rh->region_lock, flags);
+		should_wake = 1;
+	}
+
+	if (should_wake)
+		wake();
+}
+
+/*
+ * Starts quiescing a region in preparation for recovery.
+ */
+static int __rh_recovery_prepare(struct region_hash *rh)
+{
+	int r;
+	struct region *reg;
+	region_t region;
+
+	/*
+	 * Ask the dirty log what's next.
+	 */
+	r = rh->log->type->get_resync_work(rh->log, &region);
+	if (r <= 0)
+		return r;
+
+	/*
+	 * Get this region, and start it quiescing by setting the
+	 * recovering flag.
+	 */
+	read_lock(&rh->hash_lock);
+	reg = __rh_find(rh, region);
+	read_unlock(&rh->hash_lock);
+
+	spin_lock_irq(&rh->region_lock);
+	reg->state = RH_RECOVERING;
+
+	/* Already quiesced ? */
+	if (atomic_read(&reg->pending))
+		list_del_init(&reg->list);
+
+	else {
+		list_del_init(&reg->list);
+		list_add(&reg->list, &rh->quiesced_regions);
+	}
+	spin_unlock_irq(&rh->region_lock);
+
+	return 1;
+}
+
+static void rh_recovery_prepare(struct region_hash *rh)
+{
+	while (!down_trylock(&rh->recovery_count))
+		if (__rh_recovery_prepare(rh) <= 0) {
+			up(&rh->recovery_count);
+			break;
+		}
+}
+
+/*
+ * Returns any quiesced regions.
+ */
+static struct region *rh_recovery_start(struct region_hash *rh)
+{
+	struct region *reg = NULL;
+
+	spin_lock_irq(&rh->region_lock);
+	if (!list_empty(&rh->quiesced_regions)) {
+		reg = list_entry(rh->quiesced_regions.next,
+				 struct region, list);
+		list_del_init(&reg->list);	/* remove from the quiesced list */
+	}
+	spin_unlock_irq(&rh->region_lock);
+
+	return reg;
+}
+
+/* FIXME: success ignored for now */
+static void rh_recovery_end(struct region *reg, int success)
+{
+	struct region_hash *rh = reg->rh;
+
+	spin_lock_irq(&rh->region_lock);
+	list_add(&reg->list, &reg->rh->recovered_regions);
+	spin_unlock_irq(&rh->region_lock);
+
+	wake();
+}
+
+static void rh_flush(struct region_hash *rh)
+{
+	rh->log->type->flush(rh->log);
+}
+
+static void rh_delay(struct region_hash *rh, struct bio *bio)
+{
+	struct region *reg;
+
+	read_lock(&rh->hash_lock);
+	reg = __rh_find(rh, bio_to_region(rh, bio));
+	bio_list_add(&reg->delayed_bios, bio);
+	read_unlock(&rh->hash_lock);
+}
+
+static void rh_stop_recovery(struct region_hash *rh)
+{
+	int i;
+
+	/* wait for any recovering regions */
+	for (i = 0; i < MAX_RECOVERY; i++)
+		down(&rh->recovery_count);
+}
+
+static void rh_start_recovery(struct region_hash *rh)
+{
+	int i;
+
+	for (i = 0; i < MAX_RECOVERY; i++)
+		up(&rh->recovery_count);
+
+	wake();
+}
+
+/*-----------------------------------------------------------------
+ * Mirror set structures.
+ *---------------------------------------------------------------*/
+struct mirror {
+	atomic_t error_count;
+	struct dm_dev *dev;
+	sector_t offset;
+};
+
+struct mirror_set {
+	struct dm_target *ti;
+	struct list_head list;
+	struct region_hash rh;
+	struct kcopyd_client *kcopyd_client;
+
+	spinlock_t lock;	/* protects the next two lists */
+	struct bio_list reads;
+	struct bio_list writes;
+
+	/* recovery */
+	region_t nr_regions;
+	int in_sync;
+
+	unsigned int nr_mirrors;
+	struct mirror mirror[0];
+};
+
+/*
+ * Every mirror should look like this one.
+ */
+#define DEFAULT_MIRROR 0
+
+/*
+ * This is yucky.  We squirrel the mirror_set struct away inside
+ * bi_next for write buffers.  This is safe since the bh
+ * doesn't get submitted to the lower levels of block layer.
+ */
+static struct mirror_set *bio_get_ms(struct bio *bio)
+{
+	return (struct mirror_set *) bio->bi_next;
+}
+
+static void bio_set_ms(struct bio *bio, struct mirror_set *ms)
+{
+	bio->bi_next = (struct bio *) ms;
+}
+
+/*-----------------------------------------------------------------
+ * Recovery.
+ *
+ * When a mirror is first activated we may find that some regions
+ * are in the no-sync state.  We have to recover these by
+ * recopying from the default mirror to all the others.
+ *---------------------------------------------------------------*/
+static void recovery_complete(int read_err, unsigned int write_err,
+			      void *context)
+{
+	struct region *reg = (struct region *) context;
+
+	/* FIXME: better error handling */
+	rh_recovery_end(reg, read_err || write_err);
+}
+
+static int recover(struct mirror_set *ms, struct region *reg)
+{
+	int r;
+	unsigned int i;
+	struct io_region from, to[ms->nr_mirrors - 1], *dest;
+	struct mirror *m;
+	unsigned long flags = 0;
+
+	/* fill in the source */
+	m = ms->mirror + DEFAULT_MIRROR;
+	from.bdev = m->dev->bdev;
+	from.sector = m->offset + region_to_sector(reg->rh, reg->key);
+	if (reg->key == (ms->nr_regions - 1)) {
+		/*
+		 * The final region may be smaller than
+		 * region_size.
+		 */
+		from.count = ms->ti->len & (reg->rh->region_size - 1);
+		if (!from.count)
+			from.count = reg->rh->region_size;
+	} else
+		from.count = reg->rh->region_size;
+
+	/* fill in the destinations */
+	for (i = 0, dest = to; i < ms->nr_mirrors; i++) {
+		if (i == DEFAULT_MIRROR)
+			continue;
+
+		m = ms->mirror + i;
+		dest->bdev = m->dev->bdev;
+		dest->sector = m->offset + region_to_sector(reg->rh, reg->key);
+		dest->count = from.count;
+		dest++;
+	}
+
+	/* hand to kcopyd */
+	set_bit(KCOPYD_IGNORE_ERROR, &flags);
+	r = kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to, flags,
+			recovery_complete, reg);
+
+	return r;
+}
+
+static void do_recovery(struct mirror_set *ms)
+{
+	int r;
+	struct region *reg;
+	struct dirty_log *log = ms->rh.log;
+
+	/*
+	 * Start quiescing some regions.
+	 */
+	rh_recovery_prepare(&ms->rh);
+
+	/*
+	 * Copy any already quiesced regions.
+	 */
+	while ((reg = rh_recovery_start(&ms->rh))) {
+		r = recover(ms, reg);
+		if (r)
+			rh_recovery_end(reg, 0);
+	}
+
+	/*
+	 * Update the in sync flag.
+	 */
+	if (!ms->in_sync &&
+	    (log->type->get_sync_count(log) == ms->nr_regions)) {
+		/* the sync is complete */
+		dm_table_event(ms->ti->table);
+		ms->in_sync = 1;
+	}
+}
+
+/*-----------------------------------------------------------------
+ * Reads
+ *---------------------------------------------------------------*/
+static struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector)
+{
+	/* FIXME: add read balancing */
+	return ms->mirror + DEFAULT_MIRROR;
+}
+
+/*
+ * remap a buffer to a particular mirror.
+ */
+static void map_bio(struct mirror_set *ms, struct mirror *m, struct bio *bio)
+{
+	bio->bi_bdev = m->dev->bdev;
+	bio->bi_sector = m->offset + (bio->bi_sector - ms->ti->begin);
+}
+
+static void do_reads(struct mirror_set *ms, struct bio_list *reads)
+{
+	region_t region;
+	struct bio *bio;
+	struct mirror *m;
+
+	while ((bio = bio_list_pop(reads))) {
+		region = bio_to_region(&ms->rh, bio);
+
+		/*
+		 * We can only read balance if the region is in sync.
+		 */
+		if (rh_in_sync(&ms->rh, region, 0))
+			m = choose_mirror(ms, bio->bi_sector);
+		else
+			m = ms->mirror + DEFAULT_MIRROR;
+
+		map_bio(ms, m, bio);
+		generic_make_request(bio);
+	}
+}
+
+/*-----------------------------------------------------------------
+ * Writes.
+ *
+ * We do different things with the write io depending on the
+ * state of the region that it's in:
+ *
+ * SYNC: 	increment pending, use kcopyd to write to *all* mirrors
+ * RECOVERING:	delay the io until recovery completes
+ * NOSYNC:	increment pending, just write to the default mirror
+ *---------------------------------------------------------------*/
+static void write_callback(unsigned long error, void *context)
+{
+	unsigned int i;
+	int uptodate = 1;
+	struct bio *bio = (struct bio *) context;
+	struct mirror_set *ms;
+
+	ms = bio_get_ms(bio);
+	bio_set_ms(bio, NULL);
+
+	/*
+	 * NOTE: We don't decrement the pending count here,
+	 * instead it is done by the targets endio function.
+	 * This way we handle both writes to SYNC and NOSYNC
+	 * regions with the same code.
+	 */
+
+	if (error) {
+		/*
+		 * only error the io if all mirrors failed.
+		 * FIXME: bogus
+		 */
+		uptodate = 0;
+		for (i = 0; i < ms->nr_mirrors; i++)
+			if (!test_bit(i, &error)) {
+				uptodate = 1;
+				break;
+			}
+	}
+	bio_endio(bio, bio->bi_size, 0);
+}
+
+static void do_write(struct mirror_set *ms, struct bio *bio)
+{
+	unsigned int i;
+	struct io_region io[ms->nr_mirrors];
+	struct mirror *m;
+
+	for (i = 0; i < ms->nr_mirrors; i++) {
+		m = ms->mirror + i;
+
+		io[i].bdev = m->dev->bdev;
+		io[i].sector = m->offset + (bio->bi_sector - ms->ti->begin);
+		io[i].count = bio->bi_size >> 9;
+	}
+
+	bio_set_ms(bio, ms);
+	dm_io_async_bvec(ms->nr_mirrors, io, WRITE,
+			 bio->bi_io_vec + bio->bi_idx,
+			 write_callback, bio);
+}
+
+static void do_writes(struct mirror_set *ms, struct bio_list *writes)
+{
+	int state;
+	struct bio *bio;
+	struct bio_list sync, nosync, recover, *this_list = NULL;
+
+	if (!writes->head)
+		return;
+
+	/*
+	 * Classify each write.
+	 */
+	bio_list_init(&sync);
+	bio_list_init(&nosync);
+	bio_list_init(&recover);
+
+	while ((bio = bio_list_pop(writes))) {
+		state = rh_state(&ms->rh, bio_to_region(&ms->rh, bio), 1);
+		switch (state) {
+		case RH_CLEAN:
+		case RH_DIRTY:
+			this_list = &sync;
+			break;
+
+		case RH_NOSYNC:
+			this_list = &nosync;
+			break;
+
+		case RH_RECOVERING:
+			this_list = &recover;
+			break;
+		}
+
+		bio_list_add(this_list, bio);
+	}
+
+	/*
+	 * Increment the pending counts for any regions that will
+	 * be written to (writes to recover regions are going to
+	 * be delayed).
+	 */
+	rh_inc_pending(&ms->rh, &sync);
+	rh_inc_pending(&ms->rh, &nosync);
+	rh_flush(&ms->rh);
+
+	/*
+	 * Dispatch io.
+	 */
+	while ((bio = bio_list_pop(&sync)))
+		do_write(ms, bio);
+
+	while ((bio = bio_list_pop(&recover)))
+		rh_delay(&ms->rh, bio);
+
+	while ((bio = bio_list_pop(&nosync))) {
+		map_bio(ms, ms->mirror + DEFAULT_MIRROR, bio);
+		generic_make_request(bio);
+	}
+}
+
+/*-----------------------------------------------------------------
+ * kmirrord
+ *---------------------------------------------------------------*/
+static LIST_HEAD(_mirror_sets);
+static DECLARE_RWSEM(_mirror_sets_lock);
+
+static void do_mirror(struct mirror_set *ms)
+{
+	struct bio_list reads, writes;
+
+	spin_lock(&ms->lock);
+	reads = ms->reads;
+	writes = ms->writes;
+	bio_list_init(&ms->reads);
+	bio_list_init(&ms->writes);
+	spin_unlock(&ms->lock);
+
+	rh_update_states(&ms->rh);
+	do_recovery(ms);
+	do_reads(ms, &reads);
+	do_writes(ms, &writes);
+}
+
+static void do_work(void *ignored)
+{
+	struct mirror_set *ms;
+
+	down_read(&_mirror_sets_lock);
+	list_for_each_entry (ms, &_mirror_sets, list)
+		do_mirror(ms);
+	up_read(&_mirror_sets_lock);
+}
+
+/*-----------------------------------------------------------------
+ * Target functions
+ *---------------------------------------------------------------*/
+static struct mirror_set *alloc_context(unsigned int nr_mirrors,
+					sector_t region_size,
+					struct dm_target *ti,
+					struct dirty_log *dl)
+{
+	size_t len;
+	struct mirror_set *ms = NULL;
+
+	if (array_too_big(sizeof(*ms), sizeof(ms->mirror[0]), nr_mirrors))
+		return NULL;
+
+	len = sizeof(*ms) + (sizeof(ms->mirror[0]) * nr_mirrors);
+
+	ms = kmalloc(len, GFP_KERNEL);
+	if (!ms) {
+		ti->error = "dm-mirror: Cannot allocate mirror context";
+		return NULL;
+	}
+
+	memset(ms, 0, len);
+	spin_lock_init(&ms->lock);
+
+	ms->ti = ti;
+	ms->nr_mirrors = nr_mirrors;
+	ms->nr_regions = dm_div_up(ti->len, region_size);
+	ms->in_sync = 0;
+
+	if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) {
+		ti->error = "dm-mirror: Error creating dirty region hash";
+		kfree(ms);
+		return NULL;
+	}
+
+	return ms;
+}
+
+static void free_context(struct mirror_set *ms, struct dm_target *ti,
+			 unsigned int m)
+{
+	while (m--)
+		dm_put_device(ti, ms->mirror[m].dev);
+
+	rh_exit(&ms->rh);
+	kfree(ms);
+}
+
+static inline int _check_region_size(struct dm_target *ti, sector_t size)
+{
+	return !(size % (PAGE_SIZE >> 9) || (size & (size - 1)) ||
+		 size > ti->len);
+}
+
+static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
+		      unsigned int mirror, char **argv)
+{
+	sector_t offset;
+
+	if (sscanf(argv[1], SECTOR_FORMAT, &offset) != 1) {
+		ti->error = "dm-mirror: Invalid offset";
+		return -EINVAL;
+	}
+
+	if (dm_get_device(ti, argv[0], offset, ti->len,
+			  dm_table_get_mode(ti->table),
+			  &ms->mirror[mirror].dev)) {
+		ti->error = "dm-mirror: Device lookup failure";
+		return -ENXIO;
+	}
+
+	ms->mirror[mirror].offset = offset;
+
+	return 0;
+}
+
+static int add_mirror_set(struct mirror_set *ms)
+{
+	down_write(&_mirror_sets_lock);
+	list_add_tail(&ms->list, &_mirror_sets);
+	up_write(&_mirror_sets_lock);
+	wake();
+
+	return 0;
+}
+
+static void del_mirror_set(struct mirror_set *ms)
+{
+	down_write(&_mirror_sets_lock);
+	list_del(&ms->list);
+	up_write(&_mirror_sets_lock);
+}
+
+/*
+ * Create dirty log: log_type #log_params <log_params>
+ */
+static struct dirty_log *create_dirty_log(struct dm_target *ti,
+					  unsigned int argc, char **argv,
+					  unsigned int *args_used)
+{
+	unsigned int param_count;
+	struct dirty_log *dl;
+
+	if (argc < 2) {
+		ti->error = "dm-mirror: Insufficient mirror log arguments";
+		return NULL;
+	}
+
+	if (sscanf(argv[1], "%u", &param_count) != 1) {
+		ti->error = "dm-mirror: Invalid mirror log argument count";
+		return NULL;
+	}
+
+	*args_used = 2 + param_count;
+
+	if (argc < *args_used) {
+		ti->error = "dm-mirror: Insufficient mirror log arguments";
+		return NULL;
+	}
+
+	dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2);
+	if (!dl) {
+		ti->error = "dm-mirror: Error creating mirror dirty log";
+		return NULL;
+	}
+
+	if (!_check_region_size(ti, dl->type->get_region_size(dl))) {
+		ti->error = "dm-mirror: Invalid region size";
+		dm_destroy_dirty_log(dl);
+		return NULL;
+	}
+
+	return dl;
+}
+
+/*
+ * Construct a mirror mapping:
+ *
+ * log_type #log_params <log_params>
+ * #mirrors [mirror_path offset]{2,}
+ *
+ * For now, #log_params = 1, log_type = "core"
+ *
+ */
+#define DM_IO_PAGES 64
+static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+	int r;
+	unsigned int nr_mirrors, m, args_used;
+	struct mirror_set *ms;
+	struct dirty_log *dl;
+
+	dl = create_dirty_log(ti, argc, argv, &args_used);
+	if (!dl)
+		return -EINVAL;
+
+	argv += args_used;
+	argc -= args_used;
+
+	if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 ||
+	    nr_mirrors < 2) {
+		ti->error = "dm-mirror: Invalid number of mirrors";
+		dm_destroy_dirty_log(dl);
+		return -EINVAL;
+	}
+
+	argv++, argc--;
+
+	if (argc != nr_mirrors * 2) {
+		ti->error = "dm-mirror: Wrong number of mirror arguments";
+		dm_destroy_dirty_log(dl);
+		return -EINVAL;
+	}
+
+	ms = alloc_context(nr_mirrors, dl->type->get_region_size(dl), ti, dl);
+	if (!ms) {
+		dm_destroy_dirty_log(dl);
+		return -ENOMEM;
+	}
+
+	/* Get the mirror parameter sets */
+	for (m = 0; m < nr_mirrors; m++) {
+		r = get_mirror(ms, ti, m, argv);
+		if (r) {
+			free_context(ms, ti, m);
+			return r;
+		}
+		argv += 2;
+		argc -= 2;
+	}
+
+	ti->private = ms;
+
+	r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
+	if (r) {
+		free_context(ms, ti, ms->nr_mirrors);
+		return r;
+	}
+
+	add_mirror_set(ms);
+	return 0;
+}
+
+static void mirror_dtr(struct dm_target *ti)
+{
+	struct mirror_set *ms = (struct mirror_set *) ti->private;
+
+	del_mirror_set(ms);
+	kcopyd_client_destroy(ms->kcopyd_client);
+	free_context(ms, ti, ms->nr_mirrors);
+}
+
+static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw)
+{
+	int should_wake = 0;
+	struct bio_list *bl;
+
+	bl = (rw == WRITE) ? &ms->writes : &ms->reads;
+	spin_lock(&ms->lock);
+	should_wake = !(bl->head);
+	bio_list_add(bl, bio);
+	spin_unlock(&ms->lock);
+
+	if (should_wake)
+		wake();
+}
+
+/*
+ * Mirror mapping function
+ */
+static int mirror_map(struct dm_target *ti, struct bio *bio,
+		      union map_info *map_context)
+{
+	int r, rw = bio_rw(bio);
+	struct mirror *m;
+	struct mirror_set *ms = ti->private;
+
+	map_context->ll = bio->bi_sector >> ms->rh.region_shift;
+
+	if (rw == WRITE) {
+		queue_bio(ms, bio, rw);
+		return 0;
+	}
+
+	r = ms->rh.log->type->in_sync(ms->rh.log,
+				      bio_to_region(&ms->rh, bio), 0);
+	if (r < 0 && r != -EWOULDBLOCK)
+		return r;
+
+	if (r == -EWOULDBLOCK)	/* FIXME: ugly */
+		r = 0;
+
+	/*
+	 * We don't want to fast track a recovery just for a read
+	 * ahead.  So we just let it silently fail.
+	 * FIXME: get rid of this.
+	 */
+	if (!r && rw == READA)
+		return -EIO;
+
+	if (!r) {
+		/* Pass this io over to the daemon */
+		queue_bio(ms, bio, rw);
+		return 0;
+	}
+
+	m = choose_mirror(ms, bio->bi_sector);
+	if (!m)
+		return -EIO;
+
+	map_bio(ms, m, bio);
+	return 1;
+}
+
+static int mirror_end_io(struct dm_target *ti, struct bio *bio,
+			 int error, union map_info *map_context)
+{
+	int rw = bio_rw(bio);
+	struct mirror_set *ms = (struct mirror_set *) ti->private;
+	region_t region = map_context->ll;
+
+	/*
+	 * We need to dec pending if this was a write.
+	 */
+	if (rw == WRITE)
+		rh_dec(&ms->rh, region);
+
+	return 0;
+}
+
+static void mirror_suspend(struct dm_target *ti)
+{
+	struct mirror_set *ms = (struct mirror_set *) ti->private;
+	struct dirty_log *log = ms->rh.log;
+	rh_stop_recovery(&ms->rh);
+	if (log->type->suspend && log->type->suspend(log))
+		/* FIXME: need better error handling */
+		DMWARN("log suspend failed");
+}
+
+static void mirror_resume(struct dm_target *ti)
+{
+	struct mirror_set *ms = (struct mirror_set *) ti->private;
+	struct dirty_log *log = ms->rh.log;
+	if (log->type->resume && log->type->resume(log))
+		/* FIXME: need better error handling */
+		DMWARN("log resume failed");
+	rh_start_recovery(&ms->rh);
+}
+
+static int mirror_status(struct dm_target *ti, status_type_t type,
+			 char *result, unsigned int maxlen)
+{
+	char buffer[32];
+	unsigned int m, sz = 0;
+	struct mirror_set *ms = (struct mirror_set *) ti->private;
+
+#define EMIT(x...) sz += ((sz >= maxlen) ? \
+			  0 : scnprintf(result + sz, maxlen - sz, x))
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		EMIT("%d ", ms->nr_mirrors);
+
+		for (m = 0; m < ms->nr_mirrors; m++) {
+			format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
+			EMIT("%s ", buffer);
+		}
+
+		EMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
+		     ms->rh.log->type->get_sync_count(ms->rh.log),
+		     ms->nr_regions);
+		break;
+
+	case STATUSTYPE_TABLE:
+		EMIT("%s 1 " SECTOR_FORMAT " %d ",
+		     ms->rh.log->type->name, ms->rh.region_size,
+		     ms->nr_mirrors);
+
+		for (m = 0; m < ms->nr_mirrors; m++) {
+			format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
+			EMIT("%s " SECTOR_FORMAT " ",
+			     buffer, ms->mirror[m].offset);
+		}
+	}
+
+	return 0;
+}
+
+static struct target_type mirror_target = {
+	.name	 = "mirror",
+	.version = {1, 0, 1},
+	.module	 = THIS_MODULE,
+	.ctr	 = mirror_ctr,
+	.dtr	 = mirror_dtr,
+	.map	 = mirror_map,
+	.end_io	 = mirror_end_io,
+	.suspend = mirror_suspend,
+	.resume	 = mirror_resume,
+	.status	 = mirror_status,
+};
+
+static int __init dm_mirror_init(void)
+{
+	int r;
+
+	r = dm_dirty_log_init();
+	if (r)
+		return r;
+
+	_kmirrord_wq = create_workqueue("kmirrord");
+	if (!_kmirrord_wq) {
+		DMERR("couldn't start kmirrord");
+		dm_dirty_log_exit();
+		return r;
+	}
+	INIT_WORK(&_kmirrord_work, do_work, NULL);
+
+	r = dm_register_target(&mirror_target);
+	if (r < 0) {
+		DMERR("%s: Failed to register mirror target",
+		      mirror_target.name);
+		dm_dirty_log_exit();
+		destroy_workqueue(_kmirrord_wq);
+	}
+
+	return r;
+}
+
+static void __exit dm_mirror_exit(void)
+{
+	int r;
+
+	r = dm_unregister_target(&mirror_target);
+	if (r < 0)
+		DMERR("%s: unregister failed %d", mirror_target.name, r);
+
+	destroy_workqueue(_kmirrord_wq);
+	dm_dirty_log_exit();
+}
+
+/* Module hooks */
+module_init(dm_mirror_init);
+module_exit(dm_mirror_exit);
+
+MODULE_DESCRIPTION(DM_NAME " mirror target");
+MODULE_AUTHOR("Joe Thornber");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-snap.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,1213 @@
+/*
+ * dm-snapshot.c
+ *
+ * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/blkdev.h>
+#include <linux/config.h>
+#include <linux/ctype.h>
+#include <linux/device-mapper.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kdev_t.h>
+#include <linux/list.h>
+#include <linux/mempool.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include "dm-snap.h"
+#include "dm-bio-list.h"
+#include "kcopyd.h"
+
+/*
+ * The percentage increment we will wake up users at
+ */
+#define WAKE_UP_PERCENT 5
+
+/*
+ * kcopyd priority of snapshot operations
+ */
+#define SNAPSHOT_COPY_PRIORITY 2
+
+/*
+ * Each snapshot reserves this many pages for io
+ */
+#define SNAPSHOT_PAGES 256
+
+struct pending_exception {
+	struct exception e;
+
+	/*
+	 * Origin buffers waiting for this to complete are held
+	 * in a bio list
+	 */
+	struct bio_list origin_bios;
+	struct bio_list snapshot_bios;
+
+	/*
+	 * Other pending_exceptions that are processing this
+	 * chunk.  When this list is empty, we know we can
+	 * complete the origins.
+	 */
+	struct list_head siblings;
+
+	/* Pointer back to snapshot context */
+	struct dm_snapshot *snap;
+
+	/*
+	 * 1 indicates the exception has already been sent to
+	 * kcopyd.
+	 */
+	int started;
+};
+
+/*
+ * Hash table mapping origin volumes to lists of snapshots and
+ * a lock to protect it
+ */
+static kmem_cache_t *exception_cache;
+static kmem_cache_t *pending_cache;
+static mempool_t *pending_pool;
+
+/*
+ * One of these per registered origin, held in the snapshot_origins hash
+ */
+struct origin {
+	/* The origin device */
+	struct block_device *bdev;
+
+	struct list_head hash_list;
+
+	/* List of snapshots for this origin */
+	struct list_head snapshots;
+};
+
+/*
+ * Size of the hash table for origin volumes. If we make this
+ * the size of the minors list then it should be nearly perfect
+ */
+#define ORIGIN_HASH_SIZE 256
+#define ORIGIN_MASK      0xFF
+static struct list_head *_origins;
+static struct rw_semaphore _origins_lock;
+
+static int init_origin_hash(void)
+{
+	int i;
+
+	_origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head),
+			   GFP_KERNEL);
+	if (!_origins) {
+		DMERR("Device mapper: Snapshot: unable to allocate memory");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < ORIGIN_HASH_SIZE; i++)
+		INIT_LIST_HEAD(_origins + i);
+	init_rwsem(&_origins_lock);
+
+	return 0;
+}
+
+static void exit_origin_hash(void)
+{
+	kfree(_origins);
+}
+
+static inline unsigned int origin_hash(struct block_device *bdev)
+{
+	return bdev->bd_dev & ORIGIN_MASK;
+}
+
+static struct origin *__lookup_origin(struct block_device *origin)
+{
+	struct list_head *ol;
+	struct origin *o;
+
+	ol = &_origins[origin_hash(origin)];
+	list_for_each_entry (o, ol, hash_list)
+		if (bdev_equal(o->bdev, origin))
+			return o;
+
+	return NULL;
+}
+
+static void __insert_origin(struct origin *o)
+{
+	struct list_head *sl = &_origins[origin_hash(o->bdev)];
+	list_add_tail(&o->hash_list, sl);
+}
+
+/*
+ * Make a note of the snapshot and its origin so we can look it
+ * up when the origin has a write on it.
+ */
+static int register_snapshot(struct dm_snapshot *snap)
+{
+	struct origin *o;
+	struct block_device *bdev = snap->origin->bdev;
+
+	down_write(&_origins_lock);
+	o = __lookup_origin(bdev);
+
+	if (!o) {
+		/* New origin */
+		o = kmalloc(sizeof(*o), GFP_KERNEL);
+		if (!o) {
+			up_write(&_origins_lock);
+			return -ENOMEM;
+		}
+
+		/* Initialise the struct */
+		INIT_LIST_HEAD(&o->snapshots);
+		o->bdev = bdev;
+
+		__insert_origin(o);
+	}
+
+	list_add_tail(&snap->list, &o->snapshots);
+
+	up_write(&_origins_lock);
+	return 0;
+}
+
+static void unregister_snapshot(struct dm_snapshot *s)
+{
+	struct origin *o;
+
+	down_write(&_origins_lock);
+	o = __lookup_origin(s->origin->bdev);
+
+	list_del(&s->list);
+	if (list_empty(&o->snapshots)) {
+		list_del(&o->hash_list);
+		kfree(o);
+	}
+
+	up_write(&_origins_lock);
+}
+
+/*
+ * Implementation of the exception hash tables.
+ */
+static int init_exception_table(struct exception_table *et, uint32_t size)
+{
+	unsigned int i;
+
+	et->hash_mask = size - 1;
+	et->table = dm_vcalloc(size, sizeof(struct list_head));
+	if (!et->table)
+		return -ENOMEM;
+
+	for (i = 0; i < size; i++)
+		INIT_LIST_HEAD(et->table + i);
+
+	return 0;
+}
+
+static void exit_exception_table(struct exception_table *et, kmem_cache_t *mem)
+{
+	struct list_head *slot;
+	struct exception *ex, *next;
+	int i, size;
+
+	size = et->hash_mask + 1;
+	for (i = 0; i < size; i++) {
+		slot = et->table + i;
+
+		list_for_each_entry_safe (ex, next, slot, hash_list)
+			kmem_cache_free(mem, ex);
+	}
+
+	vfree(et->table);
+}
+
+static inline uint32_t exception_hash(struct exception_table *et, chunk_t chunk)
+{
+	return chunk & et->hash_mask;
+}
+
+static void insert_exception(struct exception_table *eh, struct exception *e)
+{
+	struct list_head *l = &eh->table[exception_hash(eh, e->old_chunk)];
+	list_add(&e->hash_list, l);
+}
+
+static inline void remove_exception(struct exception *e)
+{
+	list_del(&e->hash_list);
+}
+
+/*
+ * Return the exception data for a sector, or NULL if not
+ * remapped.
+ */
+static struct exception *lookup_exception(struct exception_table *et,
+					  chunk_t chunk)
+{
+	struct list_head *slot;
+	struct exception *e;
+
+	slot = &et->table[exception_hash(et, chunk)];
+	list_for_each_entry (e, slot, hash_list)
+		if (e->old_chunk == chunk)
+			return e;
+
+	return NULL;
+}
+
+static inline struct exception *alloc_exception(void)
+{
+	struct exception *e;
+
+	e = kmem_cache_alloc(exception_cache, GFP_NOIO);
+	if (!e)
+		e = kmem_cache_alloc(exception_cache, GFP_ATOMIC);
+
+	return e;
+}
+
+static inline void free_exception(struct exception *e)
+{
+	kmem_cache_free(exception_cache, e);
+}
+
+static inline struct pending_exception *alloc_pending_exception(void)
+{
+	return mempool_alloc(pending_pool, GFP_NOIO);
+}
+
+static inline void free_pending_exception(struct pending_exception *pe)
+{
+	mempool_free(pe, pending_pool);
+}
+
+int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new)
+{
+	struct exception *e;
+
+	e = alloc_exception();
+	if (!e)
+		return -ENOMEM;
+
+	e->old_chunk = old;
+	e->new_chunk = new;
+	insert_exception(&s->complete, e);
+	return 0;
+}
+
+/*
+ * Hard coded magic.
+ */
+static int calc_max_buckets(void)
+{
+	/* use a fixed size of 2MB */
+	unsigned long mem = 2 * 1024 * 1024;
+	mem /= sizeof(struct list_head);
+
+	return mem;
+}
+
+/*
+ * Rounds a number down to a power of 2.
+ */
+static inline uint32_t round_down(uint32_t n)
+{
+	while (n & (n - 1))
+		n &= (n - 1);
+	return n;
+}
+
+/*
+ * Allocate room for a suitable hash table.
+ */
+static int init_hash_tables(struct dm_snapshot *s)
+{
+	sector_t hash_size, cow_dev_size, origin_dev_size, max_buckets;
+
+	/*
+	 * Calculate based on the size of the original volume or
+	 * the COW volume...
+	 */
+	cow_dev_size = get_dev_size(s->cow->bdev);
+	origin_dev_size = get_dev_size(s->origin->bdev);
+	max_buckets = calc_max_buckets();
+
+	hash_size = min(origin_dev_size, cow_dev_size) >> s->chunk_shift;
+	hash_size = min(hash_size, max_buckets);
+
+	/* Round it down to a power of 2 */
+	hash_size = round_down(hash_size);
+	if (init_exception_table(&s->complete, hash_size))
+		return -ENOMEM;
+
+	/*
+	 * Allocate hash table for in-flight exceptions
+	 * Make this smaller than the real hash table
+	 */
+	hash_size >>= 3;
+	if (hash_size < 64)
+		hash_size = 64;
+
+	if (init_exception_table(&s->pending, hash_size)) {
+		exit_exception_table(&s->complete, exception_cache);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * Round a number up to the nearest 'size' boundary.  size must
+ * be a power of 2.
+ */
+static inline ulong round_up(ulong n, ulong size)
+{
+	size--;
+	return (n + size) & ~size;
+}
+
+/*
+ * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
+ */
+static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+	struct dm_snapshot *s;
+	unsigned long chunk_size;
+	int r = -EINVAL;
+	char persistent;
+	char *origin_path;
+	char *cow_path;
+	char *value;
+	int blocksize;
+
+	if (argc < 4) {
+		ti->error = "dm-snapshot: requires exactly 4 arguments";
+		r = -EINVAL;
+		goto bad1;
+	}
+
+	origin_path = argv[0];
+	cow_path = argv[1];
+	persistent = toupper(*argv[2]);
+
+	if (persistent != 'P' && persistent != 'N') {
+		ti->error = "Persistent flag is not P or N";
+		r = -EINVAL;
+		goto bad1;
+	}
+
+	chunk_size = simple_strtoul(argv[3], &value, 10);
+	if (chunk_size == 0 || value == NULL) {
+		ti->error = "Invalid chunk size";
+		r = -EINVAL;
+		goto bad1;
+	}
+
+	s = kmalloc(sizeof(*s), GFP_KERNEL);
+	if (s == NULL) {
+		ti->error = "Cannot allocate snapshot context private "
+		    "structure";
+		r = -ENOMEM;
+		goto bad1;
+	}
+
+	r = dm_get_device(ti, origin_path, 0, ti->len, FMODE_READ, &s->origin);
+	if (r) {
+		ti->error = "Cannot get origin device";
+		goto bad2;
+	}
+
+	r = dm_get_device(ti, cow_path, 0, 0,
+			  FMODE_READ | FMODE_WRITE, &s->cow);
+	if (r) {
+		dm_put_device(ti, s->origin);
+		ti->error = "Cannot get COW device";
+		goto bad2;
+	}
+
+	/*
+	 * Chunk size must be multiple of page size.  Silently
+	 * round up if it's not.
+	 */
+	chunk_size = round_up(chunk_size, PAGE_SIZE >> 9);
+
+	/* Validate the chunk size against the device block size */
+	blocksize = s->cow->bdev->bd_disk->queue->hardsect_size;
+	if (chunk_size % (blocksize >> 9)) {
+		ti->error = "Chunk size is not a multiple of device blocksize";
+		r = -EINVAL;
+		goto bad3;
+	}
+
+	/* Check chunk_size is a power of 2 */
+	if (chunk_size & (chunk_size - 1)) {
+		ti->error = "Chunk size is not a power of 2";
+		r = -EINVAL;
+		goto bad3;
+	}
+
+	s->chunk_size = chunk_size;
+	s->chunk_mask = chunk_size - 1;
+	s->type = persistent;
+	s->chunk_shift = ffs(chunk_size) - 1;
+
+	s->valid = 1;
+	s->have_metadata = 0;
+	s->last_percent = 0;
+	init_rwsem(&s->lock);
+	s->table = ti->table;
+
+	/* Allocate hash table for COW data */
+	if (init_hash_tables(s)) {
+		ti->error = "Unable to allocate hash table space";
+		r = -ENOMEM;
+		goto bad3;
+	}
+
+	/*
+	 * Check the persistent flag - done here because we need the iobuf
+	 * to check the LV header
+	 */
+	s->store.snap = s;
+
+	if (persistent == 'P')
+		r = dm_create_persistent(&s->store, chunk_size);
+	else
+		r = dm_create_transient(&s->store, s, blocksize);
+
+	if (r) {
+		ti->error = "Couldn't create exception store";
+		r = -EINVAL;
+		goto bad4;
+	}
+
+	r = kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
+	if (r) {
+		ti->error = "Could not create kcopyd client";
+		goto bad5;
+	}
+
+	/* Add snapshot to the list of snapshots for this origin */
+	if (register_snapshot(s)) {
+		r = -EINVAL;
+		ti->error = "Cannot register snapshot origin";
+		goto bad6;
+	}
+
+	ti->private = s;
+	ti->split_io = chunk_size;
+
+	return 0;
+
+ bad6:
+	kcopyd_client_destroy(s->kcopyd_client);
+
+ bad5:
+	s->store.destroy(&s->store);
+
+ bad4:
+	exit_exception_table(&s->pending, pending_cache);
+	exit_exception_table(&s->complete, exception_cache);
+
+ bad3:
+	dm_put_device(ti, s->cow);
+	dm_put_device(ti, s->origin);
+
+ bad2:
+	kfree(s);
+
+ bad1:
+	return r;
+}
+
+static void snapshot_dtr(struct dm_target *ti)
+{
+	struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+
+	unregister_snapshot(s);
+
+	exit_exception_table(&s->pending, pending_cache);
+	exit_exception_table(&s->complete, exception_cache);
+
+	/* Deallocate memory used */
+	s->store.destroy(&s->store);
+
+	dm_put_device(ti, s->origin);
+	dm_put_device(ti, s->cow);
+	kcopyd_client_destroy(s->kcopyd_client);
+	kfree(s);
+}
+
+/*
+ * Flush a list of buffers.
+ */
+static void flush_bios(struct bio *bio)
+{
+	struct bio *n;
+
+	while (bio) {
+		n = bio->bi_next;
+		bio->bi_next = NULL;
+		generic_make_request(bio);
+		bio = n;
+	}
+}
+
+/*
+ * Error a list of buffers.
+ */
+static void error_bios(struct bio *bio)
+{
+	struct bio *n;
+
+	while (bio) {
+		n = bio->bi_next;
+		bio->bi_next = NULL;
+		bio_io_error(bio, bio->bi_size);
+		bio = n;
+	}
+}
+
+static struct bio *__flush_bios(struct pending_exception *pe)
+{
+	struct pending_exception *sibling;
+
+	if (list_empty(&pe->siblings))
+		return bio_list_get(&pe->origin_bios);
+
+	sibling = list_entry(pe->siblings.next,
+			     struct pending_exception, siblings);
+
+	list_del(&pe->siblings);
+
+	/* This is fine as long as kcopyd is single-threaded. If kcopyd
+	 * becomes multi-threaded, we'll need some locking here.
+	 */
+	bio_list_merge(&sibling->origin_bios, &pe->origin_bios);
+
+	return NULL;
+}
+
+static void pending_complete(struct pending_exception *pe, int success)
+{
+	struct exception *e;
+	struct dm_snapshot *s = pe->snap;
+	struct bio *flush = NULL;
+
+	if (success) {
+		e = alloc_exception();
+		if (!e) {
+			DMWARN("Unable to allocate exception.");
+			down_write(&s->lock);
+			s->store.drop_snapshot(&s->store);
+			s->valid = 0;
+			flush = __flush_bios(pe);
+			up_write(&s->lock);
+
+			error_bios(bio_list_get(&pe->snapshot_bios));
+			goto out;
+		}
+		*e = pe->e;
+
+		/*
+		 * Add a proper exception, and remove the
+		 * in-flight exception from the list.
+		 */
+		down_write(&s->lock);
+		insert_exception(&s->complete, e);
+		remove_exception(&pe->e);
+		flush = __flush_bios(pe);
+
+		/* Submit any pending write bios */
+		up_write(&s->lock);
+
+		flush_bios(bio_list_get(&pe->snapshot_bios));
+	} else {
+		/* Read/write error - snapshot is unusable */
+		down_write(&s->lock);
+		if (s->valid)
+			DMERR("Error reading/writing snapshot");
+		s->store.drop_snapshot(&s->store);
+		s->valid = 0;
+		remove_exception(&pe->e);
+		flush = __flush_bios(pe);
+		up_write(&s->lock);
+
+		error_bios(bio_list_get(&pe->snapshot_bios));
+
+		dm_table_event(s->table);
+	}
+
+ out:
+	free_pending_exception(pe);
+
+	if (flush)
+		flush_bios(flush);
+}
+
+static void commit_callback(void *context, int success)
+{
+	struct pending_exception *pe = (struct pending_exception *) context;
+	pending_complete(pe, success);
+}
+
+/*
+ * Called when the copy I/O has finished.  kcopyd actually runs
+ * this code so don't block.
+ */
+static void copy_callback(int read_err, unsigned int write_err, void *context)
+{
+	struct pending_exception *pe = (struct pending_exception *) context;
+	struct dm_snapshot *s = pe->snap;
+
+	if (read_err || write_err)
+		pending_complete(pe, 0);
+
+	else
+		/* Update the metadata if we are persistent */
+		s->store.commit_exception(&s->store, &pe->e, commit_callback,
+					  pe);
+}
+
+/*
+ * Dispatches the copy operation to kcopyd.
+ */
+static inline void start_copy(struct pending_exception *pe)
+{
+	struct dm_snapshot *s = pe->snap;
+	struct io_region src, dest;
+	struct block_device *bdev = s->origin->bdev;
+	sector_t dev_size;
+
+	dev_size = get_dev_size(bdev);
+
+	src.bdev = bdev;
+	src.sector = chunk_to_sector(s, pe->e.old_chunk);
+	src.count = min(s->chunk_size, dev_size - src.sector);
+
+	dest.bdev = s->cow->bdev;
+	dest.sector = chunk_to_sector(s, pe->e.new_chunk);
+	dest.count = src.count;
+
+	/* Hand over to kcopyd */
+	kcopyd_copy(s->kcopyd_client,
+		    &src, 1, &dest, 0, copy_callback, pe);
+}
+
+/*
+ * Looks to see if this snapshot already has a pending exception
+ * for this chunk, otherwise it allocates a new one and inserts
+ * it into the pending table.
+ *
+ * NOTE: a write lock must be held on snap->lock before calling
+ * this.
+ */
+static struct pending_exception *
+__find_pending_exception(struct dm_snapshot *s, struct bio *bio)
+{
+	struct exception *e;
+	struct pending_exception *pe;
+	chunk_t chunk = sector_to_chunk(s, bio->bi_sector);
+
+	/*
+	 * Is there a pending exception for this already ?
+	 */
+	e = lookup_exception(&s->pending, chunk);
+	if (e) {
+		/* cast the exception to a pending exception */
+		pe = container_of(e, struct pending_exception, e);
+
+	} else {
+		/*
+		 * Create a new pending exception, we don't want
+		 * to hold the lock while we do this.
+		 */
+		up_write(&s->lock);
+		pe = alloc_pending_exception();
+		down_write(&s->lock);
+
+		e = lookup_exception(&s->pending, chunk);
+		if (e) {
+			free_pending_exception(pe);
+			pe = container_of(e, struct pending_exception, e);
+		} else {
+			pe->e.old_chunk = chunk;
+			bio_list_init(&pe->origin_bios);
+			bio_list_init(&pe->snapshot_bios);
+			INIT_LIST_HEAD(&pe->siblings);
+			pe->snap = s;
+			pe->started = 0;
+
+			if (s->store.prepare_exception(&s->store, &pe->e)) {
+				free_pending_exception(pe);
+				s->valid = 0;
+				return NULL;
+			}
+
+			insert_exception(&s->pending, &pe->e);
+		}
+	}
+
+	return pe;
+}
+
+static inline void remap_exception(struct dm_snapshot *s, struct exception *e,
+				   struct bio *bio)
+{
+	bio->bi_bdev = s->cow->bdev;
+	bio->bi_sector = chunk_to_sector(s, e->new_chunk) +
+		(bio->bi_sector & s->chunk_mask);
+}
+
+static int snapshot_map(struct dm_target *ti, struct bio *bio,
+			union map_info *map_context)
+{
+	struct exception *e;
+	struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+	int r = 1;
+	chunk_t chunk;
+	struct pending_exception *pe;
+
+	chunk = sector_to_chunk(s, bio->bi_sector);
+
+	/* Full snapshots are not usable */
+	if (!s->valid)
+		return -1;
+
+	/*
+	 * Write to snapshot - higher level takes care of RW/RO
+	 * flags so we should only get this if we are
+	 * writeable.
+	 */
+	if (bio_rw(bio) == WRITE) {
+
+		/* FIXME: should only take write lock if we need
+		 * to copy an exception */
+		down_write(&s->lock);
+
+		/* If the block is already remapped - use that, else remap it */
+		e = lookup_exception(&s->complete, chunk);
+		if (e) {
+			remap_exception(s, e, bio);
+			up_write(&s->lock);
+
+		} else {
+			pe = __find_pending_exception(s, bio);
+
+			if (!pe) {
+				if (s->store.drop_snapshot)
+					s->store.drop_snapshot(&s->store);
+				s->valid = 0;
+				r = -EIO;
+				up_write(&s->lock);
+			} else {
+				remap_exception(s, &pe->e, bio);
+				bio_list_add(&pe->snapshot_bios, bio);
+
+				if (!pe->started) {
+					/* this is protected by snap->lock */
+					pe->started = 1;
+					up_write(&s->lock);
+					start_copy(pe);
+				} else
+					up_write(&s->lock);
+				r = 0;
+			}
+		}
+
+	} else {
+		/*
+		 * FIXME: this read path scares me because we
+		 * always use the origin when we have a pending
+		 * exception.  However I can't think of a
+		 * situation where this is wrong - ejt.
+		 */
+
+		/* Do reads */
+		down_read(&s->lock);
+
+		/* See if it it has been remapped */
+		e = lookup_exception(&s->complete, chunk);
+		if (e)
+			remap_exception(s, e, bio);
+		else
+			bio->bi_bdev = s->origin->bdev;
+
+		up_read(&s->lock);
+	}
+
+	return r;
+}
+
+static void snapshot_resume(struct dm_target *ti)
+{
+	struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+
+	if (s->have_metadata)
+		return;
+
+	if (s->store.read_metadata(&s->store)) {
+		down_write(&s->lock);
+		s->valid = 0;
+		up_write(&s->lock);
+	}
+
+	s->have_metadata = 1;
+}
+
+static int snapshot_status(struct dm_target *ti, status_type_t type,
+			   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:
+		if (!snap->valid)
+			snprintf(result, maxlen, "Invalid");
+		else {
+			if (snap->store.fraction_full) {
+				sector_t numerator, denominator;
+				snap->store.fraction_full(&snap->store,
+							  &numerator,
+							  &denominator);
+				snprintf(result, maxlen,
+					 SECTOR_FORMAT "/" SECTOR_FORMAT,
+					 numerator, denominator);
+			}
+			else
+				snprintf(result, maxlen, "Unknown");
+		}
+		break;
+
+	case STATUSTYPE_TABLE:
+		/*
+		 * kdevname returns a static pointer so we need
+		 * 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,
+			 snap->type, snap->chunk_size);
+		break;
+	}
+
+	return 0;
+}
+
+/*-----------------------------------------------------------------
+ * Origin methods
+ *---------------------------------------------------------------*/
+static void list_merge(struct list_head *l1, struct list_head *l2)
+{
+	struct list_head *l1_n, *l2_p;
+
+	l1_n = l1->next;
+	l2_p = l2->prev;
+
+	l1->next = l2;
+	l2->prev = l1;
+
+	l2_p->next = l1_n;
+	l1_n->prev = l2_p;
+}
+
+static int __origin_write(struct list_head *snapshots, struct bio *bio)
+{
+	int r = 1, first = 1;
+	struct dm_snapshot *snap;
+	struct exception *e;
+	struct pending_exception *pe, *last = NULL;
+	chunk_t chunk;
+
+	/* Do all the snapshots on this origin */
+	list_for_each_entry (snap, snapshots, list) {
+
+		/* Only deal with valid snapshots */
+		if (!snap->valid)
+			continue;
+
+		down_write(&snap->lock);
+
+		/*
+		 * Remember, different snapshots can have
+		 * different chunk sizes.
+		 */
+		chunk = sector_to_chunk(snap, bio->bi_sector);
+
+		/*
+		 * Check exception table to see if block
+		 * is already remapped in this snapshot
+		 * and trigger an exception if not.
+		 */
+		e = lookup_exception(&snap->complete, chunk);
+		if (!e) {
+			pe = __find_pending_exception(snap, bio);
+			if (!pe) {
+				snap->store.drop_snapshot(&snap->store);
+				snap->valid = 0;
+
+			} else {
+				if (last)
+					list_merge(&pe->siblings,
+						   &last->siblings);
+
+				last = pe;
+				r = 0;
+			}
+		}
+
+		up_write(&snap->lock);
+	}
+
+	/*
+	 * Now that we have a complete pe list we can start the copying.
+	 */
+	if (last) {
+		pe = last;
+		do {
+			down_write(&pe->snap->lock);
+			if (first)
+				bio_list_add(&pe->origin_bios, bio);
+			if (!pe->started) {
+				pe->started = 1;
+				up_write(&pe->snap->lock);
+				start_copy(pe);
+			} else
+				up_write(&pe->snap->lock);
+			first = 0;
+			pe = list_entry(pe->siblings.next,
+					struct pending_exception, siblings);
+
+		} while (pe != last);
+	}
+
+	return r;
+}
+
+/*
+ * Called on a write from the origin driver.
+ */
+static int do_origin(struct dm_dev *origin, struct bio *bio)
+{
+	struct origin *o;
+	int r = 1;
+
+	down_read(&_origins_lock);
+	o = __lookup_origin(origin->bdev);
+	if (o)
+		r = __origin_write(&o->snapshots, bio);
+	up_read(&_origins_lock);
+
+	return r;
+}
+
+/*
+ * Origin: maps a linear range of a device, with hooks for snapshotting.
+ */
+
+/*
+ * Construct an origin mapping: <dev_path>
+ * The context for an origin is merely a 'struct dm_dev *'
+ * pointing to the real device.
+ */
+static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+	int r;
+	struct dm_dev *dev;
+
+	if (argc != 1) {
+		ti->error = "dm-origin: incorrect number of arguments";
+		return -EINVAL;
+	}
+
+	r = dm_get_device(ti, argv[0], 0, ti->len,
+			  dm_table_get_mode(ti->table), &dev);
+	if (r) {
+		ti->error = "Cannot get target device";
+		return r;
+	}
+
+	ti->private = dev;
+	return 0;
+}
+
+static void origin_dtr(struct dm_target *ti)
+{
+	struct dm_dev *dev = (struct dm_dev *) ti->private;
+	dm_put_device(ti, dev);
+}
+
+static int origin_map(struct dm_target *ti, struct bio *bio,
+		      union map_info *map_context)
+{
+	struct dm_dev *dev = (struct dm_dev *) ti->private;
+	bio->bi_bdev = dev->bdev;
+
+	/* Only tell snapshots if this is a write */
+	return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1;
+}
+
+#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
+
+/*
+ * Set the target "split_io" field to the minimum of all the snapshots'
+ * chunk sizes.
+ */
+static void origin_resume(struct dm_target *ti)
+{
+	struct dm_dev *dev = (struct dm_dev *) ti->private;
+	struct dm_snapshot *snap;
+	struct origin *o;
+	chunk_t chunk_size = 0;
+
+	down_read(&_origins_lock);
+	o = __lookup_origin(dev->bdev);
+	if (o)
+		list_for_each_entry (snap, &o->snapshots, list)
+			chunk_size = min_not_zero(chunk_size, snap->chunk_size);
+	up_read(&_origins_lock);
+
+	ti->split_io = chunk_size;
+}
+
+static int origin_status(struct dm_target *ti, status_type_t type, char *result,
+			 unsigned int maxlen)
+{
+	struct dm_dev *dev = (struct dm_dev *) ti->private;
+	char buffer[32];
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		result[0] = '\0';
+		break;
+
+	case STATUSTYPE_TABLE:
+		format_dev_t(buffer, dev->bdev->bd_dev);
+		snprintf(result, maxlen, "%s", buffer);
+		break;
+	}
+
+	return 0;
+}
+
+static struct target_type origin_target = {
+	.name    = "snapshot-origin",
+	.version = {1, 0, 1},
+	.module  = THIS_MODULE,
+	.ctr     = origin_ctr,
+	.dtr     = origin_dtr,
+	.map     = origin_map,
+	.resume  = origin_resume,
+	.status  = origin_status,
+};
+
+static struct target_type snapshot_target = {
+	.name    = "snapshot",
+	.version = {1, 0, 1},
+	.module  = THIS_MODULE,
+	.ctr     = snapshot_ctr,
+	.dtr     = snapshot_dtr,
+	.map     = snapshot_map,
+	.resume  = snapshot_resume,
+	.status  = snapshot_status,
+};
+
+static int __init dm_snapshot_init(void)
+{
+	int r;
+
+	r = dm_register_target(&snapshot_target);
+	if (r) {
+		DMERR("snapshot target register failed %d", r);
+		return r;
+	}
+
+	r = dm_register_target(&origin_target);
+	if (r < 0) {
+		DMERR("Device mapper: Origin: register failed %d\n", r);
+		goto bad1;
+	}
+
+	r = init_origin_hash();
+	if (r) {
+		DMERR("init_origin_hash failed.");
+		goto bad2;
+	}
+
+	exception_cache = kmem_cache_create("dm-snapshot-ex",
+					    sizeof(struct exception),
+					    __alignof__(struct exception),
+					    0, NULL, NULL);
+	if (!exception_cache) {
+		DMERR("Couldn't create exception cache.");
+		r = -ENOMEM;
+		goto bad3;
+	}
+
+	pending_cache =
+	    kmem_cache_create("dm-snapshot-in",
+			      sizeof(struct pending_exception),
+			      __alignof__(struct pending_exception),
+			      0, NULL, NULL);
+	if (!pending_cache) {
+		DMERR("Couldn't create pending cache.");
+		r = -ENOMEM;
+		goto bad4;
+	}
+
+	pending_pool = mempool_create(128, mempool_alloc_slab,
+				      mempool_free_slab, pending_cache);
+	if (!pending_pool) {
+		DMERR("Couldn't create pending pool.");
+		r = -ENOMEM;
+		goto bad5;
+	}
+
+	return 0;
+
+      bad5:
+	kmem_cache_destroy(pending_cache);
+      bad4:
+	kmem_cache_destroy(exception_cache);
+      bad3:
+	exit_origin_hash();
+      bad2:
+	dm_unregister_target(&origin_target);
+      bad1:
+	dm_unregister_target(&snapshot_target);
+	return r;
+}
+
+static void __exit dm_snapshot_exit(void)
+{
+	int r;
+
+	r = dm_unregister_target(&snapshot_target);
+	if (r)
+		DMERR("snapshot unregister failed %d", r);
+
+	r = dm_unregister_target(&origin_target);
+	if (r)
+		DMERR("origin unregister failed %d", r);
+
+	exit_origin_hash();
+	mempool_destroy(pending_pool);
+	kmem_cache_destroy(pending_cache);
+	kmem_cache_destroy(exception_cache);
+}
+
+/* Module hooks */
+module_init(dm_snapshot_init);
+module_exit(dm_snapshot_exit);
+
+MODULE_DESCRIPTION(DM_NAME " snapshot target");
+MODULE_AUTHOR("Joe Thornber");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-snap.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,161 @@
+/*
+ * dm-snapshot.c
+ *
+ * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_SNAPSHOT_H
+#define DM_SNAPSHOT_H
+
+#include "dm.h"
+#include <linux/blkdev.h>
+
+struct exception_table {
+	uint32_t hash_mask;
+	struct list_head *table;
+};
+
+/*
+ * The snapshot code deals with largish chunks of the disk at a
+ * time. Typically 64k - 256k.
+ */
+/* FIXME: can we get away with limiting these to a uint32_t ? */
+typedef sector_t chunk_t;
+
+/*
+ * An exception is used where an old chunk of data has been
+ * replaced by a new one.
+ */
+struct exception {
+	struct list_head hash_list;
+
+	chunk_t old_chunk;
+	chunk_t new_chunk;
+};
+
+/*
+ * Abstraction to handle the meta/layout of exception stores (the
+ * COW device).
+ */
+struct exception_store {
+
+	/*
+	 * Destroys this object when you've finished with it.
+	 */
+	void (*destroy) (struct exception_store *store);
+
+	/*
+	 * The target shouldn't read the COW device until this is
+	 * called.
+	 */
+	int (*read_metadata) (struct exception_store *store);
+
+	/*
+	 * Find somewhere to store the next exception.
+	 */
+	int (*prepare_exception) (struct exception_store *store,
+				  struct exception *e);
+
+	/*
+	 * Update the metadata with this exception.
+	 */
+	void (*commit_exception) (struct exception_store *store,
+				  struct exception *e,
+				  void (*callback) (void *, int success),
+				  void *callback_context);
+
+	/*
+	 * The snapshot is invalid, note this in the metadata.
+	 */
+	void (*drop_snapshot) (struct exception_store *store);
+
+	/*
+	 * Return how full the snapshot is.
+	 */
+	void (*fraction_full) (struct exception_store *store,
+			       sector_t *numerator,
+			       sector_t *denominator);
+
+	struct dm_snapshot *snap;
+	void *context;
+};
+
+struct dm_snapshot {
+	struct rw_semaphore lock;
+	struct dm_table *table;
+
+	struct dm_dev *origin;
+	struct dm_dev *cow;
+
+	/* List of snapshots per Origin */
+	struct list_head list;
+
+	/* Size of data blocks saved - must be a power of 2 */
+	chunk_t chunk_size;
+	chunk_t chunk_mask;
+	chunk_t chunk_shift;
+
+	/* You can't use a snapshot if this is 0 (e.g. if full) */
+	int valid;
+	int have_metadata;
+
+	/* Used for display of table */
+	char type;
+
+	/* The last percentage we notified */
+	int last_percent;
+
+	struct exception_table pending;
+	struct exception_table complete;
+
+	/* The on disk metadata handler */
+	struct exception_store store;
+
+	struct kcopyd_client *kcopyd_client;
+};
+
+/*
+ * Used by the exception stores to load exceptions hen
+ * initialising.
+ */
+int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new);
+
+/*
+ * Constructor and destructor for the default persistent
+ * store.
+ */
+int dm_create_persistent(struct exception_store *store, uint32_t chunk_size);
+
+int dm_create_transient(struct exception_store *store,
+			struct dm_snapshot *s, int blocksize);
+
+/*
+ * Return the number of sectors in the device.
+ */
+static inline sector_t get_dev_size(struct block_device *bdev)
+{
+	return bdev->bd_inode->i_size >> SECTOR_SHIFT;
+}
+
+static inline chunk_t sector_to_chunk(struct dm_snapshot *s, sector_t sector)
+{
+	return (sector & ~s->chunk_mask) >> s->chunk_shift;
+}
+
+static inline sector_t chunk_to_sector(struct dm_snapshot *s, chunk_t chunk)
+{
+	return chunk << s->chunk_shift;
+}
+
+static inline int bdev_equal(struct block_device *lhs, struct block_device *rhs)
+{
+	/*
+	 * There is only ever one instance of a particular block
+	 * device so we can compare pointers safely.
+	 */
+	return lhs == rhs;
+}
+
+#endif
diff -Nru a/drivers/md/dm-table.c b/drivers/md/dm-table.c
--- a/drivers/md/dm-table.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/md/dm-table.c	2004-06-23 19:04:28 -07:00
@@ -400,7 +400,7 @@
 	struct dm_dev dd_copy;
 	dev_t dev = dd->bdev->bd_dev;
 
-	memcpy(&dd_copy, dd, sizeof(dd_copy));
+	dd_copy = *dd;
 
 	dd->mode |= new_mode;
 	dd->bdev = NULL;
@@ -408,7 +408,7 @@
 	if (!r)
 		close_dev(&dd_copy);
 	else
-		memcpy(dd, &dd_copy, sizeof(dd_copy));
+		*dd = dd_copy;
 
 	return r;
 }
diff -Nru a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-zero.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/bio.h>
+
+/*
+ * Construct a dummy mapping that only returns zeros
+ */
+static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+	if (argc != 0) {
+		ti->error = "dm-zero: No arguments required";
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * 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,
+		      union map_info *map_context)
+{
+	switch(bio_rw(bio)) {
+	case READ:
+		zero_fill_bio(bio);
+		break;
+	case READA:
+		/* readahead of null bytes only wastes buffer cache */
+		return -EIO;
+	case WRITE:
+		/* writes get silently dropped */
+		break;
+	}
+
+	bio_endio(bio, bio->bi_size, 0);
+
+	/* accepted bio, don't make new request */
+	return 0;
+}
+
+static struct target_type zero_target = {
+	.name   = "zero",
+	.version = {1, 0, 0},
+	.module = THIS_MODULE,
+	.ctr    = zero_ctr,
+	.map    = zero_map,
+};
+
+int __init dm_zero_init(void)
+{
+	int r = dm_register_target(&zero_target);
+
+	if (r < 0)
+		DMERR("zero: register failed %d", r);
+
+	return r;
+}
+
+void __exit dm_zero_exit(void)
+{
+	int r = dm_unregister_target(&zero_target);
+
+	if (r < 0)
+		DMERR("zero: unregister failed %d", r);
+}
+
+module_init(dm_zero_init)
+module_exit(dm_zero_exit)
+
+MODULE_AUTHOR("Christophe Saout <christophe@saout.de>");
+MODULE_DESCRIPTION(DM_NAME " dummy target returning zeros");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/md/dm.c	2004-06-23 19:04:28 -07:00
@@ -394,7 +394,7 @@
 	struct bio_vec *bv = bio->bi_io_vec + idx;
 
 	clone = bio_alloc(GFP_NOIO, 1);
-	memcpy(clone->bi_io_vec, bv, sizeof(*bv));
+	*clone->bi_io_vec = *bv;
 
 	clone->bi_sector = sector;
 	clone->bi_bdev = bio->bi_bdev;
diff -Nru a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/kcopyd.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2002 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ *
+ * Kcopyd provides a simple interface for copying an area of one
+ * block-device to one or more other block-devices, with an asynchronous
+ * completion notification.
+ */
+
+#include <asm/atomic.h>
+
+#include <linux/blkdev.h>
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mempool.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+
+#include "kcopyd.h"
+
+/* FIXME: this is only needed for the DMERR macros */
+#include "dm.h"
+
+static struct workqueue_struct *_kcopyd_wq;
+static struct work_struct _kcopyd_work;
+
+static inline void wake(void)
+{
+	queue_work(_kcopyd_wq, &_kcopyd_work);
+}
+
+/*-----------------------------------------------------------------
+ * Each kcopyd client has its own little pool of preallocated
+ * pages for kcopyd io.
+ *---------------------------------------------------------------*/
+struct kcopyd_client {
+	struct list_head list;
+
+	spinlock_t lock;
+	struct page_list *pages;
+	unsigned int nr_pages;
+	unsigned int nr_free_pages;
+};
+
+static struct page_list *alloc_pl(void)
+{
+	struct page_list *pl;
+
+	pl = kmalloc(sizeof(*pl), GFP_KERNEL);
+	if (!pl)
+		return NULL;
+
+	pl->page = alloc_page(GFP_KERNEL);
+	if (!pl->page) {
+		kfree(pl);
+		return NULL;
+	}
+
+	return pl;
+}
+
+static void free_pl(struct page_list *pl)
+{
+	__free_page(pl->page);
+	kfree(pl);
+}
+
+static int kcopyd_get_pages(struct kcopyd_client *kc,
+			    unsigned int nr, struct page_list **pages)
+{
+	struct page_list *pl;
+
+	spin_lock(&kc->lock);
+	if (kc->nr_free_pages < nr) {
+		spin_unlock(&kc->lock);
+		return -ENOMEM;
+	}
+
+	kc->nr_free_pages -= nr;
+	for (*pages = pl = kc->pages; --nr; pl = pl->next)
+		;
+
+	kc->pages = pl->next;
+	pl->next = 0;
+
+	spin_unlock(&kc->lock);
+
+	return 0;
+}
+
+static void kcopyd_put_pages(struct kcopyd_client *kc, struct page_list *pl)
+{
+	struct page_list *cursor;
+
+	spin_lock(&kc->lock);
+	for (cursor = pl; cursor->next; cursor = cursor->next)
+		kc->nr_free_pages++;
+
+	kc->nr_free_pages++;
+	cursor->next = kc->pages;
+	kc->pages = pl;
+	spin_unlock(&kc->lock);
+}
+
+/*
+ * These three functions resize the page pool.
+ */
+static void drop_pages(struct page_list *pl)
+{
+	struct page_list *next;
+
+	while (pl) {
+		next = pl->next;
+		free_pl(pl);
+		pl = next;
+	}
+}
+
+static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr)
+{
+	unsigned int i;
+	struct page_list *pl = NULL, *next;
+
+	for (i = 0; i < nr; i++) {
+		next = alloc_pl();
+		if (!next) {
+			if (pl)
+				drop_pages(pl);
+			return -ENOMEM;
+		}
+		next->next = pl;
+		pl = next;
+	}
+
+	kcopyd_put_pages(kc, pl);
+	kc->nr_pages += nr;
+	return 0;
+}
+
+static void client_free_pages(struct kcopyd_client *kc)
+{
+	BUG_ON(kc->nr_free_pages != kc->nr_pages);
+	drop_pages(kc->pages);
+	kc->pages = NULL;
+	kc->nr_free_pages = kc->nr_pages = 0;
+}
+
+/*-----------------------------------------------------------------
+ * kcopyd_jobs need to be allocated by the *clients* of kcopyd,
+ * for this reason we use a mempool to prevent the client from
+ * ever having to do io (which could cause a deadlock).
+ *---------------------------------------------------------------*/
+struct kcopyd_job {
+	struct kcopyd_client *kc;
+	struct list_head list;
+	unsigned long flags;
+
+	/*
+	 * Error state of the job.
+	 */
+	int read_err;
+	unsigned int write_err;
+
+	/*
+	 * Either READ or WRITE
+	 */
+	int rw;
+	struct io_region source;
+
+	/*
+	 * The destinations for the transfer.
+	 */
+	unsigned int num_dests;
+	struct io_region dests[KCOPYD_MAX_REGIONS];
+
+	sector_t offset;
+	unsigned int nr_pages;
+	struct page_list *pages;
+
+	/*
+	 * Set this to ensure you are notified when the job has
+	 * completed.  'context' is for callback to use.
+	 */
+	kcopyd_notify_fn fn;
+	void *context;
+
+	/*
+	 * These fields are only used if the job has been split
+	 * into more manageable parts.
+	 */
+	struct semaphore lock;
+	atomic_t sub_jobs;
+	sector_t progress;
+};
+
+/* FIXME: this should scale with the number of pages */
+#define MIN_JOBS 512
+
+static kmem_cache_t *_job_cache;
+static mempool_t *_job_pool;
+
+/*
+ * We maintain three lists of jobs:
+ *
+ * i)   jobs waiting for pages
+ * ii)  jobs that have pages, and are waiting for the io to be issued.
+ * iii) jobs that have completed.
+ *
+ * All three of these are protected by job_lock.
+ */
+static spinlock_t _job_lock = SPIN_LOCK_UNLOCKED;
+
+static LIST_HEAD(_complete_jobs);
+static LIST_HEAD(_io_jobs);
+static LIST_HEAD(_pages_jobs);
+
+static int jobs_init(void)
+{
+	_job_cache = kmem_cache_create("kcopyd-jobs",
+				       sizeof(struct kcopyd_job),
+				       __alignof__(struct kcopyd_job),
+				       0, NULL, NULL);
+	if (!_job_cache)
+		return -ENOMEM;
+
+	_job_pool = mempool_create(MIN_JOBS, mempool_alloc_slab,
+				   mempool_free_slab, _job_cache);
+	if (!_job_pool) {
+		kmem_cache_destroy(_job_cache);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void jobs_exit(void)
+{
+	BUG_ON(!list_empty(&_complete_jobs));
+	BUG_ON(!list_empty(&_io_jobs));
+	BUG_ON(!list_empty(&_pages_jobs));
+
+	mempool_destroy(_job_pool);
+	kmem_cache_destroy(_job_cache);
+	_job_pool = NULL;
+	_job_cache = NULL;
+}
+
+/*
+ * Functions to push and pop a job onto the head of a given job
+ * list.
+ */
+static inline struct kcopyd_job *pop(struct list_head *jobs)
+{
+	struct kcopyd_job *job = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&_job_lock, flags);
+
+	if (!list_empty(jobs)) {
+		job = list_entry(jobs->next, struct kcopyd_job, list);
+		list_del(&job->list);
+	}
+	spin_unlock_irqrestore(&_job_lock, flags);
+
+	return job;
+}
+
+static inline void push(struct list_head *jobs, struct kcopyd_job *job)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&_job_lock, flags);
+	list_add_tail(&job->list, jobs);
+	spin_unlock_irqrestore(&_job_lock, flags);
+}
+
+/*
+ * These three functions process 1 item from the corresponding
+ * job list.
+ *
+ * They return:
+ * < 0: error
+ *   0: success
+ * > 0: can't process yet.
+ */
+static int run_complete_job(struct kcopyd_job *job)
+{
+	void *context = job->context;
+	int read_err = job->read_err;
+	unsigned int write_err = job->write_err;
+	kcopyd_notify_fn fn = job->fn;
+
+	kcopyd_put_pages(job->kc, job->pages);
+	mempool_free(job, _job_pool);
+	fn(read_err, write_err, context);
+	return 0;
+}
+
+static void complete_io(unsigned long error, void *context)
+{
+	struct kcopyd_job *job = (struct kcopyd_job *) context;
+
+	if (error) {
+		if (job->rw == WRITE)
+			job->write_err &= error;
+		else
+			job->read_err = 1;
+
+		if (!test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
+			push(&_complete_jobs, job);
+			wake();
+			return;
+		}
+	}
+
+	if (job->rw == WRITE)
+		push(&_complete_jobs, job);
+
+	else {
+		job->rw = WRITE;
+		push(&_io_jobs, job);
+	}
+
+	wake();
+}
+
+/*
+ * Request io on as many buffer heads as we can currently get for
+ * a particular job.
+ */
+static int run_io_job(struct kcopyd_job *job)
+{
+	int r;
+
+	if (job->rw == READ)
+		r = dm_io_async(1, &job->source, job->rw,
+				job->pages,
+				job->offset, complete_io, job);
+
+	else
+		r = dm_io_async(job->num_dests, job->dests, job->rw,
+				job->pages,
+				job->offset, complete_io, job);
+
+	return r;
+}
+
+static int run_pages_job(struct kcopyd_job *job)
+{
+	int r;
+
+	job->nr_pages = dm_div_up(job->dests[0].count + job->offset,
+				  PAGE_SIZE >> 9);
+	r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages);
+	if (!r) {
+		/* this job is ready for io */
+		push(&_io_jobs, job);
+		return 0;
+	}
+
+	if (r == -ENOMEM)
+		/* can't complete now */
+		return 1;
+
+	return r;
+}
+
+/*
+ * Run through a list for as long as possible.  Returns the count
+ * of successful jobs.
+ */
+static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
+{
+	struct kcopyd_job *job;
+	int r, count = 0;
+
+	while ((job = pop(jobs))) {
+
+		r = fn(job);
+
+		if (r < 0) {
+			/* error this rogue job */
+			if (job->rw == WRITE)
+				job->write_err = (unsigned int) -1;
+			else
+				job->read_err = 1;
+			push(&_complete_jobs, job);
+			break;
+		}
+
+		if (r > 0) {
+			/*
+			 * We couldn't service this job ATM, so
+			 * push this job back onto the list.
+			 */
+			push(jobs, job);
+			break;
+		}
+
+		count++;
+	}
+
+	return count;
+}
+
+/*
+ * kcopyd does this every time it's woken up.
+ */
+static void do_work(void *ignored)
+{
+	/*
+	 * The order that these are called is *very* important.
+	 * complete jobs can free some pages for pages jobs.
+	 * Pages jobs when successful will jump onto the io jobs
+	 * list.  io jobs call wake when they complete and it all
+	 * starts again.
+	 */
+	process_jobs(&_complete_jobs, run_complete_job);
+	process_jobs(&_pages_jobs, run_pages_job);
+	process_jobs(&_io_jobs, run_io_job);
+}
+
+/*
+ * If we are copying a small region we just dispatch a single job
+ * to do the copy, otherwise the io has to be split up into many
+ * jobs.
+ */
+static void dispatch_job(struct kcopyd_job *job)
+{
+	push(&_pages_jobs, job);
+	wake();
+}
+
+#define SUB_JOB_SIZE 128
+static void segment_complete(int read_err,
+			     unsigned int write_err, void *context)
+{
+	/* FIXME: tidy this function */
+	sector_t progress = 0;
+	sector_t count = 0;
+	struct kcopyd_job *job = (struct kcopyd_job *) context;
+
+	down(&job->lock);
+
+	/* update the error */
+	if (read_err)
+		job->read_err = 1;
+
+	if (write_err)
+		job->write_err &= write_err;
+
+	/*
+	 * Only dispatch more work if there hasn't been an error.
+	 */
+	if ((!job->read_err && !job->write_err) ||
+	    test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
+		/* get the next chunk of work */
+		progress = job->progress;
+		count = job->source.count - progress;
+		if (count) {
+			if (count > SUB_JOB_SIZE)
+				count = SUB_JOB_SIZE;
+
+			job->progress += count;
+		}
+	}
+	up(&job->lock);
+
+	if (count) {
+		int i;
+		struct kcopyd_job *sub_job = mempool_alloc(_job_pool, GFP_NOIO);
+
+		*sub_job = *job;
+		sub_job->source.sector += progress;
+		sub_job->source.count = count;
+
+		for (i = 0; i < job->num_dests; i++) {
+			sub_job->dests[i].sector += progress;
+			sub_job->dests[i].count = count;
+		}
+
+		sub_job->fn = segment_complete;
+		sub_job->context = job;
+		dispatch_job(sub_job);
+
+	} else if (atomic_dec_and_test(&job->sub_jobs)) {
+
+		/*
+		 * To avoid a race we must keep the job around
+		 * until after the notify function has completed.
+		 * Otherwise the client may try and stop the job
+		 * after we've completed.
+		 */
+		job->fn(read_err, write_err, job->context);
+		mempool_free(job, _job_pool);
+	}
+}
+
+/*
+ * Create some little jobs that will do the move between
+ * them.
+ */
+#define SPLIT_COUNT 8
+static void split_job(struct kcopyd_job *job)
+{
+	int i;
+
+	atomic_set(&job->sub_jobs, SPLIT_COUNT);
+	for (i = 0; i < SPLIT_COUNT; i++)
+		segment_complete(0, 0u, job);
+}
+
+int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+		unsigned int num_dests, struct io_region *dests,
+		unsigned int flags, kcopyd_notify_fn fn, void *context)
+{
+	struct kcopyd_job *job;
+
+	/*
+	 * Allocate a new job.
+	 */
+	job = mempool_alloc(_job_pool, GFP_NOIO);
+
+	/*
+	 * set up for the read.
+	 */
+	job->kc = kc;
+	job->flags = flags;
+	job->read_err = 0;
+	job->write_err = 0;
+	job->rw = READ;
+
+	job->source = *from;
+
+	job->num_dests = num_dests;
+	memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
+
+	job->offset = 0;
+	job->nr_pages = 0;
+	job->pages = NULL;
+
+	job->fn = fn;
+	job->context = context;
+
+	if (job->source.count < SUB_JOB_SIZE)
+		dispatch_job(job);
+
+	else {
+		init_MUTEX(&job->lock);
+		job->progress = 0;
+		split_job(job);
+	}
+
+	return 0;
+}
+
+/*
+ * Cancels a kcopyd job, eg. someone might be deactivating a
+ * mirror.
+ */
+int kcopyd_cancel(struct kcopyd_job *job, int block)
+{
+	/* FIXME: finish */
+	return -1;
+}
+
+/*-----------------------------------------------------------------
+ * Unit setup
+ *---------------------------------------------------------------*/
+static DECLARE_MUTEX(_client_lock);
+static LIST_HEAD(_clients);
+
+static int client_add(struct kcopyd_client *kc)
+{
+	down(&_client_lock);
+	list_add(&kc->list, &_clients);
+	up(&_client_lock);
+	return 0;
+}
+
+static void client_del(struct kcopyd_client *kc)
+{
+	down(&_client_lock);
+	list_del(&kc->list);
+	up(&_client_lock);
+}
+
+static DECLARE_MUTEX(kcopyd_init_lock);
+static int kcopyd_clients = 0;
+
+static int kcopyd_init(void)
+{
+	int r;
+
+	down(&kcopyd_init_lock);
+
+	if (kcopyd_clients) {
+		/* Already initialized. */
+		kcopyd_clients++;
+		up(&kcopyd_init_lock);
+		return 0;
+	}
+
+	r = jobs_init();
+	if (r) {
+		up(&kcopyd_init_lock);
+		return r;
+	}
+
+	_kcopyd_wq = create_singlethread_workqueue("kcopyd");
+	if (!_kcopyd_wq) {
+		jobs_exit();
+		up(&kcopyd_init_lock);
+		return -ENOMEM;
+	}
+
+	kcopyd_clients++;
+	INIT_WORK(&_kcopyd_work, do_work, NULL);
+	up(&kcopyd_init_lock);
+	return 0;
+}
+
+static void kcopyd_exit(void)
+{
+	down(&kcopyd_init_lock);
+	kcopyd_clients--;
+	if (!kcopyd_clients) {
+		jobs_exit();
+		destroy_workqueue(_kcopyd_wq);
+		_kcopyd_wq = NULL;
+	}
+	up(&kcopyd_init_lock);
+}
+
+int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
+{
+	int r = 0;
+	struct kcopyd_client *kc;
+
+	r = kcopyd_init();
+	if (r)
+		return r;
+
+	kc = kmalloc(sizeof(*kc), GFP_KERNEL);
+	if (!kc) {
+		kcopyd_exit();
+		return -ENOMEM;
+	}
+
+	kc->lock = SPIN_LOCK_UNLOCKED;
+	kc->pages = NULL;
+	kc->nr_pages = kc->nr_free_pages = 0;
+	r = client_alloc_pages(kc, nr_pages);
+	if (r) {
+		kfree(kc);
+		kcopyd_exit();
+		return r;
+	}
+
+	r = dm_io_get(nr_pages);
+	if (r) {
+		client_free_pages(kc);
+		kfree(kc);
+		kcopyd_exit();
+		return r;
+	}
+
+	r = client_add(kc);
+	if (r) {
+		dm_io_put(nr_pages);
+		client_free_pages(kc);
+		kfree(kc);
+		kcopyd_exit();
+		return r;
+	}
+
+	*result = kc;
+	return 0;
+}
+
+void kcopyd_client_destroy(struct kcopyd_client *kc)
+{
+	dm_io_put(kc->nr_pages);
+	client_free_pages(kc);
+	client_del(kc);
+	kfree(kc);
+	kcopyd_exit();
+}
+
+EXPORT_SYMBOL(kcopyd_client_create);
+EXPORT_SYMBOL(kcopyd_client_destroy);
+EXPORT_SYMBOL(kcopyd_copy);
+EXPORT_SYMBOL(kcopyd_cancel);
diff -Nru a/drivers/md/kcopyd.h b/drivers/md/kcopyd.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/kcopyd.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2001 Sistina Software
+ *
+ * This file is released under the GPL.
+ *
+ * Kcopyd provides a simple interface for copying an area of one
+ * block-device to one or more other block-devices, with an asynchronous
+ * completion notification.
+ */
+
+#ifndef DM_KCOPYD_H
+#define DM_KCOPYD_H
+
+#include "dm-io.h"
+
+/* FIXME: make this configurable */
+#define KCOPYD_MAX_REGIONS 8
+
+#define KCOPYD_IGNORE_ERROR 1
+
+/*
+ * To use kcopyd you must first create a kcopyd client object.
+ */
+struct kcopyd_client;
+int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result);
+void kcopyd_client_destroy(struct kcopyd_client *kc);
+
+/*
+ * Submit a copy job to kcopyd.  This is built on top of the
+ * previous three fns.
+ *
+ * read_err is a boolean,
+ * write_err is a bitset, with 1 bit for each destination region
+ */
+typedef void (*kcopyd_notify_fn)(int read_err,
+				 unsigned int write_err, void *context);
+
+int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+		unsigned int num_dests, struct io_region *dests,
+		unsigned int flags, kcopyd_notify_fn fn, void *context);
+
+#endif
diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c
--- a/drivers/md/raid1.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/md/raid1.c	2004-06-23 19:04:27 -07:00
@@ -376,7 +376,8 @@
 	 * device if no resync is going on, or below the resync window.
 	 * We take the first readable disk when above the resync window.
 	 */
-	if (!conf->mddev->in_sync && (this_sector + sectors >= conf->next_resync)) {
+	if (conf->mddev->recovery_cp < MaxSector &&
+	    (this_sector + sectors >= conf->next_resync)) {
 		/* make sure that disk is operational */
 		new_disk = 0;
 
diff -Nru a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
--- a/drivers/media/common/ir-common.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/common/ir-common.c	2004-06-23 19:04:28 -07:00
@@ -75,6 +75,8 @@
 	[ 0x35 ] = KEY_PLAY,            // play
 	[ 0x36 ] = KEY_STOP,            // stop
 	[ 0x37 ] = KEY_RECORD,          // recording
+	[ 0x3c ] = KEY_TEXT,            // teletext submode (Japan: 12)
+	[ 0x3d ] = KEY_SUSPEND,         // system standby
 
 #if 0 /* FIXME */
 	[ 0x0a ] = KEY_RESERVED,        // 1/2/3 digits (japan: 10)
@@ -106,8 +108,6 @@
 	[ 0x39 ] = KEY_RESERVED,        // external 2
 	[ 0x3a ] = KEY_RESERVED,        // PIP display mode
 	[ 0x3b ] = KEY_RESERVED,        // view data mode / advance
-	[ 0x3c ] = KEY_RESERVED,        // teletext submode (Japan: 12)
-	[ 0x3d ] = KEY_RESERVED,        // system standby
 	[ 0x3e ] = KEY_RESERVED,        // crispener on/off
 	[ 0x3f ] = KEY_RESERVED,        // system select
 #endif
diff -Nru a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
--- a/drivers/media/radio/radio-zoltrix.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/media/radio/radio-zoltrix.c	2004-06-23 19:04:29 -07:00
@@ -273,7 +273,7 @@
 	case VIDIOCGAUDIO:
 		{
 			struct video_audio *v = arg;
-			memset(&v, 0, sizeof(*v));
+			memset(v, 0, sizeof(*v));
 			v->flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
 			v->mode |= zol_is_stereo(zol)
 				? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
diff -Nru a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
--- a/drivers/media/video/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/video/Kconfig	2004-06-23 19:04:28 -07:00
@@ -295,5 +295,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called cx8800
 
+config VIDEO_OVCAMCHIP
+	tristate "OmniVision Camera Chip support"
+	depends on VIDEO_DEV && I2C
+	---help---
+	  Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
+	  This driver is intended to be used with the ov511 and w9968cf USB
+	  camera drivers.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ovcamchip
+
 endmenu
 
diff -Nru a/drivers/media/video/Makefile b/drivers/media/video/Makefile
--- a/drivers/media/video/Makefile	2004-06-23 19:04:26 -07:00
+++ b/drivers/media/video/Makefile	2004-06-23 19:04:26 -07:00
@@ -37,6 +37,7 @@
 obj-$(CONFIG_VIDEO_MEYE) += meye.o
 obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
 obj-$(CONFIG_VIDEO_CX88) += cx88/
+obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
 obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
 obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
diff -Nru a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
--- a/drivers/media/video/bttv-cards.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/media/video/bttv-cards.c	2004-06-23 19:04:27 -07:00
@@ -71,6 +71,9 @@
 
 static void PXC200_muxsel(struct bttv *btv, unsigned int input);
 
+static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input);
+static void picolo_tetra_init(struct bttv *btv);
+
 static int terratec_active_radio_upgrade(struct bttv *btv);
 static int tea5757_read(struct bttv *btv);
 static int tea5757_write(struct bttv *btv, int value);
@@ -181,6 +184,7 @@
 	{ 0xff00bd11, BTTV_PINNACLE,      "Pinnacle PCTV [bswap]" },
 
 	{ 0x3000121a, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
+	{ 0x263710b4, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
 	{ 0x3060121a, BTTV_STB2,	  "3Dfx VoodooTV 100/ STB OEM" },
 	
 	{ 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
@@ -260,12 +264,15 @@
 	{ 0x41424344, BTTV_GRANDTEC,      "GrandTec Multi Capture" },
 	{ 0x01020304, BTTV_XGUARD,        "Grandtec Grand X-Guard" },
 	
-    	{ 0x010115cb, BTTV_GMV1,          "AG GMV1" },
-	{ 0x010114c7, BTTV_MODTEC_205,    "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
 	{ 0x18501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
 	{ 0x18511851, BTTV_FLYVIDEO98EZ,  "FlyVideo 98EZ (LR51)/ CyberMail AV" },
 	{ 0x18521852, BTTV_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
 	{ 0x41a0a051, BTTV_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" },
+	{ 0x18501f7f, BTTV_FLYVIDEO_98,   "Lifeview Flyvideo 98" },
+
+    	{ 0x010115cb, BTTV_GMV1,          "AG GMV1" },
+	{ 0x010114c7, BTTV_MODTEC_205,    "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
+
 	{ 0x10b42636, BTTV_HAUPPAUGE878,  "STB ???" },
 	{ 0x217d6606, BTTV_WINFAST2000,   "Leadtek WinFast TV 2000" },
 	{ 0xfff6f6ff, BTTV_WINFAST2000,   "Leadtek WinFast TV 2000" },
@@ -280,14 +287,21 @@
 	{ 0x40111554, BTTV_PV_BT878P_9B,  "Prolink Pixelview PV-BT" },
 	{ 0x17de0a01, BTTV_KWORLD,        "Mecer TV/FM/Video Tuner" },
 
+	{ 0x01051805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" },
+	{ 0x01061805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" },
+	{ 0x01071805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" },
+	{ 0x01081805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" },
+
 	// likely broken, vendor id doesn't match the other magic views ...
 	//{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
 	
 	// DVB cards (using pci function .1 for mpeg data xfer)
 	{ 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
+	{ 0x07611461, BTTV_NEBULA_DIGITV, "AverMedia AverTV DVB-T" },
 	{ 0x002611bd, BTTV_TWINHAN_DST,   "Pinnacle PCTV SAT CI" },
 	{ 0x00011822, BTTV_TWINHAN_DST,   "Twinhan VisionPlus DVB-T" },
 	{ 0xfc00270f, BTTV_TWINHAN_DST,   "ChainTech digitop DST-1000 DVB-S" },
+	{ 0x07711461, BTTV_AVDVBT_771,    "AVermedia DVB-T 771" },
 	
 	{ 0, -1, NULL }
 };
@@ -835,7 +849,7 @@
 	.svhs		= 2,
 	.gpiomask	= 0x03000F,
 	.muxsel		= { 2, 3, 1, 1},
-	.audiomux	= { 2, 0, 0, 0, 1},
+	.audiomux	= { 2, 0xd0001, 0, 0, 1},
 	.needs_tvaudio	= 0,
 	.pll		= PLL_28,
 	.tuner_type	= -1,
@@ -1646,6 +1660,7 @@
 	.muxsel         = { 3, 0, 1, 2},
 	.needs_tvaudio  = 0, 
 	.pll            = PLL_28,
+	.no_gpioirq     = 1,
 },{
         .name           = "Formac ProTV II (bt878)",
         .video_inputs   = 4,
@@ -2012,6 +2027,57 @@
 	.tuner_type     = TUNER_PHILIPS_PAL,
 	.has_remote     = 1,
 	.has_radio      = 1,
+},{
+	/*Eric DEBIEF <debief@telemsa.com>*/
+	/*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/
+	/* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_PICOLO_TETRA_CHIP*/
+	/*0x79 in bttv.h*/
+	.name           = "Euresys Picolo Tetra",
+	.video_inputs   = 4,
+	.audio_inputs   = 0,
+	.tuner          = -1,
+	.svhs           = -1,
+	.gpiomask       = 0,
+	.gpiomask2      = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/
+	.no_msp34xx     = 1,
+	.no_tda9875     = 1,
+	.no_tda7432     = 1,
+	.muxsel         = {2,2,2,2},/*878A input is always MUX0, see above.*/
+	.audiomux       = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+	.pll            = PLL_28,
+	.needs_tvaudio  = 0,
+	.muxsel_hook    = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
+},{
+	/* Spirit TV Tuner from http://spiritmodems.com.au */
+	/* Stafford Goodsell <surge@goliath.homeunix.org> */
+	.name           = "Spirit TV Tuner",
+	.video_inputs   = 3,
+	.audio_inputs   = 1,
+	.tuner          = 0,
+	.svhs           = 2,
+	.gpiomask       = 0x0000000f,
+	.muxsel         = { 2, 1, 1 },
+	.audiomux       = { 0x02, 0x00, 0x00, 0x00, 0x00},
+	.tuner_type     = TUNER_TEMIC_PAL,
+	.no_msp34xx     = 1,
+	.no_tda9875     = 1,
+},{
+	/* Wolfram Joost <wojo@frokaschwei.de> */
+        .name           = "AVerMedia AVerTV DVB-T 771",
+        .video_inputs   = 2,
+        .svhs           = 1,
+        .tuner          = -1,
+        .tuner_type     = TUNER_ABSENT,
+        .muxsel         = { 3 , 3 },
+        .no_msp34xx     = 1,
+        .no_tda9875     = 1,
+        .no_tda7432     = 1,
+        .pll            = PLL_28,
+        .has_dvb        = 1,
+        .no_gpioirq     = 1,
+#if 0 /* untested */
+        .has_remote     = 1,
+#endif
 }};
 
 const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2381,6 +2447,7 @@
 		pvr_boot(btv);
 		break;
 	case BTTV_TWINHAN_DST:
+	case BTTV_AVDVBT_771:
 		btv->use_i2c_hw = 1;
 		break;
 	}
@@ -2432,6 +2499,9 @@
 	case BTTV_PXC200:
 		init_PXC200(btv);
 		break;
+	case BTTV_PICOLO_TETRA_CHIP:
+		picolo_tetra_init(btv);
+		break;
 	case BTTV_VHX:
 		btv->has_radio    = 1;
 		btv->has_matchbox = 1;
@@ -2668,6 +2738,10 @@
 		btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I;
 		printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
                        btv->c.nr,&eeprom_data[0x1e]);
+        } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) {
+                btv->tuner_type=TUNER_PHILIPS_NTSC;
+                printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
+                       btv->c.nr,&eeprom_data[0x1e]);
 	} else {
 		printk("bttv%d: Modtec: Unknown TunerString: %s\n",
 		       btv->c.nr,&eeprom_data[0x1e]);
@@ -3785,6 +3859,21 @@
                 ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11,
 	};
 	gpio_write(masks[input%16]);
+}
+static void picolo_tetra_init(struct bttv *btv)
+{
+	/*This is the video input redirection fonctionality : I DID NOT USED IT. */
+	btwrite (0x08<<16,BT848_GPIO_DATA);/*GPIO[19] [==> 4053 B+C] set to 1 */
+	btwrite (0x04<<16,BT848_GPIO_DATA);/*GPIO[18] [==> 4053 A]  set to 1*/
+}
+static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
+{
+
+	dprintk (KERN_DEBUG "bttv%d : picolo_tetra_muxsel =>  input = %d\n",btv->c.nr,input);
+	/*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/
+	/*GPIO[20]&GPIO[21] used to choose the right input*/
+	btwrite (input<<20,BT848_GPIO_DATA);
+
 }
 
 /*
diff -Nru a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
--- a/drivers/media/video/bttv-driver.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/video/bttv-driver.c	2004-06-23 19:04:28 -07:00
@@ -1334,7 +1334,8 @@
 	spin_lock_irqsave(&btv->s_lock,flags);
 	old = btv->screen;
 	btv->screen = new;
-	bttv_set_dma(btv, 0x03, 1);
+	btv->curr.irqflags |= 1;
+	bttv_set_dma(btv, 0x03, btv->curr.irqflags);
 	spin_unlock_irqrestore(&btv->s_lock,flags);
 	if (NULL == new)
 		free_btres(btv,fh,RESOURCE_OVERLAY);
@@ -1441,7 +1442,8 @@
 
 	buf->vb.state = STATE_QUEUED;
 	list_add_tail(&buf->vb.queue,&fh->btv->capture);
-	bttv_set_dma(fh->btv, 0x03, 1);
+	fh->btv->curr.irqflags |= 1;
+	bttv_set_dma(fh->btv, 0x03, fh->btv->curr.irqflags);
 }
 
 static void buffer_release(struct file *file, struct videobuf_buffer *vb)
@@ -3203,8 +3205,8 @@
 	printk("  main: %08Lx\n",
 	       (unsigned long long)btv->main.dma);
 	printk("  vbi : o=%08Lx e=%08Lx\n",
-	       btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0,
-	       btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0);
+	       btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
+	       btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
 	printk("  cap : o=%08Lx e=%08Lx\n",
 	       btv->curr.top    ? (unsigned long long)btv->curr.top->top.dma : 0,
 	       btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
@@ -3224,7 +3226,7 @@
 
 	if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
 		printk("bttv%d: Oh, there (temporarely?) is no input signal. "
-		       "Ok, then this is harmless, don't worry ;)",
+		       "Ok, then this is harmless, don't worry ;)\n",
 		       btv->c.nr);
 		return;
 	}
@@ -3236,18 +3238,12 @@
 }
 
 static int
-bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set)
+bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
 {
 	struct bttv_buffer *item;
 
 	memset(set,0,sizeof(*set));
 
-	/* vbi request ? */
-	if (!list_empty(&btv->vcapture)) {
-		set->irqflags = 1;
-		set->vbi = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
-	}
-
 	/* capture request ? */
 	if (!list_empty(&btv->capture)) {
 		set->irqflags = 1;
@@ -3295,27 +3291,20 @@
 		}
 	}
 
-	dprintk("bttv%d: next set: top=%p bottom=%p vbi=%p "
-		"[screen=%p,irq=%d,%d]\n",
-		btv->c.nr,set->top, set->bottom, set->vbi,
+	dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
+		btv->c.nr,set->top, set->bottom,
 		btv->screen,set->irqflags,set->topirq);
 	return 0;
 }
 
 static void
-bttv_irq_wakeup_set(struct bttv *btv, struct bttv_buffer_set *wakeup,
-		    struct bttv_buffer_set *curr, unsigned int state)
+bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
+		      struct bttv_buffer_set *curr, unsigned int state)
 {
 	struct timeval ts;
 
 	do_gettimeofday(&ts);
 
-	if (NULL != wakeup->vbi) {
-		wakeup->vbi->vb.ts = ts;
-		wakeup->vbi->vb.field_count = btv->field_count;
-		wakeup->vbi->vb.state = state;
-		wake_up(&wakeup->vbi->vb.done);
-	}
 	if (wakeup->top == wakeup->bottom) {
 		if (NULL != wakeup->top && curr->top != wakeup->top) {
 			if (irq_debug > 1)
@@ -3345,10 +3334,27 @@
 	}
 }
 
+static void
+bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
+		    unsigned int state)
+{
+	struct timeval ts;
+
+	if (NULL == wakeup)
+		return;
+
+	do_gettimeofday(&ts);
+	wakeup->vb.ts = ts;
+	wakeup->vb.field_count = btv->field_count;
+	wakeup->vb.state = state;
+	wake_up(&wakeup->vb.done);
+}
+
 static void bttv_irq_timeout(unsigned long data)
 {
 	struct bttv *btv = (struct bttv *)data;
 	struct bttv_buffer_set old,new;
+	struct bttv_buffer *ovbi;
 	struct bttv_buffer *item;
 	unsigned long flags;
 	
@@ -3364,13 +3370,17 @@
 	
 	/* deactivate stuff */
 	memset(&new,0,sizeof(new));
-	old = btv->curr;
+	old  = btv->curr;
+	ovbi = btv->cvbi;
 	btv->curr = new;
-	bttv_buffer_set_activate(btv, &new);
+	btv->cvbi = NULL;
+	bttv_buffer_activate_video(btv, &new);
+	bttv_buffer_activate_vbi(btv,   NULL);
 	bttv_set_dma(btv, 0, 0);
 
 	/* wake up */
-	bttv_irq_wakeup_set(btv, &old, &new, STATE_ERROR);
+	bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR);
+	bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR);
 
 	/* cancel all outstanding capture / vbi requests */
 	while (!list_empty(&btv->capture)) {
@@ -3410,8 +3420,17 @@
 	spin_unlock(&btv->s_lock);
 }
 
+static inline int is_active(struct btcx_riscmem *risc, u32 rc)
+{
+	if (rc < risc->dma)
+		return 0;
+	if (rc > risc->dma + risc->size)
+		return 0;
+	return 1;
+}
+
 static void
-bttv_irq_switch_fields(struct bttv *btv)
+bttv_irq_switch_video(struct bttv *btv)
 {
 	struct bttv_buffer_set new;
 	struct bttv_buffer_set old;
@@ -3420,9 +3439,10 @@
 	spin_lock(&btv->s_lock);
 
 	/* new buffer set */
-	bttv_irq_next_set(btv, &new);
+	bttv_irq_next_video(btv, &new);
 	rc = btread(BT848_RISC_COUNT);
-	if (rc < btv->main.dma || rc > btv->main.dma + 0x100) {
+	if ((btv->curr.top    && is_active(&btv->curr.top->top,       rc)) ||
+	    (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
 		btv->framedrop++;
 		if (debug_latency)
 			bttv_irq_debug_low_latency(btv, rc);
@@ -3433,7 +3453,7 @@
 	/* switch over */
 	old = btv->curr;
 	btv->curr = new;
-	bttv_buffer_set_activate(btv, &new);
+	bttv_buffer_activate_video(btv, &new);
 	bttv_set_dma(btv, 0, new.irqflags);
 
 	/* switch input */
@@ -3443,7 +3463,39 @@
 	}
 
 	/* wake up finished buffers */
-	bttv_irq_wakeup_set(btv, &old, &new, STATE_DONE);
+	bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE);
+	spin_unlock(&btv->s_lock);
+}
+
+static void
+bttv_irq_switch_vbi(struct bttv *btv)
+{
+	struct bttv_buffer *new = NULL;
+	struct bttv_buffer *old;
+	u32 rc;
+
+	spin_lock(&btv->s_lock);
+
+	if (!list_empty(&btv->vcapture))
+		new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
+	old = btv->cvbi;
+
+	rc = btread(BT848_RISC_COUNT);
+	if (NULL != old && (is_active(&old->top,    rc) ||
+			    is_active(&old->bottom, rc))) {
+		btv->framedrop++;
+		if (debug_latency)
+			bttv_irq_debug_low_latency(btv, rc);
+		spin_unlock(&btv->s_lock);
+		return;
+	}
+
+	/* switch */
+	btv->cvbi = new;
+	bttv_buffer_activate_vbi(btv, new);
+	bttv_set_dma(btv, 0, btv->curr.irqflags);
+
+	bttv_irq_wakeup_vbi(btv, old, STATE_DONE);
 	spin_unlock(&btv->s_lock);
 }
 
@@ -3500,11 +3552,14 @@
 			wake_up(&btv->i2c_queue);
 		}
 
+                if ((astat & BT848_INT_RISCI)  &&  (stat & (4<<28)))
+			bttv_irq_switch_vbi(btv);
+
                 if ((astat & BT848_INT_RISCI)  &&  (stat & (2<<28)))
 			bttv_irq_wakeup_top(btv);
 
                 if ((astat & BT848_INT_RISCI)  &&  (stat & (1<<28)))
-			bttv_irq_switch_fields(btv);
+			bttv_irq_switch_video(btv);
 
 		if ((astat & BT848_INT_HLOCK)  &&  btv->opt_automute)
 			audio_mux(btv, -1);
@@ -3872,9 +3927,11 @@
 	/* stop dma + irqs */
 	spin_lock_irqsave(&btv->s_lock,flags);
 	memset(&idle, 0, sizeof(idle));
-	btv->state.set = btv->curr;
+	btv->state.video = btv->curr;
+	btv->state.vbi   = btv->cvbi;
 	btv->curr = idle;
-	bttv_buffer_set_activate(btv, &idle);
+	bttv_buffer_activate_video(btv, &idle);
+	bttv_buffer_activate_vbi(btv, NULL);
 	bttv_set_dma(btv, 0, 0);
 	btwrite(0, BT848_INT_MASK);
 	spin_unlock_irqrestore(&btv->s_lock,flags);
@@ -3914,8 +3971,10 @@
 
 	/* restart dma */
 	spin_lock_irqsave(&btv->s_lock,flags);
-	btv->curr = btv->state.set;
-	bttv_buffer_set_activate(btv, &btv->curr);
+	btv->curr = btv->state.video;
+	btv->cvbi = btv->state.vbi;
+	bttv_buffer_activate_video(btv, &btv->curr);
+	bttv_buffer_activate_vbi(btv, btv->cvbi);
 	bttv_set_dma(btv, 0, btv->curr.irqflags);
 	spin_unlock_irqrestore(&btv->s_lock,flags);
 	return 0;
diff -Nru a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c
--- a/drivers/media/video/bttv-risc.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/media/video/bttv-risc.c	2004-06-23 19:04:27 -07:00
@@ -379,7 +379,7 @@
 	btv->cap_ctl = 0;
 	if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
 	if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
-	if (NULL != btv->curr.vbi)      btv->cap_ctl |= 0x0c;
+	if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
 
 	capctl  = 0;
 	capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
@@ -389,9 +389,9 @@
 	d2printk(KERN_DEBUG
 		 "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
 		 btv->c.nr,capctl,irqflags,
-		 btv->curr.vbi     ? (unsigned long long)btv->curr.vbi->top.dma        : 0,
+		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
 		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
-		 btv->curr.vbi     ? (unsigned long long)btv->curr.vbi->bottom.dma     : 0,
+		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
 		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
 	
 	cmd = BT848_RISC_JUMP;
@@ -399,6 +399,8 @@
 		cmd |= BT848_RISC_IRQ;
 		cmd |= (irqflags  & 0x0f) << 16;
 		cmd |= (~irqflags & 0x0f) << 20;
+	}
+	if (irqflags || btv->cvbi) {
 		mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
 	} else {
 		del_timer(&btv->timeout);
@@ -501,20 +503,26 @@
 }
 
 int
-bttv_buffer_set_activate(struct bttv *btv,
-			 struct bttv_buffer_set *set)
+bttv_buffer_activate_vbi(struct bttv *btv,
+			 struct bttv_buffer *vbi)
 {
 	/* vbi capture */
-	if (set->vbi) {
-		set->vbi->vb.state = STATE_ACTIVE;
-		list_del(&set->vbi->vb.queue);
-		bttv_risc_hook(btv, RISC_SLOT_O_VBI, &set->vbi->top,    0);
-		bttv_risc_hook(btv, RISC_SLOT_E_VBI, &set->vbi->bottom, 0);
+	if (vbi) {
+		vbi->vb.state = STATE_ACTIVE;
+		list_del(&vbi->vb.queue);
+		bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top,    0);
+		bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4);
 	} else {
 		bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
 		bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
 	}
+	return 0;
+}
 
+int
+bttv_buffer_activate_video(struct bttv *btv,
+			   struct bttv_buffer_set *set)
+{
 	/* video capture */
 	if (NULL != set->top  &&  NULL != set->bottom) {
 		if (set->top == set->bottom) {
diff -Nru a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c
--- a/drivers/media/video/bttv-vbi.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/media/video/bttv-vbi.c	2004-06-23 19:04:27 -07:00
@@ -114,7 +114,10 @@
 	dprintk("queue %p\n",vb);
 	buf->vb.state = STATE_QUEUED;
 	list_add_tail(&buf->vb.queue,&btv->vcapture);
-	bttv_set_dma(btv,0x0c,1);
+	if (NULL == btv->cvbi) {
+		fh->btv->curr.irqflags |= 4;
+		bttv_set_dma(btv,0x0c,fh->btv->curr.irqflags);
+	}
 }
 
 static void vbi_buffer_release(struct file *file, struct videobuf_buffer *vb)
diff -Nru a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
--- a/drivers/media/video/bttv.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/media/video/bttv.h	2004-06-23 19:04:25 -07:00
@@ -124,6 +124,8 @@
 #define BTTV_SIMUS_GVC1100  0x74
 #define BTTV_NGSTV_PLUS     0x75
 #define BTTV_LMLBT4         0x76
+#define BTTV_PICOLO_TETRA_CHIP 0x79
+#define BTTV_AVDVBT_771     0x7b
 
 /* i2c address list */
 #define I2C_TSA5522        0xc2
diff -Nru a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
--- a/drivers/media/video/bttvp.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/media/video/bttvp.h	2004-06-23 19:04:26 -07:00
@@ -25,7 +25,7 @@
 #define _BTTVP_H_
 
 #include <linux/version.h>
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,14)
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,15)
 
 #include <linux/types.h>
 #include <linux/wait.h>
@@ -127,7 +127,6 @@
 struct bttv_buffer_set {
 	struct bttv_buffer     *top;       /* top field buffer    */
 	struct bttv_buffer     *bottom;    /* bottom field buffer */
-	struct bttv_buffer     *vbi;       /* vbi buffer */
 	unsigned int           irqflags;
 	unsigned int           topirq;
 };
@@ -197,8 +196,10 @@
 
 /* capture buffer handling */
 int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf);
-int bttv_buffer_set_activate(struct bttv *btv,
-			     struct bttv_buffer_set *set);
+int bttv_buffer_activate_video(struct bttv *btv,
+			       struct bttv_buffer_set *set);
+int bttv_buffer_activate_vbi(struct bttv *btv,
+			     struct bttv_buffer *vbi);
 void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf);
 
 /* overlay handling */
@@ -279,7 +280,8 @@
 	u32  gpio_enable;
 	u32  gpio_data;
 	int  disabled;
-	struct bttv_buffer_set set;
+	struct bttv_buffer_set video;
+	struct bttv_buffer     *vbi;
 };
 
 struct bttv {
@@ -377,6 +379,7 @@
 	struct list_head        capture;    /* video capture queue */
 	struct list_head        vcapture;   /* vbi capture queue   */
 	struct bttv_buffer_set  curr;       /* active buffers      */
+	struct bttv_buffer      *cvbi;      /* active vbi buffer   */
 	int                     new_input;
 
 	unsigned long cap_ctl;
diff -Nru a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
--- a/drivers/media/video/cx88/cx88-cards.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/video/cx88/cx88-cards.c	2004-06-23 19:04:28 -07:00
@@ -99,6 +99,10 @@
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
+                        .gpio0  = 0x000003ff,
+                        .gpio1  = 0x000000ff,
+                        .gpio2  = 0x000000ff,
+                        .gpio3  = 0x00000000,
 		},{
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
@@ -111,6 +115,7 @@
         [CX88_BOARD_WINFAST2000XP] = {
                 .name           = "Leadtek Winfast 2000XP Expert",
                 .tuner_type     = 44,
+		.needs_tda9887  = 1,
                 .input          = {{
                         .type   = CX88_VMUX_TELEVISION,
                         .vmux   = 0,
@@ -149,22 +154,33 @@
 			.vmux   = 0,
 		}},
 	},
-	[CX88_BOARD_MSI_TVANYWHERE] = {
+	[CX88_BOARD_MSI_TVANYWHERE_MASTER] = {
+		//added gpio values thanks to Torsten Seeboth
+		//values for PAL from DScaler
 		.name           = "MSI TV-@nywhere Master",
 		.tuner_type     = 33,
+		.needs_tda9887	= 1,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
+			.gpio0  = 0x000040bf,
+			.gpio1  = 0x000080c0,
+			.gpio2  = 0x0000ff40,
+                   	.gpio3  = 0x00000000,
 		},{
                         .type   = CX88_VMUX_COMPOSITE1,
                         .vmux   = 1,
-		},{
-			 // temporarly for testing ...
-                        .type   = CX88_VMUX_COMPOSITE2,
-                        .vmux   = 2,
+			.gpio0  = 0x000040bf,
+			.gpio1  = 0x000080c0,
+			.gpio2  = 0x0000ff40,
+			.gpio3  = 0x00000000,
 		},{
                         .type   = CX88_VMUX_SVIDEO,
                         .vmux   = 2,
+			.gpio0  = 0x000040bf,
+			.gpio1  = 0x000080c0,
+			.gpio2  = 0x0000ff40,
+			.gpio3  = 0x00000000,
                 }},
                 .radio = {
                         .type   = CX88_RADIO,
@@ -199,8 +215,97 @@
                         .type   = CX88_RADIO,
                 },
         },
-
-
+	[CX88_BOARD_IODATA_GVVCP3PCI] = {
+ 		.name		= "IODATA GV-VCP3/PCI",
+		.tuner_type     = TUNER_ABSENT,
+		.needs_tda9887  = 0,
+ 		.input          = {{
+ 			.type   = CX88_VMUX_COMPOSITE1,
+ 			.vmux   = 0,
+ 		},{
+ 			.type   = CX88_VMUX_COMPOSITE2,
+ 			.vmux   = 1,
+ 		},{
+ 			.type   = CX88_VMUX_SVIDEO,
+ 			.vmux   = 2,
+ 		}},
+ 	},
+	[CX88_BOARD_PROLINK_PLAYTVPVR] = {
+                .name           = "Prolink PlayTV PVR",
+                .tuner_type     = 43,
+		.needs_tda9887	= 1,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xff00,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0xff03,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0xff03,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0xff00,
+		},
+	},
+	[CX88_BOARD_ASUS_PVR_416] = {
+		.name		= "ASUS PVR-416",
+		.tuner_type     = 43,
+                .needs_tda9887  = 1,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0000fde6,
+			.gpio1  = 0x00000000, // possibly for mpeg data
+			.gpio2  = 0x000000e9,
+                   	.gpio3  = 0x00000000,
+ 		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
+			.gpio1  = 0x00000000, // possibly for mpeg data
+			.gpio2  = 0x000000e9,
+                   	.gpio3  = 0x00000000,
+		}},
+                .radio = {
+                        .type   = CX88_RADIO,
+			.gpio0  = 0x0000fde2,
+			.gpio1  = 0x00000000,
+			.gpio2  = 0x000000e9,
+                   	.gpio3  = 0x00000000,
+                },
+	},
+	[CX88_BOARD_MSI_TVANYWHERE] = {
+		.name           = "MSI TV-@nywhere",
+		.tuner_type     = 33,
+		.needs_tda9887  = 1,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00000fbf,
+			.gpio1  = 0x000000c0,
+			.gpio2  = 0x0000fc08,
+			.gpio3  = 0x00000000,
+		},{
+  			.type   = CX88_VMUX_COMPOSITE1,
+  			.vmux   = 1,
+			.gpio0  = 0x00000fbf,
+			.gpio1  = 0x000000c0,
+			.gpio2  = 0x0000fc68,
+			.gpio3  = 0x00000000,
+		},{
+  			.type   = CX88_VMUX_SVIDEO,
+  			.vmux   = 2,
+			.gpio0  = 0x00000fbf,
+			.gpio1  = 0x000000c0,
+			.gpio2  = 0x0000fc68,
+			.gpio3  = 0x00000000,
+  		}},
+	},
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
 
@@ -242,6 +347,10 @@
                 .card      = CX88_BOARD_WINFAST_DV2000,
         },{
                 .subvendor = 0x107d,
+                .subdevice = 0x663b,
+                .card      = CX88_BOARD_LEADTEK_PVR2000,
+        },{
+                .subvendor = 0x107d,
                 .subdevice = 0x663C,
                 .card      = CX88_BOARD_LEADTEK_PVR2000,
         },{
@@ -251,12 +360,19 @@
 	},{
 		.subvendor = 0x1462,
 		.subdevice = 0x8606,
-		.card      = CX88_BOARD_MSI_TVANYWHERE,
-	}
+		.card      = CX88_BOARD_MSI_TVANYWHERE_MASTER,
+	},{
+ 		.subvendor = 0x10fc,
+ 		.subdevice = 0xd003,
+ 		.card      = CX88_BOARD_IODATA_GVVCP3PCI,
+	},{
+ 		.subvendor = 0x1043,
+ 		.subdevice = 0x4823,  /* with mpeg encoder */
+ 		.card      = CX88_BOARD_ASUS_PVR_416,
+ 	}
 };
 const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
 
-
 /* ----------------------------------------------------------------------- */
 /* some leadtek specific stuff                                             */
 
@@ -386,20 +502,22 @@
 	[ 0x02 ] = { .id   = TUNER_ABSENT,
 		     .name = "PAL_B" },
 	[ 0x03 ] = { .id   = TUNER_ABSENT,
-		     .name = "BAL_I" },
+		     .name = "PAL_I" },
 	[ 0x04 ] = { .id   = TUNER_ABSENT,
 		     .name = "PAL_D" },
 	[ 0x05 ] = { .id   = TUNER_ABSENT,
 		     .name = "SECAM" },
 
-	[ 0x10 ] = { .id   = TUNER_ABSENT, .fm = 1, 
+	[ 0x10 ] = { .id   = TUNER_ABSENT,
+		     .fm   = 1,
 		     .name = "TEMIC_4049" },
 	[ 0x11 ] = { .id   = TUNER_TEMIC_4136FY5,
 		     .name = "TEMIC_4136" },
 	[ 0x12 ] = { .id   = TUNER_ABSENT,
 		     .name = "TEMIC_4146" },
 
-	[ 0x20 ] = { .id   = TUNER_PHILIPS_FQ1216ME, .fm = 1,
+	[ 0x20 ] = { .id   = TUNER_PHILIPS_FQ1216ME,
+		     .fm   = 1,
 		     .name = "PHILIPS_FQ1216_MK3" },
 	[ 0x21 ] = { .id   = TUNER_ABSENT, .fm = 1,
 		     .name = "PHILIPS_FQ1236_MK3" },
@@ -454,7 +572,33 @@
 	return 0;
 }
 
-void __devinit cx88_card_setup(struct cx8800_dev *dev)
+void cx88_card_list(struct cx8800_dev *dev)
+{
+	int i;
+
+	if (0 == dev->pci->subsystem_vendor &&
+	    0 == dev->pci->subsystem_device) {
+		printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n"
+		       "%s: be autodetected.  Please pass card=<n> insmod option to\n"
+		       "%s: workaround that.  Redirect complaints to the vendor of\n"
+		       "%s: the TV card.  Best regards,\n"
+		       "%s:         -- tux\n",
+		       dev->name,dev->name,dev->name,dev->name,dev->name);
+	} else {
+		printk("%s: Your board isn't known (yet) to the driver.  You can\n"
+		       "%s: try to pick one of the existing card configs via\n"
+		       "%s: card=<n> insmod option.  Updating to the latest\n"
+		       "%s: version might help as well.\n",
+		       dev->name,dev->name,dev->name,dev->name);
+	}
+	printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+	       dev->name);
+	for (i = 0; i < cx88_bcount; i++)
+		printk("%s:    card=%d -> %s\n",
+		       dev->name, i, cx88_boards[i].name);
+}
+
+void cx88_card_setup(struct cx8800_dev *dev)
 {
 	static u8 eeprom[128];
 		
@@ -474,6 +618,9 @@
 			i2c_eeprom(&dev->i2c_client,eeprom,sizeof(eeprom));
 		leadtek_eeprom(dev,eeprom);
 		break;
+        case CX88_BOARD_ASUS_PVR_416:
+		dev->has_radio = 1;
+                break;
 	}
 }
 
@@ -483,6 +630,7 @@
 EXPORT_SYMBOL(cx88_bcount);
 EXPORT_SYMBOL(cx88_subids);
 EXPORT_SYMBOL(cx88_idcount);
+EXPORT_SYMBOL(cx88_card_list);
 EXPORT_SYMBOL(cx88_card_setup);
 
 /*
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	2004-06-23 19:04:26 -07:00
+++ b/drivers/media/video/cx88/cx88-i2c.c	2004-06-23 19:04:26 -07:00
@@ -22,8 +22,6 @@
     
 */
 
-#define __NO_VERSION__ 1
-
 #include <linux/module.h>
 #include <linux/init.h>
 
diff -Nru a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
--- a/drivers/media/video/cx88/cx88-reg.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/media/video/cx88/cx88-reg.h	2004-06-23 19:04:26 -07:00
@@ -599,10 +599,20 @@
 #define EN_I2SIN_STR2DAC        0x00004000
 #define EN_I2SIN_ENABLE         0x00008000
 
+#if 0
+/* old */
 #define EN_DMTRX_SUMDIFF        0x00000800
 #define EN_DMTRX_SUMR           0x00000880
 #define EN_DMTRX_LR             0x00000900
 #define EN_DMTRX_MONO           0x00000980
+#else
+/* dscaler cvs */
+#define EN_DMTRX_SUMDIFF        (0 << 7)
+#define EN_DMTRX_SUMR           (1 << 7)
+#define EN_DMTRX_LR             (2 << 7)
+#define EN_DMTRX_MONO           (3 << 7)
+#define EN_DMTRX_BYPASS         (1 << 11)
+#endif
 
 // Video 
 #define VID_CAPTURE_CONTROL		0x310180
diff -Nru a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
--- a/drivers/media/video/cx88/cx88-tvaudio.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/media/video/cx88/cx88-tvaudio.c	2004-06-23 19:04:26 -07:00
@@ -48,6 +48,7 @@
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 
 #include "cx88.h"
 
@@ -60,6 +61,33 @@
 
 /* ----------------------------------------------------------- */
 
+static char *aud_ctl_names[64] =
+{
+	[ EN_BTSC_FORCE_MONO       ] = "BTSC_FORCE_MONO",
+	[ EN_BTSC_FORCE_STEREO     ] = "BTSC_FORCE_STEREO",
+	[ EN_BTSC_FORCE_SAP        ] = "BTSC_FORCE_SAP",
+	[ EN_BTSC_AUTO_STEREO      ] = "BTSC_AUTO_STEREO",
+	[ EN_BTSC_AUTO_SAP         ] = "BTSC_AUTO_SAP",
+	[ EN_A2_FORCE_MONO1        ] = "A2_FORCE_MONO1",
+	[ EN_A2_FORCE_MONO2        ] = "A2_FORCE_MONO2",
+	[ EN_A2_FORCE_STEREO       ] = "A2_FORCE_STEREO",
+	[ EN_A2_AUTO_MONO2         ] = "A2_AUTO_MONO2",
+	[ EN_A2_AUTO_STEREO        ] = "A2_AUTO_STEREO",
+	[ EN_EIAJ_FORCE_MONO1      ] = "EIAJ_FORCE_MONO1",
+	[ EN_EIAJ_FORCE_MONO2      ] = "EIAJ_FORCE_MONO2",
+	[ EN_EIAJ_FORCE_STEREO     ] = "EIAJ_FORCE_STEREO",
+	[ EN_EIAJ_AUTO_MONO2       ] = "EIAJ_AUTO_MONO2",
+	[ EN_EIAJ_AUTO_STEREO      ] = "EIAJ_AUTO_STEREO",
+	[ EN_NICAM_FORCE_MONO1     ] = "NICAM_FORCE_MONO1",
+	[ EN_NICAM_FORCE_MONO2     ] = "NICAM_FORCE_MONO2",
+	[ EN_NICAM_FORCE_STEREO    ] = "NICAM_FORCE_STEREO",
+	[ EN_NICAM_AUTO_MONO2      ] = "NICAM_AUTO_MONO2",
+	[ EN_NICAM_AUTO_STEREO     ] = "NICAM_AUTO_STEREO",
+	[ EN_FMRADIO_FORCE_MONO    ] = "FMRADIO_FORCE_MONO",
+	[ EN_FMRADIO_FORCE_STEREO  ] = "FMRADIO_FORCE_STEREO",
+	[ EN_FMRADIO_AUTO_STEREO   ] = "FMRADIO_AUTO_STEREO",
+};
+
 struct rlist {
 	u32 reg;
 	u32 val;
@@ -125,26 +153,116 @@
 static void set_audio_standard_BTSC(struct cx8800_dev *dev, unsigned int sap)
 {
 	static const struct rlist btsc[] = {
-		/* Magic stuff from leadtek driver + datasheet.*/
-		{ AUD_DBX_IN_GAIN,   0x4734 },
-		{ AUD_DBX_WBE_GAIN,  0x4640 },
-		{ AUD_DBX_SE_GAIN,   0x8D31 },
-		{ AUD_DEEMPH0_G0,    0x1604 },
-		{ AUD_PHASE_FIX_CTL, 0x0020 },
-
+		/* from dscaler */
+		{ AUD_OUT1_SEL,                0x00000013 },
+		{ AUD_OUT1_SHIFT,              0x00000000 },
+		{ AUD_POLY0_DDS_CONSTANT,      0x0012010c },
+		{ AUD_DMD_RA_DDS,              0x00c3e7aa },
+		{ AUD_DBX_IN_GAIN,             0x00004734 },
+		{ AUD_DBX_WBE_GAIN,            0x00004640 },
+		{ AUD_DBX_SE_GAIN,             0x00008d31 },
+		{ AUD_DCOC_0_SRC,              0x0000001a },
+		{ AUD_IIR1_4_SEL,              0x00000021 },
+		{ AUD_DCOC_PASS_IN,            0x00000003 },
+		{ AUD_DCOC_0_SHIFT_IN0,        0x0000000a },
+		{ AUD_DCOC_0_SHIFT_IN1,        0x00000008 },
+		{ AUD_DCOC_1_SHIFT_IN0,        0x0000000a },
+		{ AUD_DCOC_1_SHIFT_IN1,        0x00000008 },
+		{ AUD_DN0_FREQ,                0x0000283b },
+		{ AUD_DN2_SRC_SEL,             0x00000008 },
+		{ AUD_DN2_FREQ,                0x00003000 },
+		{ AUD_DN2_AFC,                 0x00000002 },
+		{ AUD_DN2_SHFT,                0x00000000 },
+		{ AUD_IIR2_2_SEL,              0x00000020 },
+		{ AUD_IIR2_2_SHIFT,            0x00000000 },
+		{ AUD_IIR2_3_SEL,              0x0000001f },
+		{ AUD_IIR2_3_SHIFT,            0x00000000 },
+		{ AUD_CRDC1_SRC_SEL,           0x000003ce },
+		{ AUD_CRDC1_SHIFT,             0x00000000 },
+		{ AUD_CORDIC_SHIFT_1,          0x00000007 },
+		{ AUD_DCOC_1_SRC,              0x0000001b },
+		{ AUD_DCOC1_SHIFT,             0x00000000 },
+		{ AUD_RDSI_SEL,                0x00000008 },
+		{ AUD_RDSQ_SEL,                0x00000008 },
+		{ AUD_RDSI_SHIFT,              0x00000000 },
+		{ AUD_RDSQ_SHIFT,              0x00000000 },
+		{ AUD_POLYPH80SCALEFAC,        0x00000003 },
+                { /* end of list */ },
+	};
+	static const struct rlist btsc_sap[] = {
+		{ AUD_DBX_IN_GAIN,             0x00007200 },
+		{ AUD_DBX_WBE_GAIN,            0x00006200 },
+		{ AUD_DBX_SE_GAIN,             0x00006200 },
+		{ AUD_IIR1_1_SEL,              0x00000000 },
+		{ AUD_IIR1_3_SEL,              0x00000001 },
+		{ AUD_DN1_SRC_SEL,             0x00000007 },
+		{ AUD_IIR1_4_SHIFT,            0x00000006 },
+		{ AUD_IIR2_1_SHIFT,            0x00000000 },
+		{ AUD_IIR2_2_SHIFT,            0x00000000 },
+		{ AUD_IIR3_0_SHIFT,            0x00000000 },
+		{ AUD_IIR3_1_SHIFT,            0x00000000 },
+		{ AUD_IIR3_0_SEL,              0x0000000d },
+		{ AUD_IIR3_1_SEL,              0x0000000e },
+		{ AUD_DEEMPH1_SRC_SEL,         0x00000014 },
+		{ AUD_DEEMPH1_SHIFT,           0x00000000 },
+		{ AUD_DEEMPH1_G0,              0x00004000 },
+		{ AUD_DEEMPH1_A0,              0x00000000 },
+		{ AUD_DEEMPH1_B0,              0x00000000 },
+		{ AUD_DEEMPH1_A1,              0x00000000 },
+		{ AUD_DEEMPH1_B1,              0x00000000 },
+		{ AUD_OUT0_SEL,                0x0000003f },
+		{ AUD_OUT1_SEL,                0x0000003f },
+		{ AUD_DN1_AFC,                 0x00000002 },
+		{ AUD_DCOC_0_SHIFT_IN0,        0x0000000a },
+		{ AUD_DCOC_0_SHIFT_IN1,        0x00000008 },
+		{ AUD_DCOC_1_SHIFT_IN0,        0x0000000a },
+		{ AUD_DCOC_1_SHIFT_IN1,        0x00000008 },
+		{ AUD_IIR1_0_SEL,              0x0000001d },
+		{ AUD_IIR1_2_SEL,              0x0000001e },
+		{ AUD_IIR2_1_SEL,              0x00000002 },
+		{ AUD_IIR2_2_SEL,              0x00000004 },
+		{ AUD_IIR3_2_SEL,              0x0000000f },
+		{ AUD_DCOC2_SHIFT,             0x00000001 },
+		{ AUD_IIR3_2_SHIFT,            0x00000001 },
+		{ AUD_DEEMPH0_SRC_SEL,         0x00000014 },
+		{ AUD_CORDIC_SHIFT_1,          0x00000006 },
+		{ AUD_POLY0_DDS_CONSTANT,      0x000e4db2 },
+		{ AUD_DMD_RA_DDS,              0x00f696e6 },
+		{ AUD_IIR2_3_SEL,              0x00000025 },
+		{ AUD_IIR1_4_SEL,              0x00000021 },
+		{ AUD_DN1_FREQ,                0x0000c965 },
+		{ AUD_DCOC_PASS_IN,            0x00000003 },
+		{ AUD_DCOC_0_SRC,              0x0000001a },
+		{ AUD_DCOC_1_SRC,              0x0000001b },
+		{ AUD_DCOC1_SHIFT,             0x00000000 },
+		{ AUD_RDSI_SEL,                0x00000009 },
+		{ AUD_RDSQ_SEL,                0x00000009 },
+		{ AUD_RDSI_SHIFT,              0x00000000 },
+		{ AUD_RDSQ_SHIFT,              0x00000000 },
+		{ AUD_POLYPH80SCALEFAC,        0x00000003 },
                 { /* end of list */ },
 	};
 
-	dprintk("%s (status: unknown)\n",__FUNCTION__);
-	set_audio_start(dev, 0x0001,
-			EN_BTSC_AUTO_STEREO);
-        set_audio_registers(dev, btsc);
+	// dscaler: exactly taken from driver,
+	// dscaler: don't know why to set EN_FMRADIO_EN_RDS
+	if (sap) {
+		dprintk("%s SAP (status: unknown)\n",__FUNCTION__);
+		set_audio_start(dev, 0x0001,
+				EN_FMRADIO_EN_RDS | EN_BTSC_FORCE_SAP);
+		set_audio_registers(dev, btsc_sap);
+	} else {
+		dprintk("%s (status: known-good)\n",__FUNCTION__);
+		set_audio_start(dev, 0x0001,
+				EN_FMRADIO_EN_RDS | EN_BTSC_AUTO_STEREO);
+		set_audio_registers(dev, btsc);
+	}
 	set_audio_finish(dev);
 }
 
 static void set_audio_standard_NICAM(struct cx8800_dev *dev)
 {
-	static const struct rlist nicam[] = {
+	static const struct rlist nicam_common[] = {
+		/* from dscaler */
     		{ AUD_RATE_ADJ1,           0x00000010 },
     		{ AUD_RATE_ADJ2,           0x00000040 },
     		{ AUD_RATE_ADJ3,           0x00000100 },
@@ -152,21 +270,64 @@
     		{ AUD_RATE_ADJ5,           0x00001000 },
     //		{ AUD_DMD_RA_DDS,          0x00c0d5ce },
 
+		// Deemphasis 1:
+		{ AUD_DEEMPHGAIN_R,        0x000023c2 },
+		{ AUD_DEEMPHNUMER1_R,      0x0002a7bc },
+		{ AUD_DEEMPHNUMER2_R,      0x0003023e },
+		{ AUD_DEEMPHDENOM1_R,      0x0000f3d0 },
+		{ AUD_DEEMPHDENOM2_R,      0x00000000 },
+
+#if 0
+		// Deemphasis 2: (other tv norm?)
+		{ AUD_DEEMPHGAIN_R,        0x0000c600 },
+		{ AUD_DEEMPHNUMER1_R,      0x00066738 },
+		{ AUD_DEEMPHNUMER2_R,      0x00066739 },
+		{ AUD_DEEMPHDENOM1_R,      0x0001e88c },
+		{ AUD_DEEMPHDENOM2_R,      0x0001e88c },
+#endif
+
+		{ AUD_DEEMPHDENOM2_R,      0x00000000 },
+		{ AUD_ERRLOGPERIOD_R,      0x00000fff },
+		{ AUD_ERRINTRPTTHSHLD1_R,  0x000003ff },
+		{ AUD_ERRINTRPTTHSHLD2_R,  0x000000ff },
+		{ AUD_ERRINTRPTTHSHLD3_R,  0x0000003f },
+		{ AUD_POLYPH80SCALEFAC,    0x00000003 },
+
 		// setup QAM registers
 		{ AUD_PDF_DDS_CNST_BYTE2,  0x06 },
 		{ AUD_PDF_DDS_CNST_BYTE1,  0x82 },
 		{ AUD_PDF_DDS_CNST_BYTE0,  0x16 },
 		{ AUD_QAM_MODE,            0x05 },
+
+                { /* end of list */ },
+        };
+	static const struct rlist nicam_pal_i[] = {
+		{ AUD_PDF_DDS_CNST_BYTE0,  0x12 },
+		{ AUD_PHACC_FREQ_8MSB,     0x3a },
+		{ AUD_PHACC_FREQ_8LSB,     0x93 },
+
+                { /* end of list */ },
+	};
+	static const struct rlist nicam_default[] = {
+		{ AUD_PDF_DDS_CNST_BYTE0,  0x16 },
 		{ AUD_PHACC_FREQ_8MSB,     0x34 },
 		{ AUD_PHACC_FREQ_8LSB,     0x4c },
 
                 { /* end of list */ },
-        };
+	};
 
-	dprintk("%s (status: unknown)\n",__FUNCTION__);
         set_audio_start(dev, 0x0010,
-			EN_DMTRX_LR | EN_NICAM_FORCE_STEREO);
-        set_audio_registers(dev, nicam);
+			EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+        set_audio_registers(dev, nicam_common);
+	switch (dev->tvaudio) {
+	case WW_NICAM_I:
+		dprintk("%s PAL-I NICAM (status: unknown)\n",__FUNCTION__);
+		set_audio_registers(dev, nicam_pal_i);
+	case WW_NICAM_BGDKL:
+		dprintk("%s PAL NICAM (status: unknown)\n",__FUNCTION__);
+		set_audio_registers(dev, nicam_default);
+		break;
+	};
         set_audio_finish(dev);
 }
 
@@ -297,7 +458,7 @@
 static void set_audio_standard_A2(struct cx8800_dev *dev)
 {
 	/* from dscaler cvs */
-	static const struct rlist a2[] = {
+	static const struct rlist a2_common[] = {
 		{ AUD_PDF_DDS_CNST_BYTE2,     0x06 },
 		{ AUD_PDF_DDS_CNST_BYTE1,     0x82 },
 		{ AUD_PDF_DDS_CNST_BYTE0,     0x12 },
@@ -347,16 +508,20 @@
 		{ AUD_RDSQ_SHIFT,	0x00000000 },
 		{ AUD_POLYPH80SCALEFAC,	0x00000001 },
 
-		// Table 1
+		{ /* end of list */ },
+	};
+
+	static const struct rlist a2_table1[] = {
+		// PAL-BG
 		{ AUD_DMD_RA_DDS,	0x002a73bd },
 		{ AUD_C1_UP_THR,	0x00007000 },
 		{ AUD_C1_LO_THR,	0x00005400 },
 		{ AUD_C2_UP_THR,	0x00005400 },
 		{ AUD_C2_LO_THR,	0x00003000 },
-
-#if 0
-		// found this in WDM-driver for A2, must country spec.
-		// Table 2
+		{ /* end of list */ },
+	};
+	static const struct rlist a2_table2[] = {
+		// PAL-DK
 		{ AUD_DMD_RA_DDS,	0x002a73bd },
 		{ AUD_C1_UP_THR,	0x00007000 },
 		{ AUD_C1_LO_THR,	0x00005400 },
@@ -364,8 +529,10 @@
 		{ AUD_C2_LO_THR,	0x00003000 },
 		{ AUD_DN0_FREQ,		0x00003a1c },
 		{ AUD_DN2_FREQ,		0x0000d2e0 },
-
-		// Table 3
+		{ /* end of list */ },
+	};
+	static const struct rlist a2_table3[] = {
+		// unknown, probably NTSC-M
 		{ AUD_DMD_RA_DDS,	0x002a2873 },
 		{ AUD_C1_UP_THR,	0x00003c00 },
 		{ AUD_C1_LO_THR,	0x00003000 },
@@ -375,140 +542,26 @@
 		{ AUD_DN1_FREQ,		0x00003418 },
 		{ AUD_DN2_FREQ,		0x000029c7 },
 		{ AUD_POLY0_DDS_CONSTANT, 0x000a7540 },
-#endif
-
 		{ /* end of list */ },
 	};
 
-	static const struct rlist a2_old[] = {
-		{ AUD_DN0_FREQ,            0x0000312b },
-		{ AUD_POLY0_DDS_CONSTANT,  0x000a62b4 },
-		{ AUD_IIR1_0_SEL,          0x00000000 },
-		{ AUD_IIR1_1_SEL,          0x00000001 },
-		{ AUD_IIR1_2_SEL,          0x0000001f },
-		{ AUD_IIR1_3_SEL,          0x00000020 },
-		{ AUD_IIR1_4_SEL,          0x00000023 },
-		{ AUD_IIR1_5_SEL,          0x00000007 },
-		{ AUD_IIR1_0_SHIFT,        0x00000000 },
-		{ AUD_IIR1_1_SHIFT,        0x00000000 },
-		{ AUD_IIR1_2_SHIFT,        0x00000007 },
-		{ AUD_IIR1_3_SHIFT,        0x00000007 },
-		{ AUD_IIR1_4_SHIFT,        0x00000007 },
-		{ AUD_IIR1_5_SHIFT,        0x00000000 },
-		{ AUD_IIR2_0_SEL,          0x00000002 },
-		{ AUD_IIR2_1_SEL,          0x00000003 },
-		{ AUD_IIR2_2_SEL,          0x00000004 },
-		{ AUD_IIR2_3_SEL,          0x00000005 },
-		{ AUD_IIR3_0_SEL,          0x00000021 },
-		{ AUD_IIR3_1_SEL,          0x00000023 },
-		{ AUD_IIR3_2_SEL,          0x00000016 },
-		{ AUD_IIR3_0_SHIFT,        0x00000000 },
-		{ AUD_IIR3_1_SHIFT,        0x00000000 },
-		{ AUD_IIR3_2_SHIFT,        0x00000000 },
-		{ AUD_IIR4_0_SEL,          0x0000001d },
-		{ AUD_IIR4_1_SEL,          0x00000019 },
-		{ AUD_IIR4_2_SEL,          0x00000008 },
-		{ AUD_IIR4_0_SHIFT,        0x00000000 },
-		{ AUD_IIR4_1_SHIFT,        0x00000000 },
-		{ AUD_IIR4_2_SHIFT,        0x00000001 },
-		{ AUD_IIR4_0_CA0,          0x0003e57e },
-		{ AUD_IIR4_0_CA1,          0x00005e11 },
-		{ AUD_IIR4_0_CA2,          0x0003a7cf },
-		{ AUD_IIR4_0_CB0,          0x00002368 },
-		{ AUD_IIR4_0_CB1,          0x0003bf1b },
-		{ AUD_IIR4_1_CA0,          0x00006349 },
-		{ AUD_IIR4_1_CA1,          0x00006f27 },
-		{ AUD_IIR4_1_CA2,          0x0000e7a3 },
-		{ AUD_IIR4_1_CB0,          0x00005653 },
-		{ AUD_IIR4_1_CB1,          0x0000cf97 },
-		{ AUD_IIR4_2_CA0,          0x00006349 },
-		{ AUD_IIR4_2_CA1,          0x00006f27 },
-		{ AUD_IIR4_2_CA2,          0x0000e7a3 },
-		{ AUD_IIR4_2_CB0,          0x00005653 },
-		{ AUD_IIR4_2_CB1,          0x0000cf97 },
-		{ AUD_HP_MD_IIR4_1,        0x00000001 },
-		{ AUD_HP_PROG_IIR4_1,      0x00000017 },
-		{ AUD_DN1_FREQ,            0x00003618 },
-		{ AUD_DN1_SRC_SEL,         0x00000017 },
-		{ AUD_DN1_SHFT,            0x00000007 },
-		{ AUD_DN1_AFC,             0x00000000 },
-		{ AUD_DN1_FREQ_SHIFT,      0x00000000 },
-		{ AUD_DN2_SRC_SEL,         0x00000040 },
-		{ AUD_DN2_SHFT,            0x00000000 },
-		{ AUD_DN2_AFC,             0x00000002 },
-		{ AUD_DN2_FREQ,            0x0000caaf },
-		{ AUD_DN2_FREQ_SHIFT,      0x00000000 },
-		{ AUD_PDET_SRC,            0x00000014 },
-		{ AUD_PDET_SHIFT,          0x00000000 },
-		{ AUD_DEEMPH0_SRC_SEL,     0x00000011 },
-		{ AUD_DEEMPH1_SRC_SEL,     0x00000013 },
-		{ AUD_DEEMPH0_SHIFT,       0x00000000 },
-		{ AUD_DEEMPH1_SHIFT,       0x00000000 },
-		{ AUD_DEEMPH0_G0,          0x000004da },
-		{ AUD_DEEMPH0_A0,          0x0000777a },
-		{ AUD_DEEMPH0_B0,          0x00000000 },
-		{ AUD_DEEMPH0_A1,          0x0003f062 },
-		{ AUD_DEEMPH0_B1,          0x00000000 },
-		{ AUD_DEEMPH1_G0,          0x000004da },
-		{ AUD_DEEMPH1_A0,          0x0000777a },
-		{ AUD_DEEMPH1_B0,          0x00000000 },
-		{ AUD_DEEMPH1_A1,          0x0003f062 },
-		{ AUD_DEEMPH1_B1,          0x00000000 },
-		{ AUD_PLL_EN,              0x00000000 },
-		{ AUD_DMD_RA_DDS,          0x002a4efb },
-		{ AUD_RATE_ADJ1,           0x00001000 },
-		{ AUD_RATE_ADJ2,           0x00002000 },
-		{ AUD_RATE_ADJ3,           0x00003000 },
-		{ AUD_RATE_ADJ4,           0x00004000 },
-		{ AUD_RATE_ADJ5,           0x00005000 },
-		{ AUD_C2_UP_THR,           0x0000ffff },
-		{ AUD_C2_LO_THR,           0x0000e800 },
-		{ AUD_C1_UP_THR,           0x00008c00 },
-		{ AUD_C1_LO_THR,           0x00006c00 },
-
-		//   ; Completely ditch AFC feedback
-		{ AUD_DCOC_0_SRC,          0x00000021 },
-		{ AUD_DCOC_1_SRC,          0x0000001a },
-		{ AUD_DCOC1_SHIFT,         0x00000000 },
-		{ AUD_DCOC_1_SHIFT_IN0,    0x0000000a },
-		{ AUD_DCOC_1_SHIFT_IN1,    0x00000008 },
-		{ AUD_DCOC_PASS_IN,        0x00000000 },
-		{ AUD_IIR4_0_SEL,          0x00000023 },
-
-		//  ; Completely ditc FM-2 AFC feedback
-		{ AUD_DN1_AFC,             0x00000000 },
-		{ AUD_DCOC_2_SRC,          0x0000001b },
-		{ AUD_IIR4_1_SEL,          0x00000025 },
-
-		// ; WARNING!!! THIS CHANGE WAS NOT EXPECTED!!!
-		// ; Swap I & Q inputs into second rotator
-		// ; to reverse frequency and therefor invert
-		// ; phase from the cordic FM demodulator
-		// ; (frequency rotation must also be reversed
-		{ AUD_DN2_SRC_SEL,         0x00000001 },
-		{ AUD_DN2_FREQ,            0x00003551 },
-
-		//  setup Audio PLL
-		{ AUD_PLL_PRESCALE,        0x00000002 },
-		{ AUD_PLL_INT,             0x0000001f },
-
-		{ /* end of list */ },
+	set_audio_start(dev, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
+	set_audio_registers(dev, a2_common);
+	switch (dev->tvaudio) {
+	case WW_A2_BG:
+		dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
+		set_audio_registers(dev, a2_table1);
+		break;
+	case WW_A2_DK:
+		dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__);
+		set_audio_registers(dev, a2_table2);
+		break;
+	case WW_A2_M:
+		dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__);
+		set_audio_registers(dev, a2_table3);
+		break;
 	};
-
-
-	dprintk("%s (status: WorksForMe[tm])\n",__FUNCTION__);
-
-	if (0) {
-		/* old code */
-		set_audio_start(dev, 0x0004, EN_DMTRX_SUMR | EN_A2_AUTO_STEREO);
-		set_audio_registers(dev, a2_old);
-		set_audio_finish(dev);
-	} else {
-		/* new code */
-		set_audio_start(dev, 0x0004, EN_DMTRX_LR | EN_A2_AUTO_STEREO);
-		set_audio_registers(dev, a2);
-		set_audio_finish(dev);
-	}
+	set_audio_finish(dev);
 }
 
 static void set_audio_standard_EIAJ(struct cx8800_dev *dev)
@@ -617,9 +670,9 @@
 	reg   = cx_read(AUD_STATUS);
 	mode  = reg & 0x03;
 	pilot = (reg >> 2) & 0x03;
-	dprintk("AUD_STATUS: %s / %s [status=0x%x,ctl=0x%x,vol=0x%x]\n",
-		m[mode], p[pilot], reg,
-		cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
+	dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
+		reg, m[mode], p[pilot],
+		aud_ctl_names[cx_read(AUD_CTL) & 63]);
 
 	t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
 		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
@@ -628,6 +681,8 @@
 
 	switch (dev->tvaudio) {
 	case WW_A2_BG:
+	case WW_A2_DK:
+	case WW_A2_M:
  		if (1 == pilot) {
 			/* stereo */
 			t->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
@@ -659,6 +714,8 @@
 
 	switch (dev->tvaudio) {
 	case WW_A2_BG:
+	case WW_A2_DK:
+	case WW_A2_M:
 		switch (mode) {
 		case V4L2_TUNER_MODE_MONO:   
 		case V4L2_TUNER_MODE_LANG1:
@@ -715,6 +772,32 @@
 			cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
 	}
 	return;
+}
+
+/* just monitor the audio status for now ... */
+int cx88_audio_thread(void *data)
+{
+	struct cx8800_dev *dev = data;
+	struct v4l2_tuner t;
+
+	daemonize("msp3400");
+	allow_signal(SIGTERM);
+	dprintk("cx88: tvaudio thread started\n");
+
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ*3);
+		if (signal_pending(current))
+			break;
+		if (dev->shutdown)
+			break;
+
+		memset(&t,0,sizeof(t));
+		cx88_get_stereo(dev,&t);
+	}
+
+	dprintk("cx88: tvaudio thread exiting\n");
+        complete_and_exit(&dev->texit, 0);
 }
 
 /*
diff -Nru a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
--- a/drivers/media/video/cx88/cx88-vbi.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/media/video/cx88/cx88-vbi.c	2004-06-23 19:04:26 -07:00
@@ -28,17 +28,14 @@
 	f->fmt.vbi.count[0] = VBI_LINE_COUNT;
 	f->fmt.vbi.count[1] = VBI_LINE_COUNT;
 
-	switch (dev->tvnorm->id) {
-	case V4L2_STD_NTSC_M:
-	case V4L2_STD_NTSC_M_JP:
+	if (dev->tvnorm->id & V4L2_STD_525_60) {
+		/* ntsc */
 		f->fmt.vbi.sampling_rate = 28636363;
 		f->fmt.vbi.start[0] = 10 -1;
 		f->fmt.vbi.start[1] = 273 -1;
-		break;
-	case V4L2_STD_PAL_BG:
-	case V4L2_STD_PAL_DK:
-	case V4L2_STD_PAL_I:
-	case V4L2_STD_SECAM:
+
+	} else if (V4L2_STD_625_50) {
+		/* pal */
 		f->fmt.vbi.sampling_rate = 35468950;
 		f->fmt.vbi.start[0] = 7 -1;
 		f->fmt.vbi.start[1] = 319 -1;
diff -Nru a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
--- a/drivers/media/video/cx88/cx88-video.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/media/video/cx88/cx88-video.c	2004-06-23 19:04:27 -07:00
@@ -2,7 +2,7 @@
  * device driver for Conexant 2388x based TV cards
  * video4linux video interface
  *
- * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -19,8 +19,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define __NO_VERSION__ 1
-
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -32,6 +30,8 @@
 
 #include "cx88.h"
 
+#define V4L2_I2C_CLIENTS 1
+
 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
@@ -194,8 +194,13 @@
 		.cxiformat = VideoFormatPAL60,
 		.cxoformat = 0x181f0008,
 	},{
-		.name      = "SECAM",
-		.id        = V4L2_STD_SECAM,
+		.name      = "SECAM-L",
+		.id        = V4L2_STD_SECAM_L,
+		.cxiformat = VideoFormatSECAM,
+		.cxoformat = 0x181f0008,
+	},{
+		.name      = "SECAM-DK",
+		.id        = V4L2_STD_SECAM_DK,
 		.cxiformat = VideoFormatSECAM,
 		.cxoformat = 0x181f0008,
 	}
@@ -483,35 +488,38 @@
 	if (CX88_VMUX_TELEVISION != INPUT(dev->input)->type)
 		return 0;
 
-	switch (dev->tvnorm->id) {
-	case V4L2_STD_PAL_BG:
+	if (V4L2_STD_PAL_BG & dev->tvnorm->id) {
 		dev->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_BG;
-		break;
-	case V4L2_STD_PAL_DK:
+
+	} else if (V4L2_STD_PAL_DK & dev->tvnorm->id) {
 		dev->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_DK;
-		break;
-	case V4L2_STD_PAL_I:
+
+	} else if (V4L2_STD_PAL_I & dev->tvnorm->id) {
 		dev->tvaudio = WW_NICAM_I;
-		break;
-	case V4L2_STD_SECAM:
-		dev->tvaudio = WW_SYSTEM_L_AM;  /* FIXME: fr != ru */
-		break;
-	case V4L2_STD_NTSC_M:
+
+	} else if (V4L2_STD_SECAM_L & dev->tvnorm->id) {
+		dev->tvaudio = WW_SYSTEM_L_AM;
+
+	} else if (V4L2_STD_SECAM_DK & dev->tvnorm->id) {
+		dev->tvaudio = WW_A2_DK;
+
+	} else if ((V4L2_STD_NTSC_M & dev->tvnorm->id) ||
+		   (V4L2_STD_PAL_M  & dev->tvnorm->id)) {
 		dev->tvaudio = WW_BTSC;
-		break;
-	case V4L2_STD_NTSC_M_JP:
+
+	} else if (V4L2_STD_NTSC_M_JP & dev->tvnorm->id) {
 		dev->tvaudio = WW_EIAJ;
-		break;
-	default:
-		dprintk(1,"tvaudio support needs work for this tv norm [%s], sorry\n",
-			dev->tvnorm->name);
+
+	} else {
+		printk("%s: tvaudio support needs work for this tv norm [%s], sorry\n",
+		       dev->name, dev->tvnorm->name);
 		dev->tvaudio = 0;
 		return 0;
 	}
 
 	cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
 	cx88_set_tvaudio(dev);
-	cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
+	// cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
 
 	cx_write(MO_AUDD_LNGTH, 128/8);  /* fifo size */
 	cx_write(MO_AUDR_LNGTH, 128/8);  /* fifo size */
@@ -526,7 +534,6 @@
 	u32 vdec_clock;
 	u64 tmp64;
 	u32 bdelay,agcdelay,htotal;
-	struct video_channel c;
 	
 	dev->tvnorm = norm;
 	fsc8       = norm_fsc8(norm);
@@ -592,30 +599,43 @@
 	set_tvaudio(dev);
 
 	// tell i2c chips
-	memset(&c,0,sizeof(c));
-	c.channel = dev->input;
-	c.norm = VIDEO_MODE_PAL;
-	if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP)))
-		c.norm = VIDEO_MODE_NTSC;
-	if (norm->id & V4L2_STD_SECAM)
-		c.norm = VIDEO_MODE_SECAM;
-	cx8800_call_i2c_clients(dev,VIDIOCSCHAN,&c);
+#ifdef V4L2_I2C_CLIENTS
+	cx8800_call_i2c_clients(dev,VIDIOC_S_STD,&norm->id);
+#else
+	{
+		struct video_channel c;
+		memset(&c,0,sizeof(c));
+		c.channel = dev->input;
+		c.norm = VIDEO_MODE_PAL;
+		if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP)))
+			c.norm = VIDEO_MODE_NTSC;
+		if (norm->id & V4L2_STD_SECAM)
+			c.norm = VIDEO_MODE_SECAM;
+		cx8800_call_i2c_clients(dev,VIDIOCSCHAN,&c);
+	}
+#endif
 
 	// done
 	return 0;
 }
 
 static int set_scale(struct cx8800_dev *dev, unsigned int width, unsigned int height,
-		     int interlaced)
+		     enum v4l2_field field)
 {
 	unsigned int swidth  = norm_swidth(dev->tvnorm);
 	unsigned int sheight = norm_maxh(dev->tvnorm);
 	u32 value;
 
-	dprintk(1,"set_scale: %dx%d [%s]\n", width, height, dev->tvnorm->name);
+	dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
+		V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
+		V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
+		dev->tvnorm->name);
+	if (!V4L2_FIELD_HAS_BOTH(field))
+		height *= 2;
 
 	// recalc H delay and scale registers
 	value = (width * norm_hdelay(dev->tvnorm)) / swidth;
+	value &= 0x3fe;
 	cx_write(MO_HDELAY_EVEN,  value);
 	cx_write(MO_HDELAY_ODD,   value);
 	dprintk(1,"set_scale: hdelay  0x%04x\n", value);
@@ -646,7 +666,7 @@
 	// setup filters
 	value = 0;
 	value |= (1 << 19);        // CFILT (default)
-	if (interlaced)
+	if (V4L2_FIELD_INTERLACED == field)
 		value |= (1 << 3); // VINT (interlaced vertical scaling)
 	if (width < 385)
 		value |= (1 << 0); // 3-tap interpolation
@@ -675,10 +695,12 @@
 
 	switch (INPUT(input)->type) {
 	case CX88_VMUX_SVIDEO:
-		cx_andor(MO_AFECFG_IO, 0x01, 0x01);
+		cx_set(MO_AFECFG_IO,    0x00000001);
+		cx_set(MO_INPUT_FORMAT, 0x00010010);
 		break;
 	default:
-		cx_andor(MO_AFECFG_IO, 0x01, 0x00);
+		cx_clear(MO_AFECFG_IO,    0x00000001);
+		cx_clear(MO_INPUT_FORMAT, 0x00010010);
 		break;
 	}
 	return 0;
@@ -693,7 +715,7 @@
 	/* setup fifo + format */
 	cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH21],
 				buf->bpl, buf->risc.dma);
-	set_scale(dev, buf->vb.width, buf->vb.height, 1);
+	set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field);
 	cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
 
 	/* reset counter */
@@ -1350,6 +1372,9 @@
 	case V4L2_CID_AUDIO_BALANCE:
 		ctl->value = (value & 0x40) ? (value & 0x3f) : (0x40 - (value & 0x3f));
 		break;
+	case V4L2_CID_AUDIO_VOLUME:
+		ctl->value = 0x3f - (value & 0x3f);
+		break;
 	default:
 		ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift;
 		break;
@@ -1378,6 +1403,9 @@
 	case V4L2_CID_AUDIO_BALANCE:
 		value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value;
 		break;
+	case V4L2_CID_AUDIO_VOLUME:
+		value = 0x3f - (ctl->value & 0x3f);
+		break;
 	case V4L2_CID_SATURATION:
 		/* special v_sat handling */
 		v_sat_value = ctl->value - (0x7f - 0x5a);
@@ -1409,7 +1437,7 @@
 	};
 	static struct v4l2_control volume = {
 		.id    = V4L2_CID_AUDIO_VOLUME,
-		.value = 0,
+		.value = 0x3f,
 	};
 
 	set_control(dev,&mute);
@@ -1459,15 +1487,12 @@
 		maxw  = norm_maxw(dev->tvnorm);
 		maxh  = norm_maxh(dev->tvnorm);
 
-#if 0
 		if (V4L2_FIELD_ANY == field) {
 			field = (f->fmt.pix.height > maxh/2)
 				? V4L2_FIELD_INTERLACED
 				: V4L2_FIELD_BOTTOM;
 		}
-#else
-		field = V4L2_FIELD_INTERLACED;
-#endif
+
 		switch (field) {
 		case V4L2_FIELD_TOP:
 		case V4L2_FIELD_BOTTOM:
@@ -1480,14 +1505,15 @@
 		}
 
 		f->fmt.pix.field = field;
-		if (f->fmt.pix.width < 48)
-			f->fmt.pix.width = 48;
 		if (f->fmt.pix.height < 32)
 			f->fmt.pix.height = 32;
-		if (f->fmt.pix.width > maxw)
-			f->fmt.pix.width = maxw;
 		if (f->fmt.pix.height > maxh)
 			f->fmt.pix.height = maxh;
+		if (f->fmt.pix.width < 48)
+			f->fmt.pix.width = 48;
+		if (f->fmt.pix.width > maxw)
+			f->fmt.pix.width = maxw;
+		f->fmt.pix.width &= ~0x03;
 		f->fmt.pix.bytesperline =
 			(f->fmt.pix.width * fmt->depth) >> 3;
 		f->fmt.pix.sizeimage =
@@ -1783,7 +1809,11 @@
 			return -EINVAL;
 		down(&dev->lock);
 		dev->freq = f->frequency;
+#ifdef V4L2_I2C_CLIENTS
+		cx8800_call_i2c_clients(dev,VIDIOC_S_FREQUENCY,f);
+#else
 		cx8800_call_i2c_clients(dev,VIDIOCSFREQ,&dev->freq);
+#endif
 		up(&dev->lock);
 		return 0;
 	}
@@ -1885,7 +1915,6 @@
 	case VIDIOC_G_TUNER:
 	{
 		struct v4l2_tuner *t = arg;
-		struct video_tuner vt;
 
 		if (t->index > 0)
 			return -EINVAL;
@@ -1895,9 +1924,16 @@
                 t->rangelow  = (int)(65*16);
                 t->rangehigh = (int)(108*16);
 		
-		memset(&vt,0,sizeof(vt));
-		cx8800_call_i2c_clients(dev,VIDIOCGTUNER,&vt);
-		t->signal = vt.signal;
+#ifdef V4L2_I2C_CLIENTS
+		cx8800_call_i2c_clients(dev,VIDIOC_G_TUNER,t);
+#else
+		{
+			struct video_tuner vt;
+			memset(&vt,0,sizeof(vt));
+			cx8800_call_i2c_clients(dev,VIDIOCGTUNER,&vt);
+			t->signal = vt.signal;
+		}
+#endif
 		return 0;
 	}
 	case VIDIOC_ENUMINPUT:
@@ -2281,11 +2317,6 @@
 	}
 }
 
-/* debug that damn oops ... */
-static unsigned int oops = 0;
-MODULE_PARM(oops,"i");
-#define OOPS(msg) if (oops) printk("%s: %s\n",__FUNCTION__,msg);
-
 static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
 				    const struct pci_device_id *pci_id)
 {
@@ -2299,7 +2330,6 @@
 	memset(dev,0,sizeof(*dev));
 
 	/* pci init */
-	OOPS("pci init");
 	dev->pci = pci_dev;
 	if (pci_enable_device(pci_dev)) {
 		err = -EIO;
@@ -2308,7 +2338,6 @@
 	sprintf(dev->name,"cx%x[%d]",pci_dev->device,cx8800_devcount);
 
 	/* pci quirks */
-	OOPS("pci quirks");
 	cx88_pci_quirks(dev->name, dev->pci, &latency);
 	if (UNSET != latency) {
 		printk(KERN_INFO "%s: setting pci latency timer to %d\n",
@@ -2317,7 +2346,6 @@
 	}
 
 	/* print pci info */
-	OOPS("pci info");
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
         pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
         printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
@@ -2333,14 +2361,15 @@
 	}
 
 	/* board config */
-	OOPS("board config");
 	dev->board = card[cx8800_devcount];
 	for (i = 0; UNSET == dev->board  &&  i < cx88_idcount; i++) 
 		if (pci_dev->subsystem_vendor == cx88_subids[i].subvendor &&
 		    pci_dev->subsystem_device == cx88_subids[i].subdevice)
 			dev->board = cx88_subids[i].card;
-	if (UNSET == dev->board)
+	if (UNSET == dev->board) {
 		dev->board = CX88_BOARD_UNKNOWN;
+		cx88_card_list(dev);
+	}
         printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
 	       dev->name,pci_dev->subsystem_vendor,
 	       pci_dev->subsystem_device,cx88_boards[dev->board].name,
@@ -2352,7 +2381,6 @@
 		dev->tuner_type = cx88_boards[dev->board].tuner_type;
 
 	/* get mmio */
-	OOPS("get mmio");
 	if (!request_mem_region(pci_resource_start(pci_dev,0),
 				pci_resource_len(pci_dev,0),
 				dev->name)) {
@@ -2366,7 +2394,6 @@
 	dev->bmmio = (u8*)dev->lmmio;
 
 	/* initialize driver struct */
-	OOPS("init structs");
         init_MUTEX(&dev->lock);
 	dev->slock = SPIN_LOCK_UNLOCKED;
 	dev->tvnorm = tvnorms;
@@ -2390,11 +2417,9 @@
 			  MO_VID_DMACNTRL,0x88,0x00);
 
 	/* initialize hardware */
-	OOPS("reset hardware");
 	cx8800_reset(dev);
 
 	/* get irq */
-	OOPS("install irq handler");
 	err = request_irq(pci_dev->irq, cx8800_irq,
 			  SA_SHIRQ | SA_INTERRUPT, dev->name, dev);
 	if (err < 0) {
@@ -2404,13 +2429,10 @@
 	}
 
 	/* register i2c bus + load i2c helpers */
-	OOPS("i2c setup");
 	cx8800_i2c_init(dev);
-	OOPS("card setup");
 	cx88_card_setup(dev);
 
 	/* load and configure helper modules */
-	OOPS("configure i2c clients");
 	if (TUNER_ABSENT != dev->tuner_type)
 		request_module("tuner");
 	if (cx88_boards[dev->board].needs_tda9887)
@@ -2419,7 +2441,6 @@
 		cx8800_call_i2c_clients(dev,TUNER_SET_TYPE,&dev->tuner_type);
 
 	/* register v4l devices */
-	OOPS("register video");
 	dev->video_dev = vdev_init(dev,&cx8800_video_template,"video");
 	err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
 				    video_nr[cx8800_devcount]);
@@ -2431,7 +2452,6 @@
 	printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
 	       dev->name,dev->video_dev->minor & 0x1f);
 
-	OOPS("register vbi");
 	dev->vbi_dev = vdev_init(dev,&cx8800_vbi_template,"vbi");
 	err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
 				    vbi_nr[cx8800_devcount]);
@@ -2444,7 +2464,6 @@
 	       dev->name,dev->vbi_dev->minor & 0x1f);
 
 	if (dev->has_radio) {
-		OOPS("register radio");
 		dev->radio_dev = vdev_init(dev,&cx8800_radio_template,"radio");
 		err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
 					    radio_nr[cx8800_devcount]);
@@ -2458,32 +2477,31 @@
 	}
 
 	/* everything worked */
-	OOPS("finalize");
 	list_add_tail(&dev->devlist,&cx8800_devlist);
 	pci_set_drvdata(pci_dev,dev);
 	cx8800_devcount++;
 
 	/* initial device configuration */
-	OOPS("init device");
 	down(&dev->lock);
 	init_controls(dev);
 	set_tvnorm(dev,tvnorms);
 	video_mux(dev,0);
 	up(&dev->lock);
+
+	/* start tvaudio thread */
+	init_completion(&dev->texit);
+	dev->tpid = kernel_thread(cx88_audio_thread, dev, 0);
 	return 0;
 
  fail3:
-	OOPS("fail3");
 	cx8800_unregister_video(dev);
 	if (0 == dev->i2c_rc)
 		i2c_bit_del_bus(&dev->i2c_adap);
 	free_irq(pci_dev->irq, dev);
  fail2:
-	OOPS("fail2");
 	release_mem_region(pci_resource_start(pci_dev,0),
 			   pci_resource_len(pci_dev,0));
  fail1:
-	OOPS("fail1");
 	kfree(dev);
 	return err;
 }
@@ -2491,6 +2509,11 @@
 static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
 {
         struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+
+	/* stop thread */
+	dev->shutdown = 1;
+	if (dev->tpid >= 0)
+		wait_for_completion(&dev->texit);
 
 	cx8800_shutdown(dev);
 	pci_disable_device(pci_dev);
diff -Nru a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
--- a/drivers/media/video/cx88/cx88.h	2004-06-23 19:04:29 -07:00
+++ b/drivers/media/video/cx88/cx88.h	2004-06-23 19:04:29 -07:00
@@ -32,7 +32,7 @@
 #include "cx88-reg.h"
 
 #include <linux/version.h>
-#define CX88_VERSION_CODE KERNEL_VERSION(0,0,3)
+#define CX88_VERSION_CODE KERNEL_VERSION(0,0,4)
 
 #ifndef TRUE
 # define TRUE (1==1)
@@ -114,17 +114,20 @@
 /* card configuration                                          */
 
 #define CX88_BOARD_NOAUTO        UNSET
-#define CX88_BOARD_UNKNOWN           0
-#define CX88_BOARD_HAUPPAUGE         1
-#define CX88_BOARD_GDI               2
-#define CX88_BOARD_PIXELVIEW         3
-#define CX88_BOARD_ATI_WONDER_PRO    4
-#define CX88_BOARD_WINFAST2000XP     5
-#define CX88_BOARD_AVERTV_303        6
-#define CX88_BOARD_MSI_TVANYWHERE    7
-#define CX88_BOARD_WINFAST_DV2000    8
-#define CX88_BOARD_LEADTEK_PVR2000   9
-
+#define CX88_BOARD_UNKNOWN               0
+#define CX88_BOARD_HAUPPAUGE             1
+#define CX88_BOARD_GDI                   2
+#define CX88_BOARD_PIXELVIEW             3
+#define CX88_BOARD_ATI_WONDER_PRO        4
+#define CX88_BOARD_WINFAST2000XP         5
+#define CX88_BOARD_AVERTV_303            6
+#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7
+#define CX88_BOARD_WINFAST_DV2000        8
+#define CX88_BOARD_LEADTEK_PVR2000       9
+#define CX88_BOARD_IODATA_GVVCP3PCI      10
+#define CX88_BOARD_PROLINK_PLAYTVPVR     11
+#define CX88_BOARD_ASUS_PVR_416          12
+#define CX88_BOARD_MSI_TVANYWHERE        13
 
 enum cx88_itype {
 	CX88_VMUX_COMPOSITE1 = 1,
@@ -263,6 +266,9 @@
 
 	/* other global state info */
 	u32                         shadow[SHADOW_MAX];
+	int                         shutdown;
+	pid_t                       tpid;
+	struct completion           texit;
 	struct cx8800_suspend_state state;
 };
 
@@ -351,7 +357,8 @@
 extern struct cx88_subid cx88_subids[];
 extern const unsigned int cx88_idcount;
 
-extern void __devinit cx88_card_setup(struct cx8800_dev *dev);
+extern void cx88_card_list(struct cx8800_dev *dev);
+extern void cx88_card_setup(struct cx8800_dev *dev);
 
 /* ----------------------------------------------------------- */
 /* cx88-tvaudio.c                                              */
@@ -372,6 +379,7 @@
 void cx88_set_tvaudio(struct cx8800_dev *dev);
 void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t);
 void cx88_set_stereo(struct cx8800_dev *dev, u32 mode);
+int cx88_audio_thread(void *data);
 
 /*
  * Local variables:
diff -Nru a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
--- a/drivers/media/video/ir-kbd-gpio.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/video/ir-kbd-gpio.c	2004-06-23 19:04:28 -07:00
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 2003 Gerd Knorr
  * Copyright (c) 2003 Pavel Machek
@@ -32,47 +33,45 @@
 /* ---------------------------------------------------------------------- */
 
 static IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = {
-	[ 17 ] = KEY_KP0, 
-	[ 20 ] = KEY_KP1, 
-	[ 12 ] = KEY_KP2, 
-	[ 28 ] = KEY_KP3, 
-	[ 18 ] = KEY_KP4, 
-	[ 10 ] = KEY_KP5, 
-	[ 26 ] = KEY_KP6, 
-	[ 22 ] = KEY_KP7, 
-	[ 14 ] = KEY_KP8, 
-	[ 30 ] = KEY_KP9, 
+	[ 34 ] = KEY_KP0,
+	[ 40 ] = KEY_KP1,
+	[ 24 ] = KEY_KP2,
+	[ 56 ] = KEY_KP3,
+	[ 36 ] = KEY_KP4,
+	[ 20 ] = KEY_KP5,
+	[ 52 ] = KEY_KP6,
+	[ 44 ] = KEY_KP7,
+	[ 28 ] = KEY_KP8,
+	[ 60 ] = KEY_KP9,
 
-	[ 24 ] = KEY_EJECTCD,     // Unmarked on my controller
+	[ 48 ] = KEY_EJECTCD,     // Unmarked on my controller
 	[  0 ] = KEY_POWER, 
-	[  9 ] = BTN_LEFT,        // DISPLAY/L
-	[ 25 ] = BTN_RIGHT,       // LOOP/R
-	[  5 ] = KEY_MUTE, 
-	[ 19 ] = KEY_RECORD, 
-	[ 11 ] = KEY_PAUSE, 
-	[ 27 ] = KEY_STOP, 
-	[ 15 ] = KEY_VOLUMEDOWN, 
-	[ 31 ] = KEY_VOLUMEUP, 
-
-	[ 16 ] = KEY_TUNER,       // TV/FM
-	[  8 ] = KEY_CD, 
-	[  4 ] = KEY_VIDEO, 
-	[  2 ] = KEY_AUDIO, 
-	[  6 ] = KEY_ZOOM,        // full screen
-	[  1 ] = KEY_INFO,        // preview 
-	[ 21 ] = KEY_SEARCH,      // autoscan
-	[ 13 ] = KEY_STOP,        // freeze 
-	[ 29 ] = KEY_RECORD,      // capture 
-	[  3 ] = KEY_PLAY,        // unmarked
-	[ 23 ] = KEY_RED,         // unmarked
-	[  7 ] = KEY_GREEN,       // unmarked
-
-#if 0
-	[ 16 ] = KEY_YELLOW,      // unmarked
-	[  8 ] = KEY_CHANNELDOWN, 
-	[ 24 ] = KEY_CHANNELUP, 
-	[  0 ] = KEY_BLUE,        // unmarked
-#endif
+	[ 18 ] = BTN_LEFT,        // DISPLAY/L
+	[ 50 ] = BTN_RIGHT,       // LOOP/R
+	[ 10 ] = KEY_MUTE,
+	[ 38 ] = KEY_RECORD,
+	[ 22 ] = KEY_PAUSE,
+	[ 54 ] = KEY_STOP,
+	[ 30 ] = KEY_VOLUMEDOWN,
+	[ 62 ] = KEY_VOLUMEUP,
+
+	[ 32 ] = KEY_TUNER,       // TV/FM
+	[ 16 ] = KEY_CD,
+	[  8 ] = KEY_VIDEO,
+	[  4 ] = KEY_AUDIO,
+	[ 12 ] = KEY_ZOOM,        // full screen
+	[  2 ] = KEY_INFO,        // preview
+	[ 42 ] = KEY_SEARCH,      // autoscan
+	[ 26 ] = KEY_STOP,        // freeze
+	[ 58 ] = KEY_RECORD,      // capture
+	[  6 ] = KEY_PLAY,        // unmarked
+	[ 46 ] = KEY_RED,         // unmarked
+	[ 14 ] = KEY_GREEN,       // unmarked
+
+	[ 33 ] = KEY_YELLOW,      // unmarked
+	[ 17 ] = KEY_CHANNELDOWN,
+	[ 49 ] = KEY_CHANNELUP,
+	[  1 ] = KEY_BLUE,        // unmarked
 };
 
 static IR_KEYTAB_TYPE winfast_codes[IR_KEYTAB_SIZE] = {
@@ -280,8 +279,9 @@
 	case BTTV_AVPHONE98:
 	case BTTV_AVERMEDIA98:
 		ir_codes         = ir_codes_avermedia;
-		ir->mask_keycode = 0xf80000;
+		ir->mask_keycode = 0xf88000;
 		ir->mask_keydown = 0x010000;
+		ir->polling      = 50; // ms
 		break;
 
 	case BTTV_PXELVWPLTVPAK:
@@ -300,7 +300,7 @@
 
 	case BTTV_WINFAST2000:
 		ir_codes         = winfast_codes;
-		ir->mask_keycode = 0x8f8;
+		ir->mask_keycode = 0x1f8;
 		break;
 	case BTTV_MAGICTVIEW061:
 	case BTTV_MAGICTVIEW063:
diff -Nru a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
--- a/drivers/media/video/ir-kbd-i2c.c	2004-06-23 19:04:24 -07:00
+++ b/drivers/media/video/ir-kbd-i2c.c	2004-06-23 19:04:24 -07:00
@@ -77,6 +77,56 @@
 	[ 15 ] = KEY_SELECT, 		// SOURCE
 	[ 10 ] = KEY_KPPLUS,		// +100
 	[ 20 ] = KEY_KPEQUAL,		// SYNC
+	[ 28 ] = KEY_MEDIA,             // PC/TV
+};
+
+static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = {
+	[ 0x3  ] = KEY_POWER,
+	[ 0x6f ] = KEY_MUTE,
+	[ 0x10 ] = KEY_BACKSPACE,	// Recall
+
+	[ 0x11 ] = KEY_KP0,
+	[ 0x4  ] = KEY_KP1,
+	[ 0x5  ] = KEY_KP2,
+	[ 0x6  ] = KEY_KP3,
+	[ 0x8  ] = KEY_KP4,
+	[ 0x9  ] = KEY_KP5,
+	[ 0xa  ] = KEY_KP6,
+	[ 0xc  ] = KEY_KP7,
+	[ 0xd  ] = KEY_KP8,
+	[ 0xe  ] = KEY_KP9,
+	[ 0x12 ] = KEY_KPDOT,		// 100+
+
+	[ 0x7  ] = KEY_VOLUMEUP,
+	[ 0xb  ] = KEY_VOLUMEDOWN,
+	[ 0x1a ] = KEY_KPPLUS,
+	[ 0x18 ] = KEY_KPMINUS,
+	[ 0x15 ] = KEY_UP,
+	[ 0x1d ] = KEY_DOWN,
+	[ 0xf  ] = KEY_CHANNELUP,
+	[ 0x13 ] = KEY_CHANNELDOWN,
+	[ 0x48 ] = KEY_ZOOM,
+
+	[ 0x1b ] = KEY_VIDEO,		// Video source
+#if 0
+	[ 0x1f ] = KEY_S,       	// Snapshot
+#endif
+	[ 0x49 ] = KEY_LANGUAGE,	// MTS Select
+	[ 0x19 ] = KEY_SEARCH,		// Auto Scan
+
+	[ 0x4b ] = KEY_RECORD,
+	[ 0x46 ] = KEY_PLAY,
+	[ 0x45 ] = KEY_PAUSE,   	// Pause
+	[ 0x44 ] = KEY_STOP,
+#if 0
+	[ 0x43 ] = KEY_T,    		// Time Shift
+	[ 0x47 ] = KEY_Y,    		// Time Shift OFF
+	[ 0x4a ] = KEY_O,    		// TOP
+	[ 0x17 ] = KEY_F,    		// SURF CH
+#endif
+	[ 0x40 ] = KEY_FORWARD,   	// Forward ?
+	[ 0x42 ] = KEY_REWIND,   	// Backward ?
+
 };
 
 struct IR;
@@ -202,11 +252,33 @@
 	return 1;
 }
 
+static int get_key_purpletv(struct IR *ir, u32 *ir_key, u32 *ir_raw)
+{
+        unsigned char b;
+
+	/* poll IR chip */
+	if (1 != i2c_master_recv(&ir->c,&b,1)) {
+		dprintk(1,"read error\n");
+		return -EIO;
+	}
+
+	/* no button press */
+	if (b==0)
+		return 0;
+
+	/* repeating */
+	if (b & 0x80)
+		return 1;
+
+	*ir_key = b;
+	*ir_raw = b;
+	return 1;
+}
 /* ----------------------------------------------------------------------- */
 
 static void ir_key_poll(struct IR *ir)
 {
-	u32 ir_key, ir_raw;
+	static u32 ir_key, ir_raw;
 	int rc;
 
 	dprintk(2,"ir_poll_key\n");
@@ -300,6 +372,12 @@
 		ir_type     = IR_TYPE_OTHER;
 		ir_codes    = ir_codes_empty;
 		break;
+	case 0x7a:
+		name        = "Purple TV";
+		ir->get_key = get_key_purpletv;
+		ir_type     = IR_TYPE_OTHER;
+		ir_codes    = ir_codes_purpletv;
+		break;
 	default:
 		/* shouldn't happen */
 		printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr);
@@ -320,7 +398,8 @@
 	ir->input.name       = ir->c.name;
 	ir->input.phys       = ir->phys;
 	input_register_device(&ir->input);
-	printk(DEVNAME ": %s detected at %s\n",ir->input.name,ir->input.phys);
+	printk(DEVNAME ": %s detected at %s [%s]\n",
+	       ir->input.name,ir->input.phys,adap->name);
 	       
 	/* start polling via eventd */
 	INIT_WORK(&ir->work, ir_work, ir);
@@ -361,22 +440,33 @@
 	   That's why we probe 0x1a (~0x34) first. CB 
 	*/
 	
-	static const int probe[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
+	static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
+	static const int probe_saa7134[] = { 0x7a, -1};
+	const int *probe = NULL;
 	struct i2c_client c; char buf; int i,rc;
 
-	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) {
-		memset(&c,0,sizeof(c));
-		c.adapter = adap;
-		for (i = 0; -1 != probe[i]; i++) {
-			c.addr = probe[i];
-			rc = i2c_master_recv(&c,&buf,1);
-			dprintk(1,"probe 0x%02x @ %s: %s\n",
-				probe[i], adap->name, 
-				(1 == rc) ? "yes" : "no");
-			if (1 == rc) {
-				ir_attach(adap,probe[i],0,0);
-				break;
-			}
+	switch (adap->id) {
+	case I2C_ALGO_BIT | I2C_HW_B_BT848:
+		probe = probe_bttv;
+		break;
+	case I2C_ALGO_SAA7134:
+		probe = probe_saa7134;
+		break;
+	}
+	if (NULL == probe)
+		return 0;
+
+	memset(&c,0,sizeof(c));
+	c.adapter = adap;
+	for (i = 0; -1 != probe[i]; i++) {
+		c.addr = probe[i];
+		rc = i2c_master_recv(&c,&buf,1);
+		dprintk(1,"probe 0x%02x @ %s: %s\n",
+			probe[i], adap->name,
+			(1 == rc) ? "yes" : "no");
+		if (1 == rc) {
+			ir_attach(adap,probe[i],0,0);
+			break;
 		}
 	}
 	return 0;
diff -Nru a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
--- a/drivers/media/video/msp3400.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/media/video/msp3400.c	2004-06-23 19:04:27 -07:00
@@ -51,6 +51,7 @@
 #include <asm/pgtable.h>
 
 #include <media/audiochip.h>
+#include <media/id.h>
 #include "msp3400.h"
 
 /* insmod parameters */
@@ -80,7 +81,7 @@
 	int input;
 
 	int muted;
-	int left, right;	/* volume */
+	int volume, balance;
 	int bass, treble;
 
 	/* shadow register set */
@@ -378,26 +379,24 @@
 }
 
 static void msp3400c_setvolume(struct i2c_client *client,
-			       int muted, int left, int right)
+			       int muted, int volume, int balance)
 {
-	int vol = 0,val = 0,balance = 0;
+	int val = 0, bal = 0;
 
 	if (!muted) {
-		vol     = (left > right) ? left : right;
-		val     = (vol * 0x73 / 65535) << 8;
+		val = (volume * 0x73 / 65535) << 8;
 	}
-	if (vol > 0) {
-		balance = ((right-left) * 127) / vol;
+	if (val) {
+		bal = (balance / 256) - 128;
 	}
-
 	dprintk(KERN_DEBUG
 		"msp34xx: setvolume: mute=%s %d:%d  v=0x%02x b=0x%02x\n",
-		muted ? "on" : "off", left, right, val>>8, balance);
+		muted ? "on" : "off", volume, balance, val>>8, bal);
 	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */
 	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones  */
 	/* scart - on/off only */
 	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007, val ? 0x4000 : 0);
-	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0001, balance << 8);
+	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0001, bal << 8);
 }
 
 static void msp3400c_setbass(struct i2c_client *client, int bass)
@@ -815,7 +814,7 @@
 			/* no carrier scan, just unmute */
 			printk("msp3400: thread: no carrier scan\n");
 			msp3400c_setvolume(client, msp->muted,
-					   msp->left, msp->right);
+					   msp->volume, msp->balance);
 			continue;
 		}
 		msp->restart = 0;
@@ -960,7 +959,8 @@
 		}
 
 		/* unmute + restore dfp registers */
-		msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
+		msp3400c_setvolume(client, msp->muted,
+				   msp->volume, msp->balance);
 		msp3400c_restore_dfp(client);
 
 		if (msp->watch_stereo)
@@ -1042,7 +1042,7 @@
 			/* no carrier scan needed, just unmute */
 			dprintk(KERN_DEBUG "msp3410: thread: no carrier scan\n");
 			msp3400c_setvolume(client, msp->muted,
-					   msp->left, msp->right);
+					   msp->volume, msp->balance);
 			continue;
 		}
 		msp->restart = 0;
@@ -1194,7 +1194,8 @@
 		/* unmute + restore dfp registers */
 		msp3400c_setbass(client, msp->bass);
 		msp3400c_settreble(client, msp->treble);
-		msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
+		msp3400c_setvolume(client, msp->muted,
+				    msp->volume, msp->balance);
 		msp3400c_restore_dfp(client);
 
 		if (msp->watch_stereo)
@@ -1257,8 +1258,8 @@
 	}
 	
 	memset(msp,0,sizeof(struct msp3400c));
-	msp->left   = 65535;
-	msp->right  = 65535;
+	msp->volume = 65535;
+	msp->balance = 32768;
 	msp->bass   = 32768;
 	msp->treble = 32768;
 	msp->input  = -1;
@@ -1290,7 +1291,7 @@
 	/* this will turn on a 1kHz beep - might be useful for debugging... */
 	msp3400c_write(c,I2C_MSP3400C_DFP, 0x0014, 0x1040);
 #endif
-	msp3400c_setvolume(c,msp->muted,msp->left,msp->right);
+	msp3400c_setvolume(c, msp->muted, msp->volume, msp->balance);
 
 	snprintf(c->name, sizeof(c->name), "MSP34%02d%c-%c%d",
 		 (msp->rev2>>8)&0xff, (msp->rev1&0xff)+'@',
@@ -1440,8 +1441,10 @@
 		} else {
 			/* set msp3400 to FM radio mode */
 			msp3400c_setmode(client,MSP_MODE_FM_RADIO);
-			msp3400c_setcarrier(client, MSP_CARRIER(10.7),MSP_CARRIER(10.7));
-			msp3400c_setvolume(client,msp->muted,msp->left,msp->right);			
+			msp3400c_setcarrier(client, MSP_CARRIER(10.7),
+					    MSP_CARRIER(10.7));
+			msp3400c_setvolume(client, msp->muted,
+					   msp->volume, msp->balance);
 		}
 		if (msp->active)
 			msp->restart = 1;
@@ -1488,16 +1491,9 @@
 			VIDEO_AUDIO_MUTABLE;
 		if (msp->muted)
 			va->flags |= VIDEO_AUDIO_MUTE;
-		va->volume=max(msp->left,msp->right);
 
-		if (0 == va->volume) {
-			va->balance = 32768;
-		} else {
-			va->balance = (32768 * min(msp->left,msp->right))
-				/ va->volume;
-			va->balance = (msp->left<msp->right) ?
-				(65535 - va->balance) : va->balance;
-		}
+		va->volume = msp->volume;
+		va->balance = (va->volume) ? msp->balance : 32768;
 		va->bass = msp->bass;
 		va->treble = msp->treble;
 
@@ -1513,13 +1509,13 @@
 
 		dprintk(KERN_DEBUG "msp34xx: VIDIOCSAUDIO\n");
 		msp->muted = (va->flags & VIDEO_AUDIO_MUTE);
-		msp->left = (min(65536 - va->balance,32768) *
-			     va->volume) / 32768;
-		msp->right = (min(va->balance,(__u16)32768) *
-			      va->volume) / 32768;
+		msp->volume = va->volume;
+		msp->balance = va->balance;
 		msp->bass = va->bass;
 		msp->treble = va->treble;
-		msp3400c_setvolume(client,msp->muted,msp->left,msp->right);
+
+		msp3400c_setvolume(client, msp->muted,
+				   msp->volume, msp->balance);
 		msp3400c_setbass(client,msp->bass);
 		msp3400c_settreble(client,msp->treble);
 
diff -Nru a/drivers/media/video/ovcamchip/Makefile b/drivers/media/video/ovcamchip/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/ovcamchip/Makefile	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,4 @@
+ovcamchip-objs     := ovcamchip_core.o ov6x20.o ov6x30.o ov7x10.o ov7x20.o \
+                      ov76be.o
+
+obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip.o
diff -Nru a/drivers/media/video/ovcamchip/ov6x20.c b/drivers/media/video/ovcamchip/ov6x20.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/ovcamchip/ov6x20.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,415 @@
+/* OmniVision OV6620/OV6120 Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* Registers */
+#define REG_GAIN		0x00	/* gain [5:0] */
+#define REG_BLUE		0x01	/* blue gain */
+#define REG_RED			0x02	/* red gain */
+#define REG_SAT			0x03	/* saturation */
+#define REG_CNT			0x05	/* Y contrast */
+#define REG_BRT			0x06	/* Y brightness */
+#define REG_WB_BLUE		0x0C	/* WB blue ratio [5:0] */
+#define REG_WB_RED		0x0D	/* WB red ratio [5:0] */
+#define REG_EXP			0x10	/* exposure */
+
+/* Window parameters */
+#define HWSBASE 0x38
+#define HWEBASE 0x3A
+#define VWSBASE 0x05
+#define VWEBASE 0x06
+
+struct ov6x20 {
+	int auto_brt;
+	int auto_exp;
+	int backlight;
+	int bandfilt;
+	int mirror;
+};
+
+/* Initial values for use with OV511/OV511+ cameras */
+static struct ovcamchip_regvals regvals_init_6x20_511[] = {
+	{ 0x12, 0x80 }, /* reset */
+	{ 0x11, 0x01 },
+	{ 0x03, 0x60 },
+	{ 0x05, 0x7f }, /* For when autoadjust is off */
+	{ 0x07, 0xa8 },
+	{ 0x0c, 0x24 },
+	{ 0x0d, 0x24 },
+	{ 0x0f, 0x15 }, /* COMS */
+	{ 0x10, 0x75 }, /* AEC Exposure time */
+	{ 0x12, 0x24 }, /* Enable AGC and AWB */
+	{ 0x14, 0x04 },
+	{ 0x16, 0x03 },
+	{ 0x26, 0xb2 }, /* BLC enable */
+	/* 0x28: 0x05 Selects RGB format if RGB on */
+	{ 0x28, 0x05 },
+	{ 0x2a, 0x04 }, /* Disable framerate adjust */
+	{ 0x2d, 0x99 },
+	{ 0x33, 0xa0 }, /* Color Processing Parameter */
+	{ 0x34, 0xd2 }, /* Max A/D range */
+	{ 0x38, 0x8b },
+	{ 0x39, 0x40 },
+
+	{ 0x3c, 0x39 }, /* Enable AEC mode changing */
+	{ 0x3c, 0x3c }, /* Change AEC mode */
+	{ 0x3c, 0x24 }, /* Disable AEC mode changing */
+
+	{ 0x3d, 0x80 },
+	/* These next two registers (0x4a, 0x4b) are undocumented. They
+	 * control the color balance */
+	{ 0x4a, 0x80 },
+	{ 0x4b, 0x80 },
+	{ 0x4d, 0xd2 }, /* This reduces noise a bit */
+	{ 0x4e, 0xc1 },
+	{ 0x4f, 0x04 },
+	{ 0xff, 0xff },	/* END MARKER */
+};
+
+/* Initial values for use with OV518 cameras */
+static struct ovcamchip_regvals regvals_init_6x20_518[] = {
+	{ 0x12, 0x80 }, /* Do a reset */
+	{ 0x03, 0xc0 }, /* Saturation */
+	{ 0x05, 0x8a }, /* Contrast */
+	{ 0x0c, 0x24 }, /* AWB blue */
+	{ 0x0d, 0x24 }, /* AWB red */
+	{ 0x0e, 0x8d }, /* Additional 2x gain */
+	{ 0x0f, 0x25 }, /* Black expanding level = 1.3V */
+	{ 0x11, 0x01 }, /* Clock div. */
+	{ 0x12, 0x24 }, /* Enable AGC and AWB */
+	{ 0x13, 0x01 }, /* (default) */
+	{ 0x14, 0x80 }, /* Set reserved bit 7 */
+	{ 0x15, 0x01 }, /* (default) */
+	{ 0x16, 0x03 }, /* (default) */
+	{ 0x17, 0x38 }, /* (default) */
+	{ 0x18, 0xea }, /* (default) */
+	{ 0x19, 0x04 },
+	{ 0x1a, 0x93 },
+	{ 0x1b, 0x00 }, /* (default) */
+	{ 0x1e, 0xc4 }, /* (default) */
+	{ 0x1f, 0x04 }, /* (default) */
+	{ 0x20, 0x20 }, /* Enable 1st stage aperture correction */
+	{ 0x21, 0x10 }, /* Y offset */
+	{ 0x22, 0x88 }, /* U offset */
+	{ 0x23, 0xc0 }, /* Set XTAL power level */
+	{ 0x24, 0x53 }, /* AEC bright ratio */
+	{ 0x25, 0x7a }, /* AEC black ratio */
+	{ 0x26, 0xb2 }, /* BLC enable */
+	{ 0x27, 0xa2 }, /* Full output range */
+	{ 0x28, 0x01 }, /* (default) */
+	{ 0x29, 0x00 }, /* (default) */
+	{ 0x2a, 0x84 }, /* (default) */
+	{ 0x2b, 0xa8 }, /* Set custom frame rate */
+	{ 0x2c, 0xa0 }, /* (reserved) */
+	{ 0x2d, 0x95 }, /* Enable banding filter */
+	{ 0x2e, 0x88 }, /* V offset */
+	{ 0x33, 0x22 }, /* Luminance gamma on */
+	{ 0x34, 0xc7 }, /* A/D bias */
+	{ 0x36, 0x12 }, /* (reserved) */
+	{ 0x37, 0x63 }, /* (reserved) */
+	{ 0x38, 0x8b }, /* Quick AEC/AEB */
+	{ 0x39, 0x00 }, /* (default) */
+	{ 0x3a, 0x0f }, /* (default) */
+	{ 0x3b, 0x3c }, /* (default) */
+	{ 0x3c, 0x5c }, /* AEC controls */
+	{ 0x3d, 0x80 }, /* Drop 1 (bad) frame when AEC change */
+	{ 0x3e, 0x80 }, /* (default) */
+	{ 0x3f, 0x02 }, /* (default) */
+	{ 0x40, 0x10 }, /* (reserved) */
+	{ 0x41, 0x10 }, /* (reserved) */
+	{ 0x42, 0x00 }, /* (reserved) */
+	{ 0x43, 0x7f }, /* (reserved) */
+	{ 0x44, 0x80 }, /* (reserved) */
+	{ 0x45, 0x1c }, /* (reserved) */
+	{ 0x46, 0x1c }, /* (reserved) */
+	{ 0x47, 0x80 }, /* (reserved) */
+	{ 0x48, 0x5f }, /* (reserved) */
+	{ 0x49, 0x00 }, /* (reserved) */
+	{ 0x4a, 0x00 }, /* Color balance (undocumented) */
+	{ 0x4b, 0x80 }, /* Color balance (undocumented) */
+	{ 0x4c, 0x58 }, /* (reserved) */
+	{ 0x4d, 0xd2 }, /* U *= .938, V *= .838 */
+	{ 0x4e, 0xa0 }, /* (default) */
+	{ 0x4f, 0x04 }, /* UV 3-point average */
+	{ 0x50, 0xff }, /* (reserved) */
+	{ 0x51, 0x58 }, /* (reserved) */
+	{ 0x52, 0xc0 }, /* (reserved) */
+	{ 0x53, 0x42 }, /* (reserved) */
+	{ 0x27, 0xa6 }, /* Enable manual offset adj. (reg 21 & 22) */
+	{ 0x12, 0x20 },
+	{ 0x12, 0x24 },
+
+	{ 0xff, 0xff },	/* END MARKER */
+};
+
+/* This initializes the OV6x20 camera chip and relevant variables. */
+static int ov6x20_init(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov6x20 *s;
+	int rc;
+
+	DDEBUG(4, &c->dev, "entered");
+
+	switch (c->adapter->id) {
+	case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511:
+		rc = ov_write_regvals(c, regvals_init_6x20_511);
+		break;
+	case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518:
+		rc = ov_write_regvals(c, regvals_init_6x20_518);
+		break;
+	default:
+		dev_err(&c->dev, "ov6x20: Unsupported adapter\n");
+		rc = -ENODEV;
+	}
+
+	if (rc < 0)
+		return rc;
+
+	ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+	memset(s, 0, sizeof *s);
+
+	s->auto_brt = 1;
+	s->auto_exp = 1;
+
+	return rc;
+}
+
+static int ov6x20_free(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+
+	kfree(ov->spriv);
+	return 0;
+}
+
+static int ov6x20_set_control(struct i2c_client *c,
+			      struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov6x20 *s = ov->spriv;
+	int rc;
+	int v = ctl->value;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_CONT:
+		rc = ov_write(c, REG_CNT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_BRIGHT:
+		rc = ov_write(c, REG_BRT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_write(c, REG_SAT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_HUE:
+		rc = ov_write(c, REG_RED, 0xFF - (v >> 8));
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write(c, REG_BLUE, v >> 8);
+		break;
+	case OVCAMCHIP_CID_EXP:
+		rc = ov_write(c, REG_EXP, v);
+		break;
+	case OVCAMCHIP_CID_FREQ:
+	{
+		int sixty = (v == 60);
+
+		rc = ov_write(c, 0x2b, sixty?0xa8:0x28);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write(c, 0x2a, sixty?0x84:0xa4);
+		break;
+	}
+	case OVCAMCHIP_CID_BANDFILT:
+		rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+		s->bandfilt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+		s->auto_brt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01);
+		s->auto_exp = v;
+		break;
+	case OVCAMCHIP_CID_BACKLIGHT:
+	{
+		rc = ov_write_mask(c, 0x4e, v?0xe0:0xc0, 0xe0);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x0e, v?0x80:0x00, 0x80);
+		s->backlight = v;
+		break;
+	}
+	case OVCAMCHIP_CID_MIRROR:
+		rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+		s->mirror = v;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+out:
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+	return rc;
+}
+
+static int ov6x20_get_control(struct i2c_client *c,
+			      struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov6x20 *s = ov->spriv;
+	int rc = 0;
+	unsigned char val = 0;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_CONT:
+		rc = ov_read(c, REG_CNT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_BRIGHT:
+		rc = ov_read(c, REG_BRT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_read(c, REG_SAT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_HUE:
+		rc = ov_read(c, REG_BLUE, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_EXP:
+		rc = ov_read(c, REG_EXP, &val);
+		ctl->value = val;
+		break;
+	case OVCAMCHIP_CID_BANDFILT:
+		ctl->value = s->bandfilt;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		ctl->value = s->auto_brt;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		ctl->value = s->auto_exp;
+		break;
+	case OVCAMCHIP_CID_BACKLIGHT:
+		ctl->value = s->backlight;
+		break;
+	case OVCAMCHIP_CID_MIRROR:
+		ctl->value = s->mirror;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+	return rc;
+}
+
+static int ov6x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	/******** QCIF-specific regs ********/
+
+	ov_write(c, 0x14, win->quarter?0x24:0x04);
+
+	/******** Palette-specific regs ********/
+
+	/* OV518 needs 8 bit multiplexed in color mode, and 16 bit in B&W */
+	if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+		if (win->format == VIDEO_PALETTE_GREY)
+			ov_write_mask(c, 0x13, 0x00, 0x20);
+		else
+			ov_write_mask(c, 0x13, 0x20, 0x20);
+	} else {
+		if (win->format == VIDEO_PALETTE_GREY)
+			ov_write_mask(c, 0x13, 0x20, 0x20);
+		else
+			ov_write_mask(c, 0x13, 0x00, 0x20);
+	}
+
+	/******** Clock programming ********/
+
+	/* The OV6620 needs special handling. This prevents the
+	 * severe banding that normally occurs */
+
+	/* Clock down */
+	ov_write(c, 0x2a, 0x04);
+
+	ov_write(c, 0x11, win->clockdiv);
+
+	ov_write(c, 0x2a, 0x84);
+	/* This next setting is critical. It seems to improve
+	 * the gain or the contrast. The "reserved" bits seem
+	 * to have some effect in this case. */
+	ov_write(c, 0x2d, 0x85); /* FIXME: This messes up banding filter */
+
+	return 0;
+}
+
+static int ov6x20_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	int ret, hwscale, vwscale;
+
+	ret = ov6x20_mode_init(c, win);
+	if (ret < 0)
+		return ret;
+
+	if (win->quarter) {
+		hwscale = 0;
+		vwscale = 0;
+	} else {
+		hwscale = 1;
+		vwscale = 1;	/* The datasheet says 0; it's wrong */
+	}
+
+	ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+	ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+	ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+	ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+	return 0;
+}
+
+static int ov6x20_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case OVCAMCHIP_CMD_S_CTRL:
+		return ov6x20_set_control(c, arg);
+	case OVCAMCHIP_CMD_G_CTRL:
+		return ov6x20_get_control(c, arg);
+	case OVCAMCHIP_CMD_S_MODE:
+		return ov6x20_set_window(c, arg);
+	default:
+		DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+		return -ENOIOCTLCMD;
+	}
+}
+
+struct ovcamchip_ops ov6x20_ops = {
+	.init    =	ov6x20_init,
+	.free    =	ov6x20_free,
+	.command =	ov6x20_command,
+};
diff -Nru a/drivers/media/video/ovcamchip/ov6x30.c b/drivers/media/video/ovcamchip/ov6x30.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/ovcamchip/ov6x30.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,374 @@
+/* OmniVision OV6630/OV6130 Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* Registers */
+#define REG_GAIN		0x00	/* gain [5:0] */
+#define REG_BLUE		0x01	/* blue gain */
+#define REG_RED			0x02	/* red gain */
+#define REG_SAT			0x03	/* saturation [7:3] */
+#define REG_CNT			0x05	/* Y contrast [3:0] */
+#define REG_BRT			0x06	/* Y brightness */
+#define REG_SHARP		0x07	/* sharpness */
+#define REG_WB_BLUE		0x0C	/* WB blue ratio [5:0] */
+#define REG_WB_RED		0x0D	/* WB red ratio [5:0] */
+#define REG_EXP			0x10	/* exposure */
+
+/* Window parameters */
+#define HWSBASE 0x38
+#define HWEBASE 0x3A
+#define VWSBASE 0x05
+#define VWEBASE 0x06
+
+struct ov6x30 {
+	int auto_brt;
+	int auto_exp;
+	int backlight;
+	int bandfilt;
+	int mirror;
+};
+
+static struct ovcamchip_regvals regvals_init_6x30[] = {
+	{ 0x12, 0x80 }, /* reset */
+	{ 0x00, 0x1f }, /* Gain */
+	{ 0x01, 0x99 }, /* Blue gain */
+	{ 0x02, 0x7c }, /* Red gain */
+	{ 0x03, 0xc0 }, /* Saturation */
+	{ 0x05, 0x0a }, /* Contrast */
+	{ 0x06, 0x95 }, /* Brightness */
+	{ 0x07, 0x2d }, /* Sharpness */
+	{ 0x0c, 0x20 },
+	{ 0x0d, 0x20 },
+	{ 0x0e, 0x20 },
+	{ 0x0f, 0x05 },
+	{ 0x10, 0x9a }, /* "exposure check" */
+	{ 0x11, 0x00 }, /* Pixel clock = fastest */
+	{ 0x12, 0x24 }, /* Enable AGC and AWB */
+	{ 0x13, 0x21 },
+	{ 0x14, 0x80 },
+	{ 0x15, 0x01 },
+	{ 0x16, 0x03 },
+	{ 0x17, 0x38 },
+	{ 0x18, 0xea },
+	{ 0x19, 0x04 },
+	{ 0x1a, 0x93 },
+	{ 0x1b, 0x00 },
+	{ 0x1e, 0xc4 },
+	{ 0x1f, 0x04 },
+	{ 0x20, 0x20 },
+	{ 0x21, 0x10 },
+	{ 0x22, 0x88 },
+	{ 0x23, 0xc0 }, /* Crystal circuit power level */
+	{ 0x25, 0x9a }, /* Increase AEC black pixel ratio */
+	{ 0x26, 0xb2 }, /* BLC enable */
+	{ 0x27, 0xa2 },
+	{ 0x28, 0x00 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x84 }, /* (keep) */
+	{ 0x2b, 0xa8 }, /* (keep) */
+	{ 0x2c, 0xa0 },
+	{ 0x2d, 0x95 },	/* Enable auto-brightness */
+	{ 0x2e, 0x88 },
+	{ 0x33, 0x26 },
+	{ 0x34, 0x03 },
+	{ 0x36, 0x8f },
+	{ 0x37, 0x80 },
+	{ 0x38, 0x83 },
+	{ 0x39, 0x80 },
+	{ 0x3a, 0x0f },
+	{ 0x3b, 0x3c },
+	{ 0x3c, 0x1a },
+	{ 0x3d, 0x80 },
+	{ 0x3e, 0x80 },
+	{ 0x3f, 0x0e },
+	{ 0x40, 0x00 }, /* White bal */
+	{ 0x41, 0x00 }, /* White bal */
+	{ 0x42, 0x80 },
+	{ 0x43, 0x3f }, /* White bal */
+	{ 0x44, 0x80 },
+	{ 0x45, 0x20 },
+	{ 0x46, 0x20 },
+	{ 0x47, 0x80 },
+	{ 0x48, 0x7f },
+	{ 0x49, 0x00 },
+	{ 0x4a, 0x00 },
+	{ 0x4b, 0x80 },
+	{ 0x4c, 0xd0 },
+	{ 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
+	{ 0x4e, 0x40 },
+	{ 0x4f, 0x07 }, /* UV average mode, color killer: strongest */
+	{ 0x50, 0xff },
+	{ 0x54, 0x23 }, /* Max AGC gain: 18dB */
+	{ 0x55, 0xff },
+	{ 0x56, 0x12 },
+	{ 0x57, 0x81 }, /* (default) */
+	{ 0x58, 0x75 },
+	{ 0x59, 0x01 }, /* AGC dark current compensation: +1 */
+	{ 0x5a, 0x2c },
+	{ 0x5b, 0x0f }, /* AWB chrominance levels */
+	{ 0x5c, 0x10 },
+	{ 0x3d, 0x80 },
+	{ 0x27, 0xa6 },
+	/* Toggle AWB off and on */
+	{ 0x12, 0x20 },
+	{ 0x12, 0x24 },
+
+	{ 0xff, 0xff },	/* END MARKER */
+};
+
+/* This initializes the OV6x30 camera chip and relevant variables. */
+static int ov6x30_init(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov6x30 *s;
+	int rc;
+
+	DDEBUG(4, &c->dev, "entered");
+
+	rc = ov_write_regvals(c, regvals_init_6x30);
+	if (rc < 0)
+		return rc;
+
+	ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+	memset(s, 0, sizeof *s);
+
+	s->auto_brt = 1;
+	s->auto_exp = 1;
+
+	return rc;
+}
+
+static int ov6x30_free(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+
+	kfree(ov->spriv);
+	return 0;
+}
+
+static int ov6x30_set_control(struct i2c_client *c,
+			      struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov6x30 *s = ov->spriv;
+	int rc;
+	int v = ctl->value;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_CONT:
+		rc = ov_write_mask(c, REG_CNT, v >> 12, 0x0f);
+		break;
+	case OVCAMCHIP_CID_BRIGHT:
+		rc = ov_write(c, REG_BRT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_write(c, REG_SAT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_HUE:
+		rc = ov_write(c, REG_RED, 0xFF - (v >> 8));
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write(c, REG_BLUE, v >> 8);
+		break;
+	case OVCAMCHIP_CID_EXP:
+		rc = ov_write(c, REG_EXP, v);
+		break;
+	case OVCAMCHIP_CID_FREQ:
+	{
+		int sixty = (v == 60);
+
+		rc = ov_write(c, 0x2b, sixty?0xa8:0x28);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write(c, 0x2a, sixty?0x84:0xa4);
+		break;
+	}
+	case OVCAMCHIP_CID_BANDFILT:
+		rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+		s->bandfilt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+		s->auto_brt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		rc = ov_write_mask(c, 0x28, v?0x00:0x10, 0x10);
+		s->auto_exp = v;
+		break;
+	case OVCAMCHIP_CID_BACKLIGHT:
+	{
+		rc = ov_write_mask(c, 0x4e, v?0x80:0x60, 0xe0);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x28, v?0x02:0x00, 0x02);
+		s->backlight = v;
+		break;
+	}
+	case OVCAMCHIP_CID_MIRROR:
+		rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+		s->mirror = v;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+out:
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+	return rc;
+}
+
+static int ov6x30_get_control(struct i2c_client *c,
+			      struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov6x30 *s = ov->spriv;
+	int rc = 0;
+	unsigned char val = 0;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_CONT:
+		rc = ov_read(c, REG_CNT, &val);
+		ctl->value = (val & 0x0f) << 12;
+		break;
+	case OVCAMCHIP_CID_BRIGHT:
+		rc = ov_read(c, REG_BRT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_read(c, REG_SAT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_HUE:
+		rc = ov_read(c, REG_BLUE, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_EXP:
+		rc = ov_read(c, REG_EXP, &val);
+		ctl->value = val;
+		break;
+	case OVCAMCHIP_CID_BANDFILT:
+		ctl->value = s->bandfilt;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		ctl->value = s->auto_brt;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		ctl->value = s->auto_exp;
+		break;
+	case OVCAMCHIP_CID_BACKLIGHT:
+		ctl->value = s->backlight;
+		break;
+	case OVCAMCHIP_CID_MIRROR:
+		ctl->value = s->mirror;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+	return rc;
+}
+
+static int ov6x30_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	/******** QCIF-specific regs ********/
+
+	ov_write_mask(c, 0x14, win->quarter?0x20:0x00, 0x20);
+
+	/******** Palette-specific regs ********/
+
+	if (win->format == VIDEO_PALETTE_GREY) {
+		if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+			/* Do nothing - we're already in 8-bit mode */
+		} else {
+			ov_write_mask(c, 0x13, 0x20, 0x20);
+		}
+	} else {
+		/* The OV518 needs special treatment. Although both the OV518
+		 * and the OV6630 support a 16-bit video bus, only the 8 bit Y
+		 * bus is actually used. The UV bus is tied to ground.
+		 * Therefore, the OV6630 needs to be in 8-bit multiplexed
+		 * output mode */
+
+		if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+			/* Do nothing - we want to stay in 8-bit mode */
+			/* Warning: Messing with reg 0x13 breaks OV518 color */
+		} else {
+			ov_write_mask(c, 0x13, 0x00, 0x20);
+		}
+	}
+
+	/******** Clock programming ********/
+
+	ov_write(c, 0x11, win->clockdiv);
+
+	return 0;
+}
+
+static int ov6x30_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	int ret, hwscale, vwscale;
+
+	ret = ov6x30_mode_init(c, win);
+	if (ret < 0)
+		return ret;
+
+	if (win->quarter) {
+		hwscale = 0;
+		vwscale = 0;
+	} else {
+		hwscale = 1;
+		vwscale = 1;	/* The datasheet says 0; it's wrong */
+	}
+
+	ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+	ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+	ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+	ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+	return 0;
+}
+
+static int ov6x30_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case OVCAMCHIP_CMD_S_CTRL:
+		return ov6x30_set_control(c, arg);
+	case OVCAMCHIP_CMD_G_CTRL:
+		return ov6x30_get_control(c, arg);
+	case OVCAMCHIP_CMD_S_MODE:
+		return ov6x30_set_window(c, arg);
+	default:
+		DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+		return -ENOIOCTLCMD;
+	}
+}
+
+struct ovcamchip_ops ov6x30_ops = {
+	.init    =	ov6x30_init,
+	.free    =	ov6x30_free,
+	.command =	ov6x30_command,
+};
diff -Nru a/drivers/media/video/ovcamchip/ov76be.c b/drivers/media/video/ovcamchip/ov76be.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/ovcamchip/ov76be.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,303 @@
+/* OmniVision OV76BE Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* OV7610 registers: Since the OV76BE is undocumented, we'll settle for these
+ * for now. */
+#define REG_GAIN		0x00	/* gain [5:0] */
+#define REG_BLUE		0x01	/* blue channel balance */
+#define REG_RED			0x02	/* red channel balance */
+#define REG_SAT			0x03	/* saturation */
+#define REG_CNT			0x05	/* Y contrast */
+#define REG_BRT			0x06	/* Y brightness */
+#define REG_BLUE_BIAS		0x0C	/* blue channel bias [5:0] */
+#define REG_RED_BIAS		0x0D	/* red channel bias [5:0] */
+#define REG_GAMMA_COEFF		0x0E	/* gamma settings */
+#define REG_WB_RANGE		0x0F	/* AEC/ALC/S-AWB settings */
+#define REG_EXP			0x10	/* manual exposure setting */
+#define REG_CLOCK		0x11	/* polarity/clock prescaler */
+#define REG_FIELD_DIVIDE	0x16	/* field interval/mode settings */
+#define REG_HWIN_START		0x17	/* horizontal window start */
+#define REG_HWIN_END		0x18	/* horizontal window end */
+#define REG_VWIN_START		0x19	/* vertical window start */
+#define REG_VWIN_END		0x1A	/* vertical window end */
+#define REG_PIXEL_SHIFT   	0x1B	/* pixel shift */
+#define REG_YOFFSET		0x21	/* Y channel offset */
+#define REG_UOFFSET		0x22	/* U channel offset */
+#define REG_ECW			0x24	/* exposure white level for AEC */
+#define REG_ECB			0x25	/* exposure black level for AEC */
+#define REG_FRAMERATE_H		0x2A	/* frame rate MSB + misc */
+#define REG_FRAMERATE_L		0x2B	/* frame rate LSB */
+#define REG_ALC			0x2C	/* Auto Level Control settings */
+#define REG_VOFFSET		0x2E	/* V channel offset adjustment */
+#define REG_ARRAY_BIAS		0x2F	/* array bias -- don't change */
+#define REG_YGAMMA		0x33	/* misc gamma settings [7:6] */
+#define REG_BIAS_ADJUST		0x34	/* misc bias settings */
+
+/* Window parameters */
+#define HWSBASE 0x38
+#define HWEBASE 0x3a
+#define VWSBASE 0x05
+#define VWEBASE 0x05
+
+struct ov76be {
+	int auto_brt;
+	int auto_exp;
+	int bandfilt;
+	int mirror;
+};
+
+/* NOTE: These are the same as the 7x10 settings, but should eventually be
+ * optimized for the OV76BE */
+static struct ovcamchip_regvals regvals_init_76be[] = {
+	{ 0x10, 0xff },
+	{ 0x16, 0x03 },
+	{ 0x28, 0x24 },
+	{ 0x2b, 0xac },
+	{ 0x12, 0x00 },
+	{ 0x38, 0x81 },
+	{ 0x28, 0x24 },	/* 0c */
+	{ 0x0f, 0x85 },	/* lg's setting */
+	{ 0x15, 0x01 },
+	{ 0x20, 0x1c },
+	{ 0x23, 0x2a },
+	{ 0x24, 0x10 },
+	{ 0x25, 0x8a },
+	{ 0x26, 0xa2 },
+	{ 0x27, 0xc2 },
+	{ 0x2a, 0x04 },
+	{ 0x2c, 0xfe },
+	{ 0x2d, 0x93 },
+	{ 0x30, 0x71 },
+	{ 0x31, 0x60 },
+	{ 0x32, 0x26 },
+	{ 0x33, 0x20 },
+	{ 0x34, 0x48 },
+	{ 0x12, 0x24 },
+	{ 0x11, 0x01 },
+	{ 0x0c, 0x24 },
+	{ 0x0d, 0x24 },
+	{ 0xff, 0xff },	/* END MARKER */
+};
+
+/* This initializes the OV76be camera chip and relevant variables. */
+static int ov76be_init(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov76be *s;
+	int rc;
+
+	DDEBUG(4, &c->dev, "entered");
+
+	rc = ov_write_regvals(c, regvals_init_76be);
+	if (rc < 0)
+		return rc;
+
+	ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+	memset(s, 0, sizeof *s);
+
+	s->auto_brt = 1;
+	s->auto_exp = 1;
+
+	return rc;
+}
+
+static int ov76be_free(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+
+	kfree(ov->spriv);
+	return 0;
+}
+
+static int ov76be_set_control(struct i2c_client *c,
+			      struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov76be *s = ov->spriv;
+	int rc;
+	int v = ctl->value;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_BRIGHT:
+		rc = ov_write(c, REG_BRT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_write(c, REG_SAT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_EXP:
+		rc = ov_write(c, REG_EXP, v);
+		break;
+	case OVCAMCHIP_CID_FREQ:
+	{
+		int sixty = (v == 60);
+
+		rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write(c, 0x2b, sixty?0x00:0xac);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x76, 0x01, 0x01);
+		break;
+	}
+	case OVCAMCHIP_CID_BANDFILT:
+		rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+		s->bandfilt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+		s->auto_brt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01);
+		s->auto_exp = v;
+		break;
+	case OVCAMCHIP_CID_MIRROR:
+		rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+		s->mirror = v;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+out:
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+	return rc;
+}
+
+static int ov76be_get_control(struct i2c_client *c,
+			      struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov76be *s = ov->spriv;
+	int rc = 0;
+	unsigned char val = 0;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_BRIGHT:
+		rc = ov_read(c, REG_BRT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_read(c, REG_SAT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_EXP:
+		rc = ov_read(c, REG_EXP, &val);
+		ctl->value = val;
+		break;
+	case OVCAMCHIP_CID_BANDFILT:
+		ctl->value = s->bandfilt;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		ctl->value = s->auto_brt;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		ctl->value = s->auto_exp;
+		break;
+	case OVCAMCHIP_CID_MIRROR:
+		ctl->value = s->mirror;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+	return rc;
+}
+
+static int ov76be_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	int qvga = win->quarter;
+
+	/******** QVGA-specific regs ********/
+
+	ov_write(c, 0x14, qvga?0xa4:0x84);
+
+	/******** Palette-specific regs ********/
+
+	if (win->format == VIDEO_PALETTE_GREY) {
+		ov_write_mask(c, 0x0e, 0x40, 0x40);
+		ov_write_mask(c, 0x13, 0x20, 0x20);
+	} else {
+		ov_write_mask(c, 0x0e, 0x00, 0x40);
+		ov_write_mask(c, 0x13, 0x00, 0x20);
+	}
+
+	/******** Clock programming ********/
+
+	ov_write(c, 0x11, win->clockdiv);
+
+	/******** Resolution-specific ********/
+
+	if (win->width == 640 && win->height == 480)
+		ov_write(c, 0x35, 0x9e);
+	else
+		ov_write(c, 0x35, 0x1e);
+
+	return 0;
+}
+
+static int ov76be_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	int ret, hwscale, vwscale;
+
+	ret = ov76be_mode_init(c, win);
+	if (ret < 0)
+		return ret;
+
+	if (win->quarter) {
+		hwscale = 1;
+		vwscale = 0;
+	} else {
+		hwscale = 2;
+		vwscale = 1;
+	}
+
+	ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+	ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+	ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+	ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+	return 0;
+}
+
+static int ov76be_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case OVCAMCHIP_CMD_S_CTRL:
+		return ov76be_set_control(c, arg);
+	case OVCAMCHIP_CMD_G_CTRL:
+		return ov76be_get_control(c, arg);
+	case OVCAMCHIP_CMD_S_MODE:
+		return ov76be_set_window(c, arg);
+	default:
+		DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+		return -ENOIOCTLCMD;
+	}
+}
+
+struct ovcamchip_ops ov76be_ops = {
+	.init    =	ov76be_init,
+	.free    =	ov76be_free,
+	.command =	ov76be_command,
+};
diff -Nru a/drivers/media/video/ovcamchip/ov7x10.c b/drivers/media/video/ovcamchip/ov7x10.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/ovcamchip/ov7x10.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,335 @@
+/* OmniVision OV7610/OV7110 Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* Registers */
+#define REG_GAIN		0x00	/* gain [5:0] */
+#define REG_BLUE		0x01	/* blue channel balance */
+#define REG_RED			0x02	/* red channel balance */
+#define REG_SAT			0x03	/* saturation */
+#define REG_CNT			0x05	/* Y contrast */
+#define REG_BRT			0x06	/* Y brightness */
+#define REG_BLUE_BIAS		0x0C	/* blue channel bias [5:0] */
+#define REG_RED_BIAS		0x0D	/* red channel bias [5:0] */
+#define REG_GAMMA_COEFF		0x0E	/* gamma settings */
+#define REG_WB_RANGE		0x0F	/* AEC/ALC/S-AWB settings */
+#define REG_EXP			0x10	/* manual exposure setting */
+#define REG_CLOCK		0x11	/* polarity/clock prescaler */
+#define REG_FIELD_DIVIDE	0x16	/* field interval/mode settings */
+#define REG_HWIN_START		0x17	/* horizontal window start */
+#define REG_HWIN_END		0x18	/* horizontal window end */
+#define REG_VWIN_START		0x19	/* vertical window start */
+#define REG_VWIN_END		0x1A	/* vertical window end */
+#define REG_PIXEL_SHIFT   	0x1B	/* pixel shift */
+#define REG_YOFFSET		0x21	/* Y channel offset */
+#define REG_UOFFSET		0x22	/* U channel offset */
+#define REG_ECW			0x24	/* exposure white level for AEC */
+#define REG_ECB			0x25	/* exposure black level for AEC */
+#define REG_FRAMERATE_H		0x2A	/* frame rate MSB + misc */
+#define REG_FRAMERATE_L		0x2B	/* frame rate LSB */
+#define REG_ALC			0x2C	/* Auto Level Control settings */
+#define REG_VOFFSET		0x2E	/* V channel offset adjustment */
+#define REG_ARRAY_BIAS		0x2F	/* array bias -- don't change */
+#define REG_YGAMMA		0x33	/* misc gamma settings [7:6] */
+#define REG_BIAS_ADJUST		0x34	/* misc bias settings */
+
+/* Window parameters */
+#define HWSBASE 0x38
+#define HWEBASE 0x3a
+#define VWSBASE 0x05
+#define VWEBASE 0x05
+
+struct ov7x10 {
+	int auto_brt;
+	int auto_exp;
+	int bandfilt;
+	int mirror;
+};
+
+/* Lawrence Glaister <lg@jfm.bc.ca> reports:
+ *
+ * Register 0x0f in the 7610 has the following effects:
+ *
+ * 0x85 (AEC method 1): Best overall, good contrast range
+ * 0x45 (AEC method 2): Very overexposed
+ * 0xa5 (spec sheet default): Ok, but the black level is
+ *	shifted resulting in loss of contrast
+ * 0x05 (old driver setting): very overexposed, too much
+ *	contrast
+ */
+static struct ovcamchip_regvals regvals_init_7x10[] = {
+	{ 0x10, 0xff },
+	{ 0x16, 0x03 },
+	{ 0x28, 0x24 },
+	{ 0x2b, 0xac },
+	{ 0x12, 0x00 },
+	{ 0x38, 0x81 },
+	{ 0x28, 0x24 },	/* 0c */
+	{ 0x0f, 0x85 },	/* lg's setting */
+	{ 0x15, 0x01 },
+	{ 0x20, 0x1c },
+	{ 0x23, 0x2a },
+	{ 0x24, 0x10 },
+	{ 0x25, 0x8a },
+	{ 0x26, 0xa2 },
+	{ 0x27, 0xc2 },
+	{ 0x2a, 0x04 },
+	{ 0x2c, 0xfe },
+	{ 0x2d, 0x93 },
+	{ 0x30, 0x71 },
+	{ 0x31, 0x60 },
+	{ 0x32, 0x26 },
+	{ 0x33, 0x20 },
+	{ 0x34, 0x48 },
+	{ 0x12, 0x24 },
+	{ 0x11, 0x01 },
+	{ 0x0c, 0x24 },
+	{ 0x0d, 0x24 },
+	{ 0xff, 0xff },	/* END MARKER */
+};
+
+/* This initializes the OV7x10 camera chip and relevant variables. */
+static int ov7x10_init(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov7x10 *s;
+	int rc;
+
+	DDEBUG(4, &c->dev, "entered");
+
+	rc = ov_write_regvals(c, regvals_init_7x10);
+	if (rc < 0)
+		return rc;
+
+	ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+	memset(s, 0, sizeof *s);
+
+	s->auto_brt = 1;
+	s->auto_exp = 1;
+
+	return rc;
+}
+
+static int ov7x10_free(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+
+	kfree(ov->spriv);
+	return 0;
+}
+
+static int ov7x10_set_control(struct i2c_client *c,
+			      struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov7x10 *s = ov->spriv;
+	int rc;
+	int v = ctl->value;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_CONT:
+		rc = ov_write(c, REG_CNT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_BRIGHT:
+		rc = ov_write(c, REG_BRT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_write(c, REG_SAT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_HUE:
+		rc = ov_write(c, REG_RED, 0xFF - (v >> 8));
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write(c, REG_BLUE, v >> 8);
+		break;
+	case OVCAMCHIP_CID_EXP:
+		rc = ov_write(c, REG_EXP, v);
+		break;
+	case OVCAMCHIP_CID_FREQ:
+	{
+		int sixty = (v == 60);
+
+		rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write(c, 0x2b, sixty?0x00:0xac);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x13, 0x10, 0x10);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x13, 0x00, 0x10);
+		break;
+	}
+	case OVCAMCHIP_CID_BANDFILT:
+		rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+		s->bandfilt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+		s->auto_brt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		rc = ov_write_mask(c, 0x29, v?0x00:0x80, 0x80);
+		s->auto_exp = v;
+		break;
+	case OVCAMCHIP_CID_MIRROR:
+		rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+		s->mirror = v;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+out:
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+	return rc;
+}
+
+static int ov7x10_get_control(struct i2c_client *c,
+			      struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov7x10 *s = ov->spriv;
+	int rc = 0;
+	unsigned char val = 0;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_CONT:
+		rc = ov_read(c, REG_CNT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_BRIGHT:
+		rc = ov_read(c, REG_BRT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_read(c, REG_SAT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_HUE:
+		rc = ov_read(c, REG_BLUE, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_EXP:
+		rc = ov_read(c, REG_EXP, &val);
+		ctl->value = val;
+		break;
+	case OVCAMCHIP_CID_BANDFILT:
+		ctl->value = s->bandfilt;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		ctl->value = s->auto_brt;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		ctl->value = s->auto_exp;
+		break;
+	case OVCAMCHIP_CID_MIRROR:
+		ctl->value = s->mirror;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+	return rc;
+}
+
+static int ov7x10_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	int qvga = win->quarter;
+
+	/******** QVGA-specific regs ********/
+
+	ov_write(c, 0x14, qvga?0x24:0x04);
+
+	/******** Palette-specific regs ********/
+
+	if (win->format == VIDEO_PALETTE_GREY) {
+		ov_write_mask(c, 0x0e, 0x40, 0x40);
+		ov_write_mask(c, 0x13, 0x20, 0x20);
+	} else {
+		ov_write_mask(c, 0x0e, 0x00, 0x40);
+		ov_write_mask(c, 0x13, 0x00, 0x20);
+	}
+
+	/******** Clock programming ********/
+
+	ov_write(c, 0x11, win->clockdiv);
+
+	/******** Resolution-specific ********/
+
+	if (win->width == 640 && win->height == 480)
+		ov_write(c, 0x35, 0x9e);
+	else
+		ov_write(c, 0x35, 0x1e);
+
+	return 0;
+}
+
+static int ov7x10_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	int ret, hwscale, vwscale;
+
+	ret = ov7x10_mode_init(c, win);
+	if (ret < 0)
+		return ret;
+
+	if (win->quarter) {
+		hwscale = 1;
+		vwscale = 0;
+	} else {
+		hwscale = 2;
+		vwscale = 1;
+	}
+
+	ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+	ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+	ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+	ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+	return 0;
+}
+
+static int ov7x10_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case OVCAMCHIP_CMD_S_CTRL:
+		return ov7x10_set_control(c, arg);
+	case OVCAMCHIP_CMD_G_CTRL:
+		return ov7x10_get_control(c, arg);
+	case OVCAMCHIP_CMD_S_MODE:
+		return ov7x10_set_window(c, arg);
+	default:
+		DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+		return -ENOIOCTLCMD;
+	}
+}
+
+struct ovcamchip_ops ov7x10_ops = {
+	.init    =	ov7x10_init,
+	.free    =	ov7x10_free,
+	.command =	ov7x10_command,
+};
diff -Nru a/drivers/media/video/ovcamchip/ov7x20.c b/drivers/media/video/ovcamchip/ov7x20.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/ovcamchip/ov7x20.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,455 @@
+/* OmniVision OV7620/OV7120 Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * OV7620 fixes by Charl P. Botha <cpbotha@ieee.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. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* Registers */
+#define REG_GAIN		0x00	/* gain [5:0] */
+#define REG_BLUE		0x01	/* blue gain */
+#define REG_RED			0x02	/* red gain */
+#define REG_SAT			0x03	/* saturation */
+#define REG_BRT			0x06	/* Y brightness */
+#define REG_SHARP		0x07	/* analog sharpness */
+#define REG_BLUE_BIAS		0x0C	/* WB blue ratio [5:0] */
+#define REG_RED_BIAS		0x0D	/* WB red ratio [5:0] */
+#define REG_EXP			0x10	/* exposure */
+
+/* Default control settings. Values are in terms of V4L2 controls. */
+#define OV7120_DFL_BRIGHT     0x60
+#define OV7620_DFL_BRIGHT     0x60
+#define OV7120_DFL_SAT        0xb0
+#define OV7620_DFL_SAT        0xc0
+#define DFL_AUTO_EXP             1
+#define DFL_AUTO_GAIN            1
+#define OV7120_DFL_GAIN       0x00
+#define OV7620_DFL_GAIN       0x00
+/* NOTE: Since autoexposure is the default, these aren't programmed into the
+ * OV7x20 chip. They are just here because V4L2 expects a default */
+#define OV7120_DFL_EXP        0x7f
+#define OV7620_DFL_EXP        0x7f
+
+/* Window parameters */
+#define HWSBASE 0x2F	/* From 7620.SET (spec is wrong) */
+#define HWEBASE 0x2F
+#define VWSBASE 0x05
+#define VWEBASE 0x05
+
+struct ov7x20 {
+	int auto_brt;
+	int auto_exp;
+	int auto_gain;
+	int backlight;
+	int bandfilt;
+	int mirror;
+};
+
+/* Contrast look-up table */
+static unsigned char ctab[] = {
+	0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
+	0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
+};
+
+/* Settings for (Black & White) OV7120 camera chip */
+static struct ovcamchip_regvals regvals_init_7120[] = {
+	{ 0x12, 0x80 }, /* reset */
+	{ 0x13, 0x00 }, /* Autoadjust off */
+	{ 0x12, 0x20 }, /* Disable AWB */
+	{ 0x13, DFL_AUTO_GAIN?0x01:0x00 }, /* Autoadjust on (if desired) */
+	{ 0x00, OV7120_DFL_GAIN },
+	{ 0x01, 0x80 },
+	{ 0x02, 0x80 },
+	{ 0x03, OV7120_DFL_SAT },
+	{ 0x06, OV7120_DFL_BRIGHT },
+	{ 0x07, 0x00 },
+	{ 0x0c, 0x20 },
+	{ 0x0d, 0x20 },
+	{ 0x11, 0x01 },
+	{ 0x14, 0x84 },
+	{ 0x15, 0x01 },
+	{ 0x16, 0x03 },
+	{ 0x17, 0x2f },
+	{ 0x18, 0xcf },
+	{ 0x19, 0x06 },
+	{ 0x1a, 0xf5 },
+	{ 0x1b, 0x00 },
+	{ 0x20, 0x08 },
+	{ 0x21, 0x80 },
+	{ 0x22, 0x80 },
+	{ 0x23, 0x00 },
+	{ 0x26, 0xa0 },
+	{ 0x27, 0xfa },
+	{ 0x28, 0x20 }, /* DON'T set bit 6. It is for the OV7620 only */
+	{ 0x29, DFL_AUTO_EXP?0x00:0x80 },
+	{ 0x2a, 0x10 },
+	{ 0x2b, 0x00 },
+	{ 0x2c, 0x88 },
+	{ 0x2d, 0x95 },
+	{ 0x2e, 0x80 },
+	{ 0x2f, 0x44 },
+	{ 0x60, 0x20 },
+	{ 0x61, 0x02 },
+	{ 0x62, 0x5f },
+	{ 0x63, 0xd5 },
+	{ 0x64, 0x57 },
+	{ 0x65, 0x83 }, /* OV says "don't change this value" */
+	{ 0x66, 0x55 },
+	{ 0x67, 0x92 },
+	{ 0x68, 0xcf },
+	{ 0x69, 0x76 },
+	{ 0x6a, 0x22 },
+	{ 0x6b, 0xe2 },
+	{ 0x6c, 0x40 },
+	{ 0x6d, 0x48 },
+	{ 0x6e, 0x80 },
+	{ 0x6f, 0x0d },
+	{ 0x70, 0x89 },
+	{ 0x71, 0x00 },
+	{ 0x72, 0x14 },
+	{ 0x73, 0x54 },
+	{ 0x74, 0xa0 },
+	{ 0x75, 0x8e },
+	{ 0x76, 0x00 },
+	{ 0x77, 0xff },
+	{ 0x78, 0x80 },
+	{ 0x79, 0x80 },
+	{ 0x7a, 0x80 },
+	{ 0x7b, 0xe6 },
+	{ 0x7c, 0x00 },
+	{ 0x24, 0x3a },
+	{ 0x25, 0x60 },
+	{ 0xff, 0xff },	/* END MARKER */
+};
+
+/* Settings for (color) OV7620 camera chip */
+static struct ovcamchip_regvals regvals_init_7620[] = {
+	{ 0x12, 0x80 }, /* reset */
+	{ 0x00, OV7620_DFL_GAIN },
+	{ 0x01, 0x80 },
+	{ 0x02, 0x80 },
+	{ 0x03, OV7620_DFL_SAT },
+	{ 0x06, OV7620_DFL_BRIGHT },
+	{ 0x07, 0x00 },
+	{ 0x0c, 0x24 },
+	{ 0x0c, 0x24 },
+	{ 0x0d, 0x24 },
+	{ 0x11, 0x01 },
+	{ 0x12, 0x24 },
+	{ 0x13, DFL_AUTO_GAIN?0x01:0x00 },
+	{ 0x14, 0x84 },
+	{ 0x15, 0x01 },
+	{ 0x16, 0x03 },
+	{ 0x17, 0x2f },
+	{ 0x18, 0xcf },
+	{ 0x19, 0x06 },
+	{ 0x1a, 0xf5 },
+	{ 0x1b, 0x00 },
+	{ 0x20, 0x18 },
+	{ 0x21, 0x80 },
+	{ 0x22, 0x80 },
+	{ 0x23, 0x00 },
+	{ 0x26, 0xa2 },
+	{ 0x27, 0xea },
+	{ 0x28, 0x20 },
+	{ 0x29, DFL_AUTO_EXP?0x00:0x80 },
+	{ 0x2a, 0x10 },
+	{ 0x2b, 0x00 },
+	{ 0x2c, 0x88 },
+	{ 0x2d, 0x91 },
+	{ 0x2e, 0x80 },
+	{ 0x2f, 0x44 },
+	{ 0x60, 0x27 },
+	{ 0x61, 0x02 },
+	{ 0x62, 0x5f },
+	{ 0x63, 0xd5 },
+	{ 0x64, 0x57 },
+	{ 0x65, 0x83 },
+	{ 0x66, 0x55 },
+	{ 0x67, 0x92 },
+	{ 0x68, 0xcf },
+	{ 0x69, 0x76 },
+	{ 0x6a, 0x22 },
+	{ 0x6b, 0x00 },
+	{ 0x6c, 0x02 },
+	{ 0x6d, 0x44 },
+	{ 0x6e, 0x80 },
+	{ 0x6f, 0x1d },
+	{ 0x70, 0x8b },
+	{ 0x71, 0x00 },
+	{ 0x72, 0x14 },
+	{ 0x73, 0x54 },
+	{ 0x74, 0x00 },
+	{ 0x75, 0x8e },
+	{ 0x76, 0x00 },
+	{ 0x77, 0xff },
+	{ 0x78, 0x80 },
+	{ 0x79, 0x80 },
+	{ 0x7a, 0x80 },
+	{ 0x7b, 0xe2 },
+	{ 0x7c, 0x00 },
+	{ 0xff, 0xff },	/* END MARKER */
+};
+
+/* Returns index into the specified look-up table, with 'n' elements, for which
+ * the value is greater than or equal to "val". If a match isn't found, (n-1)
+ * is returned. The entries in the table must be in ascending order. */
+static inline int ov7x20_lut_find(unsigned char lut[], int n, unsigned char val)
+{
+	int i = 0;
+
+	while (lut[i] < val && i < n)
+		i++;
+
+	return i;
+}
+
+/* This initializes the OV7x20 camera chip and relevant variables. */
+static int ov7x20_init(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov7x20 *s;
+	int rc;
+
+	DDEBUG(4, &c->dev, "entered");
+
+	if (ov->mono)
+		rc = ov_write_regvals(c, regvals_init_7120);
+	else
+		rc = ov_write_regvals(c, regvals_init_7620);
+
+	if (rc < 0)
+		return rc;
+
+	ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+	memset(s, 0, sizeof *s);
+
+	s->auto_brt = 1;
+	s->auto_exp = DFL_AUTO_EXP;
+	s->auto_gain = DFL_AUTO_GAIN;
+
+	return 0;
+}
+
+static int ov7x20_free(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+
+	kfree(ov->spriv);
+	return 0;
+}
+
+static int ov7x20_set_v4l1_control(struct i2c_client *c,
+				   struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov7x20 *s = ov->spriv;
+	int rc;
+	int v = ctl->value;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_CONT:
+	{
+		/* Use Y gamma control instead. Bit 0 enables it. */
+		rc = ov_write(c, 0x64, ctab[v >> 12]);
+		break;
+	}
+	case OVCAMCHIP_CID_BRIGHT:
+		/* 7620 doesn't like manual changes when in auto mode */
+		if (!s->auto_brt)
+			rc = ov_write(c, REG_BRT, v >> 8);
+		else
+			rc = 0;
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_write(c, REG_SAT, v >> 8);
+		break;
+	case OVCAMCHIP_CID_EXP:
+		if (!s->auto_exp)
+			rc = ov_write(c, REG_EXP, v);
+		else
+			rc = -EBUSY;
+		break;
+	case OVCAMCHIP_CID_FREQ:
+	{
+		int sixty = (v == 60);
+
+		rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write(c, 0x2b, sixty?0x00:0xac);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x76, 0x01, 0x01);
+		break;
+	}
+	case OVCAMCHIP_CID_BANDFILT:
+		rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+		s->bandfilt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+		s->auto_brt = v;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01);
+		s->auto_exp = v;
+		break;
+	case OVCAMCHIP_CID_BACKLIGHT:
+	{
+		rc = ov_write_mask(c, 0x68, v?0xe0:0xc0, 0xe0);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08);
+		if (rc < 0)
+			goto out;
+
+		rc = ov_write_mask(c, 0x28, v?0x02:0x00, 0x02);
+		s->backlight = v;
+		break;
+	}
+	case OVCAMCHIP_CID_MIRROR:
+		rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+		s->mirror = v;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+out:
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+	return rc;
+}
+
+static int ov7x20_get_v4l1_control(struct i2c_client *c,
+				   struct ovcamchip_control *ctl)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ov7x20 *s = ov->spriv;
+	int rc = 0;
+	unsigned char val = 0;
+
+	switch (ctl->id) {
+	case OVCAMCHIP_CID_CONT:
+		rc = ov_read(c, 0x64, &val);
+		ctl->value = ov7x20_lut_find(ctab, 16, val) << 12;
+		break;
+	case OVCAMCHIP_CID_BRIGHT:
+		rc = ov_read(c, REG_BRT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_SAT:
+		rc = ov_read(c, REG_SAT, &val);
+		ctl->value = val << 8;
+		break;
+	case OVCAMCHIP_CID_EXP:
+		rc = ov_read(c, REG_EXP, &val);
+		ctl->value = val;
+		break;
+	case OVCAMCHIP_CID_BANDFILT:
+		ctl->value = s->bandfilt;
+		break;
+	case OVCAMCHIP_CID_AUTOBRIGHT:
+		ctl->value = s->auto_brt;
+		break;
+	case OVCAMCHIP_CID_AUTOEXP:
+		ctl->value = s->auto_exp;
+		break;
+	case OVCAMCHIP_CID_BACKLIGHT:
+		ctl->value = s->backlight;
+		break;
+	case OVCAMCHIP_CID_MIRROR:
+		ctl->value = s->mirror;
+		break;
+	default:
+		DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+		return -EPERM;
+	}
+
+	DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+	return rc;
+}
+
+static int ov7x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	int qvga = win->quarter;
+
+	/******** QVGA-specific regs ********/
+	ov_write_mask(c, 0x14, qvga?0x20:0x00, 0x20);
+	ov_write_mask(c, 0x28, qvga?0x00:0x20, 0x20);
+	ov_write(c, 0x24, qvga?0x20:0x3a);
+	ov_write(c, 0x25, qvga?0x30:0x60);
+	ov_write_mask(c, 0x2d, qvga?0x40:0x00, 0x40);
+	if (!ov->mono)
+		ov_write_mask(c, 0x67, qvga?0xf0:0x90, 0xf0);
+	ov_write_mask(c, 0x74, qvga?0x20:0x00, 0x20);
+
+	/******** Clock programming ********/
+
+	ov_write(c, 0x11, win->clockdiv);
+
+	return 0;
+}
+
+static int ov7x20_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+	int ret, hwscale, vwscale;
+
+	ret = ov7x20_mode_init(c, win);
+	if (ret < 0)
+		return ret;
+
+	if (win->quarter) {
+		hwscale = 1;
+		vwscale = 0;
+	} else {
+		hwscale = 2;
+		vwscale = 1;
+	}
+
+	ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+	ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+	ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+	ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+	return 0;
+}
+
+static int ov7x20_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case OVCAMCHIP_CMD_S_CTRL:
+		return ov7x20_set_v4l1_control(c, arg);
+	case OVCAMCHIP_CMD_G_CTRL:
+		return ov7x20_get_v4l1_control(c, arg);
+	case OVCAMCHIP_CMD_S_MODE:
+		return ov7x20_set_window(c, arg);
+	default:
+		DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+		return -ENOIOCTLCMD;
+	}
+}
+
+struct ovcamchip_ops ov7x20_ops = {
+	.init    =	ov7x20_init,
+	.free    =	ov7x20_free,
+	.command =	ov7x20_command,
+};
diff -Nru a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,446 @@
+/* Shared Code for OmniVision Camera Chip Drivers
+ *
+ * Copyright (c) 2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+#define DRIVER_VERSION "v2.27 for Linux 2.6"
+#define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org>"
+#define DRIVER_DESC "OV camera chip I2C driver"
+
+#define PINFO(fmt, args...) printk(KERN_INFO "ovcamchip: " fmt "\n" , ## args);
+#define PERROR(fmt, args...) printk(KERN_ERR "ovcamchip: " fmt "\n" , ## args);
+
+#ifdef DEBUG
+int ovcamchip_debug = 0;
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug,
+  "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=all");
+#endif
+
+/* By default, let bridge driver tell us if chip is monochrome. mono=0
+ * will ignore that and always treat chips as color. mono=1 will force
+ * monochrome mode for all chips. */
+static int mono = -1;
+module_param(mono, int, 0);
+MODULE_PARM_DESC(mono,
+  "1=chips are monochrome (OVx1xx), 0=force color, -1=autodetect (default)");
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* Registers common to all chips, that are needed for detection */
+#define GENERIC_REG_ID_HIGH       0x1C	/* manufacturer ID MSB */
+#define GENERIC_REG_ID_LOW        0x1D	/* manufacturer ID LSB */
+#define GENERIC_REG_COM_I         0x29	/* misc ID bits */
+
+extern struct ovcamchip_ops ov6x20_ops;
+extern struct ovcamchip_ops ov6x30_ops;
+extern struct ovcamchip_ops ov7x10_ops;
+extern struct ovcamchip_ops ov7x20_ops;
+extern struct ovcamchip_ops ov76be_ops;
+
+static char *chip_names[NUM_CC_TYPES] = {
+	[CC_UNKNOWN]	= "Unknown chip",
+	[CC_OV76BE]	= "OV76BE",
+	[CC_OV7610]	= "OV7610",
+	[CC_OV7620]	= "OV7620",
+	[CC_OV7620AE]	= "OV7620AE",
+	[CC_OV6620]	= "OV6620",
+	[CC_OV6630]	= "OV6630",
+	[CC_OV6630AE]	= "OV6630AE",
+	[CC_OV6630AF]	= "OV6630AF",
+};
+
+/* Forward declarations */
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+/* ----------------------------------------------------------------------- */
+
+int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals)
+{
+	int rc;
+
+	while (rvals->reg != 0xff) {
+		rc = ov_write(c, rvals->reg, rvals->val);
+		if (rc < 0)
+			return rc;
+		rvals++;
+	}
+
+	return 0;
+}
+
+/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
+ * the same position as 1's in "mask" are cleared and set to "value". Bits
+ * that are in the same position as 0's in "mask" are preserved, regardless
+ * of their respective state in "value".
+ */
+int ov_write_mask(struct i2c_client *c,
+		  unsigned char reg,
+		  unsigned char value,
+		  unsigned char mask)
+{
+	int rc;
+	unsigned char oldval, newval;
+
+	if (mask == 0xff) {
+		newval = value;
+	} else {
+		rc = ov_read(c, reg, &oldval);
+		if (rc < 0)
+			return rc;
+
+		oldval &= (~mask);		/* Clear the masked bits */
+		value &= mask;			/* Enforce mask on value */
+		newval = oldval | value;	/* Set the desired bits */
+	}
+
+	return ov_write(c, reg, newval);
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* Reset the chip and ensure that I2C is synchronized. Returns <0 if failure.
+ */
+static int init_camchip(struct i2c_client *c)
+{
+	int i, success;
+	unsigned char high, low;
+
+	/* Reset the chip */
+	ov_write(c, 0x12, 0x80);
+
+	/* Wait for it to initialize */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(1 + 150 * HZ / 1000);
+
+	for (i = 0, success = 0; i < I2C_DETECT_RETRIES && !success; i++) {
+		if (ov_read(c, GENERIC_REG_ID_HIGH, &high) >= 0) {
+			if (ov_read(c, GENERIC_REG_ID_LOW, &low) >= 0) {
+				if (high == 0x7F && low == 0xA2) {
+					success = 1;
+					continue;
+				}
+			}
+		}
+
+		/* Reset the chip */
+		ov_write(c, 0x12, 0x80);
+
+		/* Wait for it to initialize */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1 + 150 * HZ / 1000);
+
+		/* Dummy read to sync I2C */
+		ov_read(c, 0x00, &low);
+	}
+
+	if (!success)
+		return -EIO;
+
+	PDEBUG(1, "I2C synced in %d attempt(s)", i);
+
+	return 0;
+}
+
+/* This detects the OV7610, OV7620, or OV76BE chip. */
+static int ov7xx0_detect(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	int rc;
+	unsigned char val;
+
+	PDEBUG(4, "");
+
+	/* Detect chip (sub)type */
+	rc = ov_read(c, GENERIC_REG_COM_I, &val);
+	if (rc < 0) {
+		PERROR("Error detecting ov7xx0 type");
+		return rc;
+	}
+
+	if ((val & 3) == 3) {
+		PINFO("Camera chip is an OV7610");
+		ov->subtype = CC_OV7610;
+	} else if ((val & 3) == 1) {
+		rc = ov_read(c, 0x15, &val);
+		if (rc < 0) {
+			PERROR("Error detecting ov7xx0 type");
+			return rc;
+		}
+
+		if (val & 1) {
+			PINFO("Camera chip is an OV7620AE");
+			/* OV7620 is a close enough match for now. There are
+			 * some definite differences though, so this should be
+			 * fixed */
+			ov->subtype = CC_OV7620;
+		} else {
+			PINFO("Camera chip is an OV76BE");
+			ov->subtype = CC_OV76BE;
+		}
+	} else if ((val & 3) == 0) {
+		PINFO("Camera chip is an OV7620");
+		ov->subtype = CC_OV7620;
+	} else {
+		PERROR("Unknown camera chip version: %d", val & 3);
+		return -ENOSYS;
+	}
+
+	if (ov->subtype == CC_OV76BE)
+		ov->sops = &ov76be_ops;
+	else if (ov->subtype == CC_OV7620)
+		ov->sops = &ov7x20_ops;
+	else
+		ov->sops = &ov7x10_ops;
+
+	return 0;
+}
+
+/* This detects the OV6620, OV6630, OV6630AE, or OV6630AF chip. */
+static int ov6xx0_detect(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	int rc;
+	unsigned char val;
+
+	PDEBUG(4, "");
+
+	/* Detect chip (sub)type */
+	rc = ov_read(c, GENERIC_REG_COM_I, &val);
+	if (rc < 0) {
+		PERROR("Error detecting ov6xx0 type");
+		return -1;
+	}
+
+	if ((val & 3) == 0) {
+		ov->subtype = CC_OV6630;
+		PINFO("Camera chip is an OV6630");
+	} else if ((val & 3) == 1) {
+		ov->subtype = CC_OV6620;
+		PINFO("Camera chip is an OV6620");
+	} else if ((val & 3) == 2) {
+		ov->subtype = CC_OV6630;
+		PINFO("Camera chip is an OV6630AE");
+	} else if ((val & 3) == 3) {
+		ov->subtype = CC_OV6630;
+		PINFO("Camera chip is an OV6630AF");
+	}
+
+	if (ov->subtype == CC_OV6620)
+		ov->sops = &ov6x20_ops;
+	else
+		ov->sops = &ov6x30_ops;
+
+	return 0;
+}
+
+static int ovcamchip_detect(struct i2c_client *c)
+{
+	/* Ideally we would just try a single register write and see if it NAKs.
+	 * That isn't possible since the OV518 can't report I2C transaction
+	 * failures. So, we have to try to initialize the chip (i.e. reset it
+	 * and check the ID registers) to detect its presence. */
+
+	/* Test for 7xx0 */
+	PDEBUG(3, "Testing for 0V7xx0");
+	c->addr = OV7xx0_SID;
+	if (init_camchip(c) < 0) {
+		/* Test for 6xx0 */
+		PDEBUG(3, "Testing for 0V6xx0");
+		c->addr = OV6xx0_SID;
+		if (init_camchip(c) < 0) {
+ 			return -ENODEV;
+		} else {
+			if (ov6xx0_detect(c) < 0) {
+				PERROR("Failed to init OV6xx0");
+ 				return -EIO;
+			}
+		}
+	} else {
+		if (ov7xx0_detect(c) < 0) {
+			PERROR("Failed to init OV7xx0");
+ 			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int ovcamchip_attach(struct i2c_adapter *adap)
+{
+	int rc = 0;
+	struct ovcamchip *ov;
+	struct i2c_client *c;
+
+	/* I2C is not a PnP bus, so we can never be certain that we're talking
+	 * to the right chip. To prevent damage to EEPROMS and such, only
+	 * attach to adapters that are known to contain OV camera chips. */
+
+	switch (adap->id) {
+	case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511):
+	case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518):
+	case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OVFX2):
+	case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF):
+		PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
+		break;
+	default:
+		PDEBUG(1, "Adapter ID 0x%06x rejected", adap->id);
+		return -ENODEV;
+	}
+
+	c = kmalloc(sizeof *c, GFP_KERNEL);
+	if (!c) {
+		rc = -ENOMEM;
+		goto no_client;
+	}
+	memcpy(c, &client_template, sizeof *c);
+	c->adapter = adap;
+	strcpy(i2c_clientname(c), "OV????");
+
+	ov = kmalloc(sizeof *ov, GFP_KERNEL);
+	if (!ov) {
+		rc = -ENOMEM;
+		goto no_ov;
+	}
+	memset(ov, 0, sizeof *ov);
+	i2c_set_clientdata(c, ov);
+
+	rc = ovcamchip_detect(c);
+	if (rc < 0)
+		goto error;
+
+	strcpy(i2c_clientname(c), chip_names[ov->subtype]);
+
+	PDEBUG(1, "Camera chip detection complete");
+
+	i2c_attach_client(c);
+
+	return rc;
+error:
+	kfree(ov);
+no_ov:
+	kfree(c);
+no_client:
+	PDEBUG(1, "returning %d", rc);
+	return rc;
+}
+
+static int ovcamchip_detach(struct i2c_client *c)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+	int rc;
+
+	rc = ov->sops->free(c);
+	if (rc < 0)
+		return rc;
+
+	i2c_detach_client(c);
+
+	kfree(ov);
+	kfree(c);
+	return 0;
+}
+
+static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+	struct ovcamchip *ov = i2c_get_clientdata(c);
+
+	if (!ov->initialized &&
+	    cmd != OVCAMCHIP_CMD_Q_SUBTYPE &&
+	    cmd != OVCAMCHIP_CMD_INITIALIZE) {
+		dev_err(&c->dev, "ERROR: Camera chip not initialized yet!\n");
+		return -EPERM;
+	}
+
+	switch (cmd) {
+	case OVCAMCHIP_CMD_Q_SUBTYPE:
+	{
+		*(int *)arg = ov->subtype;
+		return 0;
+	}
+	case OVCAMCHIP_CMD_INITIALIZE:
+	{
+		int rc;
+
+		if (mono == -1)
+			ov->mono = *(int *)arg;
+		else
+			ov->mono = mono;
+
+		if (ov->mono) {
+			if (ov->subtype != CC_OV7620)
+				dev_warn(&c->dev, "Warning: Monochrome not "
+					"implemented for this chip\n");
+			else
+				dev_info(&c->dev, "Initializing chip as "
+					"monochrome\n");
+		}
+
+		rc = ov->sops->init(c);
+		if (rc < 0)
+			return rc;
+
+		ov->initialized = 1;
+		return 0;
+	}
+	default:
+		return ov->sops->command(c, cmd, arg);
+	}
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver driver = {
+	.owner =		THIS_MODULE,
+	.name =			"ovcamchip",
+	.id =			I2C_DRIVERID_OVCAMCHIP,
+	.class =		I2C_CLASS_CAM_DIGITAL,
+	.flags =		I2C_DF_NOTIFY,
+	.attach_adapter =	ovcamchip_attach,
+	.detach_client =	ovcamchip_detach,
+	.command =		ovcamchip_command,
+};
+
+static struct i2c_client client_template = {
+	I2C_DEVNAME("(unset)"),
+	.id =		-1,
+	.driver =	&driver,
+};
+
+static int __init ovcamchip_init(void)
+{
+#ifdef DEBUG
+	ovcamchip_debug = debug;
+#endif
+
+	PINFO(DRIVER_VERSION " : " DRIVER_DESC);
+	return i2c_add_driver(&driver);
+}
+
+static void __exit ovcamchip_exit(void)
+{
+	i2c_del_driver(&driver);
+}
+
+module_init(ovcamchip_init);
+module_exit(ovcamchip_exit);
diff -Nru a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,87 @@
+/* OmniVision* camera chip driver private definitions for core code and
+ * chip-specific code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ *
+ * * OmniVision is a trademark of OmniVision Technologies, Inc. This driver
+ * is not sponsored or developed by them.
+ */
+
+#ifndef __LINUX_OVCAMCHIP_PRIV_H
+#define __LINUX_OVCAMCHIP_PRIV_H
+
+#include <media/ovcamchip.h>
+
+#ifdef DEBUG
+extern int ovcamchip_debug;
+#endif
+
+#define PDEBUG(level, fmt, args...) \
+	if (ovcamchip_debug >= (level))	pr_debug("[%s:%d] " fmt "\n", \
+		__FUNCTION__, __LINE__ , ## args)
+
+#define DDEBUG(level, dev, fmt, args...) \
+	if (ovcamchip_debug >= (level))	dev_dbg(dev, "[%s:%d] " fmt "\n", \
+		__FUNCTION__, __LINE__ , ## args)
+
+/* Number of times to retry chip detection. Increase this if you are getting
+ * "Failed to init camera chip" */
+#define I2C_DETECT_RETRIES	10
+
+struct ovcamchip_regvals {
+	unsigned char reg;
+	unsigned char val;
+};
+
+struct ovcamchip_ops {
+	int (*init)(struct i2c_client *);
+	int (*free)(struct i2c_client *);
+	int (*command)(struct i2c_client *, unsigned int, void *);
+};
+
+struct ovcamchip {
+	struct ovcamchip_ops *sops;
+	void *spriv;               /* Private data for OV7x10.c etc... */
+	int subtype;               /* = SEN_OV7610 etc... */
+	int mono;                  /* Monochrome chip? (invalid until init) */
+	int initialized;           /* OVCAMCHIP_CMD_INITIALIZE was successful */
+};
+
+/* --------------------------------- */
+/*              I2C I/O              */
+/* --------------------------------- */
+
+static inline int ov_read(struct i2c_client *c, unsigned char reg,
+			  unsigned char *value)
+{
+	int rc;
+
+	rc = i2c_smbus_read_byte_data(c, reg);
+	*value = (unsigned char) rc;
+	return rc;
+}
+
+static inline int ov_write(struct i2c_client *c, unsigned char reg,
+			   unsigned char value )
+{
+	return i2c_smbus_write_byte_data(c, reg, value);
+}
+
+/* --------------------------------- */
+/*        FUNCTION PROTOTYPES        */
+/* --------------------------------- */
+
+/* Functions in ovcamchip_core.c */
+
+extern int ov_write_regvals(struct i2c_client *c,
+			    struct ovcamchip_regvals *rvals);
+
+extern int ov_write_mask(struct i2c_client *c, unsigned char reg,
+	      		 unsigned char value, unsigned char mask);
+
+#endif
diff -Nru a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
--- a/drivers/media/video/saa7134/saa6752hs.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/video/saa7134/saa6752hs.c	2004-06-23 19:04:28 -07:00
@@ -337,7 +337,6 @@
 {
 	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, saa6752hs_attach);
-
 	return 0;
 }
 
diff -Nru a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
--- a/drivers/media/video/saa7134/saa7134-cards.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/video/saa7134/saa7134-cards.c	2004-06-23 19:04:28 -07:00
@@ -420,20 +420,14 @@
 			.vmux   = 1,
 			.amux   = TV,
 			.tv     = 1,
-#if 0
 		},{
 			.name   = name_comp1,
 			.vmux   = 0,
 			.amux   = LINE2,
 		},{
-			.name   = name_comp2,
-			.vmux   = 3,
-			.amux   = LINE2,
-		},{
 			.name   = name_svideo,
 			.vmux   = 8,
 			.amux   = LINE2,
-#endif
 		}},
 		.radio = {
 			.name   = name_radio,
@@ -515,24 +509,14 @@
                         .vmux = 1,
                         .amux = TV,
                         .tv   = 1,
-#if 0 /* untested */
                 },{
                         .name = name_comp1,
                         .vmux = 4,
                         .amux = LINE2,
                 },{
-                        .name = name_comp2,
-                        .vmux = 2,
-                        .amux = LINE2,
-                },{
                         .name = name_svideo,
                         .vmux = 6,
                         .amux = LINE2,
-                },{
-                        .name = "S-Video2",
-                        .vmux = 7,
-                        .amux = LINE2,
-#endif
                 }},
                 .radio = {
                         .name = name_radio,
@@ -679,7 +663,7 @@
                 }},
         },
 	[SAA7134_BOARD_MD2819] = {
-		.name           = "Medion 2819/ AverMedia M156",
+		.name           = "AverMedia M156 / Medion 2819",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
 		.need_tda9887   = 1,
@@ -951,6 +935,96 @@
 			.vmux = 3,
 		}},
 	},
+        [SAA7134_BOARD_NOVAC_PRIMETV7133] = {
+                /* toshii@netbsd.org */
+                .name           = "Noval Prime TV 7133",
+                .audio_clock    = 0x00200000,
+                .tuner_type     = TUNER_ALPS_TSBH1_NTSC,
+                .inputs         = {{
+                        .name = name_comp1,
+                        .vmux = 3,
+                },{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = TV,
+                        .tv   = 1,
+                },{
+                        .name = name_svideo,
+                        .vmux = 8,
+                }},
+        },
+	[SAA7134_BOARD_AVERMEDIA_305] = {
+		.name           = "AverMedia 305",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.need_tda9887   = 1,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+		.radio = {
+			 .name = name_radio,
+			 .amux = LINE2,
+		 },
+		.mute = {
+			 .name = name_mute,
+			 .amux = LINE1,
+		},
+	},
+  	[SAA7133_BOARD_UPMOST_PURPLE_TV] = {
+  		.name           = "UPMOST PURPLE TV",
+  		.audio_clock    = 0x00187de7,
+  		.tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+  		.need_tda9887   = 1,
+  		.inputs         = {{
+  			.name = name_tv,
+  			.vmux = 7,
+  			.amux = TV,
+  			.tv   = 1,
+  		},{
+  			.name = name_svideo,
+  			.vmux = 7,
+  			.amux = LINE1,
+  		}},
+          },
+	[SAA7134_BOARD_ITEMS_MTV005] = {
+		/* Norman Jonas <normanjonas@arcor.de> */
+		.name           = "Items MuchTV Plus / IT-005",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
 };
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
 
@@ -1103,12 +1177,11 @@
                 .subdevice    = 0xa70b,
 		.driver_data  = SAA7134_BOARD_MD2819,
 	},{
-		/* AverMedia Studio 305, using AverMedia M156 entry for now */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
-		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
                 .subvendor    = 0x1461, /* Avermedia Technologies Inc */
                 .subdevice    = 0x2115,
-		.driver_data  = SAA7134_BOARD_MD2819,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_305,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
@@ -1141,7 +1214,13 @@
                 .subdevice    = 0x4cb5,
                 .driver_data  = SAA7134_BOARD_ECS_TVP3XP_4CB5,
         },{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+ 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+                .subvendor    = 0x12ab,
+                .subdevice    = 0x0800,
+ 		.driver_data  = SAA7133_BOARD_UPMOST_PURPLE_TV,
 		
+ 	},{
 		/* --- boards without eeprom + subsystem ID --- */
                 .vendor       = PCI_VENDOR_ID_PHILIPS,
                 .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -1249,6 +1328,9 @@
 	case SAA7134_BOARD_CINERGY600:
 	case SAA7134_BOARD_ECS_TVP3XP:
 	case SAA7134_BOARD_ECS_TVP3XP_4CB5:
+		dev->has_remote = 1;
+		break;
+	case SAA7134_BOARD_AVACSSMARTTV:
 		dev->has_remote = 1;
 		break;
 	}
diff -Nru a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
--- a/drivers/media/video/saa7134/saa7134-core.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/media/video/saa7134/saa7134-core.c	2004-06-23 19:04:26 -07:00
@@ -607,10 +607,18 @@
 	};
 	if (10 == loop) {
 		print_irqstatus(dev,loop,report,status);
-		printk(KERN_WARNING "%s/irq: looping -- clearing enable bits\n",dev->name);
-		/* disable all irqs */
-		saa_writel(SAA7134_IRQ1,0);
-		saa_writel(SAA7134_IRQ2,0);
+		if (report & SAA7134_IRQ_REPORT_PE) {
+			/* disable all parity error */
+			printk(KERN_WARNING "%s/irq: looping -- "
+			       "clearing PE (parity error!) enable bit\n",dev->name);
+			saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE);
+		} else {
+			/* disable all irqs */
+			printk(KERN_WARNING "%s/irq: looping -- "
+			       "clearing all enable bits\n",dev->name);
+			saa_writel(SAA7134_IRQ1,0);
+			saa_writel(SAA7134_IRQ2,0);
+		}
 	}
 
  out:
diff -Nru a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
--- a/drivers/media/video/saa7134/saa7134-input.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/video/saa7134/saa7134-input.c	2004-06-23 19:04:28 -07:00
@@ -20,12 +20,24 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
 
+static unsigned int disable_ir = 0;
+MODULE_PARM(disable_ir,"i");
+MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
+
+static unsigned int ir_debug = 0;
+MODULE_PARM(ir_debug,"i");
+MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
+
+#define dprintk(fmt, arg...)	if (ir_debug) \
+	printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
+
 /* ---------------------------------------------------------------------- */
 
 static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = {
@@ -156,6 +168,47 @@
         [ 33 ] = KEY_KPDOT,          // . (decimal dot)
 };
 
+static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = {
+        [ 30 ] = KEY_POWER,		// power
+	[ 28 ] = KEY_SEARCH,		// scan
+        [  7 ] = KEY_SELECT,		// source
+
+	[ 22 ] = KEY_VOLUMEUP,
+	[ 20 ] = KEY_VOLUMEDOWN,
+        [ 31 ] = KEY_CHANNELUP,
+	[ 23 ] = KEY_CHANNELDOWN,
+	[ 24 ] = KEY_MUTE,
+
+	[  2 ] = KEY_KP0,
+        [  1 ] = KEY_KP1,
+        [ 11 ] = KEY_KP2,
+        [ 27 ] = KEY_KP3,
+        [  5 ] = KEY_KP4,
+        [  9 ] = KEY_KP5,
+        [ 21 ] = KEY_KP6,
+	[  6 ] = KEY_KP7,
+        [ 10 ] = KEY_KP8,
+	[ 18 ] = KEY_KP9,
+	[ 16 ] = KEY_KPDOT,
+
+	[  3 ] = KEY_TUNER,		// tv/fm
+        [  4 ] = KEY_REWIND,		// fm tuning left or function left
+        [ 12 ] = KEY_FORWARD,		// fm tuning right or function right
+
+	[  0 ] = KEY_RECORD,
+        [  8 ] = KEY_STOP,
+        [ 17 ] = KEY_PLAY,
+
+	[ 25 ] = KEY_ZOOM,
+	[ 14 ] = KEY_MENU,		// function
+	[ 19 ] = KEY_AGAIN,		// recall
+	[ 29 ] = KEY_RESTART,		// reset
+
+// FIXME
+	[ 13 ] = KEY_F21,		// mts
+        [ 15 ] = KEY_F22,		// min
+	[ 26 ] = KEY_F23,		// freeze
+};
 /* ---------------------------------------------------------------------- */
 
 static int build_key(struct saa7134_dev *dev)
@@ -175,8 +228,8 @@
         }
 
  	data = ir_extract_bits(gpio, ir->mask_keycode);
-	printk("%s: build_key gpio=0x%x mask=0x%x data=%d\n",
-	       dev->name, gpio, ir->mask_keycode, data);
+	dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
+		gpio, ir->mask_keycode, data);
 
 	if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
 	    (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
@@ -218,9 +271,12 @@
 	int polling      = 0;
 	int ir_type      = IR_TYPE_OTHER;
 
-	/* detect & configure */
 	if (!dev->has_remote)
 		return -ENODEV;
+	if (disable_ir)
+		return -ENODEV;
+
+	/* detect & configure */
 	switch (dev->board) {
 	case SAA7134_BOARD_FLYVIDEO2000:
 	case SAA7134_BOARD_FLYVIDEO3000:
@@ -241,6 +297,12 @@
                 mask_keyup   = 0x000002;
 		polling      = 50; // ms
                 break;
+	case SAA7134_BOARD_AVACSSMARTTV:
+	        ir_codes     = avacssmart_codes;
+		mask_keycode = 0x00001F;
+		mask_keyup   = 0x000020;
+		polling      = 50; // ms
+		break;
 	}
 	if (NULL == ir_codes) {
 		printk("%s: Oops: IR config error [card=%d]\n",
diff -Nru a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
--- a/drivers/media/video/saa7134/saa7134-oss.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/media/video/saa7134/saa7134-oss.c	2004-06-23 19:04:27 -07:00
@@ -50,7 +50,7 @@
 	if (blksize < 0x100)
 		blksize = 0x100;
 	if (blksize > 0x10000)
-		blksize = 0x100;
+		blksize = 0x10000;
 
 	if (blocks < 2)
 		blocks = 2;
@@ -74,6 +74,7 @@
 
 	if (!dev->oss.bufsize)
 		BUG();
+	videobuf_dma_init(&dev->oss.dma);
 	err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE,
 				       dev->oss.bufsize >> PAGE_SHIFT);
 	if (0 != err)
@@ -172,7 +173,7 @@
 			fmt |= (2 << 4);
 		if (!sign)
 			fmt |= 0x04;
-		saa_writel(0x588 >> 2, dev->oss.blksize);
+		saa_writel(0x588 >> 2, dev->oss.blksize -4);
 		saa_writel(0x58c >> 2, 0x543210 | (fmt << 24));
 		break;
 	}
diff -Nru a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
--- a/drivers/media/video/saa7134/saa7134-ts.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/media/video/saa7134/saa7134-ts.c	2004-06-23 19:04:25 -07:00
@@ -33,6 +33,8 @@
 
 /* ------------------------------------------------------------------ */
 
+#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
+
 static unsigned int ts_debug  = 0;
 MODULE_PARM(ts_debug,"i");
 MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
@@ -41,8 +43,9 @@
 MODULE_PARM(tsbufs,"i");
 MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32");
 
-#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
-#define TS_NR_PACKETS 312
+static unsigned int ts_nr_packets = 30;
+MODULE_PARM(ts_nr_packets,"i");
+MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)");
 
 #define dprintk(fmt, arg...)	if (ts_debug) \
 	printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg)
@@ -96,7 +99,7 @@
 	dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
 
 	llength = TS_PACKET_SIZE;
-	lines = TS_NR_PACKETS;
+	lines = ts_nr_packets;
 	
 	size = lines * llength;
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
@@ -135,7 +138,7 @@
 static int
 buffer_setup(struct file *file, unsigned int *count, unsigned int *size)
 {
-	*size = TS_PACKET_SIZE * TS_NR_PACKETS;
+	*size = TS_PACKET_SIZE * ts_nr_packets;
 	if (0 == *count)
 		*count = tsbufs;
 	*count = saa7134_buffer_count(*size,*count);
@@ -353,7 +356,7 @@
 		f->fmt.pix.width        = 720; /* D1 */
 		f->fmt.pix.height       = 576;
 		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-		f->fmt.pix.sizeimage    = TS_PACKET_SIZE*TS_NR_PACKETS;
+		f->fmt.pix.sizeimage    = TS_PACKET_SIZE*ts_nr_packets;
 		return 0;
 	}
 	
@@ -379,7 +382,7 @@
 		f->fmt.pix.width        = 720; /* D1 */
 		f->fmt.pix.height       = 576;
 		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-		f->fmt.pix.sizeimage    = TS_PACKET_SIZE*TS_NR_PACKETS;
+		f->fmt.pix.sizeimage    = TS_PACKET_SIZE*ts_nr_packets;
 		return 0;
 	}
 
@@ -408,7 +411,7 @@
 
 	case MPEG_SETPARAMS:
 		return ts_init_encoder(dev, arg);
-	  
+
 	default:
 		return -ENOIOCTLCMD;
 	}
@@ -455,6 +458,10 @@
 		tsbufs = 2;
 	if (tsbufs > VIDEO_MAX_FRAME)
 		tsbufs = VIDEO_MAX_FRAME;
+	if (ts_nr_packets < 4)
+		ts_nr_packets = 4;
+	if (ts_nr_packets > 312)
+		ts_nr_packets = 312;
 
 	INIT_LIST_HEAD(&dev->ts_q.queue);
 	init_timer(&dev->ts_q.timeout);
@@ -472,9 +479,9 @@
 	saa_writeb(SAA7134_TS_SERIAL1, 0x00);  /* deactivate TS softreset */
 	saa_writeb(SAA7134_TS_PARALLEL, 0xec); /* TSSOP high active, TSVAL high active, TSLOCK ignored */
 	saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
-	saa_writeb(SAA7134_TS_DMA0, ((TS_NR_PACKETS-1)&0xff));
-	saa_writeb(SAA7134_TS_DMA1, (((TS_NR_PACKETS-1)>>8)&0xff));
-	saa_writeb(SAA7134_TS_DMA2, ((((TS_NR_PACKETS-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */	 
+	saa_writeb(SAA7134_TS_DMA0, ((ts_nr_packets-1)&0xff));
+	saa_writeb(SAA7134_TS_DMA1, (((ts_nr_packets-1)>>8)&0xff));
+	saa_writeb(SAA7134_TS_DMA2, ((((ts_nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */
  
 	return 0;
 }
diff -Nru a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c	2004-06-23 19:04:25 -07:00
@@ -37,10 +37,6 @@
 MODULE_PARM(audio_debug,"i");
 MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]");
 
-static unsigned int audio_carrier = 0;
-MODULE_PARM(audio_carrier,"i");
-MODULE_PARM_DESC(audio_carrier,"audio carrier location");
-
 static unsigned int audio_ddep = 0;
 MODULE_PARM(audio_ddep,"i");
 MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite");
@@ -67,6 +63,30 @@
 /* ------------------------------------------------------------------ */
 /* saa7134 code                                                       */
 
+static struct mainscan {
+	char         *name;
+	v4l2_std_id  std;
+	int          carr;
+} mainscan[] = {
+	{
+		.name = "M",
+		.std  = V4L2_STD_NTSC | V4L2_STD_PAL_M,
+		.carr = 4500,
+	},{
+		.name = "BG",
+		.std  = V4L2_STD_PAL_BG,
+		.carr = 5500,
+	},{
+		.name = "I",
+		.std  = V4L2_STD_PAL_I,
+		.carr = 6000,
+	},{
+		.name = "DKL",
+		.std  = V4L2_STD_PAL_DK | V4L2_STD_SECAM,
+		.carr = 6500,
+	}
+};
+
 static struct saa7134_tvaudio tvaudio[] = {
 	{
 		.name          = "PAL-B/G FM-stereo",
@@ -314,15 +334,15 @@
 	return dev->thread.scan1 != dev->thread.scan2;
 }
 
-static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier)
+static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
 {
 	__s32 left,right,value;
 
 	if (audio_debug > 1) {
 		int i;
-		dprintk("debug %d:",carrier);
+		dprintk("debug %d:",scan->carr);
 		for (i = -150; i <= 150; i += 30) {
-			tvaudio_setcarrier(dev,carrier+i,carrier+i);
+			tvaudio_setcarrier(dev,scan->carr+i,scan->carr+i);
 			saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
 			if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
 				return -1;
@@ -334,24 +354,31 @@
 		}
 		printk("\n");
 	}
-	
-	tvaudio_setcarrier(dev,carrier-90,carrier-90);
-	saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-	if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
-		return -1;
-	left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
-	tvaudio_setcarrier(dev,carrier+90,carrier+90);
-	saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-	if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
-		return -1;
-	right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
-	left >>= 16;
-        right >>= 16;
-	value = left > right ? left - right : right - left;
-	dprintk("scanning %d.%03d MHz =>  dc is %5d [%d/%d]\n",
-		carrier/1000,carrier%1000,value,left,right);
+
+	if (dev->tvnorm->id & scan->std) {
+		tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90);
+		saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+		if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+			return -1;
+		left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+		tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90);
+		saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+		if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+			return -1;
+		right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+		left >>= 16;
+		right >>= 16;
+		value = left > right ? left - right : right - left;
+		dprintk("scanning %d.%03d MHz [%4s] =>  dc is %5d [%d/%d]\n",
+			scan->carr / 1000, scan->carr % 1000,
+			scan->name, value, left, right);
+	} else {
+		value = 0;
+		dprintk("skipping %d.%03d MHz [%4s]\n",
+			scan->carr / 1000, scan->carr % 1000, scan->name);
+	}
 	return value;
 }
 
@@ -384,6 +411,7 @@
 	case TVAUDIO_FM_K_STEREO:
 	case TVAUDIO_FM_BG_STEREO:
 		idp = (saa_readb(SAA7134_IDENT_SIF) & 0xe0) >> 5;
+		dprintk("getstereo: fm/stereo: idp=0x%x\n",idp);
 		if (0x03 == (idp & 0x03))
 			retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
 		else if (0x05 == (idp & 0x05))
@@ -397,6 +425,7 @@
 	case TVAUDIO_NICAM_FM:
 	case TVAUDIO_NICAM_AM:
 		nicam = saa_readb(SAA7134_NICAM_STATUS);
+		dprintk("getstereo: nicam=0x%x\n",nicam);
 		switch (nicam & 0x0b) {
 		case 0x08:
 			retval = V4L2_TUNER_SUB_MONO;
@@ -458,16 +487,10 @@
 
 static int tvaudio_thread(void *data)
 {
-#define MAX_SCAN 4
-	static const int carr_pal[MAX_SCAN]     = { 5500, 6000, 6500 };
-	static const int carr_ntsc[MAX_SCAN]    = { 4500 };
-	static const int carr_secam[MAX_SCAN]   = { 6500 };
-	static const int carr_default[MAX_SCAN] = { 4500, 5500, 6000, 6500 };
 	struct saa7134_dev *dev = data;
-	const int *carr_scan;
-	int carr_vals[4];
-	unsigned int i, audio;
-	int max1,max2,carrier,rx,mode,lastmode;
+	int carr_vals[ARRAY_SIZE(mainscan)];
+	unsigned int i, audio, nscan;
+	int max1,max2,carrier,rx,mode,lastmode,default_carrier;
 
 	daemonize("%s", dev->name);
 	allow_signal(SIGTERM);
@@ -488,32 +511,40 @@
 		if (tvaudio_sleep(dev,SCAN_INITIAL_DELAY))
 			goto restart;
 
-		/* find the main carrier */
-		carr_scan = carr_default;
-		if (dev->tvnorm->id & V4L2_STD_PAL)
-			carr_scan = carr_pal;
-		if (dev->tvnorm->id & V4L2_STD_NTSC)
-			carr_scan = carr_ntsc;
-		if (dev->tvnorm->id & V4L2_STD_SECAM)
-			carr_scan = carr_secam;
-		saa_writeb(SAA7134_MONITOR_SELECT,0x00);
-		tvaudio_setmode(dev,&tvaudio[0],NULL);
-		for (i = 0; i < MAX_SCAN; i++) {
-			if (!carr_scan[i])
+		max1 = 0;
+		max2 = 0;
+		nscan = 0;
+		carrier = 0;
+		default_carrier = 0;
+		for (i = 0; i < ARRAY_SIZE(mainscan); i++) {
+			if (!(dev->tvnorm->id & mainscan[i].std))
 				continue;
-			carr_vals[i] = tvaudio_checkcarrier(dev,carr_scan[i]);
-			if (dev->thread.scan1 != dev->thread.scan2)
-				goto restart;
+			if (!default_carrier)
+				default_carrier = mainscan[i].carr;
+			nscan++;
 		}
-		for (carrier = 0, max1 = 0, max2 = 0, i = 0; i < MAX_SCAN; i++) {
-			if (!carr_scan[i])
-				continue;
-			if (max1 < carr_vals[i]) {
-				max2 = max1;
-				max1 = carr_vals[i];
-				carrier = carr_scan[i];
-			} else if (max2 < carr_vals[i]) {
-				max2 = carr_vals[i];
+
+		if (1 == nscan) {
+			/* only one candidate -- skip scan ;) */
+			max1 = 12345;
+			carrier = default_carrier;
+		} else {
+			/* scan for the main carrier */
+			saa_writeb(SAA7134_MONITOR_SELECT,0x00);
+			tvaudio_setmode(dev,&tvaudio[0],NULL);
+			for (i = 0; i < ARRAY_SIZE(mainscan); i++) {
+				carr_vals[i] = tvaudio_checkcarrier(dev, mainscan+i);
+				if (dev->thread.scan1 != dev->thread.scan2)
+					goto restart;
+			}
+			for (max1 = 0, max2 = 0, i = 0; i < ARRAY_SIZE(mainscan); i++) {
+				if (max1 < carr_vals[i]) {
+					max2 = max1;
+					max1 = carr_vals[i];
+					carrier = mainscan[i].carr;
+				} else if (max2 < carr_vals[i]) {
+					max2 = carr_vals[i];
+				}
 			}
 		}
 
@@ -523,21 +554,17 @@
 				dev->tvnorm->name, carrier/1000, carrier%1000,
 				max1, max2);
 			dev->last_carrier = carrier;
-		} else if (0 != audio_carrier) {
-			/* no carrier -- try insmod option as fallback */
-			carrier = audio_carrier;
-			printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
-			       "using %d.%03d MHz [insmod option]\n",
-			       dev->name, carrier/1000, carrier%1000);
+
 		} else if (0 != dev->last_carrier) {
 			/* no carrier -- try last detected one as fallback */
 			carrier = dev->last_carrier;
 			printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
 			       "using %d.%03d MHz [last detected]\n",
 			       dev->name, carrier/1000, carrier%1000);
+
 		} else {
-			/* no carrier + no fallback -- try first in list */
-			carrier = carr_scan[0];
+			/* no carrier + no fallback -- use default */
+			carrier = default_carrier;
 			printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
 			       "using %d.%03d MHz [default]\n",
 			       dev->name, carrier/1000, carrier%1000);
@@ -550,7 +577,7 @@
 		/* find the exact tv audio norm */
 		for (audio = UNSET, i = 0; i < TVAUDIO; i++) {
 			if (dev->tvnorm->id != UNSET &&
-			    dev->tvnorm->id != tvaudio[i].std)
+			    !(dev->tvnorm->id & tvaudio[i].std))
 				continue;
 			if (tvaudio[i].carr1 != carrier)
 				continue;
@@ -722,11 +749,16 @@
 static int tvaudio_thread_ddep(void *data)
 {
 	struct saa7134_dev *dev = data;
-	u32 value, norms;
+	u32 value, norms, clock;
 
 	daemonize("%s", dev->name);
 	allow_signal(SIGTERM);
 
+	clock = saa7134_boards[dev->board].audio_clock;
+	if (UNSET != audio_clock_override)
+		clock = audio_clock_override;
+	saa_writel(0x598 >> 2, clock);
+
 	/* unmute */
 	saa_dsp_writel(dev, 0x474 >> 2, 0x00);
 	saa_dsp_writel(dev, 0x450 >> 2, 0x00);
@@ -769,9 +801,11 @@
 				(norms & 0x40) ? " M"    : "");
 		}
 
-		/* quick & dirty -- to be fixed up later ... */
+		/* kick automatic standard detection */
 		saa_dsp_writel(dev, 0x454 >> 2, 0);
 		saa_dsp_writel(dev, 0x454 >> 2, norms | 0x80);
+
+		/* setup crossbars */
 		saa_dsp_writel(dev, 0x464 >> 2, 0x000000);
 		saa_dsp_writel(dev, 0x470 >> 2, 0x101010);
 
diff -Nru a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
--- a/drivers/media/video/saa7134/saa7134-video.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/media/video/saa7134/saa7134-video.c	2004-06-23 19:04:25 -07:00
@@ -28,13 +28,15 @@
 #include "saa7134-reg.h"
 #include "saa7134.h"
 
+#define V4L2_I2C_CLIENTS 1
+
 /* ------------------------------------------------------------------ */
 
 static unsigned int video_debug   = 0;
 static unsigned int gbuffers      = 8;
 static unsigned int noninterlaced = 0;
-static unsigned int gbufsize      = 768*576*4;
-static unsigned int gbufsize_max  = 768*576*4;
+static unsigned int gbufsize      = 720*576*4;
+static unsigned int gbufsize_max  = 720*576*4;
 MODULE_PARM(video_debug,"i");
 MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
 MODULE_PARM(gbuffers,"i");
@@ -148,10 +150,65 @@
 };
 #define FORMATS ARRAY_SIZE(formats)
 
+#define NORM_625_50			\
+		.h_start       = 0,	\
+		.h_stop        = 719,	\
+		.video_v_start = 24,	\
+		.video_v_stop  = 311,	\
+		.vbi_v_start   = 7,	\
+		.vbi_v_stop    = 22,	\
+		.src_timing    = 4
+
+#define NORM_525_60			\
+		.h_start       = 0,	\
+		.h_stop        = 703,	\
+		.video_v_start = 22,	\
+		.video_v_stop  = 22+239, \
+		.vbi_v_start   = 10, /* FIXME */ \
+		.vbi_v_stop    = 21, /* FIXME */ \
+		.src_timing    = 1
+
 static struct saa7134_tvnorm tvnorms[] = {
 	{
-		.name          = "PAL",
+		.name          = "PAL", /* autodetect */
 		.id            = V4L2_STD_PAL,
+		NORM_625_50,
+
+		.sync_control  = 0x18,
+		.luma_control  = 0x40,
+		.chroma_ctrl1  = 0x81,
+		.chroma_gain   = 0x2a,
+		.chroma_ctrl2  = 0x06,
+		.vgate_misc    = 0x1c,
+
+	},{
+		.name          = "PAL-BG",
+		.id            = V4L2_STD_PAL_BG,
+		NORM_625_50,
+
+		.sync_control  = 0x18,
+		.luma_control  = 0x40,
+		.chroma_ctrl1  = 0x81,
+		.chroma_gain   = 0x2a,
+		.chroma_ctrl2  = 0x06,
+		.vgate_misc    = 0x1c,
+
+	},{
+		.name          = "PAL-I",
+		.id            = V4L2_STD_PAL_I,
+		NORM_625_50,
+
+		.sync_control  = 0x18,
+		.luma_control  = 0x40,
+		.chroma_ctrl1  = 0x81,
+		.chroma_gain   = 0x2a,
+		.chroma_ctrl2  = 0x06,
+		.vgate_misc    = 0x1c,
+
+	},{
+		.name          = "PAL-DK",
+		.id            = V4L2_STD_PAL_DK,
+		NORM_625_50,
 
 		.sync_control  = 0x18,
 		.luma_control  = 0x40,
@@ -160,16 +217,10 @@
 		.chroma_ctrl2  = 0x06,
 		.vgate_misc    = 0x1c,
 
-		.h_start       = 0,
-		.h_stop        = 719,
-		.video_v_start = 24,
-		.video_v_stop  = 311,
-		.vbi_v_start   = 7,
-		.vbi_v_stop    = 22,
-		.src_timing    = 4,
 	},{
 		.name          = "NTSC",
 		.id            = V4L2_STD_NTSC,
+		NORM_525_60,
 
 		.sync_control  = 0x59,
 		.luma_control  = 0x40,
@@ -178,16 +229,10 @@
 		.chroma_ctrl2  = 0x0e,
 		.vgate_misc    = 0x18,
 
-		.h_start       = 0,
-		.h_stop        = 719,
-		.video_v_start = 22,
-		.video_v_stop  = 22+240,
-		.vbi_v_start   = 10, /* FIXME */
-		.vbi_v_stop    = 21, /* FIXME */
-		.src_timing    = 1,
 	},{
 		.name          = "SECAM",
 		.id            = V4L2_STD_SECAM,
+		NORM_625_50,
 
 		.sync_control  = 0x18, /* old: 0x58, */
 		.luma_control  = 0x1b,
@@ -196,16 +241,10 @@
 		.chroma_ctrl2  = 0x00,
 		.vgate_misc    = 0x1c,
 
-		.h_start       = 0,
-		.h_stop        = 719,
-		.video_v_start = 24,
-		.video_v_stop  = 311,
-		.vbi_v_start   = 7,
-		.vbi_v_stop    = 22,
-		.src_timing    = 4,
 	},{
 		.name          = "PAL-M",
 		.id            = V4L2_STD_PAL_M,
+		NORM_525_60,
 
 		.sync_control  = 0x59,
 		.luma_control  = 0x40,
@@ -214,16 +253,10 @@
 		.chroma_ctrl2  = 0x0e,
 		.vgate_misc    = 0x18,
 
-		.h_start       = 0,
-		.h_stop        = 719,
-		.video_v_start = 22,
-		.video_v_stop  = 22+240,
-		.vbi_v_start   = 10, /* FIXME */
-		.vbi_v_stop    = 21, /* FIXME */
-		.src_timing    = 1,
 	},{
 		.name          = "PAL-Nc",
 		.id            = V4L2_STD_PAL_Nc,
+		NORM_625_50,
 
 		.sync_control  = 0x18,
 		.luma_control  = 0x40,
@@ -232,35 +265,6 @@
 		.chroma_ctrl2  = 0x06,
 		.vgate_misc    = 0x1c,
 
-		.h_start       = 0,
-		.h_stop        = 719,
-		.video_v_start = 24,
-		.video_v_stop  = 311,
-		.vbi_v_start   = 7,
-		.vbi_v_stop    = 22,
-		.src_timing    = 4,
-#if 0
-	},{
-		.name          = "AUTO",
-		.id            = V4L2_STD_PAL|V4L2_STD_NTSC|V4L2_STD_SECAM,
-		.width         = 768,
-		.height        = 576,
-
-		.sync_control  = 0x98,
-		.luma_control  = 0x40,
-		.chroma_ctrl1  = 0x8b,
-		.chroma_gain   = 0x00,
-		.chroma_ctrl2  = 0x00,
-		.vgate_misc    = 0x18,
-
-		.h_start       = 0,
-		.h_stop        = 719,
-		.video_v_start = 24,
-		.video_v_stop  = 311,
-		.vbi_v_start   = 7,
-		.vbi_v_stop    = 22,
-		.src_timing    = 4,
-#endif
 	}
 };
 #define TVNORMS ARRAY_SIZE(tvnorms)
@@ -429,7 +433,6 @@
 
 static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
 {
-	struct video_channel c;
 	int luma_control,sync_control,mux;
 
 	dprintk("set tv norm = %s\n",norm->name);
@@ -489,15 +492,22 @@
 	saa_writeb(SAA7134_RAW_DATA_GAIN,         0x40);
 	saa_writeb(SAA7134_RAW_DATA_OFFSET,       0x80);
 
-	/* pass down info to the i2c chips (v4l1) */
-	memset(&c,0,sizeof(c));
-	c.channel = dev->ctl_input;
-	c.norm = VIDEO_MODE_PAL;
-	if (norm->id & V4L2_STD_NTSC)
-		c.norm = VIDEO_MODE_NTSC;
-	if (norm->id & V4L2_STD_SECAM)
-		c.norm = VIDEO_MODE_SECAM;
-	saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c);
+#ifdef V4L2_I2C_CLIENTS
+	saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id);
+#else
+	{
+		/* pass down info to the i2c chips (v4l1) */
+		struct video_channel c;
+		memset(&c,0,sizeof(c));
+		c.channel = dev->ctl_input;
+		c.norm = VIDEO_MODE_PAL;
+		if (norm->id & V4L2_STD_NTSC)
+			c.norm = VIDEO_MODE_NTSC;
+		if (norm->id & V4L2_STD_SECAM)
+			c.norm = VIDEO_MODE_SECAM;
+		saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c);
+	}
+#endif
 }
 
 static void video_mux(struct saa7134_dev *dev, int input)
@@ -593,11 +603,11 @@
 	saa_writeb(SAA7134_VIDEO_V_STOP1(task),  v_stop  &  0xff);
 	saa_writeb(SAA7134_VIDEO_V_STOP2(task),  v_stop  >> 8);
 
-	prescale = dev->crop_defrect.width / width;
+	prescale = dev->crop_current.width / width;
 	if (0 == prescale)
 		prescale = 1;
-	xscale = 1024 * dev->crop_defrect.width / prescale / width;
-	yscale = 512 * div * dev->crop_defrect.height / height;
+	xscale = 1024 * dev->crop_current.width / prescale / width;
+	yscale = 512 * div * dev->crop_current.height / height;
        	dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale);
 	set_h_prescale(dev,task,prescale);
 	saa_writeb(SAA7134_H_SCALE_INC1(task),      xscale &  0xff);
@@ -909,10 +919,12 @@
 	/* sanity checks */
 	if (NULL == fh->fmt)
 		return -EINVAL;
-	if (fh->width  < 48 ||
-	    fh->height < 32 ||
-	    fh->width  > dev->crop_current.width ||
-	    fh->height > dev->crop_current.height)
+	if (fh->width    < 48 ||
+	    fh->height   < 32 ||
+	    fh->width/4  > dev->crop_current.width  ||
+	    fh->height/4 > dev->crop_current.height ||
+	    fh->width    > dev->crop_bounds.width  ||
+	    fh->height   > dev->crop_bounds.height)
 		return -EINVAL;
 	size = (fh->width * fh->height * fh->fmt->depth) >> 3;
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
@@ -1192,7 +1204,7 @@
 	fh->radio    = radio;
 	fh->type     = type;
 	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
-	fh->width    = 768;
+	fh->width    = 720;
 	fh->height   = 576;
 #ifdef VIDIOC_G_PRIORITY
 	v4l2_prio_open(&dev->prio,&fh->prio);
@@ -1409,8 +1421,8 @@
 			return -EINVAL;
 
 		field = f->fmt.pix.field;
-		maxw  = dev->crop_current.width;
-		maxh  = dev->crop_current.height;
+		maxw  = min(dev->crop_current.width*4,  dev->crop_bounds.width);
+		maxh  = min(dev->crop_current.height*4, dev->crop_bounds.height);
 		
 		if (V4L2_FIELD_ANY == field) {
 			field = (f->fmt.pix.height > maxh/2)
@@ -1670,10 +1682,14 @@
 		v4l2_std_id *id = arg;
 		unsigned int i;
 
-		for(i = 0; i < TVNORMS; i++)
-			if (*id & tvnorms[i].id)
+		for (i = 0; i < TVNORMS; i++)
+			if (*id == tvnorms[i].id)
 				break;
 		if (i == TVNORMS)
+			for (i = 0; i < TVNORMS; i++)
+				if (*id & tvnorms[i].id)
+					break;
+		if (i == TVNORMS)
 			return -EINVAL;
 
 		down(&dev->lock);
@@ -1685,6 +1701,7 @@
 			spin_unlock_irqrestore(&dev->slock,flags);
 		} else 
 			set_tvnorm(dev,&tvnorms[i]);
+		saa7134_tvaudio_do_scan(dev);
 		up(&dev->lock);
 		return 0;
 	}
@@ -1817,7 +1834,11 @@
 			return -EINVAL;
 		down(&dev->lock);
 		dev->ctl_freq = f->frequency;
+#ifdef V4L2_I2C_CLIENTS
+		saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f);
+#else
 		saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&dev->ctl_freq);
+#endif
 		saa7134_tvaudio_do_scan(dev);
 		up(&dev->lock);
 		return 0;
@@ -2064,7 +2085,6 @@
 	case VIDIOC_G_TUNER:
 	{
 		struct v4l2_tuner *t = arg;
-		struct video_tuner vt;
 
 		if (0 != t->index)
 			return -EINVAL;
@@ -2073,10 +2093,17 @@
 		strcpy(t->name, "Radio");
                 t->rangelow  = (int)(65*16);
                 t->rangehigh = (int)(108*16);
-		
-		memset(&vt,0,sizeof(vt));
-		saa7134_i2c_call_clients(dev,VIDIOCGTUNER,&vt);
-		t->signal = vt.signal;
+
+#ifdef V4L2_I2C_CLIENTS
+		saa7134_i2c_call_clients(dev,VIDIOC_G_TUNER,t);
+#else
+		{
+			struct video_tuner vt;
+			memset(&vt,0,sizeof(vt));
+			saa7134_i2c_call_clients(dev,VIDIOCGTUNER,&vt);
+			t->signal = vt.signal;
+		}
+#endif
 		return 0;
 	}
 	case VIDIOC_ENUMINPUT:
diff -Nru a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
--- a/drivers/media/video/saa7134/saa7134.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/video/saa7134/saa7134.h	2004-06-23 19:04:28 -07:00
@@ -19,7 +19,7 @@
  */
 
 #include <linux/version.h>
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,11)
+#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,12)
 
 #include <linux/pci.h>
 #include <linux/i2c.h>
@@ -152,6 +152,10 @@
 #define SAA7134_BOARD_ECS_TVP3XP_4CB5  31
 #define SAA7134_BOARD_AVACSSMARTTV     32
 #define SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER 33
+#define SAA7134_BOARD_NOVAC_PRIMETV7133 34
+#define SAA7134_BOARD_AVERMEDIA_305    35
+#define SAA7133_BOARD_UPMOST_PURPLE_TV 36
+#define SAA7134_BOARD_ITEMS_MTV005     37
 
 #define SAA7134_INPUT_MAX 8
 
diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
--- a/drivers/media/video/tda9887.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/media/video/tda9887.c	2004-06-23 19:04:25 -07:00
@@ -21,7 +21,7 @@
       Note: OP2 of tda988x must be set to 1, else MT2032 is disabled!
    - KNC One TV-Station RDS (saa7134)
 */
-    
+
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = {
@@ -33,22 +33,30 @@
 I2C_CLIENT_INSMOD;
 
 /* insmod options */
-static int debug =  0;
-static char *pal =  "b";
-static char *secam =  "l";
+static unsigned int debug = 0;
 MODULE_PARM(debug,"i");
-MODULE_PARM(pal,"s");
-MODULE_PARM(secam,"s");
 MODULE_LICENSE("GPL");
 
 /* ---------------------------------------------------------------------- */
 
+#define UNSET       (-1U)
+#define PREFIX      "tda9885/6/7: "
 #define dprintk     if (debug) printk
 
 struct tda9887 {
-	struct i2c_client client;
-	int radio,tvnorm;
-	int pinnacle_id;
+	struct i2c_client  client;
+	v4l2_std_id        std;
+	unsigned int       radio;
+	unsigned int       pinnacle_id;
+	unsigned int       using_v4l2;
+};
+
+struct tvnorm {
+	v4l2_std_id       std;
+	char              *name;
+	unsigned char     b;
+	unsigned char     c;
+	unsigned char     e;
 };
 
 static struct i2c_driver driver;
@@ -60,7 +68,7 @@
 // TDA defines
 //
 
-//// first reg
+//// first reg (b)
 #define cVideoTrapBypassOFF     0x00    // bit b0
 #define cVideoTrapBypassON      0x01    // bit b0
 
@@ -85,7 +93,7 @@
 #define cOutputPort2Inactive    0x80    // bit b7
 
 
-//// second reg
+//// second reg (c)
 #define cDeemphasisOFF          0x00    // bit c5
 #define cDeemphasisON           0x20    // bit c5
 
@@ -96,7 +104,7 @@
 #define cAudioGain6             0x80    // bit c7
 
 
-//// third reg
+//// third reg (e)
 #define cAudioIF_4_5             0x00    // bit e0:1
 #define cAudioIF_5_5             0x01    // bit e0:1
 #define cAudioIF_6_0             0x02    // bit e0:1
@@ -122,126 +130,287 @@
 #define cAgcOutON                0x80    // bit e7
 #define cAgcOutOFF               0x00    // bit e7
 
-static int tda9887_miro(struct tda9887 *t)
+/* ---------------------------------------------------------------------- */
+
+static struct tvnorm tvnorms[] = {
+	{
+		.std   = V4L2_STD_PAL_BG,
+		.name  = "PAL-BG",
+		.b     = ( cNegativeFmTV  |
+			   cQSS           ),
+		.c     = ( cDeemphasisON  |
+			   cDeemphasis50  ),
+		.e     = ( cAudioIF_5_5   |
+			   cVideoIF_38_90 ),
+	},{
+		.std   = V4L2_STD_PAL_I,
+		.name  = "PAL-I",
+		.b     = ( cNegativeFmTV  |
+			   cQSS           ),
+		.c     = ( cDeemphasisON  |
+			   cDeemphasis50  ),
+		.e     = ( cAudioIF_6_0   |
+			   cVideoIF_38_90 ),
+	},{
+		.std   = V4L2_STD_PAL_DK,
+		.name  = "PAL-DK",
+		.b     = ( cNegativeFmTV  |
+			   cQSS           ),
+		.c     = ( cDeemphasisON  |
+			   cDeemphasis50  ),
+		.e     = ( cAudioIF_6_5   |
+			   cVideoIF_38_00 ),
+	},{
+		.std   = V4L2_STD_PAL_M | V4L2_STD_PAL_N,
+		.name  = "PAL-M/N",
+		.b     = ( cNegativeFmTV  |
+			   cQSS           ),
+		.c     = ( cDeemphasisON  |
+			   cDeemphasis75  ),
+		.e     = ( cAudioIF_4_5   |
+			   cVideoIF_45_75 ),
+	},{
+		.std   = V4L2_STD_SECAM_L,
+		.name  = "SECAM-L",
+		.b     = ( cPositiveAmTV  |
+			   cQSS           ),
+		.e     = ( cAudioIF_6_5   |
+			   cVideoIF_38_90 ),
+	},{
+		.std   = V4L2_STD_SECAM_DK,
+		.name  = "SECAM-DK",
+		.b     = ( cNegativeFmTV  |
+			   cQSS           ),
+		.c     = ( cDeemphasisON  |
+			   cDeemphasis50  ),
+		.e     = ( cAudioIF_6_5   |
+			   cVideoIF_38_00 ),
+	},{
+		.std   = V4L2_STD_NTSC_M,
+		.name  = "NTSC-M",
+		.b     = ( cNegativeFmTV  |
+			   cQSS           ),
+		.c     = ( cDeemphasisON  |
+			   cDeemphasis50  ),
+		.e     = ( cGating_36     |
+			   cAudioIF_4_5   |
+			   cVideoIF_45_75 ),
+	},{
+		.std   = V4L2_STD_NTSC_M_JP,
+		.name  = "NTSC-JP",
+		.b     = ( cNegativeFmTV  |
+			   cQSS           ),
+		.c     = ( cDeemphasisON  |
+			   cDeemphasis50  ),
+		.e     = ( cGating_36     |
+			   cAudioIF_4_5   |
+			   cVideoIF_58_75 ),
+	}
+};
+
+static struct tvnorm radio = {
+	.name = "radio",
+	.b    = ( cFmRadio       |
+		  cQSS           ),
+	.c    = ( cDeemphasisON  |
+		  cDeemphasis50  ),
+	.e    = ( cAudioIF_5_5   |
+		  cRadioIF_38_90 ),
+};
+
+/* ---------------------------------------------------------------------- */
+
+static void dump_read_message(unsigned char *buf)
 {
-	int rc;
-	u8   bData[4]     = { 0 };
-	u8   bVideoIF     = 0;
-	u8   bAudioIF     = 0;
-	u8   bDeEmphasis  = 0;
-	u8   bDeEmphVal   = 0;
-	u8   bModulation  = 0;
-	u8   bCarrierMode = 0;
-	u8   bOutPort1    = cOutputPort1Inactive;
-#if 0
-	u8   bOutPort2    = cOutputPort2Inactive & mbTADState; // store i2c tuner state
-#else
-	u8   bOutPort2    = cOutputPort2Inactive;
-#endif
-	u8   bVideoTrap   = cVideoTrapBypassOFF;
-#if 1
-	u8   bTopAdjust   = 0x0e /* -2dB */;
-#else
-	u8   bTopAdjust   = 0;
-#endif
+	static char *afc[16] = {
+		"- 12.5 kHz",
+		"- 37.5 kHz",
+		"- 62.5 kHz",
+		"- 87.5 kHz",
+		"-112.5 kHz",
+		"-137.5 kHz",
+		"-162.5 kHz",
+		"-187.5 kHz [min]",
+		"+187.5 kHz [max]",
+		"+162.5 kHz",
+		"+137.5 kHz",
+		"+112.5 kHz",
+		"+ 87.5 kHz",
+		"+ 62.5 kHz",
+		"+ 37.5 kHz",
+		"+ 12.5 kHz",
+	};
+	printk(PREFIX "read: 0x%2x\n", buf[0]);
+	printk("  after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
+	printk("  afc            : %s\n", afc[(buf[0] >> 1) & 0x0f]);
+	printk("  afc window     : %s\n", (buf[0] & 0x40) ? "in" : "out");
+	printk("  vfi level      : %s\n", (buf[0] & 0x80) ? "high" : "low");
+}
 
-#if 0
-	if (mParams.fVideoTrap)
-		bVideoTrap   = cVideoTrapBypassON;
-#endif
+static void dump_write_message(unsigned char *buf)
+{
+	static char *sound[4] = {
+		"AM/TV",
+		"FM/radio",
+		"FM/TV",
+		"FM/radio"
+	};
+	static char *adjust[32] = {
+		"-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
+		"-8",  "-7",  "-6",  "-5",  "-4",  "-3",  "-2",  "-1",
+		"0",   "+1",  "+2",  "+3",  "+4",  "+5",  "+6",  "+7",
+		"+8",  "+9",  "+10", "+11", "+12", "+13", "+14", "+15"
+	};
+	static char *deemph[4] = {
+		"no", "no", "75", "50"
+	};
+	static char *carrier[4] = {
+		"4.5 MHz",
+		"5.5 MHz",
+		"6.0 MHz",
+		"6.5 MHz / AM"
+	};
+	static char *vif[8] = {
+		"58.75 MHz",
+		"45.75 MHz",
+		"38.9 MHz",
+		"38.0 MHz",
+		"33.9 MHz",
+		"33.4 MHz",
+		"45.75 MHz + pin13",
+		"38.9 MHz + pin13",
+	};
+	static char *rif[4] = {
+		"44 MHz",
+		"52 MHz",
+		"52 MHz",
+		"44 MHz",
+	};
+
+	printk(PREFIX "write: byte B 0x%02x\n",buf[1]);
+	printk("  B0   video mode      : %s\n",
+	       (buf[1] & 0x01) ? "video trap" : "sound trap");
+	printk("  B1   auto mute fm    : %s\n",
+	       (buf[1] & 0x02) ? "yes" : "no");
+	printk("  B2   carrier mode    : %s\n",
+	       (buf[1] & 0x04) ? "QSS" : "Intercarrier");
+	printk("  B3-4 tv sound/radio  : %s\n",
+	       sound[(buf[1] & 0x18) >> 3]);
+	printk("  B5   force mute audio: %s\n",
+	       (buf[1] & 0x20) ? "yes" : "no");
+	printk("  B6   output port 1   : %s\n",
+	       (buf[1] & 0x40) ? "high" : "low");
+	printk("  B7   output port 2   : %s\n",
+	       (buf[1] & 0x80) ? "high" : "low");
+
+	printk(PREFIX "write: byte C 0x%02x\n",buf[2]);
+	printk("  C0-4 top adjustment  : %s dB\n", adjust[buf[2] & 0x1f]);
+	printk("  C5-6 de-emphasis     : %s\n", deemph[(buf[2] & 0x60) >> 5]);
+	printk("  C7   audio gain      : %s\n",
+	       (buf[2] & 0x80) ? "-6" : "0");
+
+	printk(PREFIX "write: byte E 0x%02x\n",buf[3]);
+	printk("  E0-1 sound carrier   : %s\n",
+	       carrier[(buf[3] & 0x03)]);
+	printk("  E6   l pll ganting   : %s\n",
+	       (buf[3] & 0x40) ? "36" : "13");
+
+	if (buf[1] & 0x08) {
+		/* radio */
+		printk("  E2-4 video if        : %s\n",
+		       rif[(buf[3] & 0x0c) >> 2]);
+		printk("  E7   vif agc output  : %s\n",
+		       (buf[3] & 0x80)
+		       ? ((buf[3] & 0x10) ? "fm-agc radio" : "sif-agc radio")
+		       : "fm radio carrier afc");
+	} else {
+		/* video */
+		printk("  E2-4 video if        : %s\n",
+		       vif[(buf[3] & 0x1c) >> 2]);
+		printk("  E5   tuner gain      : %s\n",
+		       (buf[3] & 0x80)
+		       ? ((buf[3] & 0x20) ? "external" : "normal")
+		       : ((buf[3] & 0x20) ? "minimum"  : "normal"));
+		printk("  E7   vif agc output  : %s\n",
+		       (buf[3] & 0x80)
+		       ? ((buf[3] & 0x20)
+			  ? "pin3 port, pin22 vif agc out"
+			  : "pin22 port, pin3 vif acg ext in")
+		       : "pin3+pin22 port");
+	}
+	printk("--\n");
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
+{
+	struct tvnorm *norm = NULL;
+	int i;
 
 	if (t->radio) {
-		bVideoTrap   = cVideoTrapBypassOFF;
-		bCarrierMode = cQSS;
-		bModulation  = cFmRadio;
-		bOutPort1    = cOutputPort1Inactive;
-		bDeEmphasis  = cDeemphasisON;
-		if (3 == t->pinnacle_id) {
-			/* ntsc */
-			bDeEmphVal   = cDeemphasis75;
-			bAudioIF     = cAudioIF_4_5;
-			bVideoIF     = cRadioIF_45_75;
-		} else {
-			/* pal */
-			bAudioIF     = cAudioIF_5_5;
-			bVideoIF     = cRadioIF_38_90;
-			bDeEmphVal   = cDeemphasis50;
+		norm = &radio;
+	} else {
+		for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
+			if (tvnorms[i].std & t->std) {
+				norm = tvnorms+i;
+				break;
+			}
 		}
+	}
+	if (NULL == norm) {
+		dprintk(PREFIX "Oops: no tvnorm entry found\n");
+		return -1;
+	}
+
+	dprintk(PREFIX "configure for: %s\n",norm->name);
+	buf[1] = norm->b;
+	buf[2] = norm->c;
+	buf[3] = norm->e;
+	return 0;
+}
+
+static unsigned int port1  = 1;
+static unsigned int port2  = 1;
+static unsigned int qss    = UNSET;
+static unsigned int adjust = 0x10;
+MODULE_PARM(port1,"i");
+MODULE_PARM(port2,"i");
+MODULE_PARM(qss,"i");
+MODULE_PARM(adjust,"i");
+
+static int tda9887_set_insmod(struct tda9887 *t, char *buf)
+{
+	if (port1)
+		buf[1] |= cOutputPort1Inactive;
+	if (port2)
+		buf[1] |= cOutputPort2Inactive;
+	if (UNSET != qss) {
+		if (qss)
+			buf[1] |= cQSS;
+		else
+			buf[1] &= ~cQSS;
+	}
+
+	if (adjust >= 0x00 && adjust < 0x20)
+		buf[2] |= adjust;
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
 
-	} else if (t->tvnorm == VIDEO_MODE_PAL) {
-		bDeEmphasis  = cDeemphasisON;
-		bDeEmphVal   = cDeemphasis50;
-		bModulation  = cNegativeFmTV;
-		bOutPort1    = cOutputPort1Inactive;
+static int tda9887_set_pinnacle(struct tda9887 *t, char *buf)
+{
+	unsigned int bCarrierMode = UNSET;
+
+	if (t->std & V4L2_STD_PAL) {
 		if ((1 == t->pinnacle_id) || (7 == t->pinnacle_id)) {
 			bCarrierMode = cIntercarrier;
 		} else {
-			// stereo boards
 			bCarrierMode = cQSS;
 		}
-		switch (pal[0]) {
-		case 'b':
-		case 'g':
-		case 'h':
-			bVideoIF     = cVideoIF_38_90;
-			bAudioIF     = cAudioIF_5_5;
-			break;
-		case 'd':
-			bVideoIF     = cVideoIF_38_00;
-			bAudioIF     = cAudioIF_6_5;
-			break;
-		case 'i':
-			bVideoIF     = cVideoIF_38_90;
-			bAudioIF     = cAudioIF_6_0;
-			break;
-		case 'm':
-		case 'n':
-			bVideoIF     = cVideoIF_45_75;
-			bAudioIF     = cAudioIF_4_5;
-			bDeEmphVal   = cDeemphasis75;
-			if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) {
-				bCarrierMode = cIntercarrier;
-			} else {
-				bCarrierMode = cQSS;
-			}
-			break;
-		}
-
-	} else if (t->tvnorm == VIDEO_MODE_SECAM) {
-		bAudioIF     = cAudioIF_6_5;
-		bDeEmphasis  = cDeemphasisON;
-		bDeEmphVal   = cDeemphasis50;
-		bModulation  = cNegativeFmTV;
-		bCarrierMode = cQSS;
-		bOutPort1    = cOutputPort1Inactive;                
-		switch (secam[0]) {
-		case 'd':
-			bVideoIF     = cVideoIF_38_00;
-			break;
-		case 'k':
-			bVideoIF     = cVideoIF_38_90;
-			break;
-		case 'l':
-			bVideoIF     = cVideoIF_38_90;
-			bDeEmphasis  = cDeemphasisOFF;
-			bDeEmphVal   = cDeemphasis75;
-			bModulation  = cPositiveAmTV;
-			break;
-		case 'L' /* L1 */:
-			bVideoIF     = cVideoIF_33_90;
-			bDeEmphasis  = cDeemphasisOFF;
-			bDeEmphVal   = cDeemphasis75;
-			bModulation  = cPositiveAmTV;
-			break;
-		}
-
-	} else if (t->tvnorm == VIDEO_MODE_NTSC) {
-                bVideoIF     = cVideoIF_45_75;
-                bAudioIF     = cAudioIF_4_5;
-                bDeEmphasis  = cDeemphasisON;
-                bDeEmphVal   = cDeemphasis75;
-                bModulation  = cNegativeFmTV;                
-                bOutPort1    = cOutputPort1Inactive;
+	}
+	if (t->std & V4L2_STD_NTSC) {
                 if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) {
 			bCarrierMode = cIntercarrier;
 		} else {
@@ -249,99 +418,102 @@
                 }
 	}
 
-	bData[1] = bVideoTrap        |  // B0: video trap bypass
-		cAutoMuteFmInactive  |  // B1: auto mute
-		bCarrierMode         |  // B2: InterCarrier for PAL else QSS 
-		bModulation          |  // B3 - B4: positive AM TV for SECAM only
-		cForcedMuteAudioOFF  |  // B5: forced Audio Mute (off)
-		bOutPort1            |  // B6: Out Port 1 
-		bOutPort2;              // B7: Out Port 2 
-	bData[2] = bTopAdjust |   // C0 - C4: Top Adjust 0 == -16dB  31 == 15dB
-		bDeEmphasis   |   // C5: De-emphasis on/off
-		bDeEmphVal    |   // C6: De-emphasis 50/75 microsec
-		cAudioGain0;      // C7: normal audio gain
-	bData[3] = bAudioIF      |  // E0 - E1: Sound IF
-		bVideoIF         |  // E2 - E4: Video IF
-		cTunerGainNormal |  // E5: Tuner gain (normal)
-		cGating_18       |  // E6: Gating (18%)
-		cAgcOutOFF;         // E7: VAGC  (off)
-	
-	dprintk("tda9885/6/7: 0x%02x 0x%02x 0x%02x [pinnacle_id=%d]\n",
-		bData[1],bData[2],bData[3],t->pinnacle_id);
-	if (4 != (rc = i2c_master_send(&t->client,bData,4)))
-		printk("tda9885/6/7: i2c i/o error: rc == %d (should be 4)\n",rc);
+	if (bCarrierMode != UNSET) {
+		buf[1] &= ~0x04;
+		buf[1] |= bCarrierMode;
+	}
 	return 0;
 }
 
 /* ---------------------------------------------------------------------- */
 
-#if 0
-/* just for reference: old knc-one saa7134 stuff */
-static unsigned char buf_pal_bg[]    = { 0x00, 0x16, 0x70, 0x49 };
-static unsigned char buf_pal_i[]     = { 0x00, 0x16, 0x70, 0x4a };
-static unsigned char buf_pal_dk[]    = { 0x00, 0x16, 0x70, 0x4b };
-static unsigned char buf_pal_l[]     = { 0x00, 0x06, 0x50, 0x4b };
-static unsigned char buf_fm_stereo[] = { 0x00, 0x0e, 0x0d, 0x77 };
-#endif
-
-static unsigned char buf_pal_bg[]    = { 0x00, 0x96, 0x70, 0x49 };
-static unsigned char buf_pal_i[]     = { 0x00, 0x96, 0x70, 0x4a };
-static unsigned char buf_pal_dk[]    = { 0x00, 0x96, 0x70, 0x4b };
-static unsigned char buf_pal_l[]     = { 0x00, 0x86, 0x50, 0x4b };
-static unsigned char buf_fm_stereo[] = { 0x00, 0x8e, 0x0d, 0x77 };
-static unsigned char buf_ntsc[]	     = { 0x00, 0x96, 0x70, 0x44 };
-static unsigned char buf_ntsc_jp[]   = { 0x00, 0x96, 0x70, 0x40 };
+static char *pal = "-";
+MODULE_PARM(pal,"s");
+static char *secam = "-";
+MODULE_PARM(secam,"s");
 
-static int tda9887_configure(struct tda9887 *t)
+static int tda9887_fixup_std(struct tda9887 *t)
 {
-	unsigned char *buf = NULL;
-	int rc;
-
-	if (t->radio) {
-		dprintk("tda9885/6/7: FM Radio mode\n");
-		buf = buf_fm_stereo;
-
-	} else if (t->tvnorm == VIDEO_MODE_PAL) {
-		dprintk("tda9885/6/7: PAL-%c mode\n",pal[0]);
+	/* get more precise norm info from insmod option */
+	if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
 		switch (pal[0]) {
 		case 'b':
+		case 'B':
 		case 'g':
-			buf = buf_pal_bg;
+		case 'G':
+			dprintk(PREFIX "insmod fixup: PAL => PAL-BG\n");
+			t->std = V4L2_STD_PAL_BG;
 			break;
 		case 'i':
-			buf = buf_pal_i;
+		case 'I':
+			dprintk(PREFIX "insmod fixup: PAL => PAL-I\n");
+			t->std = V4L2_STD_PAL_I;
+			break;
+		case 'd':
+		case 'D':
+		case 'k':
+		case 'K':
+			dprintk(PREFIX "insmod fixup: PAL => PAL-DK\n");
+			t->std = V4L2_STD_PAL_DK;
 			break;
+		}
+	}
+	if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
+		switch (secam[0]) {
 		case 'd':
+		case 'D':
 		case 'k':
-			buf = buf_pal_dk;
+		case 'K':
+			dprintk(PREFIX "insmod fixup: SECAM => SECAM-DK\n");
+			t->std = V4L2_STD_SECAM_DK;
 			break;
 		case 'l':
-			buf = buf_pal_l;
+		case 'L':
+			dprintk(PREFIX "insmod fixup: SECAM => SECAM-L\n");
+			t->std = V4L2_STD_SECAM_L;
 			break;
 		}
+	}
+	return 0;
+}
 
-	} else if (t->tvnorm == VIDEO_MODE_NTSC) {
-		dprintk("tda9885/6/7: NTSC mode\n");
-		buf = buf_ntsc;
+static int tda9887_status(struct tda9887 *t)
+{
+	unsigned char buf[1];
+	int rc;
 
-	} else if (t->tvnorm == VIDEO_MODE_SECAM) {
-		dprintk("tda9885/6/7: SECAM mode\n");
-                buf = buf_pal_l;
+	memset(buf,0,sizeof(buf));
+        if (1 != (rc = i2c_master_recv(&t->client,buf,1)))
+                printk(PREFIX "i2c i/o error: rc == %d (should be 1)\n",rc);
+	dump_read_message(buf);
+	return 0;
+}
 
-        } else if (t->tvnorm == 6 /* BTTV hack */) {
-		dprintk("tda9885/6/7: NTSC-Japan mode\n");
-                buf = buf_ntsc_jp;
-        }
+static int tda9887_configure(struct tda9887 *t)
+{
+	unsigned char buf[4];
+	int rc;
 
-	if (NULL == buf) {
-		printk("tda9885/6/7 unknown norm=%d\n",t->tvnorm);
-		return 0;
+	memset(buf,0,sizeof(buf));
+	tda9887_set_tvnorm(t,buf);
+	if (UNSET != t->pinnacle_id) {
+		tda9887_set_pinnacle(t,buf);
 	}
+	tda9887_set_insmod(t,buf);
 
-	dprintk("tda9885/6/7: 0x%02x 0x%02x 0x%02x\n",
+	dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n",
 		buf[1],buf[2],buf[3]);
+	if (debug > 1)
+		dump_write_message(buf);
+
         if (4 != (rc = i2c_master_send(&t->client,buf,4)))
-                printk("tda9885/6/7: i2c i/o error: rc == %d (should be 4)\n",rc);
+                printk(PREFIX "i2c i/o error: rc == %d (should be 4)\n",rc);
+
+	if (debug > 2) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ);
+		tda9887_status(t);
+	}
 	return 0;
 }
 
@@ -354,14 +526,14 @@
         client_template.adapter = adap;
         client_template.addr    = addr;
 
-        printk("tda9887: chip found @ 0x%x\n", addr<<1);
+        printk(PREFIX "chip found @ 0x%x\n", addr<<1);
 
         if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
                 return -ENOMEM;
 	memset(t,0,sizeof(*t));
-	t->client = client_template;
-	t->pinnacle_id = -1;
-	t->tvnorm=VIDEO_MODE_PAL;
+	t->client      = client_template;
+	t->std         = 0;;
+	t->pinnacle_id = UNSET;
         i2c_set_clientdata(&t->client, t);
         i2c_attach_client(&t->client);
         
@@ -394,6 +566,13 @@
 	return 0;
 }
 
+#define SWITCH_V4L2	if (!t->using_v4l2 && debug) \
+		          printk(PREFIX "switching to v4l2\n"); \
+	                  t->using_v4l2 = 1;
+#define CHECK_V4L2	if (t->using_v4l2) { if (debug) \
+			  printk(PREFIX "ignore v4l1 call\n"); \
+		          return 0; }
+
 static int
 tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
@@ -404,10 +583,7 @@
 	/* --- configuration --- */
 	case AUDC_SET_RADIO:
 		t->radio = 1;
-		if (-1 != t->pinnacle_id)
-			tda9887_miro(t);
-		else
-			tda9887_configure(t);
+		tda9887_configure(t);
 		break;
 		
 	case AUDC_CONFIG_PINNACLE:
@@ -415,7 +591,7 @@
 		int *i = arg;
 
 		t->pinnacle_id = *i;
-		tda9887_miro(t);
+		tda9887_configure(t);
 		break;
 	}
 	/* --- v4l ioctls --- */
@@ -423,15 +599,51 @@
 	   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;
 
-		t->radio  = 0;
-		t->tvnorm = vc->norm;
-		if (-1 != t->pinnacle_id)
-			tda9887_miro(t);
-		else
-			tda9887_configure(t);
+		CHECK_V4L2;
+		t->radio = 0;
+		if (vc->norm < ARRAY_SIZE(map))
+			t->std = map[vc->norm];
+		tda9887_fixup_std(t);
+		tda9887_configure(t);
+		break;
+	}
+	case VIDIOC_S_STD:
+	{
+		v4l2_std_id *id = arg;
+
+		SWITCH_V4L2;
+		t->radio = 0;
+		t->std   = *id;
+		tda9887_fixup_std(t);
+		tda9887_configure(t);
 		break;
+	}
+	case VIDIOC_S_FREQUENCY:
+	{
+		struct v4l2_frequency *f = arg;
+
+		SWITCH_V4L2;
+		if (V4L2_TUNER_ANALOG_TV == f->type) {
+			if (t->radio == 0)
+				return 0;
+			t->radio = 0;
+		}
+		if (V4L2_TUNER_RADIO == f->type) {
+			if (t->radio == 1)
+				return 0;
+			t->radio = 1;
+		}
+		tda9887_configure(t);
 	}
 	default:
 		/* nothing */
diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c
--- a/drivers/media/video/tuner.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/media/video/tuner.c	2004-06-23 19:04:28 -07:00
@@ -26,15 +26,17 @@
 static unsigned int debug =  0;
 static unsigned int type  =  UNSET;
 static unsigned int addr  =  0;
-static char *pal =  "b";
 static unsigned int tv_range[2]    = { 44, 958 };
 static unsigned int radio_range[2] = { 65, 108 };
+static unsigned int tv_antenna = 1;
+static unsigned int radio_antenna = 0;
 MODULE_PARM(debug,"i");
 MODULE_PARM(type,"i");
 MODULE_PARM(addr,"i");
 MODULE_PARM(tv_range,"2i");
 MODULE_PARM(radio_range,"2i");
-MODULE_PARM(pal,"s");
+MODULE_PARM(tv_antenna,"i");
+MODULE_PARM(radio_antenna,"i");
 
 #define optimize_vco 1
 
@@ -48,10 +50,10 @@
 struct tuner {
 	unsigned int type;            /* chip type */
 	unsigned int freq;            /* keep track of the current settings */
-	unsigned int std;
+	v4l2_std_id  std;
+	int          using_v4l2;
 	
 	unsigned int radio;
-	unsigned int mode;            /* current norm for multi-norm tuners */
 	unsigned int input;
 	
 	// only for MT2032
@@ -537,15 +539,16 @@
 	int if2,from,to;
 
 	// signal bandwidth and picture carrier
-	if (t->mode == VIDEO_MODE_NTSC) {
-		from=40750*1000;
-		to=46750*1000;
-		if2=45750*1000; 
+	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;
+		// PAL
+		from = 32900*1000;
+		to   = 39900*1000;
+		if2  = 38900*1000;
 	}
 
         mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
@@ -619,6 +622,17 @@
         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;
@@ -683,13 +697,15 @@
 	struct tuner *t = i2c_get_clientdata(c);
 	unsigned int if2;
 	
-	if (t->mode == VIDEO_MODE_NTSC) {
-                if2=45750*1000;
+	if (t->std & V4L2_STD_525_60) {
+		// NTSC
+                if2 = 45750*1000;
         } else {
-                // Pal
-                if2=38900*1000;
+                // PAL
+                if2 = 38900*1000;
         }
-	mt2050_set_if_freq(c,freq*62500,if2);
+	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)
@@ -698,6 +714,7 @@
 	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)
@@ -731,8 +748,8 @@
         unsigned char buf[21];
 	int company_code;
 	
-        buf[0] = 0;
-	t->tv_freq = NULL;
+	memset(buf,0,sizeof(buf));
+	t->tv_freq    = NULL;
 	t->radio_freq = NULL;
 	name = "unknown";
 
@@ -751,6 +768,9 @@
 	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:
@@ -764,6 +784,7 @@
 		printk("tuner: microtune: unknown companycode\n");
 		return 0;
 	}
+#endif
 
 	if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
 	    NULL != microtune_part[buf[0x13]])
@@ -811,54 +832,40 @@
 		/* 0x02 -> PAL BDGHI / SECAM L */
 		/* 0x04 -> ??? PAL others / SECAM others ??? */
 		config &= ~0x02;
-		if (t->mode == VIDEO_MODE_SECAM)
+		if (t->std & V4L2_STD_SECAM)
 			config |= 0x02;
 		break;
 
 	case TUNER_TEMIC_4046FM5:
 		config &= ~0x0f;
-		switch (pal[0]) {
-		case 'i':
-		case 'I':
+
+		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;
-			break;
-		case 'd':
-		case 'D':
+
+		} else if (t->std & V4L2_STD_PAL_DK) {
 			config |= TEMIC_SET_PAL_DK;
-			break;
-		case 'l':
-		case 'L':
+
+		} else if (t->std & V4L2_STD_SECAM_L) {
 			config |= TEMIC_SET_PAL_L;
-			break;
-		case 'b':
-		case 'B':
-		case 'g':
-		case 'G':
-		default:
-			config |= TEMIC_SET_PAL_BG;
-			break;
+
 		}
 		break;
 
 	case TUNER_PHILIPS_FQ1216ME:
 		config &= ~0x0f;
-		switch (pal[0]) {
-		case 'i':
-		case 'I':
+
+		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;
-			break;
-		case 'l':
-		case 'L':
+
+		} else if (t->std & V4L2_STD_SECAM_L) {
 			config |= PHILIPS_SET_PAL_L;
-			break;
-		case 'd':
-		case 'D':
-		case 'b':
-		case 'B':
-		case 'g':
-		case 'G':
-			config |= PHILIPS_SET_PAL_BGDK;
-			break;
+
 		}
 		break;
 
@@ -867,12 +874,9 @@
 		/* 0x01 -> ATSC antenna input 2 */
 		/* 0x02 -> NTSC antenna input 1 */
 		/* 0x03 -> NTSC antenna input 2 */
-		
 		config &= ~0x03;
-#ifdef VIDEO_MODE_ATSC
-		if (VIDEO_MODE_ATSC != t->mode)
+		if (t->std & V4L2_STD_ATSC)
 			config |= 2;
-#endif
 		/* FIXME: input */
 		break;
 	}
@@ -990,6 +994,22 @@
 	t->radio_freq(c,freq);
 }
 
+static void set_freq(struct i2c_client *c, unsigned long freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+
+	if (t->radio) {
+		dprintk("tuner: radio freq set to %lu.%02lu\n",
+			freq/16,freq%16*100/16);
+		set_radio_freq(c,freq);
+	} else {
+		dprintk("tuner: tv freq set to %lu.%02lu\n",
+			freq/16,freq%16*100/16);
+		set_tv_freq(c, freq);
+	}
+	t->freq = freq;
+}
+
 static void set_type(struct i2c_client *c, unsigned int type, char *source)
 {
 	struct tuner *t = i2c_get_clientdata(c);
@@ -1019,6 +1039,38 @@
 	}
 }
 
+static char *pal = "-";
+MODULE_PARM(pal,"s");
+
+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)
@@ -1054,7 +1106,7 @@
 		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 card core driver (bttv, saa7134, ...) instead.\n");
+		printk("tuner: tv aard core driver (bttv, saa7134, ...) instead.\n");
 	}
 	return 0;
 }
@@ -1094,6 +1146,13 @@
 	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)
 {
@@ -1130,10 +1189,21 @@
 	   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->radio = 0;
-		t->mode = vc->norm;
+		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;
@@ -1142,22 +1212,15 @@
 	{
 		unsigned long *v = arg;
 
-		if (t->radio) {
-			dprintk("tuner: radio freq set to %lu.%02lu\n",
-				(*v)/16,(*v)%16*100/16);
-			set_radio_freq(client,*v);
-		} else {
-			dprintk("tuner: tv freq set to %lu.%02lu\n",
-				(*v)/16,(*v)%16*100/16);
-			set_tv_freq(client,*v);
-		}
-		t->freq = *v;
+		CHECK_V4L2;
+		set_freq(client,*v);
 		return 0;
 	}
 	case VIDIOCGTUNER:
 	{
 		struct video_tuner *vt = arg;
 
+		CHECK_V4L2;
 		if (t->radio)
 			vt->signal = tuner_signal(client);
 		return 0;
@@ -1165,9 +1228,51 @@
 	case VIDIOCGAUDIO:
 	{
 		struct video_audio *va = arg;
+
+		CHECK_V4L2;
 		if (t->radio)
 			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->radio = 0;
+		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_ANALOG_TV == f->type) {
+			t->radio = 0;
+		}
+		if (V4L2_TUNER_RADIO == f->type) {
+			if (!t->radio) {
+				set_tv_freq(client,400*16);
+				t->radio = 1;
+			}
+		}
+		t->freq  = f->frequency;
+		set_freq(client,t->freq);
+		break;
+	}
+	case VIDIOC_G_TUNER:
+	{
+		struct v4l2_tuner *tuner = arg;
+
+		SWITCH_V4L2;
+		if (t->radio)
+			tuner->signal = tuner_signal(client);
+		break;
 	}
 	default:
 		/* nothing */
diff -Nru a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
--- a/drivers/media/video/video-buf.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/media/video/video-buf.c	2004-06-23 19:04:27 -07:00
@@ -5,10 +5,10 @@
  * The functions expect the hardware being able to scatter gatter
  * (i.e. the buffers are not linear in physical memory, but fragmented
  * into PAGE_SIZE chunks).  They also assume the driver does not need
- * to touch the video data (thus it is probably not useful for USB as
- * data often must be uncompressed by the drivers).
+ * to touch the video data (thus it is probably not useful for USB 1.1
+ * as data often must be uncompressed by the drivers).
  * 
- * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
+ * (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
  *
  * This 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,6 +28,11 @@
 
 #include <media/video-buf.h>
 
+#define MAGIC_DMABUF 0x19721112
+#define MAGIC_BUFFER 0x20040302
+#define MAGIC_CHECK(is,should)	if (unlikely((is) != (should))) \
+	{ printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
+
 static int debug = 0;
 
 MODULE_DESCRIPTION("helper module to manage video4linux pci dma buffers");
@@ -109,6 +114,12 @@
 
 /* --------------------------------------------------------------------- */
 
+void videobuf_dma_init(struct videobuf_dmabuf *dma)
+{
+	memset(dma,0,sizeof(*dma));
+	dma->magic = MAGIC_DMABUF;
+}
+
 int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
 			   unsigned long data, unsigned long size)
 {
@@ -178,8 +189,8 @@
 
 int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
 {
-	if (0 == dma->nr_pages)
-		BUG();
+	MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+	BUG_ON(0 == dma->nr_pages);
 	
 	if (dma->pages) {
 		dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
@@ -211,8 +222,8 @@
 
 int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma)
 {
-	if (!dma->sglen)
-		BUG();
+	MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+	BUG_ON(!dma->sglen);
 
 	if (!dma->bus_addr)
 		pci_dma_sync_sg_for_cpu(dev,dma->sglist,dma->nr_pages,dma->direction);
@@ -221,6 +232,7 @@
 
 int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma)
 {
+	MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
 	if (!dma->sglen)
 		return 0;
 
@@ -234,8 +246,8 @@
 
 int videobuf_dma_free(struct videobuf_dmabuf *dma)
 {
-	if (dma->sglen)
-		BUG();
+	MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+	BUG_ON(dma->sglen);
 
 	if (dma->pages) {
 		int i;
@@ -264,7 +276,9 @@
 	vb = kmalloc(size,GFP_KERNEL);
 	if (NULL != vb) {
 		memset(vb,0,size);
+		videobuf_dma_init(&vb->dma);
 		init_waitqueue_head(&vb->done);
+		vb->magic     = MAGIC_BUFFER;
 	}
 	return vb;
 }
@@ -274,6 +288,7 @@
 	int retval = 0;
 	DECLARE_WAITQUEUE(wait, current);
 	
+	MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
 	add_wait_queue(&vb->done, &wait);
 	while (vb->state == STATE_ACTIVE || vb->state == STATE_QUEUED) {
 		if (non_blocking) {
@@ -302,6 +317,7 @@
 	int err,pages;
 	dma_addr_t bus;
 
+	MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
 	switch (vb->memory) {
 	case V4L2_MEMORY_MMAP:
 	case V4L2_MEMORY_USERPTR:
@@ -453,6 +469,8 @@
 videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb,
 		enum v4l2_buf_type type)
 {
+	MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
+
 	b->index    = vb->i;
 	b->type     = type;
 
@@ -491,6 +509,11 @@
 		break;
 	}
 
+	if (vb->input != UNSET) {
+		b->flags |= V4L2_BUF_FLAG_INPUT;
+		b->input  = vb->input;
+	}
+
 	b->field     = vb->field;
 	b->timestamp = vb->ts;
 	b->bytesused = vb->size;
@@ -513,6 +536,11 @@
 	    req->memory != V4L2_MEMORY_OVERLAY)
 		return -EINVAL;
 
+	if (q->streaming)
+		return -EBUSY;
+	if (!list_empty(&q->stream))
+		return -EBUSY;
+
 	down(&q->lock);
 	count = req->count;
 	if (count > VIDEO_MAX_FRAME)
@@ -568,12 +596,21 @@
 	buf = q->bufs[b->index];
 	if (NULL == buf)
 		goto done;
+	MAGIC_CHECK(buf->magic,MAGIC_BUFFER);
 	if (buf->memory != b->memory)
 		goto done;
 	if (buf->state == STATE_QUEUED ||
 	    buf->state == STATE_ACTIVE)
 		goto done;
 
+	if (b->flags & V4L2_BUF_FLAG_INPUT) {
+		if (b->input >= q->inputs)
+			goto done;
+		buf->input = b->input;
+	} else {
+		buf->input = UNSET;
+	}
+
 	switch (b->memory) {
 	case V4L2_MEMORY_MMAP:
 		if (0 == buf->baddr)
@@ -582,6 +619,8 @@
 	case V4L2_MEMORY_USERPTR:
 		if (b->length < buf->bsize)
 			goto done;
+		if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr)
+			q->ops->buf_release(file,buf);
 		buf->baddr = b->m.userptr;
 		break;
 	case V4L2_MEMORY_OVERLAY:
@@ -1075,6 +1114,7 @@
 	for (i = 0; i < bcount; i++) {
 		q->bufs[i] = videobuf_alloc(q->msize);
 		q->bufs[i]->i      = i;
+		q->bufs[i]->input  = UNSET;
 		q->bufs[i]->memory = memory;
 		q->bufs[i]->bsize  = bsize;
 		switch (memory) {
@@ -1085,7 +1125,7 @@
 		case V4L2_MEMORY_OVERLAY:
 			/* nothing */
 			break;
-		};
+		}
 	}
 	dprintk(1,"mmap setup: %d buffers, %d bytes each\n",
 		bcount,bsize);
@@ -1192,6 +1232,7 @@
 
 EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg);
 
+EXPORT_SYMBOL_GPL(videobuf_dma_init);
 EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
 EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
 EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay);
diff -Nru a/drivers/message/fusion/isense.c b/drivers/message/fusion/isense.c
--- a/drivers/message/fusion/isense.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/message/fusion/isense.c	2004-06-23 19:04:27 -07:00
@@ -56,14 +56,6 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <asm/io.h>
-#if defined (__sparc__)
-#include <linux/timer.h>
-#endif
-
-/* Hmmm, avoid undefined spinlock_t on lk-2.2.14-5.0 */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-#include <asm/spinlock.h>
-#endif
 
 #define MODULEAUTHOR "Steven J. Ralston"
 #define COPYRIGHT "Copyright (c) 2001-2004 " MODULEAUTHOR
diff -Nru a/drivers/message/fusion/linux_compat.h b/drivers/message/fusion/linux_compat.h
--- a/drivers/message/fusion/linux_compat.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/message/fusion/linux_compat.h	2004-06-23 19:04:26 -07:00
@@ -2,196 +2,7 @@
 
 #ifndef FUSION_LINUX_COMPAT_H
 #define FUSION_LINUX_COMPAT_H
-/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-#include <linux/version.h>
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-#ifndef rwlock_init
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-#endif
-
-#define SET_NICE(current,x) do {(current)->nice = (x);} while (0)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-#	if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
-		typedef unsigned int dma_addr_t;
-#	endif
-#else
-#	if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,42)
-		typedef unsigned int dma_addr_t;
-#	endif
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
-/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/* This block snipped from lk-2.2.18/include/linux/init.h { */
-/*
- * Used for initialization calls..
- */
-typedef int (*initcall_t)(void);
-typedef void (*exitcall_t)(void);
-
-#define __init_call	__attribute__ ((unused,__section__ (".initcall.init")))
-#define __exit_call	__attribute__ ((unused,__section__ (".exitcall.exit")))
-
-extern initcall_t __initcall_start, __initcall_end;
-
-#define __initcall(fn)								\
-	static initcall_t __initcall_##fn __init_call = fn
-#define __exitcall(fn)								\
-	static exitcall_t __exitcall_##fn __exit_call = fn
-
-#ifdef MODULE
-/* These macros create a dummy inline: gcc 2.9x does not count alias
- as usage, hence the `unused function' warning when __init functions
- are declared static. We use the dummy __*_module_inline functions
- both to kill the warning and check the type of the init/cleanup
- function. */
-typedef int (*__init_module_func_t)(void);
-typedef void (*__cleanup_module_func_t)(void);
-#define module_init(x) \
-	int init_module(void) __attribute__((alias(#x))); \
-	static inline __init_module_func_t __init_module_inline(void) \
-	{ return x; }
-#define module_exit(x) \
-	void cleanup_module(void) __attribute__((alias(#x))); \
-	static inline __cleanup_module_func_t __cleanup_module_inline(void) \
-	{ return x; }
-
-#else
-#define module_init(x)	__initcall(x);
-#define module_exit(x)	__exitcall(x);
-#endif
-/* } block snipped from lk-2.2.18/include/linux/init.h */
-
-/* This block snipped from lk-2.2.18/include/linux/sched.h { */
-/*
- * Used prior to schedule_timeout calls..
- */
-#define __set_current_state(state_value)	do { current->state = state_value; } while (0)
-#ifdef CONFIG_SMP
-#define set_current_state(state_value)		do { __set_current_state(state_value); mb(); } while (0)
-#else
-#define set_current_state(state_value)		__set_current_state(state_value)
-#endif
-/* } block snipped from lk-2.2.18/include/linux/sched.h */
-
-/* procfs compat stuff... */
-#define proc_mkdir(x,y)			create_proc_entry(x, S_IFDIR, y)
-
-/* MUTEX compat stuff... */
-#define DECLARE_MUTEX(name)		struct semaphore name=MUTEX
-#define DECLARE_MUTEX_LOCKED(name)	struct semaphore name=MUTEX_LOCKED
-#define init_MUTEX(x)			*(x)=MUTEX
-#define init_MUTEX_LOCKED(x)		*(x)=MUTEX_LOCKED
-
-/* Wait queues. */
-#define DECLARE_WAIT_QUEUE_HEAD(name)	\
-	struct wait_queue * (name) = NULL
-#define DECLARE_WAITQUEUE(name, task)	\
-	struct wait_queue (name) = { (task), NULL }
-
-#if defined(__sparc__) && defined(__sparc_v9__)
-/* The sparc64 ioremap implementation is wrong in 2.2.x,
- * but fixing it would break all of the drivers which
- * workaround it.  Fixed in 2.3.x onward. -DaveM
- */
-#define ARCH_IOREMAP(base)	((unsigned long) (base))
-#else
-#define ARCH_IOREMAP(base)	ioremap(base)
-#endif
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#else		/* LINUX_VERSION_CODE must be >= KERNEL_VERSION(2,2,18) */
-
-/* No ioremap bugs in >2.3.x kernels. */
-#define ARCH_IOREMAP(base)	ioremap(base)
-
-/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#endif		/* LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) */
-
-
-/*
- * Inclined to use:
- *   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
- * here, but MODULE_LICENSE defined in 2.4.9-6 and 2.4.9-13
- * breaks the rule:-(
- */
-#ifndef MODULE_LICENSE
-#define MODULE_LICENSE(license)
-#endif
-
-
-/* PCI/driver subsystem { */
-#define PCI_BASEADDR_FLAGS(idx)         resource[idx].flags
-#define PCI_BASEADDR_START(idx)         resource[idx].start
-#define PCI_BASEADDR_SIZE(dev,idx)      (dev)->resource[idx].end - (dev)->resource[idx].start + 1
-
-/* Compatability for the 2.3.x PCI DMA API. */
-#ifndef PCI_DMA_BIDIRECTIONAL
-/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-#define PCI_DMA_BIDIRECTIONAL	0
-#define PCI_DMA_TODEVICE	1
-#define PCI_DMA_FROMDEVICE	2
-#define PCI_DMA_NONE		3
-
-#ifdef __KERNEL__
-#include <asm/page.h>
-/* Pure 2^n version of get_order */
-static __inline__ int __get_order(unsigned long size)
-{
-	int order;
-
-	size = (size-1) >> (PAGE_SHIFT-1);
-	order = -1;
-	do {
-		size >>= 1;
-		order++;
-	} while (size);
-	return order;
-}
-#endif
-
-#define pci_alloc_consistent(hwdev, size, dma_handle) \
-({	void *__ret = (void *)__get_free_pages(GFP_ATOMIC, __get_order(size)); \
-	if (__ret != NULL) { \
-		memset(__ret, 0, size); \
-		*(dma_handle) = virt_to_bus(__ret); \
-	} \
-	__ret; \
-})
-
-#define pci_free_consistent(hwdev, size, vaddr, dma_handle) \
-	free_pages((unsigned long)vaddr, __get_order(size))
-
-#define pci_map_single(hwdev, ptr, size, direction) \
-	virt_to_bus(ptr);
-
-#define pci_unmap_single(hwdev, dma_addr, size, direction) \
-	do { /* Nothing to do */ } while (0)
-
-#define pci_map_sg(hwdev, sg, nents, direction)	(nents)
-#define pci_unmap_sg(hwdev, sg, nents, direction) \
-	do { /* Nothing to do */ } while(0)
-
-#define sg_dma_address(sg)	(virt_to_bus((sg)->address))
-#define sg_dma_len(sg)		((sg)->length)
-
-/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#endif /* PCI_DMA_BIDIRECTIONAL */
-
-
-#define mpt_work_struct work_struct
-#define MPT_INIT_WORK(_task, _func, _data) INIT_WORK(_task, _func, _data)
-#define mpt_sync_irq(_irq) synchronize_irq(_irq)
 
 /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #endif /* _LINUX_COMPAT_H */
-
diff -Nru a/drivers/message/fusion/lsi/mpi_type.h b/drivers/message/fusion/lsi/mpi_type.h
--- a/drivers/message/fusion/lsi/mpi_type.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/message/fusion/lsi/mpi_type.h	2004-06-23 19:04:27 -07:00
@@ -47,18 +47,13 @@
 typedef unsigned short  U16;
 
 
-#if defined(unix) || defined(__arm) || defined(ALPHA)
-
-    typedef signed   int   S32;
-    typedef unsigned int   U32;
-
-#else
-
-    typedef signed   long  S32;
-    typedef unsigned long  U32;
-
-#endif
+typedef int32_t   S32;
+typedef u_int32_t U32;
 
+/*
+ *  The only way crap below could work on big-endian boxen would be if it
+ *  wasn't used at all.
+ */
 
 typedef struct _S64
 {
diff -Nru a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
--- a/drivers/message/fusion/mptbase.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/message/fusion/mptbase.c	2004-06-23 19:04:26 -07:00
@@ -1311,14 +1311,14 @@
 	mem_phys = msize = 0;
 	port = psize = 0;
 	for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
-		if (pdev->PCI_BASEADDR_FLAGS(ii) & PCI_BASE_ADDRESS_SPACE_IO) {
+		if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
 			/* Get I/O space! */
-			port = pdev->PCI_BASEADDR_START(ii);
-			psize = PCI_BASEADDR_SIZE(pdev,ii);
+			port = pci_resource_start(pdev, ii);
+			psize = pci_resource_len(pdev,ii);
 		} else {
 			/* Get memmap */
-			mem_phys = pdev->PCI_BASEADDR_START(ii);
-			msize = PCI_BASEADDR_SIZE(pdev,ii);
+			mem_phys = pci_resource_start(pdev, ii);
+			msize = pci_resource_len(pdev,ii);
 			break;
 		}
 	}
@@ -1524,7 +1524,7 @@
 	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
 
 	ioc->active = 0;
-	mpt_sync_irq(pdev->irq);
+	synchronize_irq(pdev->irq);
 
 	/* Clear any lingering interrupt */
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
@@ -3799,7 +3799,8 @@
 
 		/*  Prime reply FIFO...  */
 		dprintk((KERN_INFO MYNAM ": %s.reply_alloc  @ %p[%p], sz=%d bytes\n",
-			 	ioc->name, mem, (void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz));
+			ioc->name, ioc->reply_alloc, 
+			(void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz));
 
 		b = (unsigned long) ioc->reply_alloc;
 		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
@@ -3812,7 +3813,8 @@
 	
 		/*  Request FIFO - WE manage this!  */
 		dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%p], sz=%d bytes\n",
-			 	ioc->name, mem, (void *)(ulong)ioc->req_alloc_dma, request_buffer_sz));
+			ioc->name, ioc->req_alloc,
+			(void *)(ulong)ioc->req_alloc_dma, request_buffer_sz));
 
 		b = (unsigned long) ioc->req_alloc;
 		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
diff -Nru a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
--- a/drivers/message/fusion/mptbase.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/message/fusion/mptbase.h	2004-06-23 19:04:25 -07:00
@@ -55,7 +55,11 @@
 #define MPTBASE_H_INCLUDED
 /*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-#include "linux_compat.h"	/* linux-2.2.x (vs. -2.4.x) tweaks */
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
 #include "scsi3.h"		/* SCSI defines */
 
 #include "lsi/mpi_type.h"
@@ -81,8 +85,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2004 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.01.06"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.06"
+#define MPT_LINUX_VERSION_COMMON	"3.01.07"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.07"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
--- a/drivers/message/fusion/mptctl.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/message/fusion/mptctl.c	2004-06-23 19:04:25 -07:00
@@ -83,6 +83,7 @@
 #include <linux/pci.h>
 #include <linux/miscdevice.h>
 #include <linux/smp_lock.h>
+#include <linux/compat.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -102,9 +103,6 @@
 #define my_VERSION	MPT_LINUX_VERSION_COMMON
 #define MYNAM		"mptctl"
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,62)
-EXPORT_NO_SYMBOLS;
-#endif
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
@@ -144,8 +142,8 @@
 /*
  * Private function calls.
  */
-static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local);
-static int mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen);
+static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr);
+static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
 static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frags,
 		struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
 static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
@@ -547,38 +545,6 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *  struct file_operations functionality.
- *  Members:
- *	llseek, write, read, ioctl, open, release
- */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9)
-static loff_t
-mptctl_llseek(struct file *file, loff_t offset, int origin)
-{
-	return -ESPIPE;
-}
-#define no_llseek mptctl_llseek
-#endif
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static ssize_t
-mptctl_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-	printk(KERN_ERR MYNAM ": ioctl WRITE not yet supported\n");
-	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static ssize_t
-mptctl_read(struct file *file, char *buf, size_t count, loff_t *ptr)
-{
-	printk(KERN_ERR MYNAM ": ioctl READ not yet supported\n");
-	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
  *  MPT ioctl handler
  *  cmd - specify the particular IOCTL command to be issued
  *  arg - data specific to the command. Must not be null.
@@ -586,7 +552,7 @@
 static int
 mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	mpt_ioctl_header	*uhdr = (mpt_ioctl_header *) arg;
+	mpt_ioctl_header __user *uhdr = (void __user *) arg;
 	mpt_ioctl_header	 khdr;
 	int iocnum;
 	unsigned iocnumX;
@@ -599,7 +565,7 @@
 	if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
 		printk(KERN_ERR "%s::mptctl_ioctl() @%d - "
 				"Unable to copy mpt_ioctl_header data @ %p\n",
-				__FILE__, __LINE__, (void*)uhdr);
+				__FILE__, __LINE__, uhdr);
 		return -EFAULT;
 	}
 	ret = -ENXIO;				/* (-6) No such device or address */
@@ -671,7 +637,7 @@
 
 static int mptctl_do_reset(unsigned long arg)
 {
-	struct mpt_ioctl_diag_reset *urinfo = (struct mpt_ioctl_diag_reset *) arg;
+	struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
 	struct mpt_ioctl_diag_reset krinfo;
 	MPT_ADAPTER		*iocp;
 
@@ -680,7 +646,7 @@
 	if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
 		printk(KERN_ERR "%s@%d::mptctl_do_reset - "
 				"Unable to copy mpt_ioctl_diag_reset struct @ %p\n",
-				__FILE__, __LINE__, (void*)urinfo);
+				__FILE__, __LINE__, urinfo);
 		return -EFAULT;
 	}
 
@@ -700,21 +666,6 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int mptctl_open(struct inode *inode, struct file *file)
-{
-	/*
-	 * Should support multiple management users
-	 */
-	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int mptctl_release(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  * MPT FW download function.  Cast the arg into the mpt_fw_xfer structure.
  * This structure contains: iocnum, firmware length (bytes),
@@ -734,14 +685,14 @@
 static int
 mptctl_fw_download(unsigned long arg)
 {
-	struct mpt_fw_xfer	*ufwdl = (struct mpt_fw_xfer *) arg;
+	struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
 	struct mpt_fw_xfer	 kfwdl;
 
 	dctlprintk((KERN_INFO "mptctl_fwdl called. mptctl_id = %xh\n", mptctl_id)); //tc
 	if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) {
 		printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
 				"Unable to copy mpt_fw_xfer struct @ %p\n",
-				__FILE__, __LINE__, (void*)ufwdl);
+				__FILE__, __LINE__, ufwdl);
 		return -EFAULT;
 	}
 
@@ -763,7 +714,7 @@
  *		-ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
+mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
 {
 	FWDownload_t		*dlmsg;
 	MPT_FRAME_HDR		*mf;
@@ -892,7 +843,7 @@
 			if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
 				printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
 						"Unable to copy f/w buffer hunk#%d @ %p\n",
-						__FILE__, __LINE__, n, (void*)ufwbuf);
+						__FILE__, __LINE__, n, ufwbuf);
 				goto fwdl_out;
 			}
 			fw_bytes_copied += bl->len;
@@ -1198,7 +1149,7 @@
 static int
 mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 {
-	struct mpt_ioctl_iocinfo *uarg = (struct mpt_ioctl_iocinfo *) arg;
+	struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_iocinfo *karg;
 	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
@@ -1238,7 +1189,7 @@
 	if (copy_from_user(karg, uarg, data_size)) {
 		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
 			"Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		kfree(karg);
 		return -EFAULT;
 	}
@@ -1278,10 +1229,8 @@
 	karg->pciId = pdev->device;
 	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
 	karg->hwRev = revision;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	karg->subSystemDevice = pdev->subsystem_device;
 	karg->subSystemVendor = pdev->subsystem_vendor;
-#endif
 
 	if (cim_rev == 1) {
 		/* Get the PCI bus, device, and function numbers for the IOC
@@ -1335,10 +1284,10 @@
 
 	/* Copy the data from kernel memory to user memory
 	 */
-	if (copy_to_user((char *)arg, karg, data_size)) {
+	if (copy_to_user((char __user *)arg, karg, data_size)) {
 		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
 			"Unable to write out mpt_ioctl_iocinfo struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		kfree(karg);
 		return -EFAULT;
 	}
@@ -1360,7 +1309,7 @@
 static int
 mptctl_gettargetinfo (unsigned long arg)
 {
-	struct mpt_ioctl_targetinfo *uarg = (struct mpt_ioctl_targetinfo *) arg;
+	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_targetinfo karg;
 	MPT_ADAPTER		*ioc;
 	struct Scsi_Host	*sh;
@@ -1382,7 +1331,7 @@
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
 		printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
 			"Unable to read in mpt_ioctl_targetinfo struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -1500,21 +1449,21 @@
 
 	/* Copy part of the data from kernel memory to user memory
 	 */
-	if (copy_to_user((char *)arg, &karg,
+	if (copy_to_user((char __user *)arg, &karg,
 				sizeof(struct mpt_ioctl_targetinfo))) {
 		printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
 			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		kfree(pmem);
 		return -EFAULT;
 	}
 
 	/* Copy the remaining data from kernel memory to user memory
 	 */
-	if (copy_to_user((char *) uarg->targetInfo, pmem, numBytes)) {
+	if (copy_to_user(uarg->targetInfo, pmem, numBytes)) {
 		printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
 			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-				__FILE__, __LINE__, (void*)pdata);
+				__FILE__, __LINE__, pdata);
 		kfree(pmem);
 		return -EFAULT;
 	}
@@ -1535,7 +1484,7 @@
 static int
 mptctl_readtest (unsigned long arg)
 {
-	struct mpt_ioctl_test	*uarg = (struct mpt_ioctl_test *) arg;
+	struct mpt_ioctl_test __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_test	 karg;
 	MPT_ADAPTER *ioc;
 	int iocnum;
@@ -1544,7 +1493,7 @@
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
 		printk(KERN_ERR "%s@%d::mptctl_readtest - "
 			"Unable to read in mpt_ioctl_test struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -1571,10 +1520,10 @@
 
 	/* Copy the data from kernel memory to user memory
 	 */
-	if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
+	if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
 		printk(KERN_ERR "%s@%d::mptctl_readtest - "
 			"Unable to write out mpt_ioctl_test struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -1595,7 +1544,7 @@
 static int
 mptctl_eventquery (unsigned long arg)
 {
-	struct mpt_ioctl_eventquery	*uarg = (struct mpt_ioctl_eventquery *) arg;
+	struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventquery	 karg;
 	MPT_ADAPTER *ioc;
 	int iocnum;
@@ -1604,7 +1553,7 @@
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
 		printk(KERN_ERR "%s@%d::mptctl_eventquery - "
 			"Unable to read in mpt_ioctl_eventquery struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -1620,10 +1569,10 @@
 
 	/* Copy the data from kernel memory to user memory
 	 */
-	if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
+	if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
 		printk(KERN_ERR "%s@%d::mptctl_eventquery - "
 			"Unable to write out mpt_ioctl_eventquery struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 	return 0;
@@ -1633,7 +1582,7 @@
 static int
 mptctl_eventenable (unsigned long arg)
 {
-	struct mpt_ioctl_eventenable	*uarg = (struct mpt_ioctl_eventenable *) arg;
+	struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventenable	 karg;
 	MPT_ADAPTER *ioc;
 	int iocnum;
@@ -1642,7 +1591,7 @@
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
 		printk(KERN_ERR "%s@%d::mptctl_eventenable - "
 			"Unable to read in mpt_ioctl_eventenable struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -1680,7 +1629,7 @@
 static int
 mptctl_eventreport (unsigned long arg)
 {
-	struct mpt_ioctl_eventreport	*uarg = (struct mpt_ioctl_eventreport *) arg;
+	struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventreport	 karg;
 	MPT_ADAPTER		 *ioc;
 	int			 iocnum;
@@ -1690,7 +1639,7 @@
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
 		printk(KERN_ERR "%s@%d::mptctl_eventreport - "
 			"Unable to read in mpt_ioctl_eventreport struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -1716,10 +1665,10 @@
 	/* Copy the data from kernel memory to user memory
 	 */
 	numBytes = max * sizeof(MPT_IOCTL_EVENTS);
-	if (copy_to_user((char *) uarg->eventData, ioc->events, numBytes)) {
+	if (copy_to_user(uarg->eventData, ioc->events, numBytes)) {
 		printk(KERN_ERR "%s@%d::mptctl_eventreport - "
 			"Unable to write out mpt_ioctl_eventreport struct @ %p\n",
-				__FILE__, __LINE__, (void*)ioc->events);
+				__FILE__, __LINE__, ioc->events);
 		return -EFAULT;
 	}
 
@@ -1730,7 +1679,7 @@
 static int
 mptctl_replace_fw (unsigned long arg)
 {
-	struct mpt_ioctl_replace_fw	*uarg = (struct mpt_ioctl_replace_fw *) arg;
+	struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_replace_fw	 karg;
 	MPT_ADAPTER		 *ioc;
 	fw_image_t		 **fwmem = NULL;
@@ -1744,7 +1693,7 @@
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
 		printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
 			"Unable to read in mpt_ioctl_replace_fw struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -1774,7 +1723,7 @@
 		if (copy_from_user(fwmem[ii]->fw, uarg->newImage + offset, fwmem[ii]->size)) {
 			printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
 				"Unable to read in mpt_ioctl_replace_fw image @ %p\n",
-					__FILE__, __LINE__, (void*)uarg);
+					__FILE__, __LINE__, uarg);
 
 			mpt_free_fw_memory(ioc, fwmem);
 			return -EFAULT;
@@ -1819,7 +1768,7 @@
 static int
 mptctl_mpt_command (unsigned long arg)
 {
-	struct mpt_ioctl_command *uarg = (struct mpt_ioctl_command *) arg;
+	struct mpt_ioctl_command __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_command  karg;
 	MPT_ADAPTER	*ioc;
 	int		iocnum;
@@ -1830,7 +1779,7 @@
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) {
 		printk(KERN_ERR "%s@%d::mptctl_mpt_command - "
 			"Unable to read in mpt_ioctl_command struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -1841,7 +1790,7 @@
 		return -ENODEV;
 	}
 
-	rc = mptctl_do_mpt_command (karg, (char *) &uarg->MF, 0);
+	rc = mptctl_do_mpt_command (karg, &uarg->MF);
 
 	return rc;
 }
@@ -1859,7 +1808,7 @@
  *		-EPERM if SCSI I/O and target is untagged
  */
 static int
-mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
+mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 {
 	MPT_ADAPTER	*ioc;
 	MPT_FRAME_HDR	*mf = NULL;
@@ -1923,23 +1872,15 @@
 
 	/* Copy the request frame
 	 * Reset the saved message context.
+	 * Request frame in user space
 	 */
-        if (local) {
-		/* Request frame in kernel space
-		 */
-		memcpy((char *)mf, (char *) mfPtr, karg.dataSgeOffset * 4);
-        } else {
-		/* Request frame in user space
-		 */
-		if (copy_from_user((char *)mf, (char *) mfPtr,
-					karg.dataSgeOffset * 4)){
-			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
-				"Unable to read MF from mpt_ioctl_command struct @ %p\n",
-				__FILE__, __LINE__, (void*)mfPtr);
-			rc = -EFAULT;
-			goto done_free_mem;
-		}
-        }
+	if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) {
+		printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+			"Unable to read MF from mpt_ioctl_command struct @ %p\n",
+			__FILE__, __LINE__, mfPtr);
+		rc = -EFAULT;
+		goto done_free_mem;
+	}
 	hdr->MsgContext = cpu_to_le32(msgContext);
 
 
@@ -2220,7 +2161,7 @@
 						"%s@%d::mptctl_do_mpt_command - Unable "
 						"to read user data "
 						"struct @ %p\n",
-						__FILE__, __LINE__,(void*)karg.dataOutBufPtr);
+						__FILE__, __LINE__,karg.dataOutBufPtr);
 					rc =  -EFAULT;
 					goto done_free_mem;
 				}
@@ -2321,12 +2262,12 @@
 			}
 
 			if (sz > 0) {
-				if (copy_to_user((char *)karg.replyFrameBufPtr,
+				if (copy_to_user(karg.replyFrameBufPtr,
 					 &ioc->ioctl->ReplyFrame, sz)){
 
 					 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
 					 "Unable to write out reply frame %p\n",
-					 __FILE__, __LINE__, (void*)karg.replyFrameBufPtr);
+					 __FILE__, __LINE__, karg.replyFrameBufPtr);
 					 rc =  -ENODATA;
 					 goto done_free_mem;
 				}
@@ -2338,11 +2279,11 @@
 		if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
 			sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
 			if (sz > 0) {
-				if (copy_to_user((char *)karg.senseDataPtr, ioc->ioctl->sense, sz)) {
+				if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
 					printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
 					"Unable to write sense data to user %p\n",
 					__FILE__, __LINE__,
-					(void*)karg.senseDataPtr);
+					karg.senseDataPtr);
 					rc =  -ENODATA;
 					goto done_free_mem;
 				}
@@ -2355,12 +2296,12 @@
 		if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
 					(karg.dataInSize > 0) && (bufIn.kptr)) {
 
-			if (copy_to_user((char *)karg.dataInBufPtr,
+			if (copy_to_user(karg.dataInBufPtr,
 					 bufIn.kptr, karg.dataInSize)) {
 				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
 					"Unable to write data to user %p\n",
 					__FILE__, __LINE__,
-					(void*)karg.dataInBufPtr);
+					karg.dataInBufPtr);
 				rc =  -ENODATA;
 			}
 		}
@@ -2413,7 +2354,7 @@
 static int
 mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 {
-	hp_host_info_t	*uarg = (hp_host_info_t *) arg;
+	hp_host_info_t	__user *uarg = (void __user *) arg;
 	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
 	char			*pbuf;
@@ -2437,7 +2378,7 @@
 	if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
 		printk(KERN_ERR "%s@%d::mptctl_hp_host_info - "
 			"Unable to read in hp_host_info struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -2455,10 +2396,8 @@
 
 	karg.vendor = pdev->vendor;
 	karg.device = pdev->device;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	karg.subsystem_id = pdev->subsystem_device;
 	karg.subsystem_vendor = pdev->subsystem_vendor;
-#endif
 	karg.devfn = pdev->devfn;
 	karg.bus = pdev->bus->number;
 
@@ -2540,7 +2479,7 @@
 		break;
 	}
 
-	karg.base_io_addr = pdev->PCI_BASEADDR_START(0);
+	karg.base_io_addr = pci_resource_start(pdev, 0);
 
 	if ((int)ioc->chip_type <= (int) FC929)
 		karg.bus_phys_width = HP_BUS_WIDTH_UNK;
@@ -2576,11 +2515,10 @@
 
 	/* Copy the data from kernel memory to user memory
 	 */
-	if (copy_to_user((char *)arg, &karg,
-				sizeof(hp_host_info_t))) {
+	if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
 		printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - "
 			"Unable to write out hp_host_info @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -2602,7 +2540,7 @@
 static int
 mptctl_hp_targetinfo(unsigned long arg)
 {
-	hp_target_info_t	*uarg = (hp_target_info_t *) arg;
+	hp_target_info_t __user *uarg = (void __user *) arg;
 	SCSIDevicePage0_t	*pg0_alloc;
 	SCSIDevicePage3_t	*pg3_alloc;
 	MPT_ADAPTER		*ioc;
@@ -2619,7 +2557,7 @@
 	if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) {
 		printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - "
 			"Unable to read in hp_host_targetinfo struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 	
@@ -2727,10 +2665,10 @@
 
 	/* Copy the data from kernel memory to user memory
 	 */
-	if (copy_to_user((char *)arg, &karg, sizeof(hp_target_info_t))) {
+	if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) {
 		printk(KERN_ERR "%s@%d::mptctl_hp_target_info - "
 			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
+				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
 
@@ -2739,20 +2677,10 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51)
-#define	owner_THIS_MODULE  .owner = THIS_MODULE,
-#else
-#define	owner_THIS_MODULE
-#endif
-
 static struct file_operations mptctl_fops = {
-	owner_THIS_MODULE
+	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
-	.read =		mptctl_read,
-	.write =	mptctl_write,
 	.ioctl =	mptctl_ioctl,
-	.open =		mptctl_open,
-	.release =	mptctl_release,
 };
 
 static struct miscdevice mptctl_miscdev = {
@@ -2800,7 +2728,7 @@
 
 	dctlprintk((KERN_INFO MYNAM "::compat_mptfwxfer_ioctl() called\n"));
 
-	if (copy_from_user(&kfw32, (char *)arg, sizeof(kfw32)))
+	if (copy_from_user(&kfw32, (char __user *)arg, sizeof(kfw32)))
 		return -EFAULT;
 
 	/* Verify intended MPT adapter */
@@ -2817,7 +2745,7 @@
 
 	kfw.iocnum = iocnum;
 	kfw.fwlen = kfw32.fwlen;
-	kfw.bufp = (void *)(unsigned long)kfw32.bufp;
+	kfw.bufp = compat_ptr(kfw32.bufp);
 
 	ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
 
@@ -2831,7 +2759,7 @@
 			unsigned long arg, struct file *filp)
 {
 	struct mpt_ioctl_command32 karg32;
-	struct mpt_ioctl_command32 *uarg = (struct mpt_ioctl_command32 *) arg;
+	struct mpt_ioctl_command32 __user *uarg = (struct mpt_ioctl_command32 __user *) arg;
 	struct mpt_ioctl_command karg;
 	MPT_ADAPTER *iocp = NULL;
 	int iocnum, iocnumX;
@@ -2840,7 +2768,7 @@
 
 	dctlprintk((KERN_INFO MYNAM "::compat_mpt_command() called\n"));
 
-	if (copy_from_user(&karg32, (char *)arg, sizeof(karg32)))
+	if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32)))
 		return -EFAULT;
 
 	/* Verify intended MPT adapter */
@@ -2866,14 +2794,14 @@
 	karg.maxSenseBytes = karg32.maxSenseBytes;
 	karg.dataSgeOffset = karg32.dataSgeOffset;
 
-	karg.replyFrameBufPtr = (char *)(unsigned long)karg32.replyFrameBufPtr;
-	karg.dataInBufPtr = (char *)(unsigned long)karg32.dataInBufPtr;
-	karg.dataOutBufPtr = (char *)(unsigned long)karg32.dataOutBufPtr;
-	karg.senseDataPtr = (char *)(unsigned long)karg32.senseDataPtr;
+	karg.replyFrameBufPtr = (char __user *)(unsigned long)karg32.replyFrameBufPtr;
+	karg.dataInBufPtr = (char __user *)(unsigned long)karg32.dataInBufPtr;
+	karg.dataOutBufPtr = (char __user *)(unsigned long)karg32.dataOutBufPtr;
+	karg.senseDataPtr = (char __user *)(unsigned long)karg32.senseDataPtr;
 
 	/* Pass new structure to do_mpt_command
 	 */
-	ret = mptctl_do_mpt_command (karg, (char *) &uarg->MF, 0);
+	ret = mptctl_do_mpt_command (karg, &uarg->MF);
 
 	up(&mptctl_syscall_sem_ioc[iocp->id]);
 
diff -Nru a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
--- a/drivers/message/fusion/mptctl.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/message/fusion/mptctl.h	2004-06-23 19:04:27 -07:00
@@ -115,7 +115,7 @@
 struct mpt_fw_xfer {
 	unsigned int	 iocnum;	/* IOC unit number */
 	unsigned int	 fwlen;
-	void		*bufp;		/* Pointer to firmware buffer */
+	void		__user *bufp;	/* Pointer to firmware buffer */
 };
 
 #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
@@ -332,10 +332,10 @@
 struct mpt_ioctl_command {
 	mpt_ioctl_header hdr;
 	int		timeout;	/* optional (seconds) */
-	char		*replyFrameBufPtr;
-	char		*dataInBufPtr;
-	char		*dataOutBufPtr;
-	char		*senseDataPtr;
+	char		__user *replyFrameBufPtr;
+	char		__user *dataInBufPtr;
+	char		__user *dataOutBufPtr;
+	char		__user *senseDataPtr;
 	int		maxReplyBytes;
 	int		dataInSize;
 	int		dataOutSize;
diff -Nru a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
--- a/drivers/message/fusion/mptlan.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/message/fusion/mptlan.c	2004-06-23 19:04:27 -07:00
@@ -133,7 +133,7 @@
 	u32 total_received;
 	struct net_device_stats stats;	/* Per device statistics */
 
-	struct mpt_work_struct post_buckets_task;
+	struct work_struct post_buckets_task;
 	unsigned long post_buckets_active;
 };
 
@@ -880,18 +880,9 @@
 	
 	if (test_and_set_bit(0, &priv->post_buckets_active) == 0) {
 		if (priority) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41)
 			schedule_work(&priv->post_buckets_task);
-#else
-			queue_task(&priv->post_buckets_task, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
-#endif
 		} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41)
 			schedule_delayed_work(&priv->post_buckets_task, 1);
-#else
-			queue_task(&priv->post_buckets_task, &tq_timer);
-#endif
 			dioprintk((KERN_INFO MYNAM ": post_buckets queued on "
 				   "timer.\n"));
 		}
@@ -1391,8 +1382,8 @@
 	priv->mpt_dev = mpt_dev;
 	priv->pnum = pnum;
 
-	memset(&priv->post_buckets_task, 0, sizeof(struct mpt_work_struct));
-	MPT_INIT_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets, dev);
+	memset(&priv->post_buckets_task, 0, sizeof(struct work_struct));
+	INIT_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets, dev);
 	priv->post_buckets_active = 0;
 
 	dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n",
@@ -1566,10 +1557,6 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,59)
-MODULE_PARM(tx_max_out_p, "i");
-MODULE_PARM(max_buckets_out, "i"); // Debug stuff. FIXME!
-#endif
 
 module_init(mpt_lan_init);
 module_exit(mpt_lan_exit);
diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
--- a/drivers/message/fusion/mptscsih.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/message/fusion/mptscsih.c	2004-06-23 19:04:29 -07:00
@@ -74,6 +74,8 @@
 #include <linux/delay.h>	/* for mdelay */
 #include <linux/interrupt.h>	/* needed for in_interrupt() proto */
 #include <linux/reboot.h>	/* notifier code */
+#include <linux/sched.h>
+#include <linux/workqueue.h>
 #include "../../scsi/scsi.h"
 #include <scsi/scsi_host.h>
 
@@ -185,7 +187,7 @@
 static int	mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
 static int	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
 
-static struct mpt_work_struct   mptscsih_rstTask;
+static struct work_struct   mptscsih_rstTask;
 
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 static int	mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
@@ -231,7 +233,7 @@
 static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
 static int dvtaskQ_active = 0;
 static int dvtaskQ_release = 0;
-static struct mpt_work_struct	mptscsih_dvTask;
+static struct work_struct	mptscsih_dvTask;
 #endif
 
 /*
@@ -249,31 +251,7 @@
 static Scsi_Cmnd *foo_to[8];
 #endif
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/* see mptscsih.h */
-
-static struct scsi_host_template driver_template = {
-	.proc_name			= "mptscsih",
-	.proc_info			= x_scsi_proc_info,
-	.name				= "MPT SCSI Host",
-	.info				= x_scsi_info,
-	.queuecommand			= x_scsi_queuecommand,
-	.slave_alloc			= x_scsi_slave_alloc,
-	.slave_configure		= x_scsi_slave_configure,
-	.slave_destroy			= x_scsi_slave_destroy,
-	.eh_abort_handler		= x_scsi_abort,
-	.eh_device_reset_handler	= x_scsi_dev_reset,
-	.eh_bus_reset_handler		= x_scsi_bus_reset,
-	.eh_host_reset_handler		= x_scsi_host_reset,
-	.bios_param			= x_scsi_bios_param,
-	.can_queue			= MPT_SCSI_CAN_QUEUE,
-	.this_id			= -1,
-	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
-	.max_sectors			= MPT_SCSI_MAX_SECTORS,
-	.cmd_per_lun			= MPT_SCSI_CMD_PER_LUN,
-	.use_clustering			= ENABLE_CLUSTERING,
-};
+static struct scsi_host_template driver_template;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -1459,7 +1437,6 @@
 	}
 		
 	sh->max_lun = MPT_LAST_LUN + 1;
-	sh->max_sectors = MPT_SCSI_MAX_SECTORS;
 	sh->max_channel = 0;
 	sh->this_id = ioc->pfacts[0].PortSCSIID;
 		
@@ -1800,8 +1777,8 @@
 		}
 
 		dprintk((MYIOC_s_INFO_FMT
-		  "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",
-		  hd->ioc->name, sz1, szchain, sz3, sztarget));
+		  "Free'd ScsiLookup (%d) Target (%d+%d) memory\n",
+		  hd->ioc->name, sz1, sz3, sztarget));
 		dprintk(("Free'd done and free Q (%d) memory\n", szQ));
 
 		/* NULL the Scsi_Host pointer
@@ -1879,9 +1856,9 @@
 	if (!dvtaskQ_active) {
 		dvtaskQ_active = 1;
 		spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-		MPT_INIT_WORK(&mptscsih_dvTask,
+		INIT_WORK(&mptscsih_dvTask,
 		  mptscsih_domainValidation, (void *) hd);
-		SCHEDULE_TASK(&mptscsih_dvTask);
+		schedule_work(&mptscsih_dvTask);
 	} else {
 		spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
 	}
@@ -1902,7 +1879,6 @@
 #endif
 };
 
-
 /*  SCSI host fops start here...  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -2434,9 +2410,9 @@
 					if (!dvtaskQ_active) {
 						dvtaskQ_active = 1;
 						spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-						MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
+						INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
 
-						SCHEDULE_TASK(&mptscsih_dvTask);
+						schedule_work(&mptscsih_dvTask);
 					} else {
 						spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
 					}
@@ -3905,6 +3881,29 @@
 	return 1;		/* currently means nothing really */
 }
 
+static struct scsi_host_template driver_template = {
+	.proc_name			= "mptscsih",
+	.proc_info			= mptscsih_proc_info,
+	.name				= "MPT SCSI Host",
+	.info				= mptscsih_info,
+	.queuecommand			= mptscsih_qcmd,
+	.slave_alloc			= mptscsih_slave_alloc,
+	.slave_configure		= mptscsih_slave_configure,
+	.slave_destroy			= mptscsih_slave_destroy,
+	.eh_abort_handler		= mptscsih_abort,
+	.eh_device_reset_handler	= mptscsih_dev_reset,
+	.eh_bus_reset_handler		= mptscsih_bus_reset,
+	.eh_host_reset_handler		= mptscsih_host_reset,
+	.bios_param			= mptscsih_bios_param,
+	.can_queue			= MPT_SCSI_CAN_QUEUE,
+	.this_id			= -1,
+	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
+	.max_sectors			= 8192,
+	.cmd_per_lun			= 7,
+	.use_clustering			= ENABLE_CLUSTERING,
+};
+
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  Private data...
@@ -4950,8 +4949,8 @@
 	/* Call the reset handler. Already had a TM request
 	 * timeout - so issue a diagnostic reset
 	 */
-	MPT_INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
-	SCHEDULE_TASK(&mptscsih_rstTask);
+	INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
+	schedule_work(&mptscsih_rstTask);
 	return;
 }
 
diff -Nru a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
--- a/drivers/message/fusion/mptscsih.h	2004-06-23 19:04:29 -07:00
+++ b/drivers/message/fusion/mptscsih.h	2004-06-23 19:04:29 -07:00
@@ -108,75 +108,4 @@
         MPTSCSIH_SAF_TE,                        \
 }
 
-
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	Various bits and pieces broke within the lk-2.4.0-testN series:-(
- *	So here are various HACKS to work around them.
- */
-
-/*
- *	tq_scheduler disappeared @ lk-2.4.0-test12
- *	(right when <linux/sched.h> newly defined TQ_ACTIVE)
- *	tq_struct reworked in 2.5.41. Include workqueue.h.
- */
-#	include <linux/sched.h>
-#	include <linux/workqueue.h>
-#define SCHEDULE_TASK(x)		\
-	if (schedule_work(x) == 0) {	\
-		/*MOD_DEC_USE_COUNT*/;	\
-	}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-#define x_scsi_info		mptscsih_info
-#define x_scsi_queuecommand	mptscsih_qcmd
-#define x_scsi_abort		mptscsih_abort
-#define x_scsi_bus_reset	mptscsih_bus_reset
-#define x_scsi_dev_reset	mptscsih_dev_reset
-#define x_scsi_host_reset	mptscsih_host_reset
-#define x_scsi_bios_param	mptscsih_bios_param
-
-#define x_scsi_slave_alloc	mptscsih_slave_alloc
-#define x_scsi_slave_configure	mptscsih_slave_configure
-#define x_scsi_slave_destroy	mptscsih_slave_destroy
-#define x_scsi_proc_info	mptscsih_proc_info
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	MPT SCSI Host / Initiator decls...
- */
-extern	const char	*x_scsi_info(struct Scsi_Host *);
-extern	int		 x_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern	int		 x_scsi_abort(Scsi_Cmnd *);
-extern	int		 x_scsi_bus_reset(Scsi_Cmnd *);
-extern	int		 x_scsi_dev_reset(Scsi_Cmnd *);
-extern	int		 x_scsi_host_reset(Scsi_Cmnd *);
-extern int		 x_scsi_bios_param(struct scsi_device * sdev, struct block_device *bdev,
-				sector_t capacity, int geom[]);
-extern	int		 x_scsi_slave_alloc(Scsi_Device *);
-extern	int		 x_scsi_slave_configure(Scsi_Device *);
-extern	void		 x_scsi_slave_destroy(Scsi_Device *);
-extern	int		 x_scsi_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/*  include/scsi/scsi.h may not be quite complete...  */
-#ifndef RESERVE_10
-#define RESERVE_10		0x56
 #endif
-#ifndef RELEASE_10
-#define RELEASE_10		0x57
-#endif
-#ifndef PERSISTENT_RESERVE_IN
-#define PERSISTENT_RESERVE_IN	0x5e
-#endif
-#ifndef PERSISTENT_RESERVE_OUT
-#define PERSISTENT_RESERVE_OUT	0x5f
-#endif
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-#endif
-
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/message/i2o/i2o_block.c	2004-06-23 19:04:28 -07:00
@@ -280,8 +280,8 @@
 {
 	struct i2o_controller *c = dev->controller;
 	int tid = dev->tid;
-	unsigned long msg;
-	unsigned long mptr;
+	void *msg;
+	void *mptr;
 	u64 offset;
 	struct request *req = ireq->req;
 	int count = req->nr_sectors<<9;
@@ -291,7 +291,7 @@
 
 	// printk(KERN_INFO "i2ob_send called\n");
 	/* Map the message to a virtual address */
-	msg = c->mem_offset + m;
+	msg = c->msg_virt + m;
 	
 	sgnum = i2ob_build_sglist(dev, ireq);
 	
@@ -479,7 +479,7 @@
 		/* Now flush the message by making it a NOP */
 		m[0]&=0x00FFFFFF;
 		m[0]|=(I2O_CMD_UTIL_NOP)<<24;
-		i2o_post_message(c, ((unsigned long)m) - c->mem_offset);
+		i2o_post_message(c, (unsigned long) m - (unsigned long) c->msg_virt);
 
 		return;
 	}
diff -Nru a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
--- a/drivers/message/i2o/i2o_config.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/message/i2o/i2o_config.c	2004-06-23 19:04:28 -07:00
@@ -97,7 +97,7 @@
 	u32 *msg = (u32 *)m;
 
 	if (msg[0] & MSG_FAIL) {
-		u32 *preserved_msg = (u32*)(c->mem_offset + msg[7]);
+		u32 *preserved_msg = (u32*)(c->msg_virt + msg[7]);
 
 		printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n");
 
diff -Nru a/drivers/message/i2o/i2o_core.c b/drivers/message/i2o/i2o_core.c
--- a/drivers/message/i2o/i2o_core.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/message/i2o/i2o_core.c	2004-06-23 19:04:27 -07:00
@@ -354,7 +354,7 @@
 
 	if (msg[0] & MSG_FAIL) // Fail bit is set
 	{
-		u32 *preserved_msg = (u32*)(c->mem_offset + msg[7]);
+		u32 *preserved_msg = (u32*)(c->msg_virt + msg[7]);
 
 		i2o_report_status(KERN_INFO, "i2o_core", msg);
 		i2o_dump_message(preserved_msg);
@@ -1794,7 +1794,7 @@
 	m=i2o_wait_message(c, "AdapterReset");
 	if(m==0xFFFFFFFF)	
 		return -ETIMEDOUT;
-	msg=(u32 *)(c->mem_offset+m);
+	msg=(u32 *)(c->msg_virt+m);
 	
 	status = pci_alloc_consistent(c->pdev, 4, &status_phys);
 	if(status == NULL) {
@@ -1923,7 +1923,7 @@
 	m=i2o_wait_message(c, "StatusGet");
 	if(m==0xFFFFFFFF)
 		return -ETIMEDOUT;	
-	msg=(u32 *)(c->mem_offset+m);
+	msg=(u32 *)(c->msg_virt+m);
 
 	msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
 	msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
@@ -2344,7 +2344,7 @@
 	m=i2o_wait_message(c, "OutboundInit");
 	if(m==0xFFFFFFFF)
 		return -ETIMEDOUT;
-	msg=(u32 *)(c->mem_offset+m);
+	msg=(u32 *)(c->msg_virt+m);
 
 	status = pci_alloc_consistent(c->pdev, 4, &status_phys);
 	if (status==NULL) {
@@ -2618,7 +2618,7 @@
 		sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
 		sys_tbl->iops[count].iop_capabilities = 
 				iop->status_block->iop_capabilities;
-		sys_tbl->iops[count].inbound_low = iop->post_port;
+		sys_tbl->iops[count].inbound_low = (u32)iop->post_port;
 		sys_tbl->iops[count].inbound_high = 0;	// FIXME: 64-bit support
 
 		count++;
@@ -2666,7 +2666,7 @@
 		       c->name);
 		return -ETIMEDOUT;
 	}
-	msg = (u32 *)(c->mem_offset + m);
+	msg = (u32 *)(c->msg_virt + m);
  	memcpy_toio(msg, data, len);
 	i2o_post_message(c,m);
 	return 0;
@@ -3592,7 +3592,9 @@
 	I2O_IRQ_WRITE32(c,0xFFFFFFFF);
 	if(c->irq > 0)
 		free_irq(c->irq, c);
-	iounmap(((u8 *)c->post_port)-0x40);
+	iounmap(c->base_virt);
+	if(c->raptor)
+		iounmap(c->msg_virt);
 
 #ifdef CONFIG_MTRR
 	if(c->mtrr_reg0 > 0)
@@ -3633,9 +3635,12 @@
 {
 	struct i2o_controller *c=kmalloc(sizeof(struct i2o_controller),
 						GFP_KERNEL);
-	unsigned long mem;
-	u32 memptr = 0;
-	u32 size;
+	void *bar0_virt;
+	void *bar1_virt;
+	unsigned long bar0_phys = 0;
+	unsigned long bar1_phys = 0;
+	unsigned long bar0_size = 0;
+	unsigned long bar1_size = 0;
 	
 	int i;
 
@@ -3646,37 +3651,9 @@
 	}
 	memset(c, 0, sizeof(*c));
 
-	for(i=0; i<6; i++)
-	{
-		/* Skip I/O spaces */
-		if(!(pci_resource_flags(dev, i) & IORESOURCE_IO))
-		{
-			memptr = pci_resource_start(dev, i);
-			break;
-		}
-	}
-	
-	if(i==6)
-	{
-		printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n");
-		kfree(c);
-		return -EINVAL;
-	}
-	
-	size = dev->resource[i].end-dev->resource[i].start+1;	
-	/* Map the I2O controller */
-	
-	printk(KERN_INFO "i2o: PCI I2O controller at 0x%08X size=%d\n", memptr, size);
-	mem = (unsigned long)ioremap(memptr, size);
-	if(mem==0)
-	{
-		printk(KERN_ERR "i2o: Unable to map controller.\n");
-		kfree(c);
-		return -EINVAL;
-	}
-
 	c->irq = -1;
 	c->dpt = 0;
+	c->raptor = 0;
 	c->short_req = 0;
 	c->pdev = dev;
 
@@ -3684,13 +3661,6 @@
 	c->context_list_lock = SPIN_LOCK_UNLOCKED;
 #endif
 
-	c->irq_mask = mem+0x34;
-	c->post_port = mem+0x40;
-	c->reply_port = mem+0x44;
-
-	c->mem_phys = memptr;
-	c->mem_offset = mem;
-	
 	/*
 	 *	Cards that fall apart if you hit them with large I/O
 	 *	loads...
@@ -3701,6 +3671,7 @@
 		c->short_req = 1;
 		printk(KERN_INFO "I2O: Symbios FC920 workarounds activated.\n");
 	}
+
 	if(dev->subsystem_vendor == PCI_VENDOR_ID_PROMISE)
 	{
 		c->promise = 1;
@@ -3712,15 +3683,85 @@
 	 *	them
 	 */
 	 
-	if(dev->vendor == PCI_VENDOR_ID_DPT)
+	if(dev->vendor == PCI_VENDOR_ID_DPT) {
 		c->dpt=1;
+		if(dev->device == 0xA511)
+			c->raptor=1;
+	}
+
+	for(i=0; i<6; i++)
+	{
+		/* Skip I/O spaces */
+		if(!(pci_resource_flags(dev, i) & IORESOURCE_IO))
+		{
+			if(!bar0_phys)
+			{
+				bar0_phys = pci_resource_start(dev, i);
+				bar0_size = pci_resource_len(dev, i);
+				if(!c->raptor)
+					break;
+			}
+			else
+			{
+				bar1_phys = pci_resource_start(dev, i);
+				bar1_size = pci_resource_len(dev, i);
+				break;
+			}
+		}
+	}
+
+	if(i==6)
+	{
+		printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n");
+		kfree(c);
+		return -EINVAL;
+	}
+
+
+	/* Map the I2O controller */
+	if(!c->raptor)
+		printk(KERN_INFO "i2o: PCI I2O controller at %08lX size=%ld\n", bar0_phys, bar0_size);
+	else
+		printk(KERN_INFO "i2o: PCI I2O controller\n    BAR0 at 0x%08lX size=%ld\n    BAR1 at 0x%08lX size=%ld\n", bar0_phys, bar0_size, bar1_phys, bar1_size);
+
+	bar0_virt = ioremap(bar0_phys, bar0_size);
+	if(bar0_virt==0)
+	{
+		printk(KERN_ERR "i2o: Unable to map controller.\n");
+		kfree(c);
+		return -EINVAL;
+	}
+
+	if(c->raptor)
+	{
+		bar1_virt = ioremap(bar1_phys, bar1_size);
+		if(bar1_virt==0)
+		{
+			printk(KERN_ERR "i2o: Unable to map controller.\n");
+			kfree(c);
+			iounmap(bar0_virt);
+			return -EINVAL;
+		}
+	} else {
+		bar1_virt = bar0_virt;
+		bar1_phys = bar0_phys;
+		bar1_size = bar0_size;
+	}
+
+	c->irq_mask = bar0_virt+0x34;
+	c->post_port = bar0_virt+0x40;
+	c->reply_port = bar0_virt+0x44;
+
+	c->base_phys = bar0_phys;
+	c->base_virt = bar0_virt;
+	c->msg_phys = bar1_phys;
+	c->msg_virt = bar1_virt;
 	
 	/* 
 	 * Enable Write Combining MTRR for IOP's memory region
 	 */
 #ifdef CONFIG_MTRR
-	c->mtrr_reg0 =
-		mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1);
+	c->mtrr_reg0 = mtrr_add(c->base_phys, bar0_size, MTRR_TYPE_WRCOMB, 1);
 	/*
 	 * If it is an INTEL i960 I/O processor then set the first 64K to
 	 * Uncacheable since the region contains the Messaging unit which
@@ -3730,14 +3771,16 @@
 	if(dev->vendor == PCI_VENDOR_ID_INTEL || dev->vendor == PCI_VENDOR_ID_DPT)
 	{
 		printk(KERN_INFO "I2O: MTRR workaround for Intel i960 processor\n"); 
-		c->mtrr_reg1 =	mtrr_add(c->mem_phys, 65536, MTRR_TYPE_UNCACHABLE, 1);
+		c->mtrr_reg1 =	mtrr_add(c->base_phys, 65536, MTRR_TYPE_UNCACHABLE, 1);
 		if(c->mtrr_reg1< 0)
 		{
 			printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n");
-			mtrr_del(c->mtrr_reg0, c->mem_phys, size);
+			mtrr_del(c->mtrr_reg0, c->msg_phys, bar1_size);
 			c->mtrr_reg0 = -1;
 		}
 	}
+	if(c->raptor)
+		c->mtrr_reg1 = mtrr_add(c->msg_phys, bar1_size, MTRR_TYPE_WRCOMB, 1);
 
 #endif
 
@@ -3749,7 +3792,9 @@
 	{
 		printk(KERN_ERR "i2o: Unable to install controller.\n");
 		kfree(c);
-		iounmap((void *)mem);
+		iounmap(bar0_virt);
+		if(c->raptor)
+			iounmap(bar1_virt);
 		return i;
 	}
 
@@ -3764,7 +3809,9 @@
 				c->name, dev->irq);
 			c->irq = -1;
 			i2o_delete_controller(c);
-			iounmap((void *)mem);
+			iounmap(bar0_virt);
+			if(c->raptor)
+				iounmap(bar1_virt);
 			return -EBUSY;
 		}
 	}
@@ -3797,10 +3844,12 @@
 
 	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
 	{
-		if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O)
+		if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O &&
+		   (dev->vendor!=PCI_VENDOR_ID_DPT || dev->device!=0xA511))
 			continue;
 
-		if((dev->class&0xFF)>1)
+		if((dev->class>>8)==PCI_CLASS_INTELLIGENT_I2O &&
+		   (dev->class&0xFF)>1)
 		{
 			printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n");
 			continue;
diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
--- a/drivers/message/i2o/i2o_scsi.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/message/i2o/i2o_scsi.c	2004-06-23 19:04:28 -07:00
@@ -59,9 +59,11 @@
 #include <asm/atomic.h>
 #include <linux/blkdev.h>
 #include <linux/i2o.h>
-#include "../../scsi/scsi.h"
-#include "../../scsi/hosts.h"
 
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
 
 
 #define VERSION_STRING        "Version 0.1.2"
@@ -186,7 +188,7 @@
 
 static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
 {
-	Scsi_Cmnd *current_command;
+	struct scsi_cmnd *current_command;
 	spinlock_t *lock;
 	u32 *m = (u32 *)msg;
 	u8 as,ds,st;
@@ -230,7 +232,7 @@
 		{
 			spin_unlock_irqrestore(&retry_lock, flags);
 			/* Create a scsi error for this */
-			current_command = (Scsi_Cmnd *)i2o_context_list_get(m[3], c);
+			current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c);
 			if(!current_command)
 				return;
 
@@ -277,7 +279,7 @@
 		return;
 	}
 
-	current_command = (Scsi_Cmnd *)i2o_context_list_get(m[3], c);
+	current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c);
 	
 	/*
 	 *	Is this a control request coming back - eg an abort ?
@@ -330,10 +332,17 @@
 		 */		
 		current_command->result = DID_OK << 16 | ds;
 
-	if (current_command->use_sg)
-		pci_unmap_sg(c->pdev, (struct scatterlist *)current_command->buffer, current_command->use_sg, scsi_to_pci_dma_dir(current_command->sc_data_direction));
-	else if (current_command->request_bufflen)
-		pci_unmap_single(c->pdev, (dma_addr_t)((long)current_command->SCp.ptr), current_command->request_bufflen, scsi_to_pci_dma_dir(current_command->sc_data_direction));
+	if (current_command->use_sg) {
+		pci_unmap_sg(c->pdev,
+			(struct scatterlist *)current_command->buffer,
+			current_command->use_sg,
+			current_command->sc_data_direction);
+	} else if (current_command->request_bufflen) {
+		pci_unmap_single(c->pdev,
+			(dma_addr_t)((long)current_command->SCp.ptr),
+			current_command->request_bufflen,
+			current_command->sc_data_direction);
+	}
 
 	lock = current_command->device->host->host_lock;
 	spin_lock_irqsave(lock, flags);
@@ -461,7 +470,7 @@
  *	scsi controller and then let the enumeration fake up the rest
  */
  
-static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
+static int i2o_scsi_detect(struct scsi_host_template * tpnt)
 {
 	struct Scsi_Host *shpnt = NULL;
 	int i;
@@ -592,12 +601,13 @@
  *	Locks: takes the controller lock on error path only
  */
  
-static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
+static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
+				 void (*done) (struct scsi_cmnd *))
 {
 	int i;
 	int tid;
 	struct i2o_controller *c;
-	Scsi_Cmnd *current_command;
+	struct scsi_cmnd *current_command;
 	struct Scsi_Host *host;
 	struct i2o_scsi_host *hostdata;
 	u32 *msg, *mptr;
@@ -659,7 +669,7 @@
 	if(m==0xFFFFFFFF)
 		return 1;
 
-	msg = (u32 *)(c->mem_offset + m);
+	msg = (u32 *)(c->msg_virt + m);
 	
 	/*
 	 *	Put together a scsi execscb message
@@ -668,19 +678,14 @@
 	len = SCpnt->request_bufflen;
 	direction = 0x00000000;			// SGL IN  (osm<--iop)
 	
-	if(SCpnt->sc_data_direction == SCSI_DATA_NONE)
+	if (SCpnt->sc_data_direction == DMA_NONE) {
 		scsidir = 0x00000000;			// DATA NO XFER
-	else if(SCpnt->sc_data_direction == SCSI_DATA_WRITE)
-	{
-		direction=0x04000000;	// SGL OUT  (osm-->iop)
-		scsidir  =0x80000000;	// DATA OUT (iop-->dev)
-	}
-	else if(SCpnt->sc_data_direction == SCSI_DATA_READ)
-	{
-		scsidir  =0x40000000;	// DATA IN  (iop<--dev)
-	}
-	else
-	{
+	} else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
+		direction = 0x04000000;	// SGL OUT  (osm-->iop)
+		scsidir = 0x80000000;	// DATA OUT (iop-->dev)
+	} else if(SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
+		scsidir = 0x40000000;	// DATA IN  (iop<--dev)
+	} else {
 		/* Unknown - kill the command */
 		SCpnt->result = DID_NO_CONNECT << 16;
 		
@@ -768,7 +773,7 @@
 		len = 0;
 
 		sg_count = pci_map_sg(c->pdev, sg, SCpnt->use_sg,
-				      scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+				SCpnt->sc_data_direction);
 
 		/* FIXME: handle fail */
 		if(!sg_count)
@@ -840,7 +845,7 @@
 			dma_addr = pci_map_single(c->pdev,
 					       SCpnt->request_buffer,
 					       SCpnt->request_bufflen,
-					       scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+					       SCpnt->sc_data_direction);
 			if(dma_addr == 0)
 				BUG();	/* How to handle ?? */
 			SCpnt->SCp.ptr = (char *)(unsigned long) dma_addr;
@@ -883,7 +888,7 @@
  *	Locks: no locks are held or needed
  */
  
-int i2o_scsi_abort(Scsi_Cmnd * SCpnt)
+static int i2o_scsi_abort(struct scsi_cmnd * SCpnt)
 {
 	struct i2o_controller *c;
 	struct Scsi_Host *host;
@@ -929,14 +934,14 @@
  *	Locks: called with no lock held, requires no locks.
  */
  
-static int i2o_scsi_bus_reset(Scsi_Cmnd * SCpnt)
+static int i2o_scsi_bus_reset(struct scsi_cmnd * SCpnt)
 {
 	int tid;
 	struct i2o_controller *c;
 	struct Scsi_Host *host;
 	struct i2o_scsi_host *hostdata;
 	u32 m;
-	unsigned long msg;
+	void *msg;
 	unsigned long timeout;
 
 	
@@ -974,7 +979,7 @@
 	while(time_before(jiffies, timeout));
 	
 	
-	msg = c->mem_offset + m;
+	msg = c->msg_virt + m;
 	i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg);
 	i2o_raw_writel(I2O_CMD_SCSI_BUSRESET<<24|HOST_TID<<12|tid, msg+4);
 	i2o_raw_writel(scsi_context|0x80000000, msg+8);
@@ -992,32 +997,6 @@
 }
 
 /**
- *	i2o_scsi_host_reset	-	host reset callback
- *	@SCpnt: command causing the reset
- *
- *	An I2O controller can be many things at once. While we can
- *	reset a controller the potential mess from doing so is vast, and
- *	it's better to simply hold on and pray
- */
- 
-static int i2o_scsi_host_reset(Scsi_Cmnd * SCpnt)
-{
-	return FAILED;
-}
-
-/**
- *	i2o_scsi_device_reset	-	device reset callback
- *	@SCpnt: command causing the reset
- *
- *	I2O does not (AFAIK) support doing a device reset
- */
- 
-static int i2o_scsi_device_reset(Scsi_Cmnd * SCpnt)
-{
-	return FAILED;
-}
-
-/**
  *	i2o_scsi_bios_param	-	Invent disk geometry
  *	@sdev: scsi device 
  *	@dev: block layer device
@@ -1048,7 +1027,7 @@
 MODULE_LICENSE("GPL");
 
 
-static Scsi_Host_Template driver_template = {
+static struct scsi_host_template driver_template = {
 	.proc_name		= "i2o_scsi",
 	.name			= "I2O SCSI Layer",
 	.detect			= i2o_scsi_detect,
@@ -1057,8 +1036,6 @@
 	.queuecommand		= i2o_scsi_queuecommand,
 	.eh_abort_handler	= i2o_scsi_abort,
 	.eh_bus_reset_handler	= i2o_scsi_bus_reset,
-	.eh_device_reset_handler= i2o_scsi_device_reset,
-	.eh_host_reset_handler	= i2o_scsi_host_reset,
 	.bios_param		= i2o_scsi_bios_param,
 	.can_queue		= I2O_SCSI_CAN_QUEUE,
 	.this_id		= 15,
diff -Nru a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
--- a/drivers/misc/ibmasm/ibmasmfs.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/misc/ibmasm/ibmasmfs.c	2004-06-23 19:04:28 -07:00
@@ -224,12 +224,12 @@
 	return dentry;
 }
 
-int ibmasmfs_register()
+int ibmasmfs_register(void)
 {
 	return register_filesystem(&ibmasmfs_type);
 }
 
-void ibmasmfs_unregister()
+void ibmasmfs_unregister(void)
 {
 	unregister_filesystem(&ibmasmfs_type);
 }
@@ -287,7 +287,7 @@
 	return 0;
 }
 
-static ssize_t command_file_read(struct file *file, char *buf, size_t count, loff_t *offset)
+static ssize_t command_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
 {
 	struct ibmasmfs_command_data *command_data = file->private_data;
 	struct command *cmd;
@@ -324,7 +324,7 @@
 	return len;
 }
 
-static ssize_t command_file_write(struct file *file, const char *ubuff, size_t count, loff_t *offset)
+static ssize_t command_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset)
 {
 	struct ibmasmfs_command_data *command_data = file->private_data;
 	struct command *cmd;
@@ -345,7 +345,7 @@
 	if (!cmd)
 		return -ENOMEM;
 
-	if (copy_from_user((void *)cmd->buffer, (void *)ubuff, count)) {
+	if (copy_from_user(cmd->buffer, ubuff, count)) {
 		command_put(cmd);
 		return -EFAULT;
 	}
@@ -395,7 +395,7 @@
 	return 0;
 }
 
-static ssize_t event_file_read(struct file *file, char *buf, size_t count, loff_t *offset)
+static ssize_t event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
 {
 	struct ibmasmfs_event_data *event_data = file->private_data;
 	struct event_reader *reader = &event_data->reader;
@@ -421,7 +421,7 @@
 	return reader->data_size;
 }
 
-static ssize_t event_file_write(struct file *file, const char *buf, size_t count, loff_t *offset)
+static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
 {
 	struct ibmasmfs_event_data *event_data = file->private_data;
 
@@ -462,7 +462,7 @@
 	return 0;
 }
 
-static ssize_t r_heartbeat_file_read(struct file *file, char *buf, size_t count, loff_t *offset)
+static ssize_t r_heartbeat_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
 {
 	struct ibmasmfs_heartbeat_data *rhbeat = file->private_data;
 	unsigned long flags;
@@ -490,7 +490,7 @@
 	return result;
 }
 
-static ssize_t r_heartbeat_file_write(struct file *file, const char *buf, size_t count, loff_t *offset)
+static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
 {
 	struct ibmasmfs_heartbeat_data *rhbeat = file->private_data;
 
@@ -518,7 +518,7 @@
 	return 0;
 }
 
-static ssize_t remote_settings_file_read(struct file *file, char *buf, size_t count, loff_t *offset)
+static ssize_t remote_settings_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
 {
 	unsigned long address = (unsigned long)file->private_data;
 	unsigned char *page;
@@ -552,7 +552,7 @@
 	return retval;
 }
 
-static ssize_t remote_settings_file_write(struct file *file, const char *ubuff, size_t count, loff_t *offset)
+static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset)
 {
 	unsigned long address = (unsigned long)file->private_data;
 	char *buff;
@@ -571,7 +571,7 @@
 
 	memset(buff, 0x0, count + 1);
 
-	if (copy_from_user((void *)buff, (void *)ubuff, count)) {
+	if (copy_from_user(buff, ubuff, count)) {
 		kfree(buff);
 		return -EFAULT;
 	}
@@ -618,7 +618,7 @@
 	return 0;
 }
 
-static ssize_t remote_event_file_read(struct file *file, char *buf, size_t count, loff_t *offset)
+static ssize_t remote_event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
 {
 	struct service_processor *sp = file->private_data;
 	struct remote_queue *q = &sp->remote_queue;
@@ -663,7 +663,7 @@
 	.open =		event_file_open,
 	.release =	event_file_close,
 	.read =		event_file_read,
-	.write 		event_file_write,
+	.write =	event_file_write,
 };
 
 static struct file_operations r_heartbeat_fops = {
diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
--- a/drivers/mtd/mtdblock.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/mtd/mtdblock.c	2004-06-23 19:04:26 -07:00
@@ -275,7 +275,7 @@
 	
 	/* OK, it's not open. Create cache info for it */
 	mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
-	if (!mtdblks)
+	if (!mtdblk)
 		return -ENOMEM;
 
 	memset(mtdblk, 0, sizeof(*mtdblk));
diff -Nru a/drivers/net/3c501.c b/drivers/net/3c501.c
--- a/drivers/net/3c501.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/3c501.c	2004-06-23 19:04:25 -07:00
@@ -225,7 +225,7 @@
 	 *	Reserve I/O resource for exclusive use by this driver
 	 */
 
-	if (!request_region(ioaddr, EL1_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, EL1_IO_EXTENT, DRV_NAME))
 		return -ENODEV;
 
 	/*
diff -Nru a/drivers/net/3c503.c b/drivers/net/3c503.c
--- a/drivers/net/3c503.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/3c503.c	2004-06-23 19:04:27 -07:00
@@ -147,6 +147,7 @@
 	release_region(dev->base_addr, EL2_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init el2_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -171,6 +172,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 /* Probe for the Etherlink II card at I/O port base IOADDR,
    returning non-zero on success.  If found, set the station
@@ -182,10 +184,10 @@
     static unsigned version_printed;
     unsigned long vendor_id;
 
-    if (!request_region(ioaddr, EL2_IO_EXTENT, dev->name))
+    if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME))
 	return -EBUSY;
 
-    if (!request_region(ioaddr + 0x400, 8, dev->name)) {
+    if (!request_region(ioaddr + 0x400, 8, DRV_NAME)) {
 	retval = -EBUSY;
 	goto out;
     }
diff -Nru a/drivers/net/3c505.c b/drivers/net/3c505.c
--- a/drivers/net/3c505.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/net/3c505.c	2004-06-23 19:04:29 -07:00
@@ -1614,6 +1614,7 @@
 	return err;
 }
 
+#ifndef MODULE
 struct net_device * __init elplus_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(elp_device));
@@ -1632,7 +1633,7 @@
 	return dev;
 }
 
-#ifdef MODULE
+#else
 static struct net_device *dev_3c505[ELP_MAX_CARDS];
 static int io[ELP_MAX_CARDS];
 static int irq[ELP_MAX_CARDS];
diff -Nru a/drivers/net/3c507.c b/drivers/net/3c507.c
--- a/drivers/net/3c507.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/3c507.c	2004-06-23 19:04:28 -07:00
@@ -373,7 +373,7 @@
 		init_ID_done = 1;
 	}
 
-	if (!request_region(ioaddr, EL16_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, EL16_IO_EXTENT, DRV_NAME))
 		return -ENODEV;
 
 	if ((inb(ioaddr) != '*') || (inb(ioaddr + 1) != '3') || 
@@ -392,7 +392,7 @@
 
 	irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
 
-	irqval = request_irq(irq, &el16_interrupt, 0, dev->name, dev);
+	irqval = request_irq(irq, &el16_interrupt, 0, DRV_NAME, dev);
 	if (irqval) {
 		printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval);
 		retval = -EAGAIN;
diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c
--- a/drivers/net/3c509.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/3c509.c	2004-06-23 19:04:25 -07:00
@@ -56,10 +56,6 @@
 		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
 		    - Introduce driver model for EISA cards.
 */
-/*
-  FIXES for PC-9800:
-  Shu Iwanaga: 3c569B(PC-9801 C-bus) support
-*/
 
 #define DRV_NAME	"3c509"
 #define DRV_VERSION	"1.19b"
@@ -265,7 +261,7 @@
 };
 #endif /* CONFIG_MCA */
 
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
 static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
@@ -362,7 +358,7 @@
 	if (lp->pmdev)
 		pm_unregister(lp->pmdev);
 #endif
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
 	if (lp->type == EL3_PNP)
 		pnp_device_detach(to_pnp_dev(lp->dev));
 #endif
@@ -381,7 +377,7 @@
 	u16 phys_addr[3];
 	static int current_tag;
 	int err = -ENODEV;
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
 	static int pnp_cards;
 	struct pnp_dev *idev = NULL;
 
@@ -436,9 +432,6 @@
 no_pnp:
 #endif /* __ISAPNP__ */
 
-#ifdef CONFIG_X86_PC9800
-	id_port = 0x71d0;
-#else
 	/* Select an open I/O location at 0x1*0 to do contention select. */
 	for ( ; id_port < 0x200; id_port += 0x10) {
 		if (!request_region(id_port, 1, "3c509"))
@@ -456,7 +449,7 @@
 		printk(" WARNING: No I/O port available for 3c509 activation.\n");
 		return -ENODEV;
 	}
-#endif /* CONFIG_X86_PC9800 */
+
 	/* Next check for all ISA bus boards by sending the ID sequence to the
 	   ID_PORT.  We find cards past the first by setting the 'current_tag'
 	   on cards as they are found.  Cards with their tag set will not
@@ -487,7 +480,7 @@
 		phys_addr[i] = htons(id_read_eeprom(i));
 	}
 
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
 	if (nopnp == 0) {
 		/* The ISA PnP 3c509 cards respond to the ID sequence.
 		   This check is needed in order not to register them twice. */
@@ -512,19 +505,9 @@
 	{
 		unsigned int iobase = id_read_eeprom(8);
 		if_port = iobase >> 14;
-#ifdef CONFIG_X86_PC9800
-		ioaddr = 0x40d0 + ((iobase & 0x1f) << 8);
-#else
 		ioaddr = 0x200 + ((iobase & 0x1f) << 4);
-#endif
 	}
 	irq = id_read_eeprom(9) >> 12;
-#ifdef CONFIG_X86_PC9800
-	if (irq == 7)
-		irq = 6;
-	else if (irq == 15)
-		irq = 13;
-#endif
 
 	dev = alloc_etherdev(sizeof (struct el3_private));
 	if (!dev)
@@ -555,11 +538,7 @@
 	outb(0xd0 + ++current_tag, id_port);
 
 	/* Activate the adaptor at the EEPROM location. */
-#ifdef CONFIG_X86_PC9800
-	outb((ioaddr >> 8) | 0xe0, id_port);
-#else
 	outb((ioaddr >> 4) | 0xe0, id_port);
-#endif
 
 	EL3WINDOW(0);
 	if (inw(ioaddr) != 0x6d50)
@@ -568,7 +547,7 @@
 	/* Free the interrupt so that some other card can use it. */
 	outw(0x0f00, ioaddr + WN0_IRQ);
 
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
  found:							/* PNP jumps here... */
 #endif /* __ISAPNP__ */
 
@@ -577,7 +556,7 @@
 	dev->irq = irq;
 	dev->if_port = if_port;
 	lp = netdev_priv(dev);
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
 	lp->dev = &idev->dev;
 #endif
 	err = el3_common_init(dev);
@@ -601,7 +580,7 @@
 	return 0;
 
 out1:
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
 	if (idev)
 		pnp_device_detach(idev);
 #endif
@@ -1461,12 +1440,6 @@
 	outw(0x0001, ioaddr + 4);
 
 	/* Set the IRQ line. */
-#ifdef CONFIG_X86_PC9800
-	if (dev->irq == 6)
-		dev->irq = 7;
-	else if (dev->irq == 13)
-		dev->irq = 15;
-#endif
 	outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
 
 	/* Set the station address in window 2 each time opened. */
@@ -1629,7 +1602,7 @@
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
 MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
 MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
 MODULE_PARM(nopnp, "i");
 MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
 MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
diff -Nru a/drivers/net/3c523.c b/drivers/net/3c523.c
--- a/drivers/net/3c523.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/3c523.c	2004-06-23 19:04:27 -07:00
@@ -445,7 +445,7 @@
 			slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
 			continue;
 		}
-		if (!request_region(dev->base_addr, ELMC_IO_EXTENT, dev->name)) {
+		if (!request_region(dev->base_addr, ELMC_IO_EXTENT, DRV_NAME)) {
 			slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
 			continue;
 		}
@@ -585,6 +585,7 @@
 	release_region(dev->base_addr, ELMC_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init elmc_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct priv));
@@ -609,6 +610,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 /**********************************************
  * init the chip (elmc-interrupt should be disabled?!)
diff -Nru a/drivers/net/3c527.c b/drivers/net/3c527.c
--- a/drivers/net/3c527.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/3c527.c	2004-06-23 19:04:27 -07:00
@@ -435,10 +435,10 @@
 	 *	Grab the IRQ
 	 */
 
-	err = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+	err = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, DRV_NAME, dev);
 	if (err) {
 		release_region(dev->base_addr, MC32_IO_EXTENT);
-		printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+		printk(KERN_ERR "%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq);
 		goto err_exit_ports;
 	}
 
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/3c59x.c	2004-06-23 19:04:25 -07:00
@@ -446,6 +446,7 @@
 	CH_3C905B_2,
 	CH_3C905B_FX,
 	CH_3C905C,
+	CH_3C9202,
 	CH_3C980,
 	CH_3C9805,
 
@@ -520,12 +521,14 @@
 	{"3c905B-FX Cyclone 100baseFx",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
 	{"3c905C Tornado",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
+	PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+	{"3c920B-EMB-WNM (ATI Radeon 9100 IGP)",
+	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_MII|HAS_HWCKSM, 128, },
 	{"3c980 Cyclone",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+
 	{"3c980C Python-T",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
-
 	{"3cSOHO100-TX Hurricane",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3c555 Laptop Hurricane",
@@ -536,9 +539,9 @@
 	{"3c556B Laptop Hurricane",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR|
 	                                WNO_XCVR_PWR|HAS_HWCKSM, 128, },
+
 	{"3c575 [Megahertz] 10/100 LAN 	CardBus",
 	PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
-
 	{"3c575 Boomerang CardBus",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
 	{"3CCFE575BT Cyclone CardBus",
@@ -550,10 +553,10 @@
 	{"3CCFE656 Cyclone CardBus",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
 									INVERT_LED_PWR|HAS_HWCKSM, 128, },
+
 	{"3CCFEM656B Cyclone+Winmodem CardBus",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
 									INVERT_LED_PWR|HAS_HWCKSM, 128, },
-
 	{"3CXFEM656C Tornado+Winmodem CardBus",			/* From pcmcia-cs-3.1.5 */
 	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
 									MAX_COLLISION_RESET|HAS_HWCKSM, 128, },
@@ -563,9 +566,9 @@
 	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3c982 Hydra Dual Port A",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
+
 	{"3c982 Hydra Dual Port B",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
-
 	{"3c905B-T4",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
 	{"3c920B-EMB-WNM Tornado",
@@ -597,6 +600,7 @@
 	{ 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 },
 	{ 0x10B7, 0x905A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_FX },
 	{ 0x10B7, 0x9200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905C },
+	{ 0x10B7, 0x9202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9202 },
 	{ 0x10B7, 0x9800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C980 },
 	{ 0x10B7, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9805 },
 
@@ -884,7 +888,7 @@
 static int vortex_probe1(struct device *gendev, long ioaddr, int irq,
 				   int chip_idx, int card_idx);
 static void vortex_up(struct net_device *dev);
-static void vortex_down(struct net_device *dev);
+static void vortex_down(struct net_device *dev, int final);
 static int vortex_open(struct net_device *dev);
 static void mdio_sync(long ioaddr, int bits);
 static int mdio_read(struct net_device *dev, int phy_id, int location);
@@ -948,7 +952,7 @@
 	if (dev && dev->priv) {
 		if (netif_running(dev)) {
 			netif_device_detach(dev);
-			vortex_down(dev);
+			vortex_down(dev, 1);
 		}
 	}
 	return 0;
@@ -2059,7 +2063,8 @@
 				printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status);
 
 			/* In this case, blow the card away */
-			vortex_down(dev);
+			/* Must not enter D3 or we can't legally issue the reset! */
+			vortex_down(dev, 0);
 			issue_and_wait(dev, TotalReset | 0xff);
 			vortex_up(dev);		/* AKPM: bug.  vortex_up() assumes that the rx ring is full. It may not be. */
 		} else if (fifo_diag & 0x0400)
@@ -2656,7 +2661,7 @@
 }
 
 static void
-vortex_down(struct net_device *dev)
+vortex_down(struct net_device *dev, int final_down)
 {
 	struct vortex_private *vp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
@@ -2685,7 +2690,7 @@
 	if (vp->full_bus_master_tx)
 		outl(0, ioaddr + DownListPtr);
 
-	if (VORTEX_PCI(vp) && vp->enable_wol) {
+	if (final_down && VORTEX_PCI(vp) && vp->enable_wol) {
 		pci_save_state(VORTEX_PCI(vp), vp->power_state);
 		acpi_set_WOL(dev);
 	}
@@ -2699,7 +2704,7 @@
 	int i;
 
 	if (netif_device_present(dev))
-		vortex_down(dev);
+		vortex_down(dev, 1);
 
 	if (vortex_debug > 1) {
 		printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
@@ -2869,7 +2874,7 @@
 	.get_drvinfo =		vortex_get_drvinfo,
 };
 
-static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int vortex_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct vortex_private *vp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
@@ -2904,6 +2909,30 @@
 	return retval;
 }
 
+/*
+ *	Must power the device up to do MDIO operations
+ */
+static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int err;
+	struct vortex_private *vp = netdev_priv(dev);
+	int state = 0;
+
+	if(VORTEX_PCI(vp))
+		state = VORTEX_PCI(vp)->current_state;
+
+	/* The kernel core really should have pci_get_power_state() */
+
+	if(state != 0)
+		pci_set_power_state(VORTEX_PCI(vp), 0);
+	err = vortex_do_ioctl(dev, rq, cmd);
+	if(state != 0)
+		pci_set_power_state(VORTEX_PCI(vp), state);
+
+	return err;
+}
+
+
 /* Pre-Cyclone chips have no documented multicast filter, so the only
    multicast setting is to receive all multicast frames.  At least
    the chip has a very clean way to set the mode, unlike many others. */
@@ -3059,14 +3088,14 @@
 	 * here
 	 */
 	unregister_netdev(dev);
-	/* Should really use issue_and_wait() here */
-	outw(TotalReset|0x14, dev->base_addr + EL3_CMD);
 
 	if (VORTEX_PCI(vp) && vp->enable_wol) {
 		pci_set_power_state(VORTEX_PCI(vp), 0);	/* Go active */
 		if (vp->pm_state_valid)
 			pci_restore_state(VORTEX_PCI(vp), vp->power_state);
 	}
+	/* Should really use issue_and_wait() here */
+	outw(TotalReset|0x14, dev->base_addr + EL3_CMD);
 
 	pci_free_consistent(pdev,
 						sizeof(struct boom_rx_desc) * RX_RING_SIZE
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	2004-06-23 19:04:24 -07:00
+++ b/drivers/net/8139too.c	2004-06-23 19:04:24 -07:00
@@ -87,8 +87,6 @@
 		"rtl8139-diag -mmmaaavvveefN" output
 		enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log
 
-		See 8139too.txt for more details.
-
 */
 
 #define DRV_NAME	"8139too"
diff -Nru a/drivers/net/82596.c b/drivers/net/82596.c
--- a/drivers/net/82596.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/82596.c	2004-06-23 19:04:28 -07:00
@@ -58,11 +58,12 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
-#include <asm/pgalloc.h>
 
 static char version[] __initdata =
 	"82596.c $Revision: 1.5 $\n";
 
+#define DRV_NAME	"82596"
+
 /* DEBUG flags
  */
 
@@ -1191,7 +1192,7 @@
 		/* this is easy the ethernet interface can only be at 0x300 */
 		/* first check nothing is already registered here */
 
-		if (!request_region(ioaddr, I596_TOTAL_SIZE, dev->name)) {
+		if (!request_region(ioaddr, I596_TOTAL_SIZE, DRV_NAME)) {
 			printk(KERN_ERR "82596: IO address 0x%04x in use\n", ioaddr);
 			err = -EBUSY;
 			goto out;
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/Kconfig	2004-06-23 19:04:28 -07:00
@@ -922,7 +922,7 @@
 
 config NET_ISA
 	bool "Other ISA cards"
-	depends on NET_ETHERNET && ISA && !X86_PC9800
+	depends on NET_ETHERNET && ISA
 	---help---
 	  If your network (Ethernet) card hasn't been mentioned yet and its
 	  bus system (that's the way the cards talks to the other components
@@ -1105,56 +1105,6 @@
 	  the Ethernet-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>.
 
-config NET_CBUS
-	bool "NEC PC-9800 C-bus cards"
-	depends on NET_ETHERNET && ISA && X86_PC9800
-	---help---
-	  If your network (Ethernet) card hasn't been mentioned yet and its
-	  bus system (that's the way the cards talks to the other components
-	  of your computer) is NEC PC-9800 C-Bus, say Y.
-
-config NE2K_CBUS
-	tristate "Most NE2000-based Ethernet support"
-	depends on NET_CBUS
-	select CRC32
-
-config NE2K_CBUS_EGY98
-	bool "Melco EGY-98 support"
-	depends on NE2K_CBUS
-
-config NE2K_CBUS_LGY98
-	bool "Melco LGY-98 support"
-	depends on NE2K_CBUS
-
-config NE2K_CBUS_ICM
-	bool "ICM IF-27xxET support"
-	depends on NE2K_CBUS
-
-config NE2K_CBUS_IOLA98
-	bool "I-O DATA LA-98 support"
-	depends on NE2K_CBUS
-
-config NE2K_CBUS_CNET98EL
-	bool "Contec C-NET(98)E/L support"
-	depends on NE2K_CBUS
-
-config NE2K_CBUS_CNET98EL_IO_BASE
-	hex "C-NET(98)E/L I/O base address (0xaaed or 0x55ed)"
-	depends on NE2K_CBUS_CNET98EL
-	default "0xaaed"
-
-config NE2K_CBUS_ATLA98
-	bool "Allied Telesis LA-98 Support"
-	depends on NE2K_CBUS
-
-config NE2K_CBUS_BDN
-	bool "ELECOM Laneed LD-BDN[123]A Support"
-	depends on NE2K_CBUS
-
-config NE2K_CBUS_NEC108
-	bool "NEC PC-9801-108 Support"
-	depends on NE2K_CBUS
-
 config SKMC
 	tristate "SKnet MCA support"
 	depends on NET_ETHERNET && MCA && BROKEN
@@ -1287,6 +1237,19 @@
 config AMD8111E_NAPI
 	bool "Enable NAPI support"
 	depends on AMD8111_ETH
+	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 ADAPTEC_STARFIRE
 	tristate "Adaptec Starfire/DuraLAN support"
@@ -1314,6 +1277,11 @@
 	  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 AC3200
 	tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
 	depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL
@@ -1501,6 +1469,19 @@
 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)"
@@ -1605,9 +1586,7 @@
 	---help---
 	  This is a driver for the Fast Ethernet PCI network cards based on
 	  the RTL8139 chips. If you have one of those, say Y and read
-	  <file:Documentation/networking/8139too.txt> as well as the
-	  Ethernet-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
+	  the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called 8139too.  This is recommended.
@@ -1745,6 +1724,17 @@
 
 	  If unsure, say Y.
 
+config VIA_VELOCITY
+	tristate "VIA Velocity support"
+	depends on NET_PCI && PCI
+	select CRC32
+	select MII
+	help
+	  If you have a VIA "Velocity" based network card say Y here.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called via-rhine.
+
 config LAN_SAA9730
 	bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
 	depends on NET_PCI && EXPERIMENTAL && MIPS
@@ -1963,6 +1953,19 @@
 config E1000_NAPI
 	bool "Use Rx Polling (NAPI)"
 	depends on E1000
+	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 MYRI_SBUS
 	tristate "MyriCOM Gigabit Ethernet support"
@@ -2148,6 +2151,19 @@
 config IXGB_NAPI
 	bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
 	depends on IXGB && EXPERIMENTAL
+	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 S2IO
 	tristate "S2IO 10Gbe XFrame NIC"
@@ -2160,6 +2176,19 @@
 config S2IO_NAPI
 	bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
 	depends on S2IO && EXPERIMENTAL
+	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.
 
 endmenu
 
diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/Makefile	2004-06-23 19:04:26 -07:00
@@ -52,6 +52,7 @@
 obj-$(CONFIG_SK98LIN) += sk98lin/
 obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 
 #
@@ -79,7 +80,6 @@
 obj-$(CONFIG_WD80x3) += wd.o 8390.o
 obj-$(CONFIG_EL2) += 3c503.o 8390.o
 obj-$(CONFIG_NE2000) += ne.o 8390.o
-obj-$(CONFIG_NE2K_CBUS) += ne2k_cbus.o 8390.o
 obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o
 obj-$(CONFIG_HPLAN) += hp.o 8390.o
 obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/Space.c	2004-06-23 19:04:25 -07:00
@@ -191,8 +191,8 @@
 #ifdef CONFIG_E2100		/* Cabletron E21xx series. */
 	{e2100_probe, 0},
 #endif
-#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS)	|| \
-    defined(CONFIG_NE_H8300)  /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */
+#if defined(CONFIG_NE2000) || \
+    defined(CONFIG_NE_H8300)  /* ISA (use ne2k-pci for PCI cards) */
 	{ne_probe, 0},
 #endif
 #ifdef CONFIG_LANCE		/* ISA/VLB (use pcnet32 for PCI cards) */
diff -Nru a/drivers/net/ac3200.c b/drivers/net/ac3200.c
--- a/drivers/net/ac3200.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/ac3200.c	2004-06-23 19:04:27 -07:00
@@ -39,6 +39,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME	"ac3200"
+
 /* Offsets from the base address. */
 #define AC_NIC_BASE	0x00
 #define AC_SA_PROM	0x16			/* The station address PROM. */
@@ -130,6 +132,7 @@
 		iounmap((void *)dev->mem_start);
 }
 
+#ifndef MODULE
 struct net_device * __init ac3200_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -154,12 +157,13 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init ac_probe1(int ioaddr, struct net_device *dev)
 {
 	int i, retval;
 
-	if (!request_region(ioaddr, AC_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
@@ -203,7 +207,7 @@
 		printk(", assigning");
 	}
 
-	retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
+	retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
 	if (retval) {
 		printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
 		goto out1;
diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c
--- a/drivers/net/acenic.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/acenic.c	2004-06-23 19:04:26 -07:00
@@ -85,6 +85,8 @@
 #include <asm/uaccess.h>
 
 
+#define DRV_NAME "acenic"
+
 #undef INDEX_DEBUG
 
 #ifdef CONFIG_ACENIC_OMIT_TIGON_I
@@ -443,6 +445,16 @@
   "acenic.c: v0.92 08/05/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
+static int ace_get_settings(struct net_device *, struct ethtool_cmd *);
+static int ace_set_settings(struct net_device *, struct ethtool_cmd *);
+static void ace_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
+
+static struct ethtool_ops ace_ethtool_ops = {
+	.get_settings = ace_get_settings,
+	.set_settings = ace_set_settings,
+	.get_drvinfo = ace_get_drvinfo,
+};
+
 static int __devinit acenic_probe_one(struct pci_dev *pdev,
 		const struct pci_device_id *id)
 {
@@ -480,7 +492,7 @@
 	dev->hard_start_xmit = &ace_start_xmit;
 	dev->get_stats = &ace_get_stats;
 	dev->set_multicast_list = &ace_set_multicast_list;
-	dev->do_ioctl = &ace_ioctl;
+	SET_ETHTOOL_OPS(dev, &ace_ethtool_ops);
 	dev->set_mac_address = &ace_set_mac_addr;
 	dev->change_mtu = &ace_change_mtu;
 
@@ -1195,10 +1207,10 @@
 	}
 
 	ecode = request_irq(pdev->irq, ace_interrupt, SA_SHIRQ,
-			    dev->name, dev);
+			    DRV_NAME, dev);
 	if (ecode) {
 		printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
-		       dev->name, pdev->irq);
+		       DRV_NAME, pdev->irq);
 		goto init_error;
 	} else
 		dev->irq = pdev->irq;
@@ -2688,146 +2700,136 @@
 	return 0;
 }
 
-
-static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 	struct ace_private *ap = dev->priv;
 	struct ace_regs *regs = ap->regs;
-#ifdef SIOCETHTOOL
-	struct ethtool_cmd ecmd;
-	u32 link, speed;
+	u32 link;
 
-	if (cmd != SIOCETHTOOL)
-		return -EOPNOTSUPP;
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
-		return -EFAULT;
-	switch (ecmd.cmd) {
-	case ETHTOOL_GSET:
-		ecmd.supported =
-			(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
-			 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
-			 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
-			 SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-
-		ecmd.port = PORT_FIBRE;
-		ecmd.transceiver = XCVR_INTERNAL;
-		ecmd.phy_address = 0;
-
-		link = readl(&regs->GigLnkState);
-		if (link & LNK_1000MB)
-			ecmd.speed = SPEED_1000;
-		else {
-			link = readl(&regs->FastLnkState);
-			if (link & LNK_100MB)
-				ecmd.speed = SPEED_100;
-			else if (link & LNK_100MB)
-				ecmd.speed = SPEED_10;
-			else
-				ecmd.speed = 0;
-		}
-		if (link & LNK_FULL_DUPLEX)
-			ecmd.duplex = DUPLEX_FULL;
+	memset(ecmd, 0, sizeof(struct ethtool_cmd));
+	ecmd->supported =
+		(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+		 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+		 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
+		 SUPPORTED_Autoneg | SUPPORTED_FIBRE);
+
+	ecmd->port = PORT_FIBRE;
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	link = readl(&regs->GigLnkState);
+	if (link & LNK_1000MB)
+		ecmd->speed = SPEED_1000;
+	else {
+		link = readl(&regs->FastLnkState);
+		if (link & LNK_100MB)
+			ecmd->speed = SPEED_100;
+		else if (link & LNK_10MB)
+			ecmd->speed = SPEED_10;
 		else
-			ecmd.duplex = DUPLEX_HALF;
+			ecmd->speed = 0;
+	}
+	if (link & LNK_FULL_DUPLEX)
+		ecmd->duplex = DUPLEX_FULL;
+	else
+		ecmd->duplex = DUPLEX_HALF;
 
-		if (link & LNK_NEGOTIATE)
-			ecmd.autoneg = AUTONEG_ENABLE;
-		else
-			ecmd.autoneg = AUTONEG_DISABLE;
+	if (link & LNK_NEGOTIATE)
+		ecmd->autoneg = AUTONEG_ENABLE;
+	else
+		ecmd->autoneg = AUTONEG_DISABLE;
 
 #if 0
-		/*
-		 * Current struct ethtool_cmd is insufficient
-		 */
-		ecmd.trace = readl(&regs->TuneTrace);
+	/*
+	 * Current struct ethtool_cmd is insufficient
+	 */
+	ecmd->trace = readl(&regs->TuneTrace);
 
-		ecmd.txcoal = readl(&regs->TuneTxCoalTicks);
-		ecmd.rxcoal = readl(&regs->TuneRxCoalTicks);
+	ecmd->txcoal = readl(&regs->TuneTxCoalTicks);
+	ecmd->rxcoal = readl(&regs->TuneRxCoalTicks);
 #endif
-		ecmd.maxtxpkt = readl(&regs->TuneMaxTxDesc);
-		ecmd.maxrxpkt = readl(&regs->TuneMaxRxDesc);
+	ecmd->maxtxpkt = readl(&regs->TuneMaxTxDesc);
+	ecmd->maxrxpkt = readl(&regs->TuneMaxRxDesc);
 
-		if(copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-
-	case ETHTOOL_SSET:
-		link = readl(&regs->GigLnkState);
-		if (link & LNK_1000MB)
-			speed = SPEED_1000;
-		else {
-			link = readl(&regs->FastLnkState);
-			if (link & LNK_100MB)
-				speed = SPEED_100;
-			else if (link & LNK_100MB)
-				speed = SPEED_10;
-			else
-				speed = SPEED_100;
-		}
+	return 0;
+}
 
-		link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB |
-			LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL;
-		if (!ACE_IS_TIGON_I(ap))
-			link |= LNK_TX_FLOW_CTL_Y;
-		if (ecmd.autoneg == AUTONEG_ENABLE)
-			link |= LNK_NEGOTIATE;
-		if (ecmd.speed != speed) {
-			link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB);
-			switch (speed) {
-			case SPEED_1000:
-				link |= LNK_1000MB;
-				break;
-			case SPEED_100:
-				link |= LNK_100MB;
-				break;
-			case SPEED_10:
-				link |= LNK_10MB;
-				break;
-			}
+static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct ace_private *ap = dev->priv;
+	struct ace_regs *regs = ap->regs;
+	u32 link, speed;
+
+	link = readl(&regs->GigLnkState);
+	if (link & LNK_1000MB)
+		speed = SPEED_1000;
+	else {
+		link = readl(&regs->FastLnkState);
+		if (link & LNK_100MB)
+			speed = SPEED_100;
+		else if (link & LNK_10MB)
+			speed = SPEED_10;
+		else
+			speed = SPEED_100;
+	}
+
+	link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB |
+		LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL;
+	if (!ACE_IS_TIGON_I(ap))
+		link |= LNK_TX_FLOW_CTL_Y;
+	if (ecmd->autoneg == AUTONEG_ENABLE)
+		link |= LNK_NEGOTIATE;
+	if (ecmd->speed != speed) {
+		link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB);
+		switch (speed) {
+		case SPEED_1000:
+			link |= LNK_1000MB;
+			break;
+		case SPEED_100:
+			link |= LNK_100MB;
+			break;
+		case SPEED_10:
+			link |= LNK_10MB;
+			break;
 		}
-		if (ecmd.duplex == DUPLEX_FULL)
-			link |= LNK_FULL_DUPLEX;
+	}
 
-		if (link != ap->link) {
-			struct cmd cmd;
-			printk(KERN_INFO "%s: Renegotiating link state\n",
-			       dev->name);
+	if (ecmd->duplex == DUPLEX_FULL)
+		link |= LNK_FULL_DUPLEX;
 
-			ap->link = link;
-			writel(link, &regs->TuneLink);
-			if (!ACE_IS_TIGON_I(ap))
-				writel(link, &regs->TuneFastLink);
-			wmb();
+	if (link != ap->link) {
+		struct cmd cmd;
+		printk(KERN_INFO "%s: Renegotiating link state\n",
+		       dev->name);
 
-			cmd.evt = C_LNK_NEGOTIATION;
-			cmd.code = 0;
-			cmd.idx = 0;
-			ace_issue_cmd(regs, &cmd);
-		}
-		return 0;
+		ap->link = link;
+		writel(link, &regs->TuneLink);
+		if (!ACE_IS_TIGON_I(ap))
+			writel(link, &regs->TuneFastLink);
+		wmb();
 
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-		strncpy(info.driver, "acenic", sizeof(info.driver) - 1);
-		sprintf(info.fw_version, "%i.%i.%i", 
-			 tigonFwReleaseMajor, tigonFwReleaseMinor,
-			 tigonFwReleaseFix);
-		strncpy(info.version, version, sizeof(info.version) - 1);
-		if (ap && ap->pdev)
-			strcpy(info.bus_info, pci_name(ap->pdev));
-		if (copy_to_user(ifr->ifr_data, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	default:
-		break;
+		cmd.evt = C_LNK_NEGOTIATION;
+		cmd.code = 0;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
 	}
-	
-#endif
-
-	return -EOPNOTSUPP;
+	return 0;
 }
 
+static void ace_get_drvinfo(struct net_device *dev, 
+			    struct ethtool_drvinfo *info)
+{
+	struct ace_private *ap = dev->priv;
+
+	strlcpy(info->driver, "acenic", sizeof(info->driver));
+	snprintf(info->version, sizeof(info->version), "%i.%i.%i", 
+		tigonFwReleaseMajor, tigonFwReleaseMinor,
+		tigonFwReleaseFix);
+
+	if (ap->pdev)
+		strlcpy(info->bus_info, pci_name(ap->pdev), 
+			sizeof(info->bus_info));
+
+}
 
 /*
  * Set the hardware MAC address.
diff -Nru a/drivers/net/acenic.h b/drivers/net/acenic.h
--- a/drivers/net/acenic.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/acenic.h	2004-06-23 19:04:26 -07:00
@@ -790,7 +790,6 @@
 static void ace_dump_trace(struct ace_private *ap);
 static void ace_set_multicast_list(struct net_device *dev);
 static int ace_change_mtu(struct net_device *dev, int new_mtu);
-static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 static int ace_set_mac_addr(struct net_device *dev, void *p);
 static void ace_set_rxtx_parms(struct net_device *dev, int jumbo);
 static int ace_allocate_descriptors(struct net_device *dev);
diff -Nru a/drivers/net/apne.c b/drivers/net/apne.c
--- a/drivers/net/apne.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/net/apne.c	2004-06-23 19:04:29 -07:00
@@ -49,6 +49,8 @@
 
 /* ---- No user-serviceable parts below ---- */
 
+#define DRV_NAME "apne"
+
 #define NE_BASE	 (dev->base_addr)
 #define NE_CMD	 		0x00
 #define NE_DATAPORT		0x10            /* NatSemi-defined port window offset. */
@@ -168,7 +170,7 @@
 		return ERR_PTR(-ENODEV);
 	}
 
-	if (!request_region(IOBASE, 0x20, dev->name)) {
+	if (!request_region(IOBASE, 0x20, DRV_NAME)) {
 		free_netdev(dev);
 		return ERR_PTR(-EBUSY);
 	}
@@ -310,7 +312,7 @@
     dev->base_addr = ioaddr;
 
     /* Install the Interrupt handler */
-    i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, dev->name, dev);
+    i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, DRV_NAME, dev);
     if (i) return i;
 
     for(i = 0; i < ETHER_ADDR_LEN; i++) {
diff -Nru a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
--- a/drivers/net/arm/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/arm/Kconfig	2004-06-23 19:04:28 -07:00
@@ -45,3 +45,20 @@
 	  number (MTD support is required for this). Otherwise you will
 	  need to set a suitable hw address using ifconfig.
 
+config SMC91X
+	tristate "SMC 91C9x/91C1xxx support"
+	select CRC32
+	select MII
+	depends on ARM
+	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
+	  compiled into the kernel, and read the file
+	  <file:Documentation/networking/smc9.txt>  and the Ethernet-HOWTO,
+	  available from  <http://www.linuxdoc.org/docs.html#howto>.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called smc91x.  If you want to compile it as a
+	  module, say M here and read <file:Documentation/modules.txt> as well
+	  as <file:Documentation/networking/net-modules.txt>.
diff -Nru a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
--- a/drivers/net/arm/Makefile	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/arm/Makefile	2004-06-23 19:04:27 -07:00
@@ -8,3 +8,4 @@
 obj-$(CONFIG_ARM_ETHERH)	+= etherh.o
 obj-$(CONFIG_ARM_ETHER3)	+= ether3.o
 obj-$(CONFIG_ARM_ETHER1)	+= ether1.o
+obj-$(CONFIG_SMC91X)		+= smc91x.o
diff -Nru a/drivers/net/arm/smc91x.c b/drivers/net/arm/smc91x.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/arm/smc91x.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,2171 @@
+/*
+ * smc91x.c
+ * This is a driver for SMSC's 91C9x/91C1xx single-chip Ethernet devices.
+ *
+ * Copyright (C) 1996 by Erik Stahlman
+ * Copyright (C) 2001 Standard Microsystems Corporation
+ *	Developed by Simple Network Magic Corporation
+ * Copyright (C) 2003 Monta Vista Software, Inc.
+ *	Unified SMC91x driver by Nicolas Pitre
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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
+ *
+ * Arguments:
+ * 	io	= for the base address
+ *	irq	= for the IRQ
+ *	nowait	= 0 for normal wait states, 1 eliminates additional wait states
+ *
+ * original author:
+ * 	Erik Stahlman <erik@vt.edu>
+ *
+ * hardware multicast code:
+ *    Peter Cammaert <pc@denkart.be>
+ *
+ * contributors:
+ * 	Daris A Nevil <dnevil@snmc.com>
+ *      Nicolas Pitre <nico@cam.org>
+ *	Russell King <rmk@arm.linux.org.uk>
+ *
+ * History:
+ *   08/20/00  Arnaldo Melo       fix kfree(skb) in smc_hardware_send_packet
+ *   12/15/00  Christian Jullien  fix "Warning: kfree_skb on hard IRQ"
+ *   03/16/01  Daris A Nevil      modified smc9194.c for use with LAN91C111
+ *   08/22/01  Scott Anderson     merge changes from smc9194 to smc91111
+ *   08/21/01  Pramod B Bhardwaj  added support for RevB of LAN91C111
+ *   12/20/01  Jeff Sutherland    initial port to Xscale PXA with DMA support
+ *   04/07/03  Nicolas Pitre      unified SMC91x driver, killed irq races,
+ *                                more bus abstraction, big cleanup, etc.
+ *   29/09/03  Russell King       - add driver model support
+ *                                - ethtool support
+ *                                - convert to use generic MII interface
+ *                                - add link up/down notification
+ *                                - don't try to handle full negotiation in
+ *                                  smc_phy_configure
+ *                                - clean up (and fix stack overrun) in PHY
+ *                                  MII read/write functions
+ */
+static const char version[] =
+	"smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre <nico@cam.org>\n";
+
+/* Debugging level */
+#ifndef SMC_DEBUG
+#define SMC_DEBUG		0
+#endif
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/crc32.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include "smc91x.h"
+
+#ifdef CONFIG_ISA
+/*
+ * the LAN91C111 can be at any of the following port addresses.  To change,
+ * for a slightly different card, you can add it to the array.  Keep in
+ * mind that the array must end in zero.
+ */
+static unsigned int smc_portlist[] __initdata = {
+	0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
+	0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
+};
+
+#ifndef SMC_IOADDR
+# define SMC_IOADDR		-1
+#endif
+static unsigned long io = SMC_IOADDR;
+module_param(io, ulong, 0400);
+MODULE_PARM_DESC(io, "I/O base address");
+
+#ifndef SMC_IRQ
+# define SMC_IRQ		-1
+#endif
+static int irq = SMC_IRQ;
+module_param(irq, int, 0400);
+MODULE_PARM_DESC(irq, "IRQ number");
+
+#endif  /* CONFIG_ISA */
+
+#ifndef SMC_NOWAIT
+# define SMC_NOWAIT		0
+#endif
+static int nowait = SMC_NOWAIT;
+module_param(nowait, int, 0400);
+MODULE_PARM_DESC(nowait, "set to 1 for no wait state");
+
+/*
+ * Transmit timeout, default 5 seconds.
+ */
+static int watchdog = 5000;
+module_param(watchdog, int, 0400);
+MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+
+MODULE_LICENSE("GPL");
+
+/*
+ * The internal workings of the driver.  If you are changing anything
+ * here with the SMC stuff, you should have the datasheet and know
+ * what you are doing.
+ */
+#define CARDNAME "smc91x"
+
+/*
+ * Use power-down feature of the chip
+ */
+#define POWER_DOWN		1
+
+/*
+ * Wait time for memory to be free.  This probably shouldn't be
+ * tuned that much, as waiting for this means nothing else happens
+ * in the system
+ */
+#define MEMORY_WAIT_TIME	16
+
+/*
+ * This selects whether TX packets are sent one by one to the SMC91x internal
+ * memory and throttled until transmission completes.  This may prevent
+ * RX overruns a litle by keeping much of the memory free for RX packets
+ * but to the expense of reduced TX throughput and increased IRQ overhead.
+ * Note this is not a cure for a too slow data bus or too high IRQ latency.
+ */
+#define THROTTLE_TX_PKTS	0
+
+/*
+ * The MII clock high/low times.  2x this number gives the MII clock period
+ * in microseconds. (was 50, but this gives 6.4ms for each MII transaction!)
+ */
+#define MII_DELAY		1
+
+/* store this information for the driver.. */
+struct smc_local {
+	/*
+	 * If I have to wait until memory is available to send a
+	 * packet, I will store the skbuff here, until I get the
+	 * desired memory.  Then, I'll send it out and free it.
+	 */
+	struct sk_buff *saved_skb;
+
+ 	/*
+	 * these are things that the kernel wants me to keep, so users
+	 * can find out semi-useless statistics of how well the card is
+	 * performing
+	 */
+	struct net_device_stats stats;
+
+	/* version/revision of the SMC91x chip */
+	int	version;
+
+	/* Contains the current active transmission mode */
+	int	tcr_cur_mode;
+
+	/* Contains the current active receive mode */
+	int	rcr_cur_mode;
+
+	/* Contains the current active receive/phy mode */
+	int	rpc_cur_mode;
+	int	ctl_rfduplx;
+	int	ctl_rspeed;
+
+	u32	msg_enable;
+	u32	phy_type;
+	struct mii_if_info mii;
+	spinlock_t lock;
+
+#ifdef SMC_USE_PXA_DMA
+	/* DMA needs the physical address of the chip */
+	u_long physaddr;
+#endif
+};
+
+#if SMC_DEBUG > 0
+#define DBG(n, args...)					\
+	do {						\
+		if (SMC_DEBUG >= (n))			\
+			printk(KERN_DEBUG args);	\
+	} while (0)
+
+#define PRINTK(args...)   printk(args)
+#else
+#define DBG(n, args...)   do { } while(0)
+#define PRINTK(args...)   printk(KERN_DEBUG args)
+#endif
+
+#if SMC_DEBUG > 3
+static void PRINT_PKT(u_char *buf, int length)
+{
+	int i;
+	int remainder;
+	int lines;
+
+	lines = length / 16;
+	remainder = length % 16;
+
+	for (i = 0; i < lines ; i ++) {
+		int cur;
+		for (cur = 0; cur < 8; cur++) {
+			u_char a, b;
+			a = *buf++;
+			b = *buf++;
+			printk("%02x%02x ", a, b);
+		}
+		printk("\n");
+	}
+	for (i = 0; i < remainder/2 ; i++) {
+		u_char a, b;
+		a = *buf++;
+		b = *buf++;
+		printk("%02x%02x ", a, b);
+	}
+	printk("\n");
+}
+#else
+#define PRINT_PKT(x...)  do { } while(0)
+#endif
+
+
+/* this enables an interrupt in the interrupt mask register */
+#define SMC_ENABLE_INT(x) do {						\
+	unsigned long flags;						\
+	unsigned char mask;						\
+	spin_lock_irqsave(&lp->lock, flags);				\
+	mask = SMC_GET_INT_MASK();					\
+	mask |= (x);							\
+	SMC_SET_INT_MASK(mask);						\
+	spin_unlock_irqrestore(&lp->lock, flags);			\
+} while (0)
+
+/* this disables an interrupt from the interrupt mask register */
+#define SMC_DISABLE_INT(x) do {						\
+	unsigned long flags;						\
+	unsigned char mask;						\
+	spin_lock_irqsave(&lp->lock, flags);				\
+	mask = SMC_GET_INT_MASK();					\
+	mask &= ~(x);							\
+	SMC_SET_INT_MASK(mask);						\
+	spin_unlock_irqrestore(&lp->lock, flags);			\
+} while (0)
+
+/*
+ * Wait while MMU is busy.  This is usually in the order of a few nanosecs
+ * if at all, but let's avoid deadlocking the system if the hardware
+ * decides to go south.
+ */
+#define SMC_WAIT_MMU_BUSY() do {					\
+	if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) {			\
+		unsigned long timeout = jiffies + 2;			\
+		while (SMC_GET_MMU_CMD() & MC_BUSY) {			\
+			if (time_after(jiffies, timeout)) {		\
+				printk("%s: timeout %s line %d\n",	\
+					dev->name, __FILE__, __LINE__);	\
+				break;					\
+			}						\
+			cpu_relax();					\
+		}							\
+	}								\
+} while (0)
+
+
+/*
+ * this does a soft reset on the device
+ */
+static void smc_reset(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int ctl, cfg;
+
+	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+	/*
+	 * This resets the registers mostly to defaults, but doesn't
+	 * affect EEPROM.  That seems unnecessary
+	 */
+	SMC_SELECT_BANK(0);
+	SMC_SET_RCR(RCR_SOFTRST);
+
+	/*
+	 * Setup the Configuration Register
+	 * This is necessary because the CONFIG_REG is not affected
+	 * by a soft reset
+	 */
+	SMC_SELECT_BANK(1);
+
+	cfg = CONFIG_DEFAULT;
+
+	/*
+	 * Setup for fast accesses if requested.  If the card/system
+	 * can't handle it then there will be no recovery except for
+	 * a hard reset or power cycle
+	 */
+	if (nowait)
+		cfg |= CONFIG_NO_WAIT;
+
+	/*
+	 * Release from possible power-down state
+	 * Configuration register is not affected by Soft Reset
+	 */
+	cfg |= CONFIG_EPH_POWER_EN;
+
+	SMC_SET_CONFIG(cfg);
+
+	/* this should pause enough for the chip to be happy */
+	/*
+	 * elaborate?  What does the chip _need_? --jgarzik
+	 *
+	 * This seems to be undocumented, but something the original
+	 * driver(s) have always done.  Suspect undocumented timing
+	 * info/determined empirically. --rmk
+	 */
+	udelay(1);
+
+	/* Disable transmit and receive functionality */
+	SMC_SELECT_BANK(0);
+	SMC_SET_RCR(RCR_CLEAR);
+	SMC_SET_TCR(TCR_CLEAR);
+
+	SMC_SELECT_BANK(1);
+	ctl = SMC_GET_CTL() | CTL_LE_ENABLE;
+
+	/*
+	 * Set the control register to automatically release successfully
+	 * transmitted packets, to make the best use out of our limited
+	 * memory
+	 */
+#if ! THROTTLE_TX_PKTS
+	ctl |= CTL_AUTO_RELEASE;
+#else
+	ctl &= ~CTL_AUTO_RELEASE;
+#endif
+	SMC_SET_CTL(ctl);
+
+	/* Disable all interrupts */
+	SMC_SELECT_BANK(2);
+	SMC_SET_INT_MASK(0);
+
+	/* Reset the MMU */
+	SMC_SET_MMU_CMD(MC_RESET);
+	SMC_WAIT_MMU_BUSY();
+}
+
+/*
+ * Enable Interrupts, Receive, and Transmit
+ */
+static void smc_enable(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = netdev_priv(dev);
+	int mask;
+
+	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+	/* see the header file for options in TCR/RCR DEFAULT */
+	SMC_SELECT_BANK(0);
+	SMC_SET_TCR(lp->tcr_cur_mode);
+	SMC_SET_RCR(lp->rcr_cur_mode);
+
+	/* now, enable interrupts */
+	mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT;
+	if (lp->version >= (CHIP_91100 << 4))
+		mask |= IM_MDINT;
+	SMC_SELECT_BANK(2);
+	SMC_SET_INT_MASK(mask);
+}
+
+/*
+ * this puts the device in an inactive state
+ */
+static void smc_shutdown(unsigned long ioaddr)
+{
+	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
+
+	/* no more interrupts for me */
+	SMC_SELECT_BANK(2);
+	SMC_SET_INT_MASK(0);
+
+	/* and tell the card to stay away from that nasty outside world */
+	SMC_SELECT_BANK(0);
+	SMC_SET_RCR(RCR_CLEAR);
+	SMC_SET_TCR(TCR_CLEAR);
+
+#ifdef POWER_DOWN
+	/* finally, shut the chip down */
+	SMC_SELECT_BANK(1);
+	SMC_SET_CONFIG(SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN);
+#endif
+}
+
+/*
+ * This is the procedure to handle the receipt of a packet.
+ */
+static inline void  smc_rcv(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int packet_number, status, packet_len;
+
+	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+
+	packet_number = SMC_GET_RXFIFO();
+	if (unlikely(packet_number & RXFIFO_REMPTY)) {
+		PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name);
+		return;
+	}
+
+	/* read from start of packet */
+	SMC_SET_PTR(PTR_READ | PTR_RCV | PTR_AUTOINC);
+
+	/* First two words are status and packet length */
+	SMC_GET_PKT_HDR(status, packet_len);
+	packet_len &= 0x07ff;  /* mask off top bits */
+	DBG(2, "%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n",
+		dev->name, packet_number, status,
+		packet_len, packet_len);
+
+	if (unlikely(status & RS_ERRORS)) {
+		lp->stats.rx_errors++;
+		if (status & RS_ALGNERR)
+			lp->stats.rx_frame_errors++;
+		if (status & (RS_TOOSHORT | RS_TOOLONG))
+			lp->stats.rx_length_errors++;
+		if (status & RS_BADCRC)
+			lp->stats.rx_crc_errors++;
+	} else {
+		struct sk_buff *skb;
+		unsigned char *data;
+		unsigned int data_len;
+
+		/* set multicast stats */
+		if (status & RS_MULTICAST)
+			lp->stats.multicast++;
+
+		/*
+		 * Actual payload is packet_len - 4 (or 3 if odd byte).
+		 * We want skb_reserve(2) and the final ctrl word
+		 * (2 bytes, possibly containing the payload odd byte).
+		 * Ence packet_len - 4 + 2 + 2.
+		 */
+		skb = dev_alloc_skb(packet_len);
+		if (unlikely(skb == NULL)) {
+			printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
+				dev->name);
+			lp->stats.rx_dropped++;
+			goto done;
+		}
+
+		/* Align IP header to 32 bits */
+		skb_reserve(skb, 2);
+
+		/* BUG: the LAN91C111 rev A never sets this bit. Force it. */
+		if (lp->version == 0x90)
+			status |= RS_ODDFRAME;
+
+		/*
+		 * If odd length: packet_len - 3,
+		 * otherwise packet_len - 4.
+		 */
+		data_len = packet_len - ((status & RS_ODDFRAME) ? 3 : 4);
+		data = skb_put(skb, data_len);
+		SMC_PULL_DATA(data, packet_len - 2);
+
+		PRINT_PKT(data, packet_len - 2);
+
+		dev->last_rx = jiffies;
+		skb->dev = dev;
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);
+		lp->stats.rx_packets++;
+		lp->stats.rx_bytes += data_len;
+	}
+
+done:
+	SMC_WAIT_MMU_BUSY();
+	SMC_SET_MMU_CMD(MC_RELEASE);
+}
+
+/*
+ * This is called to actually send a packet to the chip.
+ * Returns non-zero when successful.
+ */
+static void smc_hardware_send_packet(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	struct sk_buff *skb = lp->saved_skb;
+	unsigned int packet_no, len;
+	unsigned char *buf;
+
+	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+
+	packet_no = SMC_GET_AR();
+	if (unlikely(packet_no & AR_FAILED)) {
+		printk("%s: Memory allocation failed.\n", dev->name);
+		lp->saved_skb = NULL;
+		lp->stats.tx_errors++;
+		lp->stats.tx_fifo_errors++;
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
+	/* point to the beginning of the packet */
+	SMC_SET_PN(packet_no);
+	SMC_SET_PTR(PTR_AUTOINC);
+
+	buf = skb->data;
+	len = skb->len;
+	DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n",
+		dev->name, packet_no, len, len, buf);
+	PRINT_PKT(buf, len);
+
+	/*
+	 * Send the packet length (+6 for status words, length, and ctl.
+	 * The card will pad to 64 bytes with zeroes if packet is too small.
+	 */
+	SMC_PUT_PKT_HDR(0, len + 6);
+
+	/* send the actual data */
+	SMC_PUSH_DATA(buf, len & ~1);
+
+	/* Send final ctl word with the last byte if there is one */
+	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG);
+
+	/* and let the chipset deal with it */
+	SMC_SET_MMU_CMD(MC_ENQUEUE);
+	SMC_ACK_INT(IM_TX_EMPTY_INT);
+
+	dev->trans_start = jiffies;
+	dev_kfree_skb_any(skb);
+	lp->saved_skb = NULL;
+	lp->stats.tx_packets++;
+	lp->stats.tx_bytes += len;
+}
+
+/*
+ * Since I am not sure if I will have enough room in the chip's ram
+ * to store the packet, I call this routine which either sends it
+ * now, or set the card to generates an interrupt when ready
+ * for the packet.
+ */
+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;
+	unsigned int numPages, poll_count, status, saved_bank;
+
+	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+
+	BUG_ON(lp->saved_skb != NULL);
+	lp->saved_skb = skb;
+
+	/*
+	 * The MMU wants the number of pages to be the number of 256 bytes
+	 * 'pages', minus 1 (since a packet can't ever have 0 pages :))
+	 *
+	 * The 91C111 ignores the size bits, but earlier models don't.
+	 *
+	 * Pkt size for allocating is data length +6 (for additional status
+	 * words, length and ctl)
+	 *
+	 * If odd size then last byte is included in ctl word.
+	 */
+	numPages = ((skb->len & ~1) + (6 - 1)) >> 8;
+	if (unlikely(numPages > 7)) {
+		printk("%s: Far too big packet error.\n", dev->name);
+		lp->saved_skb = NULL;
+		lp->stats.tx_errors++;
+		lp->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	/* now, try to allocate the memory */
+	saved_bank = SMC_CURRENT_BANK();
+	SMC_SELECT_BANK(2);
+	SMC_SET_MMU_CMD(MC_ALLOC | numPages);
+
+	/*
+	 * Poll the chip for a short amount of time in case the
+	 * allocation succeeds quickly.
+	 */
+	poll_count = MEMORY_WAIT_TIME;
+	do {
+		status = SMC_GET_INT();
+		if (status & IM_ALLOC_INT) {
+			SMC_ACK_INT(IM_ALLOC_INT);
+  			break;
+		}
+   	} while (--poll_count);
+
+   	if (!poll_count) {
+		/* oh well, wait until the chip finds memory later */
+		netif_stop_queue(dev);
+		DBG(2, "%s: TX memory allocation deferred.\n", dev->name);
+		SMC_ENABLE_INT(IM_ALLOC_INT);
+   	} else {
+		/*
+		 * Allocation succeeded: push packet to the chip's own memory
+		 * immediately.
+		 *
+		 * If THROTTLE_TX_PKTS is selected that means we don't want
+		 * more than a single TX packet taking up space in the chip's
+		 * internal memory at all time, in which case we stop the
+		 * queue right here until we're notified of TX completion.
+		 *
+		 * Otherwise we're quite happy to feed more TX packets right
+		 * away for better TX throughput, in which case the queue is
+		 * left active.
+		 */  
+#if THROTTLE_TX_PKTS
+		netif_stop_queue(dev);
+#endif
+		smc_hardware_send_packet(dev);
+		SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
+	}
+
+	SMC_SELECT_BANK(saved_bank);
+	return 0;
+}
+
+/*
+ * This handles a TX interrupt, which is only called when:
+ * - a TX error occurred, or
+ * - CTL_AUTO_RELEASE is not set and TX of a packet completed.
+ */
+static void smc_tx(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = netdev_priv(dev);
+	unsigned int saved_packet, packet_no, tx_status, pkt_len;
+
+	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+
+	/* If the TX FIFO is empty then nothing to do */
+	packet_no = SMC_GET_TXFIFO();
+	if (unlikely(packet_no & TXFIFO_TEMPTY)) {
+		PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name);
+		return;
+	}
+
+	/* select packet to read from */
+	saved_packet = SMC_GET_PN();
+	SMC_SET_PN(packet_no);
+
+	/* read the first word (status word) from this packet */
+	SMC_SET_PTR(PTR_AUTOINC | PTR_READ);
+	SMC_GET_PKT_HDR(tx_status, pkt_len);
+	DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n",
+		dev->name, tx_status, packet_no);
+
+	if (!(tx_status & TS_SUCCESS))
+		lp->stats.tx_errors++;
+	if (tx_status & TS_LOSTCAR)
+		lp->stats.tx_carrier_errors++;
+
+	SMC_WAIT_MMU_BUSY();
+
+	if (tx_status & TS_LATCOL) {
+		PRINTK("%s: late collision occurred on last xmit\n", dev->name);
+		lp->stats.tx_window_errors++;
+		/* It's really cheap to requeue the pkt here */
+		SMC_SET_MMU_CMD( MC_ENQUEUE );
+	} else {
+		/* kill the packet */
+		SMC_SET_MMU_CMD(MC_FREEPKT);
+	}
+
+	/* Don't restore Packet Number Reg until busy bit is cleared */
+	SMC_WAIT_MMU_BUSY();
+	SMC_SET_PN(saved_packet);
+
+	/* re-enable transmit */
+	SMC_SELECT_BANK(0);
+	SMC_SET_TCR(lp->tcr_cur_mode);
+	SMC_SELECT_BANK(2);
+}
+
+
+/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/
+
+static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int mii_reg, mask;
+
+	mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
+	mii_reg |= MII_MDOE;
+
+	for (mask = 1 << (bits - 1); mask; mask >>= 1) {
+		if (val & mask)
+			mii_reg |= MII_MDO;
+		else
+			mii_reg &= ~MII_MDO;
+
+		SMC_SET_MII(mii_reg);
+		udelay(MII_DELAY);
+		SMC_SET_MII(mii_reg | MII_MCLK);
+		udelay(MII_DELAY);
+	}
+}
+
+static unsigned int smc_mii_in(struct net_device *dev, int bits)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int mii_reg, mask, val;
+
+	mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
+	SMC_SET_MII(mii_reg);
+
+	for (mask = 1 << (bits - 1), val = 0; mask; mask >>= 1) {
+		if (SMC_GET_MII() & MII_MDI)
+			val |= mask;
+
+		SMC_SET_MII(mii_reg);
+		udelay(MII_DELAY);
+		SMC_SET_MII(mii_reg | MII_MCLK);
+		udelay(MII_DELAY);
+	}
+
+	return val;
+}
+
+/*
+ * Reads a register from the MII Management serial interface
+ */
+static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int phydata, old_bank;
+
+	/* Save the current bank, and select bank 3 */
+	old_bank = SMC_CURRENT_BANK();
+	SMC_SELECT_BANK(3);
+
+	/* Idle - 32 ones */
+	smc_mii_out(dev, 0xffffffff, 32);
+
+	/* Start code (01) + read (10) + phyaddr + phyreg */
+	smc_mii_out(dev, 6 << 10 | phyaddr << 5 | phyreg, 14);
+
+	/* Turnaround (2bits) + phydata */
+	phydata = smc_mii_in(dev, 18);
+
+	/* Return to idle state */
+	SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO));
+
+	/* And select original bank */
+	SMC_SELECT_BANK(old_bank);
+
+	DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+		__FUNCTION__, phyaddr, phyreg, phydata);
+
+	return phydata;
+}
+
+/*
+ * Writes a register to the MII Management serial interface
+ */
+static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
+			  int phydata)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int old_bank;
+
+	/* Save the current bank, and select bank 3 */
+	old_bank = SMC_CURRENT_BANK();
+	SMC_SELECT_BANK(3);
+
+	/* Idle - 32 ones */
+	smc_mii_out(dev, 0xffffffff, 32);
+
+	/* Start code (01) + write (01) + phyaddr + phyreg + turnaround + phydata */
+	smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32);
+
+	/* Return to idle state */
+	SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO));
+
+	/* And select original bank */
+	SMC_SELECT_BANK(old_bank);
+
+	DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+		__FUNCTION__, phyaddr, phyreg, phydata);
+}
+
+/*
+ * Finds and reports the PHY address
+ */
+static void smc_detect_phy(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	int phyaddr;
+
+	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+	lp->phy_type = 0;
+
+	/*
+	 * Scan all 32 PHY addresses if necessary, starting at
+	 * PHY#1 to PHY#31, and then PHY#0 last.
+	 */
+	for (phyaddr = 1; phyaddr < 33; ++phyaddr) {
+		unsigned int id1, id2;
+
+		/* Read the PHY identifiers */
+		id1 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID1);
+		id2 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID2);
+
+		DBG(3, "%s: phy_id1=0x%x, phy_id2=0x%x\n",
+			dev->name, id1, id2);
+
+		/* Make sure it is a valid identifier */
+		if (id1 != 0x0000 && id1 != 0xffff && id1 != 0x8000 &&
+		    id2 != 0x0000 && id2 != 0xffff && id2 != 0x8000) {
+			/* Save the PHY's address */
+			lp->mii.phy_id = phyaddr & 31;
+			lp->phy_type = id1 << 16 | id2;
+			break;
+		}
+	}
+}
+
+/*
+ * Sets the PHY to a configuration as determined by the user
+ */
+static int smc_phy_fixed(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int phyaddr = lp->mii.phy_id;
+	int bmcr, cfg1;
+
+	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+
+	/* Enter Link Disable state */
+	cfg1 = smc_phy_read(dev, phyaddr, PHY_CFG1_REG);
+	cfg1 |= PHY_CFG1_LNKDIS;
+	smc_phy_write(dev, phyaddr, PHY_CFG1_REG, cfg1);
+
+	/*
+	 * Set our fixed capabilities
+	 * Disable auto-negotiation
+	 */
+	bmcr = 0;
+
+	if (lp->ctl_rfduplx)
+		bmcr |= BMCR_FULLDPLX;
+
+	if (lp->ctl_rspeed == 100)
+		bmcr |= BMCR_SPEED100;
+
+	/* Write our capabilities to the phy control register */
+	smc_phy_write(dev, phyaddr, MII_BMCR, bmcr);
+
+	/* Re-Configure the Receive/Phy Control register */
+	SMC_SET_RPC(lp->rpc_cur_mode);
+
+	return 1;
+}
+
+/*
+ * smc_phy_reset - reset the phy
+ * @dev: net device
+ * @phy: phy address
+ *
+ * Issue a software reset for the specified PHY and
+ * wait up to 100ms for the reset to complete.  We should
+ * not access the PHY for 50ms after issuing the reset.
+ *
+ * The time to wait appears to be dependent on the PHY.
+ *
+ * Must be called with lp->lock locked.
+ */
+static int smc_phy_reset(struct net_device *dev, int phy)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	unsigned int bmcr;
+	int timeout;
+
+	smc_phy_write(dev, phy, MII_BMCR, BMCR_RESET);
+
+	for (timeout = 2; timeout; timeout--) {
+		spin_unlock_irq(&lp->lock);
+		msleep(50);
+		spin_lock_irq(&lp->lock);
+
+		bmcr = smc_phy_read(dev, phy, MII_BMCR);
+		if (!(bmcr & BMCR_RESET))
+			break;
+	}
+
+	return bmcr & BMCR_RESET;
+}
+
+/*
+ * 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)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	unsigned int bmcr;
+
+	spin_lock_irq(&lp->lock);
+	bmcr = smc_phy_read(dev, phy, MII_BMCR);
+	smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN);
+	spin_unlock_irq(&lp->lock);
+}
+
+/*
+ * smc_phy_check_media - check the media status and adjust TCR
+ * @dev: net device
+ * @init: set true for initialisation
+ *
+ * Select duplex mode depending on negotiation state.  This
+ * also updates our carrier state.
+ */
+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;
+
+	if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
+		unsigned int old_bank;
+
+		/* duplex state has changed */
+		if (lp->mii.full_duplex) {
+			lp->tcr_cur_mode |= TCR_SWFDUP;
+		} else {
+			lp->tcr_cur_mode &= ~TCR_SWFDUP;
+		}
+
+		old_bank = SMC_CURRENT_BANK();
+		SMC_SELECT_BANK(0);
+		SMC_SET_TCR(lp->tcr_cur_mode);
+		SMC_SELECT_BANK(old_bank);
+	}
+}
+
+/*
+ * Configures the specified PHY through the MII management interface
+ * using Autonegotiation.
+ * Calls smc_phy_fixed() if the user has requested a certain config.
+ * If RPC ANEG bit is set, the media selection is dependent purely on
+ * the selection by the MII (either in the MII BMCR reg or the result
+ * of autonegotiation.)  If the RPC ANEG bit is cleared, the selection
+ * is controlled by the RPC SPEED and RPC DPLX bits.
+ */
+static void smc_phy_configure(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int phyaddr = lp->mii.phy_id;
+	int my_phy_caps; /* My PHY capabilities */
+	int my_ad_caps; /* My Advertised capabilities */
+	int status;
+
+	DBG(3, "%s:smc_program_phy()\n", dev->name);
+
+	spin_lock_irq(&lp->lock);
+
+	/*
+	 * We should not be called if phy_type is zero.
+	 */
+	if (lp->phy_type == 0)
+		goto smc_phy_configure_exit;
+
+	if (smc_phy_reset(dev, phyaddr)) {
+		printk("%s: PHY reset timed out\n", dev->name);
+		goto smc_phy_configure_exit;
+	}
+
+	/*
+	 * Enable PHY Interrupts (for register 18)
+	 * Interrupts listed here are disabled
+	 */
+	smc_phy_write(dev, phyaddr, PHY_MASK_REG,
+		PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD |
+		PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
+		PHY_INT_SPDDET | PHY_INT_DPLXDET);
+
+	/* Configure the Receive/Phy Control register */
+	SMC_SELECT_BANK(0);
+	SMC_SET_RPC(lp->rpc_cur_mode);
+
+	/* If the user requested no auto neg, then go set his request */
+	if (lp->mii.force_media) {
+		smc_phy_fixed(dev);
+		goto smc_phy_configure_exit;
+	}
+
+	/* Copy our capabilities from MII_BMSR to MII_ADVERTISE */
+	my_phy_caps = smc_phy_read(dev, phyaddr, MII_BMSR);
+
+	if (!(my_phy_caps & BMSR_ANEGCAPABLE)) {
+		printk(KERN_INFO "Auto negotiation NOT supported\n");
+		smc_phy_fixed(dev);
+		goto smc_phy_configure_exit;
+	}
+
+	my_ad_caps = ADVERTISE_CSMA; /* I am CSMA capable */
+
+	if (my_phy_caps & BMSR_100BASE4)
+		my_ad_caps |= ADVERTISE_100BASE4;
+	if (my_phy_caps & BMSR_100FULL)
+		my_ad_caps |= ADVERTISE_100FULL;
+	if (my_phy_caps & BMSR_100HALF)
+		my_ad_caps |= ADVERTISE_100HALF;
+	if (my_phy_caps & BMSR_10FULL)
+		my_ad_caps |= ADVERTISE_10FULL;
+	if (my_phy_caps & BMSR_10HALF)
+		my_ad_caps |= ADVERTISE_10HALF;
+
+	/* Disable capabilities not selected by our user */
+	if (lp->ctl_rspeed != 100)
+		my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF);
+
+	if (!lp->ctl_rfduplx)
+		my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL);
+
+	/* Update our Auto-Neg Advertisement Register */
+	smc_phy_write(dev, phyaddr, MII_ADVERTISE, my_ad_caps);
+	lp->mii.advertising = my_ad_caps;
+
+	/*
+	 * Read the register back.  Without this, it appears that when
+	 * auto-negotiation is restarted, sometimes it isn't ready and
+	 * the link does not come up.
+	 */
+	status = smc_phy_read(dev, phyaddr, MII_ADVERTISE);
+
+	DBG(2, "%s: phy caps=%x\n", dev->name, my_phy_caps);
+	DBG(2, "%s: phy advertised caps=%x\n", dev->name, my_ad_caps);
+
+	/* Restart auto-negotiation process in order to advertise my caps */
+	smc_phy_write(dev, phyaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
+
+	smc_phy_check_media(dev, 1);
+
+smc_phy_configure_exit:
+	spin_unlock_irq(&lp->lock);
+}
+
+/*
+ * smc_phy_interrupt
+ *
+ * Purpose:  Handle interrupts relating to PHY register 18. This is
+ *  called from the "hard" interrupt handler under our private spinlock.
+ */
+static void smc_phy_interrupt(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	int phyaddr = lp->mii.phy_id;
+	int phy18;
+
+	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+	if (lp->phy_type == 0)
+		return;
+
+	for(;;) {
+		smc_phy_check_media(dev, 0);
+
+		/* Read PHY Register 18, Status Output */
+		phy18 = smc_phy_read(dev, phyaddr, PHY_INT_REG);
+		if ((phy18 & PHY_INT_INT) == 0)
+			break;
+	}
+}
+
+/*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/
+
+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;
+	unsigned int old_carrier, new_carrier, old_bank;
+
+	old_bank = SMC_CURRENT_BANK();
+	SMC_SELECT_BANK(0);
+	old_carrier = netif_carrier_ok(dev) ? 1 : 0;
+	new_carrier = SMC_inw(ioaddr, EPH_STATUS_REG) & ES_LINK_OK ? 1 : 0;
+
+	if (init || (old_carrier != new_carrier)) {
+		if (!new_carrier) {
+			netif_carrier_off(dev);
+		} else {
+			netif_carrier_on(dev);
+		}
+		if (netif_msg_link(lp))
+			printk(KERN_INFO "%s: link %s\n", dev->name,
+			       new_carrier ? "up" : "down");
+	}
+	SMC_SELECT_BANK(old_bank);
+}
+
+static void smc_eph_interrupt(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int old_bank, ctl;
+
+	smc_10bt_check_media(dev, 0);
+
+	old_bank = SMC_CURRENT_BANK();
+	SMC_SELECT_BANK(1);
+
+	ctl = SMC_GET_CTL();
+	SMC_SET_CTL(ctl & ~CTL_LE_ENABLE);
+	SMC_SET_CTL(ctl);
+
+	SMC_SELECT_BANK(old_bank);
+}
+
+/*
+ * This is the main routine of the driver, to handle the device when
+ * it needs some attention.
+ */
+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);
+	int status, mask, timeout, card_stats;
+	int saved_bank, saved_pointer;
+
+	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+
+	saved_bank = SMC_CURRENT_BANK();
+	SMC_SELECT_BANK(2);
+	saved_pointer = SMC_GET_PTR();
+	mask = SMC_GET_INT_MASK();
+	SMC_SET_INT_MASK(0);
+
+	/* set a timeout value, so I don't stay here forever */
+	timeout = 8;
+
+	do {
+		status = SMC_GET_INT();
+
+		DBG(2, "%s: IRQ 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
+			dev->name, status, mask,
+			({ int meminfo; SMC_SELECT_BANK(0);
+			   meminfo = SMC_GET_MIR();
+			   SMC_SELECT_BANK(2); meminfo; }),
+			SMC_GET_FIFO());
+
+		status &= mask;
+		if (!status)
+			break;
+
+		spin_lock(&lp->lock);
+
+		if (status & IM_RCV_INT) {
+			DBG(3, "%s: RX irq\n", dev->name);
+			smc_rcv(dev);
+		} else if (status & IM_TX_INT) {
+			DBG(3, "%s: TX int\n", dev->name);
+			smc_tx(dev);
+			SMC_ACK_INT(IM_TX_INT);
+#if THROTTLE_TX_PKTS
+			netif_wake_queue(dev);
+#endif
+		} else if (status & IM_ALLOC_INT) {
+			DBG(3, "%s: Allocation irq\n", dev->name);
+			smc_hardware_send_packet(dev);
+			mask |= (IM_TX_INT | IM_TX_EMPTY_INT);
+			mask &= ~IM_ALLOC_INT;
+#if ! THROTTLE_TX_PKTS
+			netif_wake_queue(dev);
+#endif
+		} else if (status & IM_TX_EMPTY_INT) {
+			DBG(3, "%s: TX empty\n", dev->name);
+			mask &= ~IM_TX_EMPTY_INT;
+
+			/* update stats */
+			SMC_SELECT_BANK(0);
+			card_stats = SMC_GET_COUNTER();
+			SMC_SELECT_BANK(2);
+
+			/* single collisions */
+			lp->stats.collisions += card_stats & 0xF;
+			card_stats >>= 4;
+
+			/* multiple collisions */
+			lp->stats.collisions += card_stats & 0xF;
+		} else if (status & IM_RX_OVRN_INT) {
+			DBG(1, "%s: RX overrun\n", dev->name);
+			SMC_ACK_INT(IM_RX_OVRN_INT);
+			lp->stats.rx_errors++;
+			lp->stats.rx_fifo_errors++;
+		} else if (status & IM_EPH_INT) {
+			smc_eph_interrupt(dev);
+		} else if (status & IM_MDINT) {
+			SMC_ACK_INT(IM_MDINT);
+			smc_phy_interrupt(dev);
+		} else if (status & IM_ERCV_INT) {
+			SMC_ACK_INT(IM_ERCV_INT);
+			PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
+		}
+
+		spin_unlock(&lp->lock);
+	} while (--timeout);
+
+	/* restore register states */
+	SMC_SET_INT_MASK(mask);
+	SMC_SET_PTR(saved_pointer);
+	SMC_SELECT_BANK(saved_bank);
+
+	DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout);
+
+	/*
+	 * We return IRQ_HANDLED unconditionally here even if there was
+	 * nothing to do.  There is a possibility that a packet might
+	 * get enqueued into the chip right after TX_EMPTY_INT is raised
+	 * but just before the CPU acknowledges the IRQ.
+	 * Better take an unneeded IRQ in some occasions than complexifying
+	 * the code for all cases.
+	 */
+	return IRQ_HANDLED;
+}
+
+/* Our watchdog timed out. Called by the networking layer */
+static void smc_timeout(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+
+	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+	smc_reset(dev);
+	smc_enable(dev);
+
+#if 0
+	/*
+	 * Reconfiguring the PHY doesn't seem like a bad idea here, but
+	 * it introduced a problem.  Now that this is a timeout routine,
+	 * we are getting called from within an interrupt context.
+	 * smc_phy_configure() calls msleep() which calls
+	 * schedule_timeout() which calls schedule().  When schedule()
+	 * is called from an interrupt context, it prints out
+	 * "Scheduling in interrupt" and then calls BUG().  This is
+	 * obviously not desirable.  This was worked around by removing
+	 * the call to smc_phy_configure() here because it didn't seem
+	 * absolutely necessary.  Ultimately, if msleep() is
+	 * supposed to be usable from an interrupt context (which it
+	 * looks like it thinks it should handle), it should be fixed.
+	 */
+	if (lp->phy_type != 0)
+		smc_phy_configure(dev);
+#endif
+
+	/* clear anything saved */
+	if (lp->saved_skb != NULL) {
+		dev_kfree_skb (lp->saved_skb);
+		lp->saved_skb = NULL;
+		lp->stats.tx_errors++;
+		lp->stats.tx_aborted_errors++;
+	}
+	/* We can accept TX packets again */
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+}
+
+/*
+ *    This sets the internal hardware table to filter out unwanted multicast
+ *    packets before they take up memory.
+ *
+ *    The SMC chip uses a hash table where the high 6 bits of the CRC of
+ *    address are the offset into the table.  If that bit is 1, then the
+ *    multicast packet is accepted.  Otherwise, it's dropped silently.
+ *
+ *    To use the 6 bits as an offset into the table, the high 3 bits are the
+ *    number of the 8 bit register, while the low 3 bits are the bit within
+ *    that register.
+ *
+ *    This routine is based very heavily on the one provided by Peter Cammaert.
+ */
+static void
+smc_setmulticast(unsigned long ioaddr, int count, struct dev_mc_list *addrs)
+{
+	int i;
+	unsigned char multicast_table[8];
+	struct dev_mc_list *cur_addr;
+
+	/* table for flipping the order of 3 bits */
+	static unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+
+	/* start with a table of all zeros: reject all */
+	memset(multicast_table, 0, sizeof(multicast_table));
+
+	cur_addr = addrs;
+	for (i = 0; i < count; i++, cur_addr = cur_addr->next) {
+		int position;
+
+		/* do we have a pointer here? */
+		if (!cur_addr)
+			break;
+		/* make sure this is a multicast address - shouldn't this
+		   be a given if we have it here ? */
+		if (!(*cur_addr->dmi_addr & 1))
+			continue;
+
+		/* only use the low order bits */
+		position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f;
+
+		/* do some messy swapping to put the bit in the right spot */
+		multicast_table[invert3[position&7]] |=
+					(1<<invert3[(position>>3)&7]);
+
+	}
+	/* now, the table can be loaded into the chipset */
+	SMC_SELECT_BANK(3);
+	SMC_SET_MCAST(multicast_table);
+}
+
+/*
+ * This routine will, depending on the values passed to it,
+ * either make it accept multicast packets, go into
+ * promiscuous mode (for TCPDUMP and cousins) or accept
+ * a select set of multicast packets
+ */
+static void smc_set_multicast_list(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+
+	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+	SMC_SELECT_BANK(0);
+	if (dev->flags & IFF_PROMISC) {
+		DBG(2, "%s: RCR_PRMS\n", dev->name);
+		lp->rcr_cur_mode |= RCR_PRMS;
+		SMC_SET_RCR(lp->rcr_cur_mode);
+	}
+
+/* BUG?  I never disable promiscuous mode if multicasting was turned on.
+   Now, I turn off promiscuous mode, but I don't do anything to multicasting
+   when promiscuous mode is turned on.
+*/
+
+	/*
+	 * Here, I am setting this to accept all multicast packets.
+	 * I don't need to zero the multicast table, because the flag is
+	 * checked before the table is
+	 */
+	else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) {
+		lp->rcr_cur_mode |= RCR_ALMUL;
+		SMC_SET_RCR(lp->rcr_cur_mode);
+		DBG(2, "%s: RCR_ALMUL\n", dev->name);
+	}
+
+	/*
+	 * We just get all multicast packets even if we only want them
+	 * from one source.  This will be changed at some future point.
+	 */
+	else if (dev->mc_count)  {
+		/* support hardware multicasting */
+
+		/* be sure I get rid of flags I might have set */
+		lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
+		SMC_SET_RCR(lp->rcr_cur_mode);
+		/*
+		 * NOTE: this has to set the bank, so make sure it is the
+		 * last thing called.  The bank is set to zero at the top
+		 */
+		smc_setmulticast(ioaddr, dev->mc_count, dev->mc_list);
+	} else  {
+		DBG(2, "%s: ~(RCR_PRMS|RCR_ALMUL)\n", dev->name);
+		lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
+		SMC_SET_RCR(lp->rcr_cur_mode);
+
+		/*
+		 * since I'm disabling all multicast entirely, I need to
+		 * clear the multicast list
+		 */
+		SMC_SELECT_BANK(3);
+		SMC_CLEAR_MCAST();
+	}
+}
+
+
+/*
+ * Open and Initialize the board
+ *
+ * Set up everything, reset the card, etc..
+ */
+static int
+smc_open(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+
+	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+	/*
+	 * Check that the address is valid.  If its not, refuse
+	 * to bring the device up.  The user must specify an
+	 * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
+	 */
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		DBG(2, (KERN_DEBUG "smc_open: no valid ethernet hw addr\n"));
+		return -EINVAL;
+	}
+
+	/* clear out all the junk that was put here before... */
+	lp->saved_skb = NULL;
+
+	/* Setup the default Register Modes */
+	lp->tcr_cur_mode = TCR_DEFAULT;
+	lp->rcr_cur_mode = RCR_DEFAULT;
+	lp->rpc_cur_mode = RPC_DEFAULT;
+
+	/*
+	 * If we are not using a MII interface, we need to
+	 * monitor our own carrier signal to detect faults.
+	 */
+	if (lp->phy_type == 0)
+		lp->tcr_cur_mode |= TCR_MON_CSN;
+
+	/* reset the hardware */
+	smc_reset(dev);
+	smc_enable(dev);
+
+	SMC_SELECT_BANK(1);
+	SMC_SET_MAC_ADDR(dev->dev_addr);
+
+	/* Configure the PHY */
+	if (lp->phy_type != 0)
+		smc_phy_configure(dev);
+	else {
+		spin_lock_irq(&lp->lock);
+		smc_10bt_check_media(dev, 1);
+		spin_unlock_irq(&lp->lock);
+	}
+
+	/*
+	 * make sure to initialize the link state with netif_carrier_off()
+	 * somewhere, too --jgarzik
+	 *
+	 * smc_phy_configure() and smc_10bt_check_media() does that. --rmk
+	 */
+	netif_start_queue(dev);
+	return 0;
+}
+
+/*
+ * smc_close
+ *
+ * this makes the board clean up everything that it can
+ * and not talk to the outside world.   Caused by
+ * an 'ifconfig ethX down'
+ */
+static int smc_close(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+
+	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	/* clear everything */
+	smc_shutdown(dev->base_addr);
+
+	if (lp->phy_type != 0)
+		smc_phy_powerdown(dev, lp->mii.phy_id);
+
+	return 0;
+}
+
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+static struct net_device_stats *smc_query_statistics(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+
+	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+	return &lp->stats;
+}
+
+/*
+ * Ethtool support
+ */
+static int
+smc_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	int ret;
+
+	cmd->maxtxpkt = 1;
+	cmd->maxrxpkt = 1;
+
+	if (lp->phy_type != 0) {
+		spin_lock_irq(&lp->lock);
+		ret = mii_ethtool_gset(&lp->mii, cmd);
+		spin_unlock_irq(&lp->lock);
+	} else {
+		cmd->supported = SUPPORTED_10baseT_Half |
+				 SUPPORTED_10baseT_Full |
+				 SUPPORTED_TP | SUPPORTED_AUI;
+
+		if (lp->ctl_rspeed == 10)
+			cmd->speed = SPEED_10;
+		else if (lp->ctl_rspeed == 100)
+			cmd->speed = SPEED_100;
+
+		cmd->autoneg = AUTONEG_DISABLE;
+		cmd->transceiver = XCVR_INTERNAL;
+		cmd->port = 0;
+		cmd->duplex = lp->tcr_cur_mode & TCR_SWFDUP ? DUPLEX_FULL : DUPLEX_HALF;
+
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int
+smc_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	int ret;
+
+	if (lp->phy_type != 0) {
+		spin_lock_irq(&lp->lock);
+		ret = mii_ethtool_sset(&lp->mii, cmd);
+		spin_unlock_irq(&lp->lock);
+	} else {
+		if (cmd->autoneg != AUTONEG_DISABLE ||
+		    cmd->speed != SPEED_10 ||
+		    (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) ||
+		    (cmd->port != PORT_TP && cmd->port != PORT_AUI))
+			return -EINVAL;
+
+//		lp->port = cmd->port;
+		lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL;
+
+//		if (netif_running(dev))
+//			smc_set_port(dev);
+
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static void
+smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strncpy(info->driver, CARDNAME, sizeof(info->driver));
+	strncpy(info->version, version, sizeof(info->version));
+	strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info));
+}
+
+static int smc_ethtool_nwayreset(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	int ret = -EINVAL;
+
+	if (lp->phy_type != 0) {
+		spin_lock_irq(&lp->lock);
+		ret = mii_nway_restart(&lp->mii);
+		spin_unlock_irq(&lp->lock);
+	}
+
+	return ret;
+}
+
+static u32 smc_ethtool_getmsglevel(struct net_device *dev)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	return lp->msg_enable;
+}
+
+static void smc_ethtool_setmsglevel(struct net_device *dev, u32 level)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	lp->msg_enable = level;
+}
+
+static struct ethtool_ops smc_ethtool_ops = {
+	.get_settings	= smc_ethtool_getsettings,
+	.set_settings	= smc_ethtool_setsettings,
+	.get_drvinfo	= smc_ethtool_getdrvinfo,
+
+	.get_msglevel	= smc_ethtool_getmsglevel,
+	.set_msglevel	= smc_ethtool_setmsglevel,
+	.nway_reset	= smc_ethtool_nwayreset,
+	.get_link	= ethtool_op_get_link,
+//	.get_eeprom	= smc_ethtool_geteeprom,
+//	.set_eeprom	= smc_ethtool_seteeprom,
+};
+
+/*
+ * smc_findirq
+ *
+ * This routine has a simple purpose -- make the SMC chip generate an
+ * interrupt, so an auto-detect routine can detect it, and find the IRQ,
+ */
+/*
+ * does this still work?
+ *
+ * I just deleted auto_irq.c, since it was never built...
+ *   --jgarzik
+ */
+static int __init smc_findirq(unsigned long ioaddr)
+{
+	int timeout = 20;
+	unsigned long cookie;
+
+	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
+
+	cookie = probe_irq_on();
+
+	/*
+	 * What I try to do here is trigger an ALLOC_INT. This is done
+	 * by allocating a small chunk of memory, which will give an interrupt
+	 * when done.
+	 */
+	/* enable ALLOCation interrupts ONLY */
+	SMC_SELECT_BANK(2);
+	SMC_SET_INT_MASK(IM_ALLOC_INT);
+
+	/*
+ 	 * Allocate 512 bytes of memory.  Note that the chip was just
+	 * reset so all the memory is available
+	 */
+	SMC_SET_MMU_CMD(MC_ALLOC | 1);
+
+	/*
+	 * Wait until positive that the interrupt has been generated
+	 */
+	do {
+		int int_status;
+		udelay(10);
+		int_status = SMC_GET_INT();
+		if (int_status & IM_ALLOC_INT)
+			break;		/* got the interrupt */
+	} while (--timeout);
+
+	/*
+	 * there is really nothing that I can do here if timeout fails,
+	 * as autoirq_report will return a 0 anyway, which is what I
+	 * want in this case.   Plus, the clean up is needed in both
+	 * cases.
+	 */
+
+	/* and disable all interrupts again */
+	SMC_SET_INT_MASK(0);
+
+	/* and return what I found */
+	return probe_irq_off(cookie);
+}
+
+/*
+ * Function: smc_probe(unsigned long ioaddr)
+ *
+ * Purpose:
+ *	Tests to see if a given ioaddr points to an SMC91x chip.
+ *	Returns a 0 on success
+ *
+ * Algorithm:
+ *	(1) see if the high byte of BANK_SELECT is 0x33
+ * 	(2) compare the ioaddr with the base register's address
+ *	(3) see if I recognize the chip ID in the appropriate register
+ *
+ * Here I do typical initialization tasks.
+ *
+ * o  Initialize the structure if needed
+ * o  print out my vanity message if not done so already
+ * o  print out what type of hardware is detected
+ * o  print out the ethernet address
+ * o  find the IRQ
+ * o  set up my private data
+ * o  configure the dev structure with my subroutines
+ * o  actually GRAB the irq.
+ * o  GRAB the region
+ */
+static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
+{
+	struct smc_local *lp = netdev_priv(dev);
+	static int version_printed = 0;
+	int i, retval;
+	unsigned int val, revision_register;
+	const char *version_string;
+
+	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
+
+	/* First, see if the high byte is 0x33 */
+	val = SMC_CURRENT_BANK();
+	DBG(2, "%s: bank signature probe returned 0x%04x\n", CARDNAME, val);
+	if ((val & 0xFF00) != 0x3300) {
+		if ((val & 0xFF) == 0x33) {
+			printk(KERN_WARNING
+				"%s: Detected possible byte-swapped interface"
+				" at IOADDR 0x%lx\n", CARDNAME, ioaddr);
+		}
+		retval = -ENODEV;
+		goto err_out;
+	}
+
+	/*
+	 * The above MIGHT indicate a device, but I need to write to
+	 * further test this.
+	 */
+	SMC_SELECT_BANK(0);
+	val = SMC_CURRENT_BANK();
+	if ((val & 0xFF00) != 0x3300) {
+		retval = -ENODEV;
+		goto err_out;
+	}
+
+	/*
+	 * well, we've already written once, so hopefully another
+	 * time won't hurt.  This time, I need to switch the bank
+	 * register to bank 1, so I can access the base address
+	 * register
+	 */
+	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",
+			CARDNAME, ioaddr, val);
+	}
+
+	/*
+	 * check if the revision register is something that I
+	 * recognize.  These might need to be added to later,
+	 * as future revisions could be added.
+	 */
+	SMC_SELECT_BANK(3);
+	revision_register = SMC_GET_REV();
+	DBG(2, "%s: revision = 0x%04x\n", CARDNAME, revision_register);
+	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"
+			", Contact author.\n", CARDNAME,
+			ioaddr, revision_register);
+
+		retval = -ENODEV;
+		goto err_out;
+	}
+
+	/* At this point I'll assume that the chip is an SMC91x. */
+	if (version_printed++ == 0)
+		printk("%s", version);
+
+	/* fill in some of the fields */
+	dev->base_addr = ioaddr;
+	lp->version = revision_register & 0xff;
+
+	/* Get the MAC address */
+	SMC_SELECT_BANK(1);
+	SMC_GET_MAC_ADDR(dev->dev_addr);
+
+	/* now, reset the chip, and put it into a known state */
+	smc_reset(dev);
+
+	/*
+	 * If dev->irq is 0, then the device has to be banged on to see
+	 * what the IRQ is.
+ 	 *
+	 * This banging doesn't always detect the IRQ, for unknown reasons.
+	 * a workaround is to reset the chip and try again.
+	 *
+	 * Interestingly, the DOS packet driver *SETS* the IRQ on the card to
+	 * be what is requested on the command line.   I don't do that, mostly
+	 * because the card that I have uses a non-standard method of accessing
+	 * the IRQs, and because this _should_ work in most configurations.
+	 *
+	 * Specifying an IRQ is done with the assumption that the user knows
+	 * what (s)he is doing.  No checking is done!!!!
+	 */
+	if (dev->irq < 1) {
+		int trials;
+
+		trials = 3;
+		while (trials--) {
+			dev->irq = smc_findirq(ioaddr);
+			if (dev->irq)
+				break;
+			/* kick the card and try again */
+			smc_reset(dev);
+		}
+	}
+	if (dev->irq == 0) {
+		printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
+			dev->name);
+		retval = -ENODEV;
+		goto err_out;
+	}
+	dev->irq = irq_canonicalize(dev->irq);
+
+	/* Fill in the fields of the device structure with ethernet values. */
+	ether_setup(dev);
+
+	dev->open = smc_open;
+	dev->stop = smc_close;
+	dev->hard_start_xmit = smc_hard_start_xmit;
+	dev->tx_timeout = smc_timeout;
+	dev->watchdog_timeo = msecs_to_jiffies(watchdog);
+	dev->get_stats = smc_query_statistics;
+	dev->set_multicast_list = smc_set_multicast_list;
+	dev->ethtool_ops = &smc_ethtool_ops;
+
+	spin_lock_init(&lp->lock);
+	lp->mii.phy_id_mask = 0x1f;
+	lp->mii.reg_num_mask = 0x1f;
+	lp->mii.force_media = 0;
+	lp->mii.full_duplex = 0;
+	lp->mii.dev = dev;
+	lp->mii.mdio_read = smc_phy_read;
+	lp->mii.mdio_write = smc_phy_write;
+
+	/*
+	 * Locate the phy, if any.
+	 */
+	if (lp->version >= (CHIP_91100 << 4))
+		smc_detect_phy(dev);
+
+	/* Set default parameters */
+	lp->msg_enable = NETIF_MSG_LINK;
+	lp->ctl_rfduplx = 0;
+	lp->ctl_rspeed = 10;
+
+	if (lp->version >= (CHIP_91100 << 4)) {
+		lp->ctl_rfduplx = 1;
+		lp->ctl_rspeed = 100;
+	}
+
+	/* Grab the IRQ */
+      	retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
+      	if (retval)
+      		goto err_out;
+
+	set_irq_type(dev->irq, IRQT_RISING);
+#ifdef SMC_USE_PXA_DMA
+	{
+		int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
+					  smc_pxa_dma_irq, NULL);
+		if (dma >= 0)
+			dev->dma = dma;
+	}
+#endif
+
+	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",
+			dev->name, version_string, revision_register & 0x0f,
+			dev->base_addr, dev->irq);
+
+		if (dev->dma != (unsigned char)-1)
+			printk(" DMA %d", dev->dma);
+
+		printk("%s%s\n", nowait ? " [nowait]" : "",
+			THROTTLE_TX_PKTS ? " [throttle_tx]" : "");
+
+		if (!is_valid_ether_addr(dev->dev_addr)) {
+			printk("%s: Invalid ethernet MAC address.  Please "
+			       "set using ifconfig\n", dev->name);
+		} else {
+			/* Print the Ethernet address */
+			printk("%s: Ethernet addr: ", dev->name);
+			for (i = 0; i < 5; i++)
+				printk("%2.2x:", dev->dev_addr[i]);
+			printk("%2.2x\n", dev->dev_addr[5]);
+		}
+
+		if (lp->phy_type == 0) {
+			PRINTK("%s: No PHY found\n", dev->name);
+		} else if ((lp->phy_type & 0xfffffff0) == 0x0016f840) {
+			PRINTK("%s: PHY LAN83C183 (LAN91C111 Internal)\n", dev->name);
+		} else if ((lp->phy_type & 0xfffffff0) == 0x02821c50) {
+			PRINTK("%s: PHY LAN83C180\n", dev->name);
+		}
+	}
+
+err_out:
+#ifdef SMC_USE_PXA_DMA
+	if (retval && dev->dma != (unsigned char)-1)
+		pxa_free_dma(dev->dma);
+#endif
+	return retval;
+}
+
+static int smc_enable_device(unsigned long attrib_phys)
+{
+	unsigned long flags;
+	unsigned char ecor, ecsr;
+	void *addr;
+
+	/*
+	 * Map the attribute space.  This is overkill, but clean.
+	 */
+	addr = ioremap(attrib_phys, ATTRIB_SIZE);
+	if (!addr)
+		return -ENOMEM;
+
+	/*
+	 * Reset the device.  We must disable IRQs around this
+	 * since a reset causes the IRQ line become active.
+	 */
+	local_irq_save(flags);
+	ecor = readb(addr + (ECOR << SMC_IO_SHIFT)) & ~ECOR_RESET;
+	writeb(ecor | ECOR_RESET, addr + (ECOR << SMC_IO_SHIFT));
+	readb(addr + (ECOR << SMC_IO_SHIFT));
+
+	/*
+	 * Wait 100us for the chip to reset.
+	 */
+	udelay(100);
+
+	/*
+	 * The device will ignore all writes to the enable bit while
+	 * reset is asserted, even if the reset bit is cleared in the
+	 * same write.  Must clear reset first, then enable the device.
+	 */
+	writeb(ecor, addr + (ECOR << SMC_IO_SHIFT));
+	writeb(ecor | ECOR_ENABLE, addr + (ECOR << SMC_IO_SHIFT));
+
+	/*
+	 * Set the appropriate byte/word mode.
+	 */
+	ecsr = readb(addr + (ECSR << SMC_IO_SHIFT)) & ~ECSR_IOIS8;
+#ifndef SMC_CAN_USE_16BIT
+	ecsr |= ECSR_IOIS8;
+#endif
+	writeb(ecsr, addr + (ECSR << SMC_IO_SHIFT));
+	local_irq_restore(flags);
+
+	iounmap(addr);
+
+	/*
+	 * Wait for the chip to wake up.  We could poll the control
+	 * register in the main register space, but that isn't mapped
+	 * yet.  We know this is going to take 750us.
+	 */
+	msleep(1);
+
+	return 0;
+}
+
+/*
+ * smc_init(void)
+ *   Input parameters:
+ *	dev->base_addr == 0, try to find all possible locations
+ *	dev->base_addr > 0x1ff, this is the address to check
+ *	dev->base_addr == <anything else>, return failure code
+ *
+ *   Output:
+ *	0 --> there is a device
+ *	anything else, error
+ */
+static int smc_drv_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct net_device *ndev;
+	struct resource *res, *ext = NULL;
+	unsigned int *addr;
+	int ret;
+
+	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")) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ndev = alloc_etherdev(sizeof(struct smc_local));
+	if (!ndev) {
+		printk("%s: could not allocate device.\n", CARDNAME);
+		ret = -ENOMEM;
+		goto release_1;
+	}
+	SET_MODULE_OWNER(ndev);
+	SET_NETDEV_DEV(ndev, dev);
+
+	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;
+		}
+
+#if defined(CONFIG_SA1100_ASSABET)
+		NCR_0 |= NCR_ENET_OSC_EN;
+#endif
+
+		ret = smc_enable_device(ext->start);
+		if (ret)
+			goto release_both;
+	}
+
+	addr = ioremap(res->start, SMC_IO_EXTENT);
+	if (!addr) {
+		ret = -ENOMEM;
+		goto release_both;
+	}
+
+	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);
+	}
+#ifdef SMC_USE_PXA_DMA
+	else {
+		struct smc_local *lp = netdev_priv(ndev);
+		lp->physaddr = res->start;
+	}
+#endif
+
+	return ret;
+}
+
+static int smc_drv_remove(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct resource *res;
+
+	dev_set_drvdata(dev, NULL);
+
+	unregister_netdev(ndev);
+
+	free_irq(ndev->irq, ndev);
+
+#ifdef SMC_USE_PXA_DMA
+	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);
+	release_mem_region(res->start, SMC_IO_EXTENT);
+
+	free_netdev(ndev);
+
+	return 0;
+}
+
+static int smc_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	if (ndev && level == SUSPEND_DISABLE) {
+		if (netif_running(ndev)) {
+			netif_device_detach(ndev);
+			smc_shutdown(ndev->base_addr);
+		}
+	}
+	return 0;
+}
+
+static int smc_drv_resume(struct device *dev, u32 level)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	if (ndev && level == RESUME_ENABLE) {
+		struct smc_local *lp = netdev_priv(ndev);
+		unsigned long ioaddr = ndev->base_addr;
+
+		if (pdev->num_resources == 3)
+			smc_enable_device(pdev->resource[2].start);
+		if (netif_running(ndev)) {
+			smc_reset(ndev);
+			smc_enable(ndev);
+			SMC_SELECT_BANK(1);
+			SMC_SET_MAC_ADDR(ndev->dev_addr);
+			if (lp->phy_type != 0)
+				smc_phy_configure(ndev);
+			netif_device_attach(ndev);
+		}
+	}
+	return 0;
+}
+
+static struct device_driver smc_driver = {
+	.name		= CARDNAME,
+	.bus		= &platform_bus_type,
+	.probe		= smc_drv_probe,
+	.remove		= smc_drv_remove,
+	.suspend	= smc_drv_suspend,
+	.resume		= smc_drv_resume,
+};
+
+static int __init smc_init(void)
+{
+#ifdef MODULE
+	if (io == -1)
+		printk(KERN_WARNING 
+			"%s: You shouldn't use auto-probing with insmod!\n",
+			CARDNAME);
+#endif
+
+	return driver_register(&smc_driver);
+}
+
+static void __exit smc_cleanup(void)
+{
+	driver_unregister(&smc_driver);
+}
+
+module_init(smc_init);
+module_exit(smc_cleanup);
diff -Nru a/drivers/net/arm/smc91x.h b/drivers/net/arm/smc91x.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/arm/smc91x.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,829 @@
+/*------------------------------------------------------------------------
+ . smc91x.h - macros for SMSC's 91C9x/91C1xx single-chip Ethernet device.
+ .
+ . Copyright (C) 1996 by Erik Stahlman
+ . Copyright (C) 2001 Standard Microsystems Corporation
+ .	Developed by Simple Network Magic Corporation
+ . Copyright (C) 2003 Monta Vista Software, Inc.
+ .	Unified SMC91x driver by Nicolas Pitre
+ .
+ . This program is free software; you can redistribute it and/or modify
+ . it under the terms of the 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
+ .
+ . Information contained in this file was obtained from the LAN91C111
+ . manual from SMC.  To get a copy, if you really want one, you can find
+ . information under www.smsc.com.
+ .
+ . Authors
+ .	Erik Stahlman		<erik@vt.edu>
+ .	Daris A Nevil		<dnevil@snmc.com>
+ .	Nicolas Pitre 		<nico@cam.org>
+ .
+ ---------------------------------------------------------------------------*/
+#ifndef _SMC91X_H_
+#define _SMC91X_H_
+
+
+/*
+ * Define your architecture specific bus configuration parameters here.
+ */
+
+#if	defined(CONFIG_SA1100_GRAPHICSCLIENT) || \
+	defined(CONFIG_SA1100_PFS168) || \
+	defined(CONFIG_SA1100_FLEXANET) || \
+	defined(CONFIG_SA1100_GRAPHICSMASTER) || \
+	defined(CONFIG_ARCH_LUBBOCK)
+
+/* 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_NOWAIT		1
+
+/* The first two address lines aren't connected... */
+#define SMC_IO_SHIFT		2
+
+#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)
+
+#elif defined(CONFIG_SA1100_ASSABET)
+
+#include <asm/arch/neponset.h>
+
+/* We can only do 8-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT	1
+#define SMC_CAN_USE_16BIT	0
+#define SMC_CAN_USE_32BIT	0
+#define SMC_NOWAIT		1
+
+/* The first two address lines aren't connected... */
+#define SMC_IO_SHIFT		2
+
+#define SMC_inb(a, r)		readb((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_insb(a, r, p, l)	readsb((a) + (r), p, (l))
+#define SMC_outsb(a, r, p, l)	writesb((a) + (r), p, (l))
+
+#elif	defined(CONFIG_ARCH_INNOKOM) || \
+	defined(CONFIG_MACH_MAINSTONE) || \
+	defined(CONFIG_ARCH_PXA_IDP) || \
+	defined(CONFIG_ARCH_RAMSES)
+
+#define SMC_CAN_USE_8BIT	1
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	1
+#define SMC_IO_SHIFT		0
+#define SMC_NOWAIT		1
+#define SMC_USE_PXA_DMA		1
+
+#define SMC_inb(a, r)		readb((a) + (r))
+#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_inl(a, r)		readl((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (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)
+
+/* We actually can't write halfwords properly if not word aligned */
+static inline void
+SMC_outw(u16 val, unsigned long ioaddr, int reg)
+{
+	if (reg & 2) {
+		unsigned int v = val << 16;
+		v |= readl(ioaddr + (reg & ~2)) & 0xffff;
+		writel(v, ioaddr + (reg & ~2));
+	} else {
+		writew(val, ioaddr + reg);
+	}
+}
+
+#elif	defined(CONFIG_ISA)
+
+#define SMC_CAN_USE_8BIT	1
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+
+#define SMC_inb(a, r)		inb((a) + (r))
+#define SMC_inw(a, r)		inw((a) + (r))
+#define SMC_outb(v, a, r)	outb(v, (a) + (r))
+#define SMC_outw(v, a, r)	outw(v, (a) + (r))
+#define SMC_insw(a, r, p, l)	insw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)	outsw((a) + (r), p, l)
+
+#else
+
+#define SMC_CAN_USE_8BIT	1
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	1
+#define SMC_NOWAIT		1
+
+#define SMC_inb(a, r)		readb((a) + (r))
+#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_inl(a, r)		readl((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)	writew(v, (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)
+
+#define RPC_LSA_DEFAULT		RPC_LED_100_10
+#define RPC_LSB_DEFAULT		RPC_LED_TX_RX
+
+#endif
+
+
+#ifdef SMC_USE_PXA_DMA
+/*
+ * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
+ * always happening in irq context so no need to worry about races.  TX is
+ * different and probably not worth it for that reason, and not as critical
+ * as RX which can overrun memory and lose packets.
+ */
+#include <linux/pci.h>
+#include <asm/dma.h>
+
+#ifdef SMC_insl
+#undef SMC_insl
+#define SMC_insl(a, r, p, l) \
+	smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l)
+static inline void
+smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma,
+		 u_char *buf, int len)
+{
+	dma_addr_t dmabuf;
+
+	/* fallback if no DMA available */
+	if (dma == (unsigned char)-1) {
+		readsl(ioaddr + reg, buf, len);
+		return;
+	}
+
+	/* 64 bit alignment is required for memory to memory DMA */
+	if ((long)buf & 4) {
+		*((u32 *)buf)++ = SMC_inl(ioaddr, reg);
+		len--;
+	}
+
+	len *= 4;
+	dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
+	DCSR(dma) = DCSR_NODESC;
+	DTADR(dma) = dmabuf;
+	DSADR(dma) = physaddr + reg;
+	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+		     DCMD_WIDTH4 | (DCMD_LENGTH & len));
+	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+	while (!(DCSR(dma) & DCSR_STOPSTATE));
+	DCSR(dma) = 0;
+	dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE);
+}
+#endif
+
+#ifdef SMC_insw
+#undef SMC_insw
+#define SMC_insw(a, r, p, l) \
+	smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l)
+static inline void
+smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma,
+		 u_char *buf, int len)
+{
+	dma_addr_t dmabuf;
+
+	/* fallback if no DMA available */
+	if (dma == (unsigned char)-1) {
+		readsw(ioaddr + reg, buf, len);
+		return;
+	}
+
+	/* 64 bit alignment is required for memory to memory DMA */
+	while ((long)buf & 6) {
+		*((u16 *)buf)++ = SMC_inw(ioaddr, reg);
+		len--;
+	}
+
+	len *= 2;
+	dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
+	DCSR(dma) = DCSR_NODESC;
+	DTADR(dma) = dmabuf;
+	DSADR(dma) = physaddr + reg;
+	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+		     DCMD_WIDTH2 | (DCMD_LENGTH & len));
+	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+	while (!(DCSR(dma) & DCSR_STOPSTATE));
+	DCSR(dma) = 0;
+	dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE);
+}
+#endif
+
+static void
+smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
+{
+	DCSR(dma) = 0;
+}
+#endif  /* SMC_USE_PXA_DMA */
+
+
+/* Because of bank switching, the LAN91x uses only 16 I/O ports */
+#ifndef SMC_IO_SHIFT
+#define SMC_IO_SHIFT	0
+#endif
+#define SMC_IO_EXTENT	(16 << SMC_IO_SHIFT)
+
+
+/*
+ . Bank Select Register:
+ .
+ .		yyyy yyyy 0000 00xx
+ .		xx 		= bank number
+ .		yyyy yyyy	= 0x33, for identification purposes.
+*/
+#define BANK_SELECT		(14 << SMC_IO_SHIFT)
+
+
+// Transmit Control Register
+/* BANK 0  */
+#define TCR_REG 	SMC_REG(0x0000, 0)
+#define TCR_ENABLE	0x0001	// When 1 we can transmit
+#define TCR_LOOP	0x0002	// Controls output pin LBK
+#define TCR_FORCOL	0x0004	// When 1 will force a collision
+#define TCR_PAD_EN	0x0080	// When 1 will pad tx frames < 64 bytes w/0
+#define TCR_NOCRC	0x0100	// When 1 will not append CRC to tx frames
+#define TCR_MON_CSN	0x0400	// When 1 tx monitors carrier
+#define TCR_FDUPLX    	0x0800  // When 1 enables full duplex operation
+#define TCR_STP_SQET	0x1000	// When 1 stops tx if Signal Quality Error
+#define TCR_EPH_LOOP	0x2000	// When 1 enables EPH block loopback
+#define TCR_SWFDUP	0x8000	// When 1 enables Switched Full Duplex mode
+
+#define TCR_CLEAR	0	/* do NOTHING */
+/* the default settings for the TCR register : */
+#define TCR_DEFAULT	(TCR_ENABLE | TCR_PAD_EN)
+
+
+// EPH Status Register
+/* BANK 0  */
+#define EPH_STATUS_REG	SMC_REG(0x0002, 0)
+#define ES_TX_SUC	0x0001	// Last TX was successful
+#define ES_SNGL_COL	0x0002	// Single collision detected for last tx
+#define ES_MUL_COL	0x0004	// Multiple collisions detected for last tx
+#define ES_LTX_MULT	0x0008	// Last tx was a multicast
+#define ES_16COL	0x0010	// 16 Collisions Reached
+#define ES_SQET		0x0020	// Signal Quality Error Test
+#define ES_LTXBRD	0x0040	// Last tx was a broadcast
+#define ES_TXDEFR	0x0080	// Transmit Deferred
+#define ES_LATCOL	0x0200	// Late collision detected on last tx
+#define ES_LOSTCARR	0x0400	// Lost Carrier Sense
+#define ES_EXC_DEF	0x0800	// Excessive Deferral
+#define ES_CTR_ROL	0x1000	// Counter Roll Over indication
+#define ES_LINK_OK	0x4000	// Driven by inverted value of nLNK pin
+#define ES_TXUNRN	0x8000	// Tx Underrun
+
+
+// Receive Control Register
+/* BANK 0  */
+#define RCR_REG		SMC_REG(0x0004, 0)
+#define RCR_RX_ABORT	0x0001	// Set if a rx frame was aborted
+#define RCR_PRMS	0x0002	// Enable promiscuous mode
+#define RCR_ALMUL	0x0004	// When set accepts all multicast frames
+#define RCR_RXEN	0x0100	// IFF this is set, we can receive packets
+#define RCR_STRIP_CRC	0x0200	// When set strips CRC from rx packets
+#define RCR_ABORT_ENB	0x0200	// When set will abort rx on collision
+#define RCR_FILT_CAR	0x0400	// When set filters leading 12 bit s of carrier
+#define RCR_SOFTRST	0x8000 	// resets the chip
+
+/* the normal settings for the RCR register : */
+#define RCR_DEFAULT	(RCR_STRIP_CRC | RCR_RXEN)
+#define RCR_CLEAR	0x0	// set it to a base state
+
+
+// Counter Register
+/* BANK 0  */
+#define COUNTER_REG	SMC_REG(0x0006, 0)
+
+
+// Memory Information Register
+/* BANK 0  */
+#define MIR_REG		SMC_REG(0x0008, 0)
+
+
+// Receive/Phy Control Register
+/* BANK 0  */
+#define RPC_REG		SMC_REG(0x000A, 0)
+#define RPC_SPEED	0x2000	// When 1 PHY is in 100Mbps mode.
+#define RPC_DPLX	0x1000	// When 1 PHY is in Full-Duplex Mode
+#define RPC_ANEG	0x0800	// When 1 PHY is in Auto-Negotiate Mode
+#define RPC_LSXA_SHFT	5	// Bits to shift LS2A,LS1A,LS0A to lsb
+#define RPC_LSXB_SHFT	2	// Bits to get LS2B,LS1B,LS0B to lsb
+#define RPC_LED_100_10	(0x00)	// LED = 100Mbps OR's with 10Mbps link detect
+#define RPC_LED_RES	(0x01)	// LED = Reserved
+#define RPC_LED_10	(0x02)	// LED = 10Mbps link detect
+#define RPC_LED_FD	(0x03)	// LED = Full Duplex Mode
+#define RPC_LED_TX_RX	(0x04)	// LED = TX or RX packet occurred
+#define RPC_LED_100	(0x05)	// LED = 100Mbps link dectect
+#define RPC_LED_TX	(0x06)	// LED = TX packet occurred
+#define RPC_LED_RX	(0x07)	// LED = RX packet occurred
+
+#ifndef RPC_LSA_DEFAULT
+#define RPC_LSA_DEFAULT	RPC_LED_100
+#endif
+#ifndef RPC_LSB_DEFAULT
+#define RPC_LSB_DEFAULT RPC_LED_FD
+#endif
+
+#define RPC_DEFAULT (RPC_ANEG | (RPC_LSA_DEFAULT << RPC_LSXA_SHFT) | (RPC_LSB_DEFAULT << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
+
+
+/* Bank 0 0x0C is reserved */
+
+// Bank Select Register
+/* All Banks */
+#define BSR_REG		0x000E
+
+
+// Configuration Reg
+/* BANK 1 */
+#define CONFIG_REG	SMC_REG(0x0000,	1)
+#define CONFIG_EXT_PHY	0x0200	// 1=external MII, 0=internal Phy
+#define CONFIG_GPCNTRL	0x0400	// Inverse value drives pin nCNTRL
+#define CONFIG_NO_WAIT	0x1000	// When 1 no extra wait states on ISA bus
+#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode.
+
+// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low
+#define CONFIG_DEFAULT	(CONFIG_EPH_POWER_EN)
+
+
+// Base Address Register
+/* BANK 1 */
+#define BASE_REG	SMC_REG(0x0002, 1)
+
+
+// Individual Address Registers
+/* BANK 1 */
+#define ADDR0_REG	SMC_REG(0x0004, 1)
+#define ADDR1_REG	SMC_REG(0x0006, 1)
+#define ADDR2_REG	SMC_REG(0x0008, 1)
+
+
+// General Purpose Register
+/* BANK 1 */
+#define GP_REG		SMC_REG(0x000A, 1)
+
+
+// Control Register
+/* BANK 1 */
+#define CTL_REG		SMC_REG(0x000C, 1)
+#define CTL_RCV_BAD	0x4000 // When 1 bad CRC packets are received
+#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically
+#define CTL_LE_ENABLE	0x0080 // When 1 enables Link Error interrupt
+#define CTL_CR_ENABLE	0x0040 // When 1 enables Counter Rollover interrupt
+#define CTL_TE_ENABLE	0x0020 // When 1 enables Transmit Error interrupt
+#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store
+#define CTL_RELOAD	0x0002 // When set reads EEPROM into registers
+#define CTL_STORE	0x0001 // When set stores registers into EEPROM
+
+
+// MMU Command Register
+/* BANK 2 */
+#define MMU_CMD_REG	SMC_REG(0x0000, 2)
+#define MC_BUSY		1	// When 1 the last release has not completed
+#define MC_NOP		(0<<5)	// No Op
+#define MC_ALLOC	(1<<5) 	// OR with number of 256 byte packets
+#define MC_RESET	(2<<5)	// Reset MMU to initial state
+#define MC_REMOVE	(3<<5) 	// Remove the current rx packet
+#define MC_RELEASE  	(4<<5) 	// Remove and release the current rx packet
+#define MC_FREEPKT  	(5<<5) 	// Release packet in PNR register
+#define MC_ENQUEUE	(6<<5)	// Enqueue the packet for transmit
+#define MC_RSTTXFIFO	(7<<5)	// Reset the TX FIFOs
+
+
+// Packet Number Register
+/* BANK 2 */
+#define PN_REG		SMC_REG(0x0002, 2)
+
+
+// Allocation Result Register
+/* BANK 2 */
+#define AR_REG		SMC_REG(0x0003, 2)
+#define AR_FAILED	0x80	// Alocation Failed
+
+
+// TX FIFO Ports Register
+/* BANK 2 */
+#define TXFIFO_REG	SMC_REG(0x0004, 2)
+#define TXFIFO_TEMPTY	0x80	// TX FIFO Empty
+
+// RX FIFO Ports Register
+/* BANK 2 */
+#define RXFIFO_REG	SMC_REG(0x0005, 2)
+#define RXFIFO_REMPTY	0x80	// RX FIFO Empty
+
+#define FIFO_REG	SMC_REG(0x0004, 2)
+
+// Pointer Register
+/* BANK 2 */
+#define PTR_REG		SMC_REG(0x0006, 2)
+#define PTR_RCV		0x8000 // 1=Receive area, 0=Transmit area
+#define PTR_AUTOINC 	0x4000 // Auto increment the pointer on each access
+#define PTR_READ	0x2000 // When 1 the operation is a read
+
+
+// Data Register
+/* BANK 2 */
+#define DATA_REG	SMC_REG(0x0008, 2)
+
+
+// Interrupt Status/Acknowledge Register
+/* BANK 2 */
+#define INT_REG		SMC_REG(0x000C, 2)
+
+
+// Interrupt Mask Register
+/* BANK 2 */
+#define IM_REG		SMC_REG(0x000D, 2)
+#define IM_MDINT	0x80 // PHY MI Register 18 Interrupt
+#define IM_ERCV_INT	0x40 // Early Receive Interrupt
+#define IM_EPH_INT	0x20 // Set by Ethernet Protocol Handler section
+#define IM_RX_OVRN_INT	0x10 // Set by Receiver Overruns
+#define IM_ALLOC_INT	0x08 // Set when allocation request is completed
+#define IM_TX_EMPTY_INT	0x04 // Set if the TX FIFO goes empty
+#define IM_TX_INT	0x02 // Transmit Interrupt
+#define IM_RCV_INT	0x01 // Receive Interrupt
+
+
+// Multicast Table Registers
+/* BANK 3 */
+#define MCAST_REG1	SMC_REG(0x0000, 3)
+#define MCAST_REG2	SMC_REG(0x0002, 3)
+#define MCAST_REG3	SMC_REG(0x0004, 3)
+#define MCAST_REG4	SMC_REG(0x0006, 3)
+
+
+// Management Interface Register (MII)
+/* BANK 3 */
+#define MII_REG		SMC_REG(0x0008, 3)
+#define MII_MSK_CRS100	0x4000 // Disables CRS100 detection during tx half dup
+#define MII_MDOE	0x0008 // MII Output Enable
+#define MII_MCLK	0x0004 // MII Clock, pin MDCLK
+#define MII_MDI		0x0002 // MII Input, pin MDI
+#define MII_MDO		0x0001 // MII Output, pin MDO
+
+
+// Revision Register
+/* BANK 3 */
+/* ( hi: chip id   low: rev # ) */
+#define REV_REG		SMC_REG(0x000A, 3)
+
+
+// Early RCV Register
+/* BANK 3 */
+/* this is NOT on SMC9192 */
+#define ERCV_REG	SMC_REG(0x000C, 3)
+#define ERCV_RCV_DISCRD	0x0080 // When 1 discards a packet being received
+#define ERCV_THRESHOLD	0x001F // ERCV Threshold Mask
+
+
+// External Register
+/* BANK 7 */
+#define EXT_REG		SMC_REG(0x0000, 7)
+
+
+#define CHIP_9192	3
+#define CHIP_9194	4
+#define CHIP_9195	5
+#define CHIP_9196	6
+#define CHIP_91100	7
+#define CHIP_91100FD	8
+#define CHIP_91111FD	9
+
+static const char * chip_ids[ 16 ] =  {
+	NULL, NULL, NULL,
+	/* 3 */ "SMC91C90/91C92",
+	/* 4 */ "SMC91C94",
+	/* 5 */ "SMC91C95",
+	/* 6 */ "SMC91C96",
+	/* 7 */ "SMC91C100",
+	/* 8 */ "SMC91C100FD",
+	/* 9 */ "SMC91C11xFD",
+	NULL, NULL, NULL,
+	NULL, NULL, NULL};
+
+
+/*
+ . Transmit status bits
+*/
+#define TS_SUCCESS 0x0001
+#define TS_LOSTCAR 0x0400
+#define TS_LATCOL  0x0200
+#define TS_16COL   0x0010
+
+/*
+ . Receive status bits
+*/
+#define RS_ALGNERR	0x8000
+#define RS_BRODCAST	0x4000
+#define RS_BADCRC	0x2000
+#define RS_ODDFRAME	0x1000
+#define RS_TOOLONG	0x0800
+#define RS_TOOSHORT	0x0400
+#define RS_MULTICAST	0x0001
+#define RS_ERRORS	(RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
+
+
+/*
+ * PHY IDs
+ *  LAN83C183 == LAN91C111 Internal PHY
+ */
+#define PHY_LAN83C183	0x0016f840
+#define PHY_LAN83C180	0x02821c50
+
+/*
+ * PHY Register Addresses (LAN91C111 Internal PHY)
+ *
+ * Generic PHY registers can be found in <linux/mii.h>
+ *
+ * These phy registers are specific to our on-board phy.
+ */
+
+// PHY Configuration Register 1
+#define PHY_CFG1_REG		0x10
+#define PHY_CFG1_LNKDIS		0x8000	// 1=Rx Link Detect Function disabled
+#define PHY_CFG1_XMTDIS		0x4000	// 1=TP Transmitter Disabled
+#define PHY_CFG1_XMTPDN		0x2000	// 1=TP Transmitter Powered Down
+#define PHY_CFG1_BYPSCR		0x0400	// 1=Bypass scrambler/descrambler
+#define PHY_CFG1_UNSCDS		0x0200	// 1=Unscramble Idle Reception Disable
+#define PHY_CFG1_EQLZR		0x0100	// 1=Rx Equalizer Disabled
+#define PHY_CFG1_CABLE		0x0080	// 1=STP(150ohm), 0=UTP(100ohm)
+#define PHY_CFG1_RLVL0		0x0040	// 1=Rx Squelch level reduced by 4.5db
+#define PHY_CFG1_TLVL_SHIFT	2	// Transmit Output Level Adjust
+#define PHY_CFG1_TLVL_MASK	0x003C
+#define PHY_CFG1_TRF_MASK	0x0003	// Transmitter Rise/Fall time
+
+
+// PHY Configuration Register 2
+#define PHY_CFG2_REG		0x11
+#define PHY_CFG2_APOLDIS	0x0020	// 1=Auto Polarity Correction disabled
+#define PHY_CFG2_JABDIS		0x0010	// 1=Jabber disabled
+#define PHY_CFG2_MREG		0x0008	// 1=Multiple register access (MII mgt)
+#define PHY_CFG2_INTMDIO	0x0004	// 1=Interrupt signaled with MDIO pulseo
+
+// PHY Status Output (and Interrupt status) Register
+#define PHY_INT_REG		0x12	// Status Output (Interrupt Status)
+#define PHY_INT_INT		0x8000	// 1=bits have changed since last read
+#define PHY_INT_LNKFAIL		0x4000	// 1=Link Not detected
+#define PHY_INT_LOSSSYNC	0x2000	// 1=Descrambler has lost sync
+#define PHY_INT_CWRD		0x1000	// 1=Invalid 4B5B code detected on rx
+#define PHY_INT_SSD		0x0800	// 1=No Start Of Stream detected on rx
+#define PHY_INT_ESD		0x0400	// 1=No End Of Stream detected on rx
+#define PHY_INT_RPOL		0x0200	// 1=Reverse Polarity detected
+#define PHY_INT_JAB		0x0100	// 1=Jabber detected
+#define PHY_INT_SPDDET		0x0080	// 1=100Base-TX mode, 0=10Base-T mode
+#define PHY_INT_DPLXDET		0x0040	// 1=Device in Full Duplex
+
+// PHY Interrupt/Status Mask Register
+#define PHY_MASK_REG		0x13	// Interrupt Mask
+// Uses the same bit definitions as PHY_INT_REG
+
+
+/*
+ * SMC91C96 ethernet config and status registers.
+ * These are in the "attribute" space.
+ */
+#define ECOR			0x8000
+#define ECOR_RESET		0x80
+#define ECOR_LEVEL_IRQ		0x40
+#define ECOR_WR_ATTRIB		0x04
+#define ECOR_ENABLE		0x01
+
+#define ECSR			0x8002
+#define ECSR_IOIS8		0x20
+#define ECSR_PWRDWN		0x04
+#define ECSR_INT		0x02
+
+#define ATTRIB_SIZE		((64*1024) << SMC_IO_SHIFT)
+
+
+/*
+ * Macros to abstract register access according to the data bus
+ * capabilities.  Please use those and not the in/out primitives.
+ * Note: the following macros do *not* select the bank -- this must
+ * be done separately as needed in the main code.  The SMC_REG() macro
+ * only uses the bank argument for debugging purposes (when enabled).
+ */
+
+#if SMC_DEBUG > 0
+#define SMC_REG(reg, bank)						\
+	({								\
+		int __b = SMC_CURRENT_BANK();				\
+		if (unlikely((__b & ~0xf0) != (0x3300 | bank))) {	\
+			printk( "%s: bank reg screwed (0x%04x)\n",	\
+				CARDNAME, __b );			\
+			BUG();						\
+		}							\
+		reg<<SMC_IO_SHIFT;					\
+	})
+#else
+#define SMC_REG(reg, bank)	(reg<<SMC_IO_SHIFT)
+#endif
+
+#if SMC_CAN_USE_8BIT
+#define SMC_GET_PN()		SMC_inb( ioaddr, PN_REG )
+#define SMC_SET_PN(x)		SMC_outb( x, ioaddr, PN_REG )
+#define SMC_GET_AR()		SMC_inb( ioaddr, AR_REG )
+#define SMC_GET_TXFIFO()	SMC_inb( ioaddr, TXFIFO_REG )
+#define SMC_GET_RXFIFO()	SMC_inb( ioaddr, RXFIFO_REG )
+#define SMC_GET_INT()		SMC_inb( ioaddr, INT_REG )
+#define SMC_ACK_INT(x)		SMC_outb( x, ioaddr, INT_REG )
+#define SMC_GET_INT_MASK()	SMC_inb( ioaddr, IM_REG )
+#define SMC_SET_INT_MASK(x)	SMC_outb( x, ioaddr, IM_REG )
+#else
+#define SMC_GET_PN()		(SMC_inw( ioaddr, PN_REG ) & 0xFF)
+#define SMC_SET_PN(x)		SMC_outw( x, ioaddr, PN_REG )
+#define SMC_GET_AR()		(SMC_inw( ioaddr, PN_REG ) >> 8)
+#define SMC_GET_TXFIFO()	(SMC_inw( ioaddr, TXFIFO_REG ) & 0xFF)
+#define SMC_GET_RXFIFO()	(SMC_inw( ioaddr, TXFIFO_REG ) >> 8)
+#define SMC_GET_INT()		(SMC_inw( ioaddr, INT_REG ) & 0xFF)
+#define SMC_ACK_INT(x)							\
+	do {								\
+		unsigned long __flags;					\
+		int __mask;						\
+		local_irq_save(__flags);				\
+		__mask = SMC_inw( ioaddr, INT_REG ) & ~0xff;		\
+		SMC_outw( __mask | (x), ioaddr, INT_REG );		\
+		local_irq_restore(__flags);				\
+	} while (0)
+#define SMC_GET_INT_MASK()	(SMC_inw( ioaddr, INT_REG ) >> 8)
+#define SMC_SET_INT_MASK(x)	SMC_outw( (x) << 8, ioaddr, INT_REG )
+#endif
+
+#define SMC_CURRENT_BANK()	SMC_inw( ioaddr, BANK_SELECT )
+#define SMC_SELECT_BANK(x)	SMC_outw( x, ioaddr, BANK_SELECT )
+#define SMC_GET_BASE()		SMC_inw( ioaddr, BASE_REG )
+#define SMC_SET_BASE(x)		SMC_outw( x, ioaddr, BASE_REG )
+#define SMC_GET_CONFIG()	SMC_inw( ioaddr, CONFIG_REG )
+#define SMC_SET_CONFIG(x)	SMC_outw( x, ioaddr, CONFIG_REG )
+#define SMC_GET_COUNTER()	SMC_inw( ioaddr, COUNTER_REG )
+#define SMC_GET_CTL()		SMC_inw( ioaddr, CTL_REG )
+#define SMC_SET_CTL(x)		SMC_outw( x, ioaddr, CTL_REG )
+#define SMC_GET_MII()		SMC_inw( ioaddr, MII_REG )
+#define SMC_SET_MII(x)		SMC_outw( x, ioaddr, MII_REG )
+#define SMC_GET_MIR()		SMC_inw( ioaddr, MIR_REG )
+#define SMC_SET_MIR(x)		SMC_outw( x, ioaddr, MIR_REG )
+#define SMC_GET_MMU_CMD()	SMC_inw( ioaddr, MMU_CMD_REG )
+#define SMC_SET_MMU_CMD(x)	SMC_outw( x, ioaddr, MMU_CMD_REG )
+#define SMC_GET_FIFO()		SMC_inw( ioaddr, FIFO_REG )
+#define SMC_GET_PTR()		SMC_inw( ioaddr, PTR_REG )
+#define SMC_SET_PTR(x)		SMC_outw( x, ioaddr, PTR_REG )
+#define SMC_GET_RCR()		SMC_inw( ioaddr, RCR_REG )
+#define SMC_SET_RCR(x)		SMC_outw( x, ioaddr, RCR_REG )
+#define SMC_GET_REV()		SMC_inw( ioaddr, REV_REG )
+#define SMC_GET_RPC()		SMC_inw( ioaddr, RPC_REG )
+#define SMC_SET_RPC(x)		SMC_outw( x, ioaddr, RPC_REG )
+#define SMC_GET_TCR()		SMC_inw( ioaddr, TCR_REG )
+#define SMC_SET_TCR(x)		SMC_outw( x, ioaddr, TCR_REG )
+
+#ifndef SMC_GET_MAC_ADDR
+#define SMC_GET_MAC_ADDR(addr)						\
+	do {								\
+		unsigned int __v;					\
+		__v = SMC_inw( ioaddr, ADDR0_REG );			\
+		addr[0] = __v; addr[1] = __v >> 8;			\
+		__v = SMC_inw( ioaddr, ADDR1_REG );			\
+		addr[2] = __v; addr[3] = __v >> 8;			\
+		__v = SMC_inw( ioaddr, ADDR2_REG );			\
+		addr[4] = __v; addr[5] = __v >> 8;			\
+	} while (0)
+#endif
+
+#define SMC_SET_MAC_ADDR(addr)						\
+	do {								\
+		SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG );	\
+		SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG );	\
+		SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG );	\
+	} while (0)
+
+#define SMC_CLEAR_MCAST()						\
+	do {								\
+		SMC_outw( 0, ioaddr, MCAST_REG1 );			\
+		SMC_outw( 0, ioaddr, MCAST_REG2 );			\
+		SMC_outw( 0, ioaddr, MCAST_REG3 );			\
+		SMC_outw( 0, ioaddr, MCAST_REG4 );			\
+	} while (0)
+#define SMC_SET_MCAST(x)						\
+	do {								\
+		unsigned char *mt = (x);				\
+		SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 );	\
+		SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 );	\
+		SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 );	\
+		SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 );	\
+	} while (0)
+
+#if SMC_CAN_USE_32BIT
+/*
+ * Some setups just can't write 8 or 16 bits reliably when not aligned
+ * to a 32 bit boundary.  I tell you that exists!
+ * We re-do the ones here that can be easily worked around if they can have
+ * their low parts written to 0 without adverse effects.
+ */
+#undef SMC_SELECT_BANK
+#define SMC_SELECT_BANK(x)	SMC_outl( (x)<<16, ioaddr, 12<<SMC_IO_SHIFT )
+#undef SMC_SET_RPC
+#define SMC_SET_RPC(x)		SMC_outl( (x)<<16, ioaddr, SMC_REG(8, 0) )
+#undef SMC_SET_PN
+#define SMC_SET_PN(x)		SMC_outl( (x)<<16, ioaddr, SMC_REG(0, 2) )
+#undef SMC_SET_PTR
+#define SMC_SET_PTR(x)		SMC_outl( (x)<<16, ioaddr, SMC_REG(4, 2) )
+#endif
+
+#if SMC_CAN_USE_32BIT
+#define SMC_PUT_PKT_HDR(status, length)					\
+	SMC_outl( (status) | (length) << 16, ioaddr, DATA_REG )
+#define SMC_GET_PKT_HDR(status, length)					\
+	do {								\
+		unsigned int __val = SMC_inl( ioaddr, DATA_REG );	\
+		(status) = __val & 0xffff;				\
+		(length) = __val >> 16;					\
+	} while (0)
+#else
+#define SMC_PUT_PKT_HDR(status, length)					\
+	do {								\
+		SMC_outw( status, ioaddr, DATA_REG );			\
+		SMC_outw( length, ioaddr, DATA_REG );			\
+	} while (0)
+#define SMC_GET_PKT_HDR(status, length)					\
+	do {								\
+		(status) = SMC_inw( ioaddr, DATA_REG );			\
+		(length) = SMC_inw( ioaddr, DATA_REG );			\
+	} while (0)
+#endif
+
+#if SMC_CAN_USE_32BIT
+#define SMC_PUSH_DATA(p, l)						\
+	do {								\
+		char *__ptr = (p);					\
+		int __len = (l);					\
+		if (__len >= 2 && (long)__ptr & 2) {			\
+			__len -= 2;					\
+			SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\
+		}							\
+		SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2);	\
+		if (__len & 2) {					\
+			__ptr += (__len & ~3);				\
+			SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG );	\
+		}							\
+	} while (0)
+#define SMC_PULL_DATA(p, l)						\
+	do {								\
+		char *__ptr = (p);					\
+		int __len = (l);					\
+		if ((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.	\
+			 */						\
+			(long)__ptr &= ~2;				\
+			__len += 2;					\
+			SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC );	\
+		}							\
+		__len += 2;						\
+		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 )
+#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 )
+#endif
+
+#if ! SMC_CAN_USE_16BIT
+#define SMC_outw(x, ioaddr, reg)					\
+	do {								\
+		unsigned int __val16 = (x);				\
+		SMC_outb( __val16, ioaddr, reg );			\
+		SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\
+	} while (0)
+#define SMC_inw(ioaddr, reg)						\
+	({								\
+		unsigned int __val16;					\
+		__val16 =  SMC_inb( ioaddr, reg );			\
+		__val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \
+		__val16;						\
+	})
+#endif
+
+
+#endif  /* _SMC91X_H_ */
diff -Nru a/drivers/net/at1700.c b/drivers/net/at1700.c
--- a/drivers/net/at1700.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/at1700.c	2004-06-23 19:04:26 -07:00
@@ -65,6 +65,8 @@
 static char version[] __initdata =
 	"at1700.c:v1.15 4/7/98  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
+#define DRV_NAME "at1700"
+
 /* Tunable parameters. */
 
 /* When to switch from the 64-entry multicast filter to Rx-all-multicast. */
@@ -80,17 +82,10 @@
  *	ISA
  */
 
-#ifndef CONFIG_X86_PC9800
 static unsigned at1700_probe_list[] __initdata = {
 	0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
 };
 
-#else /* CONFIG_X86_PC9800 */
-static unsigned at1700_probe_list[] __initdata = {
-	0x1d6, 0x1d8, 0x1da, 0x1d4, 0xd4, 0xd2, 0xd8, 0xd0, 0
-};
-
-#endif /* CONFIG_X86_PC9800 */
 /*
  *	MCA
  */
@@ -133,7 +128,6 @@
 
 
 /* Offsets from the base address. */
-#ifndef CONFIG_X86_PC9800
 #define STATUS			0
 #define TX_STATUS		0
 #define RX_STATUS		1
@@ -161,34 +155,6 @@
 #define RESET			31		/* Write to reset some parts of the chip. */
 #define AT1700_IO_EXTENT	32
 #define PORT_OFFSET(o) (o)
-#else /* CONFIG_X86_PC9800 */
-#define STATUS			(0x0000)
-#define TX_STATUS		(0x0000)
-#define RX_STATUS		(0x0001)
-#define TX_INTR			(0x0200)/* Bit-mapped interrupt enable registers. */
-#define RX_INTR			(0x0201)
-#define TX_MODE			(0x0400)
-#define RX_MODE			(0x0401)
-#define CONFIG_0		(0x0600)/* Misc. configuration settings. */
-#define CONFIG_1		(0x0601)
-/* Run-time register bank 2 definitions. */
-#define DATAPORT		(0x0800)/* Word-wide DMA or programmed-I/O dataport. */
-#define TX_START		(0x0a00)
-#define COL16CNTL		(0x0a01)/* Controll Reg for 16 collisions */
-#define MODE13			(0x0c01)
-#define RX_CTRL			(0x0e00)
-/* Configuration registers only on the '865A/B chips. */
-#define EEPROM_Ctrl 	(0x1000)
-#define EEPROM_Data 	(0x1200)
-#define CARDSTATUS	16			/* FMV-18x Card Status */
-#define CARDSTATUS1	17			/* FMV-18x Card Status */
-#define IOCONFIG		(0x1400)/* Either read the jumper, or move the I/O. */
-#define IOCONFIG1		(0x1600)
-#define	SAPROM			20		/* The station address PROM, if no EEPROM. */
-#define	MODE24			(0x1800)/* The station address PROM, if no EEPROM. */
-#define RESET			(0x1e01)/* Write to reset some parts of the chip. */
-#define PORT_OFFSET(o) ({ int _o_ = (o); (_o_ & ~1) * 0x100 + (_o_ & 1); })
-#endif /* CONFIG_X86_PC9800 */
 
 
 #define TX_TIMEOUT		10
@@ -230,11 +196,7 @@
    (detachable devices only).
    */
 
-#ifndef CONFIG_X86_PC9800
 static int io = 0x260;
-#else
-static int io = 0xd0;
-#endif
 
 static int irq;
 
@@ -246,15 +208,7 @@
 		mca_mark_as_unused(lp->mca_slot);
 #endif	
 	free_irq(dev->irq, NULL);
-#ifndef CONFIG_X86_PC9800
 	release_region(dev->base_addr, AT1700_IO_EXTENT);
-#else
-	{
-		int i;
-		for (i = 0; i < 0x2000; i += 0x200)
-			release_region(dev->base_addr + i, 2);
-	}
-#endif
 }
 
 struct net_device * __init at1700_probe(int unit)
@@ -321,20 +275,8 @@
 	int slot, ret = -ENODEV;
 	struct net_local *lp = netdev_priv(dev);
 
-#ifndef CONFIG_X86_PC9800
-	if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, AT1700_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
-#else
-	for (i = 0; i < 0x2000; i += 0x0200) {
-		if (!request_region(ioaddr + i, 2, dev->name)) {
-			while (i > 0) {
-				i -= 0x0200;
-				release_region(ioaddr + i, 2);
-			}
-			return -EBUSY;
-		}
-	}
-#endif
 
 	/* Resetting the chip doesn't reset the ISA interface, so don't bother.
 	   That means we have to be careful with the register values we probe
@@ -425,15 +367,8 @@
 	outb(0, ioaddr + RESET);
 
 	if (is_at1700) {
-#ifndef CONFIG_X86_PC9800
 		irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
 						   | (read_eeprom(ioaddr, 0)>>14)];
-#else
-		{
-			char re1000plus_irqmap[4] = {3, 5, 6, 12};
-			irq = re1000plus_irqmap[inb(ioaddr + IOCONFIG1) >> 6];
-		}
-#endif
 	} else {
 		/* Check PnP mode for FMV-183/184/183A/184A. */
 		/* This PnP routine is very poor. IO and IRQ should be known. */
@@ -517,11 +452,7 @@
 	/* Switch to bank 2 */
 	/* Lock our I/O address, and set manual processing mode for 16 collisions. */
 	outb(0x08, ioaddr + CONFIG_1);
-#ifndef CONFIG_X86_PC9800
 	outb(dev->if_port, ioaddr + MODE13);
-#else
-	outb(0, ioaddr + MODE13);
-#endif
 	outb(0x00, ioaddr + COL16CNTL);
 
 	if (net_debug)
@@ -542,7 +473,7 @@
 	lp->jumpered = is_fmv18x;
 	lp->mca_slot = slot;
 	/* Snarf the interrupt vector now. */
-	ret = request_irq(irq, &net_interrupt, 0, dev->name, dev);
+	ret = request_irq(irq, &net_interrupt, 0, DRV_NAME, dev);
 	if (ret) {
 		printk ("  AT1700 at %#3x is unusable due to a conflict on"
 				"IRQ %d.\n", ioaddr, irq);
@@ -557,12 +488,7 @@
 		mca_mark_as_unused(slot);
 #endif
 err_out:
-#ifndef CONFIG_X86_PC9800
 	release_region(ioaddr, AT1700_IO_EXTENT);
-#else
-	for (i = 0; i < 0x2000; i += 0x0200)
-		release_region(ioaddr + i, 2);
-#endif
 	return ret;
 }
 
@@ -573,13 +499,6 @@
 #define EE_DATA_WRITE	0x80	/* EEPROM chip data in, in reg. 17. */
 #define EE_DATA_READ	0x80	/* EEPROM chip data out, in reg. 17. */
 
-/* Delay between EEPROM clock transitions. */
-#ifndef CONFIG_X86_PC9800
-#define eeprom_delay()	do { } while (0)
-#else
-#define eeprom_delay()	__asm__ ("out%B0 %%al,%0" :: "N"(0x5f))
-#endif
-
 /* The EEPROM commands include the alway-set leading bit. */
 #define EE_WRITE_CMD	(5 << 6)
 #define EE_READ_CMD		(6 << 6)
@@ -598,22 +517,17 @@
 		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
 		outb(EE_CS, ee_addr);
 		outb(dataval, ee_daddr);
-		eeprom_delay();
 		outb(EE_CS | EE_SHIFT_CLK, ee_addr);	/* EEPROM clock tick. */
-		eeprom_delay();
 	}
 	outb(EE_DATA_WRITE, ee_daddr);
 	for (i = 16; i > 0; i--) {
 		outb(EE_CS, ee_addr);
-		eeprom_delay();
 		outb(EE_CS | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay();
 		retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0);
 	}
 
 	/* Terminate the EEPROM access. */
 	outb(EE_CS, ee_addr);
-	eeprom_delay();
 	outb(EE_SHIFT_CLK, ee_addr);
 	outb(0, ee_addr);
 	return retval;
diff -Nru a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
--- a/drivers/net/cs89x0.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/cs89x0.c	2004-06-23 19:04:28 -07:00
@@ -141,6 +141,8 @@
 static char version[] __initdata =
 "cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n";
 
+#define DRV_NAME "cs89x0"
+
 /* First, a few definitions that the brave might change.
    A zero-terminated list of I/O addresses to be probed. Some special flags..
       Addr & 1 = Read back the address port, look for signature and reset
@@ -261,7 +263,6 @@
 }
 
 __setup("cs89x0_media=", media_fn);
-#endif
 
 
 /* Check for a network adaptor of this type, and return '0' iff one exists.
@@ -318,6 +319,7 @@
 	printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected.  Be sure to disable PnP with SETUP\n");
 	return ERR_PTR(err);
 }
+#endif
 
 static int
 readreg(struct net_device *dev, int portno)
@@ -425,9 +427,9 @@
 
 	/* Grab the region so we can find another board if autoIRQ fails. */
 	/* WTF is going on here? */
-	if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, dev->name)) {
+	if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) {
 		printk(KERN_ERR "%s: request_region(0x%x, 0x%x) failed\n",
-				dev->name, ioaddr, NETCARD_IO_EXTENT);
+				DRV_NAME, ioaddr, NETCARD_IO_EXTENT);
 		retval = -EBUSY;
 		goto out1;
 	}
diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c
--- a/drivers/net/defxx.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/defxx.c	2004-06-23 19:04:25 -07:00
@@ -219,6 +219,8 @@
 static char version[] __devinitdata =
 	"defxx.c:v1.06 2003/08/04  Lawrence V. Stefani and others\n";
 
+#define DRV_NAME "defxx"
+
 #define DYNAMIC_BUFFERS 1
 
 #define SKBUFF_RX_COPYBREAK 200
@@ -435,9 +437,9 @@
 
 	bp = dev->priv;
 
-	if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, dev->name)) {
+	if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, DRV_NAME)) {
 		printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n",
-			dev->name, PFI_K_CSR_IO_LEN, ioaddr);
+			DRV_NAME, PFI_K_CSR_IO_LEN, ioaddr);
 		err = -EBUSY;
 		goto err_out;
 	}
diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
--- a/drivers/net/e1000/e1000.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/e1000/e1000.h	2004-06-23 19:04:25 -07:00
@@ -196,6 +196,7 @@
 	uint32_t part_num;
 	uint32_t wol;
 	uint32_t smartspeed;
+	uint32_t en_mng_pt;
 	uint16_t link_speed;
 	uint16_t link_duplex;
 	spinlock_t stats_lock;
diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- a/drivers/net/e1000/e1000_ethtool.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/e1000/e1000_ethtool.c	2004-06-23 19:04:26 -07:00
@@ -1004,11 +1004,12 @@
 		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
 		struct sk_buff *skb;
 
-		if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + 2, GFP_KERNEL))) {
+		if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
+				     GFP_KERNEL))) {
 			ret_val = 6;
 			goto err_nomem;
 		}
-		skb_reserve(skb, 2);
+		skb_reserve(skb, NET_IP_ALIGN);
 		rxdr->buffer_info[i].skb = skb;
 		rxdr->buffer_info[i].length = E1000_RXBUFFER_2048;
 		rxdr->buffer_info[i].dma =
diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
--- a/drivers/net/e1000/e1000_hw.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/e1000/e1000_hw.c	2004-06-23 19:04:28 -07:00
@@ -265,6 +265,17 @@
         return -E1000_ERR_MAC_TYPE;
     }
 
+    switch(hw->mac_type) {
+    case e1000_82541:
+    case e1000_82547:
+    case e1000_82541_rev_2:
+    case e1000_82547_rev_2:
+        hw->asf_firmware_present = TRUE;
+        break;
+    default:
+        break;
+    }
+
     return E1000_SUCCESS;
 }
 
@@ -5189,3 +5200,27 @@
     return E1000_SUCCESS;
 }
 
+/******************************************************************************
+ * Verifies the hardware needs to allow ARPs to be processed by the host
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * returns: - TRUE/FALSE
+ *
+ *****************************************************************************/
+uint32_t
+e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+{
+    uint32_t manc;
+
+    if (hw->asf_firmware_present) {
+        manc = E1000_READ_REG(hw, MANC);
+
+        if (!(manc & E1000_MANC_RCV_TCO_EN) ||
+            !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+            return FALSE;
+        if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
+            return TRUE;
+    }
+    return FALSE;
+}
diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
--- a/drivers/net/e1000/e1000_hw.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/e1000/e1000_hw.h	2004-06-23 19:04:28 -07:00
@@ -307,6 +307,7 @@
 /* Adaptive IFS Functions */
 
 /* Everything else */
+uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
 void e1000_clear_hw_cntrs(struct e1000_hw *hw);
 void e1000_reset_adaptive(struct e1000_hw *hw);
 void e1000_update_adaptive(struct e1000_hw *hw);
@@ -983,6 +984,7 @@
     e1000_ms_type master_slave;
     e1000_ms_type original_master_slave;
     e1000_ffe_config ffe_config_state;
+    uint32_t asf_firmware_present;
     unsigned long io_base;
     uint32_t phy_id;
     uint32_t phy_revision;
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/e1000/e1000_main.c	2004-06-23 19:04:26 -07:00
@@ -299,7 +299,7 @@
 void
 e1000_reset(struct e1000_adapter *adapter)
 {
-	uint32_t pba;
+	uint32_t pba, manc;
 	/* Repartition Pba for greater than 9k mtu
 	 * To take effect CTRL.RST is required.
 	 */
@@ -341,6 +341,12 @@
 
 	e1000_reset_adaptive(&adapter->hw);
 	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+
+	if(adapter->en_mng_pt) {
+		manc = E1000_READ_REG(&adapter->hw, MANC);
+		manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
+		E1000_WRITE_REG(&adapter->hw, MANC, manc);
+	}
 }
 
 /**
@@ -483,6 +489,8 @@
 	if(pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
+	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
+
 	/* before reading the EEPROM, reset the controller to 
 	 * put the device in a known good starting state */
 	
@@ -2367,7 +2375,6 @@
 	struct e1000_rx_desc *rx_desc;
 	struct e1000_buffer *buffer_info;
 	struct sk_buff *skb;
-	int reserve_len = 2;
 	unsigned int i;
 
 	i = rx_ring->next_to_use;
@@ -2376,7 +2383,7 @@
 	while(!buffer_info->skb) {
 		rx_desc = E1000_RX_DESC(*rx_ring, i);
 
-		skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len);
+		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
 
 		if(!skb) {
 			/* Better luck next round */
@@ -2387,7 +2394,7 @@
 		 * this will result in a 16 byte aligned IP header after
 		 * the 14 byte MAC header is removed
 		 */
-		skb_reserve(skb, reserve_len);
+		skb_reserve(skb, NET_IP_ALIGN);
 
 		skb->dev = netdev;
 
diff -Nru a/drivers/net/e2100.c b/drivers/net/e2100.c
--- a/drivers/net/e2100.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/e2100.c	2004-06-23 19:04:28 -07:00
@@ -51,6 +51,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "e2100"
+
 static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
 
 /* Offsets from the base_addr.
@@ -144,6 +146,7 @@
 	release_region(dev->base_addr, E21_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init e2100_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -168,6 +171,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init e21_probe1(struct net_device *dev, int ioaddr)
 {
@@ -175,7 +179,7 @@
 	unsigned char *station_addr = dev->dev_addr;
 	static unsigned version_printed;
 
-	if (!request_region(ioaddr, E21_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, E21_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	/* First check the station address for the Ctron prefix. */
diff -Nru a/drivers/net/eepro.c b/drivers/net/eepro.c
--- a/drivers/net/eepro.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/eepro.c	2004-06-23 19:04:28 -07:00
@@ -151,6 +151,8 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 
+#define DRV_NAME "eepro"
+
 #define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) )
 /* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
 #define SLOW_DOWN inb(0x80)
@@ -577,6 +579,7 @@
 	return -ENODEV;
 }
 
+#ifndef MODULE
 struct net_device * __init eepro_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct eepro_local));
@@ -603,6 +606,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
 {
@@ -745,7 +749,7 @@
 	int ioaddr = dev->base_addr;
 
 	/* Grab the region so we can find another board if autoIRQ fails. */
-	if (!request_region(ioaddr, EEPRO_IO_EXTENT, dev->name)) { 
+	if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { 
 		if (!autoprobe)
 			printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n",
 				ioaddr);
diff -Nru a/drivers/net/eexpress.c b/drivers/net/eexpress.c
--- a/drivers/net/eexpress.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/eexpress.c	2004-06-23 19:04:25 -07:00
@@ -423,6 +423,7 @@
 	return -ENODEV;
 }
 
+#ifndef MODULE
 struct net_device * __init express_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
@@ -443,6 +444,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 /*
  * open and initialize the adapter, ready for use
diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c
--- a/drivers/net/epic100.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/epic100.c	2004-06-23 19:04:26 -07:00
@@ -1218,13 +1218,8 @@
 							    ep->rx_ring[entry].bufaddr,
 							    ep->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
-#if 1 /* HAS_IP_COPYSUM */
 				eth_copy_and_sum(skb, ep->rx_skbuff[entry]->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
-#else
-				memcpy(skb_put(skb, pkt_len), ep->rx_skbuff[entry]->tail,
-					   pkt_len);
-#endif
 				pci_dma_sync_single_for_device(ep->pci_dev,
 							       ep->rx_ring[entry].bufaddr,
 							       ep->rx_buf_sz,
diff -Nru a/drivers/net/eql.c b/drivers/net/eql.c
--- a/drivers/net/eql.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/eql.c	2004-06-23 19:04:28 -07:00
@@ -495,8 +495,12 @@
 		return -EFAULT;
 
 	slave_dev = dev_get_by_name(sc.slave_name);
+	if (!slave_dev)
+		return -ENODEV;
 
 	ret = -EINVAL;
+	if (!slave_dev)
+		return ret;
 
 	spin_lock_bh(&eql->queue.lock);
 	if (eql_is_slave(slave_dev)) {
@@ -527,11 +531,15 @@
 	if (copy_from_user(&sc, scp, sizeof (slave_config_t)))
 		return -EFAULT;
 
-	eql = dev->priv;
 	slave_dev = dev_get_by_name(sc.slave_name);
+	if (!slave_dev)
+		return -ENODEV;
 
 	ret = -EINVAL;
+	if (!slave_dev)
+		return ret;
 
+	eql = dev->priv;
 	spin_lock_bh(&eql->queue.lock);
 	if (eql_is_slave(slave_dev)) {
 		slave = __eql_find_slave_dev(&eql->queue, slave_dev);
diff -Nru a/drivers/net/es3210.c b/drivers/net/es3210.c
--- a/drivers/net/es3210.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/es3210.c	2004-06-23 19:04:28 -07:00
@@ -161,6 +161,7 @@
 	release_region(dev->base_addr, ES_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init es_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -185,6 +186,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init es_probe1(struct net_device *dev, int ioaddr)
 {
diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c
--- a/drivers/net/eth16i.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/eth16i.c	2004-06-23 19:04:28 -07:00
@@ -458,6 +458,7 @@
 	return -ENODEV;
 }
 
+#ifndef MODULE
 struct net_device * __init eth16i_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct eth16i_local));
@@ -483,6 +484,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
 {
@@ -491,7 +493,7 @@
 	int retval;
 
 	/* Let's grab the region */
-	if (!request_region(ioaddr, ETH16I_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, ETH16I_IO_EXTENT, cardname))
 		return -EBUSY;
 
 	/*
@@ -538,9 +540,9 @@
 
 	/* Try to obtain interrupt vector */
 
-	if ((retval = request_irq(dev->irq, (void *)&eth16i_interrupt, 0, dev->name, dev))) {
-		printk(KERN_WARNING "%s: %s at %#3x, but is unusable due conflicting IRQ %d.\n", 
-		       dev->name, cardname, ioaddr, dev->irq);
+	if ((retval = request_irq(dev->irq, (void *)&eth16i_interrupt, 0, cardname, dev))) {
+		printk(KERN_WARNING "%s at %#3x, but is unusable due to conflicting IRQ %d.\n", 
+		       cardname, ioaddr, dev->irq);
 		goto out;
 	}
 
diff -Nru a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
--- a/drivers/net/ewrk3.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/ewrk3.c	2004-06-23 19:04:28 -07:00
@@ -341,6 +341,7 @@
     mdelay(1);\
 }
 
+#ifndef MODULE
 struct net_device * __init ewrk3_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct ewrk3_private));
@@ -364,6 +365,7 @@
 	return ERR_PTR(err);
 	
 }
+#endif
 
 static int __init ewrk3_probe1(struct net_device *dev, u_long iobase, int irq)
 {
@@ -1269,7 +1271,7 @@
 	for (; (i < maxSlots) && (dev != NULL);
 	     iobase += EWRK3_IOP_INC, i++)
 	{
-		if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name)) {
+		if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME)) {
 			if (DevicePresent(iobase) == 0) {
 				int irq = dev->irq;
 				ret = ewrk3_hw_init(dev, iobase);
@@ -1310,7 +1312,7 @@
 
 	for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) {
 		if (EISA_signature(name, EISA_ID) == 0) {
-			if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name) &&
+			if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME) &&
 			    DevicePresent(iobase) == 0) {
 				int irq = dev->irq;
 				ret = ewrk3_hw_init(dev, iobase);
diff -Nru a/drivers/net/fealnx.c b/drivers/net/fealnx.c
--- a/drivers/net/fealnx.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/fealnx.c	2004-06-23 19:04:27 -07:00
@@ -858,11 +858,16 @@
 {
 	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
+	int i;
 
 	writel(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],
+				ioaddr + PAR0 + i*2);
 
 	init_ring(dev);
 
diff -Nru a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
--- a/drivers/net/fmv18x.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/fmv18x.c	2004-06-23 19:04:25 -07:00
@@ -57,6 +57,8 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 
+#define DRV_NAME "fmv18x"
+
 static unsigned fmv18x_probe_list[] __initdata = {
 	0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
 };
@@ -192,7 +194,7 @@
 	   That means we have to be careful with the register values we probe for.
 	   */
 
-	if (!request_region(ioaddr, FMV18X_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, FMV18X_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	dev->irq = irq;
@@ -224,7 +226,7 @@
 	}
 
 	/* Snarf the interrupt vector now. */
-	retval = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev);
+	retval = request_irq(dev->irq, &net_interrupt, 0, DRV_NAME, dev);
 	if (retval) {
 		printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
 				"IRQ %d.\n", ioaddr, dev->irq);
diff -Nru a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
--- a/drivers/net/forcedeth.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/forcedeth.c	2004-06-23 19:04:25 -07:00
@@ -81,6 +81,7 @@
  * superfluous timer interrupts from the nic.
  */
 #define FORCEDETH_VERSION		"0.25"
+#define DRV_NAME			"forcedeth"
 
 #include <linux/module.h>
 #include <linux/types.h>
@@ -1424,7 +1425,7 @@
 
 	pci_set_master(pci_dev);
 
-	err = pci_request_regions(pci_dev, dev->name);
+	err = pci_request_regions(pci_dev, DRV_NAME);
 	if (err < 0)
 		goto out_disable;
 
diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c
--- a/drivers/net/hamachi.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/net/hamachi.c	2004-06-23 19:04:29 -07:00
@@ -207,10 +207,8 @@
 /* Condensed bus+endian portability operations. */
 #if ADDRLEN == 64
 #define cpu_to_leXX(addr)	cpu_to_le64(addr)
-#define desc_to_virt(addr) bus_to_virt(le64_to_cpu(addr))
 #else 
 #define cpu_to_leXX(addr)	cpu_to_le32(addr)
-#define desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
 #endif   
 
 
@@ -1502,7 +1500,7 @@
 					    desc->addr,
 					    hmp->rx_buf_sz,
 					    PCI_DMA_FROMDEVICE);
-		buf_addr = desc_to_virt(desc->addr);
+		buf_addr = (u8 *) hmp->rx_skbuff[entry]->tail;
 		frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12])));
 		if (hamachi_debug > 4)
 			printk(KERN_DEBUG "  hamachi_rx() status was %8.8x.\n",
diff -Nru a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
--- a/drivers/net/hamradio/hdlcdrv.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/hamradio/hdlcdrv.c	2004-06-23 19:04:28 -07:00
@@ -588,6 +588,8 @@
 		return -EINVAL;
 	s = (struct hdlcdrv_state *)dev->priv;
 
+	netif_stop_queue(dev);
+
 	if (s->ops && s->ops->close)
 		i = s->ops->close(dev);
 	if (s->skb)
diff -Nru a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
--- a/drivers/net/hp-plus.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/hp-plus.c	2004-06-23 19:04:25 -07:00
@@ -37,6 +37,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "hp-plus"
+
 /* A zero-terminated list of I/O addresses to be probed. */
 static unsigned int hpplus_portlist[] __initdata =
 {0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
@@ -142,6 +144,7 @@
 	release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init hp_plus_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -166,6 +169,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 /* Do the interesting part of the probe at a single address. */
 static int __init hpp_probe1(struct net_device *dev, int ioaddr)
@@ -176,7 +180,7 @@
 	int mem_start;
 	static unsigned version_printed;
 
-	if (!request_region(ioaddr, HP_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	/* Check for the HP+ signature, 50 48 0x 53. */
diff -Nru a/drivers/net/hp.c b/drivers/net/hp.c
--- a/drivers/net/hp.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/hp.c	2004-06-23 19:04:26 -07:00
@@ -37,6 +37,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "hp"
+
 /* A zero-terminated list of I/O addresses to be probed. */
 static unsigned int hppclan_portlist[] __initdata =
 { 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
@@ -106,6 +108,7 @@
 	release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init hp_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -130,6 +133,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init hp_probe1(struct net_device *dev, int ioaddr)
 {
@@ -137,7 +141,7 @@
 	const char *name;
 	static unsigned version_printed;
 
-	if (!request_region(ioaddr, HP_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	/* Check for the HP physical address, 08 00 09 xx xx xx. */
@@ -182,7 +186,7 @@
 				outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE);
 				outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE);
 				if (irq == probe_irq_off(cookie)		 /* It's a good IRQ line! */
-					&& request_irq (irq, ei_interrupt, 0, dev->name, dev) == 0) {
+					&& request_irq (irq, ei_interrupt, 0, DRV_NAME, dev) == 0) {
 					printk(" selecting IRQ %d.\n", irq);
 					dev->irq = *irqp;
 					break;
@@ -197,7 +201,7 @@
 	} else {
 		if (dev->irq == 2)
 			dev->irq = 9;
-		if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) {
+		if ((retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev))) {
 			printk (" unable to get IRQ %d.\n", dev->irq);
 			goto out;
 		}
diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c
--- a/drivers/net/hp100.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/hp100.c	2004-06-23 19:04:26 -07:00
@@ -386,6 +386,7 @@
 }
 
 
+#ifndef MODULE
 struct net_device * __init hp100_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));
@@ -420,6 +421,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init hp100_probe1(struct net_device *dev, int ioaddr,
 			       u_char bus, struct pci_dev *pci_dev)
diff -Nru a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
--- a/drivers/net/ibmlana.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/ibmlana.c	2004-06-23 19:04:25 -07:00
@@ -98,6 +98,8 @@
 
 #undef DEBUG
 
+#define DRV_NAME "ibmlana"
+
 /* ------------------------------------------------------------------------
  * global static data - not more since we can handle multiple boards and
  * have to pack all state info into the device struct!
@@ -952,8 +954,8 @@
 	printk(KERN_INFO "%s: IBM LAN Adapter/A found in slot %d\n", dev->name, slot + 1);
 
 	/* try to obtain I/O range */
-	if (!request_region(iobase, IBM_LANA_IORANGE, dev->name)) {
-		printk(KERN_ERR "%s: cannot allocate I/O range at %#x!\n", dev->name, iobase);
+	if (!request_region(iobase, IBM_LANA_IORANGE, DRV_NAME)) {
+		printk(KERN_ERR "%s: cannot allocate I/O range at %#x!\n", DRV_NAME, iobase);
 		startslot = slot + 1;
 		return -EBUSY;
 	}
diff -Nru a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
--- a/drivers/net/irda/ali-ircc.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/irda/ali-ircc.c	2004-06-23 19:04:26 -07:00
@@ -33,6 +33,7 @@
 #include <linux/init.h>
 #include <linux/rtnetlink.h>
 #include <linux/serial_reg.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -304,16 +305,18 @@
 	self->tx_buff.truesize = 14384;
 
 	/* Allocate memory if needed */
-	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-					      GFP_KERNEL |GFP_DMA); 
+	self->rx_buff.head =
+		dma_alloc_coherent(NULL, self->rx_buff.truesize,
+				   &self->rx_buff_dma, GFP_KERNEL);
 	if (self->rx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out2;
 	}
 	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 	
-	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-					      GFP_KERNEL|GFP_DMA); 
+	self->tx_buff.head =
+		dma_alloc_coherent(NULL, self->tx_buff.truesize,
+				   &self->tx_buff_dma, GFP_KERNEL);
 	if (self->tx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out3;
@@ -362,9 +365,11 @@
 	return 0;
 
  err_out4:
-	kfree(self->tx_buff.head);
+	dma_free_coherent(NULL, self->tx_buff.truesize,
+			  self->tx_buff.head, self->tx_buff_dma);
  err_out3:
-	kfree(self->rx_buff.head);
+	dma_free_coherent(NULL, self->rx_buff.truesize,
+			  self->rx_buff.head, self->rx_buff_dma);
  err_out2:
 	release_region(self->io.fir_base, self->io.fir_ext);
  err_out1:
@@ -398,10 +403,12 @@
 	release_region(self->io.fir_base, self->io.fir_ext);
 
 	if (self->tx_buff.head)
-		kfree(self->tx_buff.head);
+		dma_free_coherent(NULL, self->tx_buff.truesize,
+				  self->tx_buff.head, self->tx_buff_dma);
 	
 	if (self->rx_buff.head)
-		kfree(self->rx_buff.head);
+		dma_free_coherent(NULL, self->rx_buff.truesize,
+				  self->rx_buff.head, self->rx_buff_dma);
 
 	dev_self[self->index] = NULL;
 	free_netdev(self->netdev);
@@ -1572,7 +1579,8 @@
 	self->io.direction = IO_XMIT;
 	
 	irda_setup_dma(self->io.dma, 
-		       self->tx_fifo.queue[self->tx_fifo.ptr].start, 
+		       ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start -
+			self->tx_buff.head) + self->tx_buff_dma,
 		       self->tx_fifo.queue[self->tx_fifo.ptr].len, 
 		       DMA_TX_MODE);
 		
@@ -1724,8 +1732,8 @@
 	self->st_fifo.len = self->st_fifo.pending_bytes = 0;
 	self->st_fifo.tail = self->st_fifo.head = 0;
 		
-	irda_setup_dma(self->io.dma, self->rx_buff.data, 
-		       self->rx_buff.truesize, DMA_RX_MODE);	
+	irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,
+		       DMA_RX_MODE);
 	 
 	/* Set Receive Mode,Brick Wall */
 	//switch_bank(iobase, BANK0);
diff -Nru a/drivers/net/irda/ali-ircc.h b/drivers/net/irda/ali-ircc.h
--- a/drivers/net/irda/ali-ircc.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/irda/ali-ircc.h	2004-06-23 19:04:27 -07:00
@@ -26,6 +26,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/pm.h>
+#include <linux/types.h>
 #include <asm/io.h>
 
 /* SIR Register */
@@ -198,6 +199,8 @@
 	chipio_t io;               /* IrDA controller information */
 	iobuff_t tx_buff;          /* Transmit buffer */
 	iobuff_t rx_buff;          /* Receive buffer */
+	dma_addr_t tx_buff_dma;
+	dma_addr_t rx_buff_dma;
 
 	__u8 ier;                  /* Interrupt enable register */
 	
diff -Nru a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
--- a/drivers/net/irda/irtty-sir.c	2004-06-23 19:04:24 -07:00
+++ b/drivers/net/irda/irtty-sir.c	2004-06-23 19:04:24 -07:00
@@ -438,7 +438,6 @@
 	struct irtty_info { char name[6]; } info;
 	struct sir_dev *dev;
 	struct sirtty_cb *priv = tty->disc_data;
-	int size = _IOC_SIZE(cmd);
 	int err = 0;
 
 	ASSERT(priv != NULL, return -ENODEV;);
@@ -449,13 +448,6 @@
 	dev = priv->dev;
 	ASSERT(dev != NULL, return -1;);
 
-	if (_IOC_DIR(cmd) & _IOC_READ)
-		err = verify_area(VERIFY_WRITE, (void *) arg, size);
-	else if (_IOC_DIR(cmd) & _IOC_WRITE)
-		err = verify_area(VERIFY_READ, (void *) arg, size);
-	if (err)
-		return err;
-	
 	switch (cmd) {
 	case TCGETS:
 	case TCGETA:
@@ -473,7 +465,7 @@
 		memset(&info, 0, sizeof(info)); 
 		strncpy(info.name, dev->netdev->name, sizeof(info.name)-1);
 
-		if (copy_to_user((void *)arg, &info, sizeof(info)))
+		if (copy_to_user((void __user *)arg, &info, sizeof(info)))
 			err = -EFAULT;
 		break;
 	default:
diff -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
--- a/drivers/net/irda/nsc-ircc.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/irda/nsc-ircc.c	2004-06-23 19:04:25 -07:00
@@ -52,6 +52,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/rtnetlink.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -307,8 +308,9 @@
 	self->tx_buff.truesize = 14384;
 
 	/* Allocate memory if needed */
-	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-					      GFP_KERNEL|GFP_DMA);
+	self->rx_buff.head =
+		dma_alloc_coherent(NULL, self->rx_buff.truesize,
+				   &self->rx_buff_dma, GFP_KERNEL);
 	if (self->rx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto out2;
@@ -316,8 +318,9 @@
 	}
 	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 	
-	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-					      GFP_KERNEL|GFP_DMA);
+	self->tx_buff.head =
+		dma_alloc_coherent(NULL, self->tx_buff.truesize,
+				   &self->tx_buff_dma, GFP_KERNEL);
 	if (self->tx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto out3;
@@ -368,9 +371,11 @@
 
 	return 0;
  out4:
-	kfree(self->tx_buff.head);
+	dma_free_coherent(NULL, self->tx_buff.truesize,
+			  self->tx_buff.head, self->tx_buff_dma);
  out3:
-	kfree(self->rx_buff.head);
+	dma_free_coherent(NULL, self->rx_buff.truesize,
+			  self->rx_buff.head, self->rx_buff_dma);
  out2:
 	release_region(self->io.fir_base, self->io.fir_ext);
  out1:
@@ -404,10 +409,12 @@
 	release_region(self->io.fir_base, self->io.fir_ext);
 
 	if (self->tx_buff.head)
-		kfree(self->tx_buff.head);
+		dma_free_coherent(NULL, self->tx_buff.truesize,
+				  self->tx_buff.head, self->tx_buff_dma);
 	
 	if (self->rx_buff.head)
-		kfree(self->rx_buff.head);
+		dma_free_coherent(NULL, self->rx_buff.truesize,
+				  self->rx_buff.head, self->rx_buff_dma);
 
 	dev_self[self->index] = NULL;
 	free_netdev(self->netdev);
@@ -1409,7 +1416,8 @@
 	outb(ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1);
 	
 	irda_setup_dma(self->io.dma, 
-		       self->tx_fifo.queue[self->tx_fifo.ptr].start, 
+		       ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start -
+			self->tx_buff.head) + self->tx_buff_dma,
 		       self->tx_fifo.queue[self->tx_fifo.ptr].len, 
 		       DMA_TX_MODE);
 
@@ -1566,8 +1574,8 @@
 	self->st_fifo.len = self->st_fifo.pending_bytes = 0;
 	self->st_fifo.tail = self->st_fifo.head = 0;
 	
-	irda_setup_dma(self->io.dma, self->rx_buff.data, 
-		       self->rx_buff.truesize, DMA_RX_MODE);
+	irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,
+		       DMA_RX_MODE);
 
 	/* Enable DMA */
 	switch_bank(iobase, BANK0);
diff -Nru a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h
--- a/drivers/net/irda/nsc-ircc.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/irda/nsc-ircc.h	2004-06-23 19:04:27 -07:00
@@ -32,6 +32,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/pm.h>
+#include <linux/types.h>
 #include <asm/io.h>
 
 /* DMA modes needed */
@@ -255,6 +256,8 @@
 	chipio_t io;               /* IrDA controller information */
 	iobuff_t tx_buff;          /* Transmit buffer */
 	iobuff_t rx_buff;          /* Receive buffer */
+	dma_addr_t tx_buff_dma;
+	dma_addr_t rx_buff_dma;
 
 	__u8 ier;                  /* Interrupt enable register */
 
diff -Nru a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
--- a/drivers/net/irda/smsc-ircc2.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/irda/smsc-ircc2.c	2004-06-23 19:04:27 -07:00
@@ -52,6 +52,7 @@
 #include <linux/init.h>
 #include <linux/rtnetlink.h>
 #include <linux/serial_reg.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -112,6 +113,8 @@
 	chipio_t io;               /* IrDA controller information */
 	iobuff_t tx_buff;          /* Transmit buffer */
 	iobuff_t rx_buff;          /* Receive buffer */
+	dma_addr_t tx_buff_dma;
+	dma_addr_t rx_buff_dma;
 
 	struct qos_info qos;       /* QoS capabilities for this device */
 
@@ -413,16 +416,18 @@
 	self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE; 
 	self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE;
 
-	self->rx_buff.head = (u8 *) kmalloc(self->rx_buff.truesize,
-					      GFP_KERNEL|GFP_DMA);
+	self->rx_buff.head =
+		dma_alloc_coherent(NULL, self->rx_buff.truesize,
+				   &self->rx_buff_dma, GFP_KERNEL);
 	if (self->rx_buff.head == NULL) {
 		ERROR("%s, Can't allocate memory for receive buffer!\n",
                       driver_name);
 		goto err_out2;
 	}
 
-	self->tx_buff.head = (u8 *) kmalloc(self->tx_buff.truesize, 
-					      GFP_KERNEL|GFP_DMA);
+	self->tx_buff.head =
+		dma_alloc_coherent(NULL, self->tx_buff.truesize,
+				   &self->tx_buff_dma, GFP_KERNEL);
 	if (self->tx_buff.head == NULL) {
 		ERROR("%s, Can't allocate memory for transmit buffer!\n",
                       driver_name);
@@ -464,9 +469,11 @@
 
 	return 0;
  err_out4:
-	kfree(self->tx_buff.head);
+	dma_free_coherent(NULL, self->tx_buff.truesize,
+			  self->tx_buff.head, self->tx_buff_dma);
  err_out3:
-	kfree(self->rx_buff.head);
+	dma_free_coherent(NULL, self->rx_buff.truesize,
+			  self->rx_buff.head, self->rx_buff_dma);
  err_out2:
 	free_netdev(self->netdev);
 	dev_self[--dev_count] = NULL;
@@ -1159,7 +1166,7 @@
 	     IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
 
 	/* Setup DMA controller (must be done after enabling chip DMA) */
-	irda_setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
+	irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len,
 		       DMA_TX_MODE);
 
 	/* Enable interrupt */
@@ -1249,8 +1256,8 @@
 	outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO);
 
 	/* Setup DMA controller */
-	irda_setup_dma(self->io.dma, self->rx_buff.data,
-		       self->rx_buff.truesize, DMA_RX_MODE);
+	irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,
+		       DMA_RX_MODE);
 
 	/* Enable burst mode chip Rx DMA */
 	register_bank(iobase, 1);
@@ -1717,10 +1724,12 @@
 	release_region(self->io.sir_base, self->io.sir_ext);
 
 	if (self->tx_buff.head)
-		kfree(self->tx_buff.head);
+		dma_free_coherent(NULL, self->tx_buff.truesize,
+				  self->tx_buff.head, self->tx_buff_dma);
 	
 	if (self->rx_buff.head)
-		kfree(self->rx_buff.head);
+		dma_free_coherent(NULL, self->rx_buff.truesize,
+				  self->rx_buff.head, self->rx_buff_dma);
 
 	free_netdev(self->netdev);
 
diff -Nru a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
--- a/drivers/net/irda/via-ircc.c	2004-06-23 19:04:24 -07:00
+++ b/drivers/net/irda/via-ircc.c	2004-06-23 19:04:24 -07:00
@@ -39,6 +39,7 @@
 #include <linux/init.h>
 #include <linux/rtnetlink.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -383,7 +384,8 @@
 
 	/* Allocate memory if needed */
 	self->rx_buff.head =
-	    (__u8 *) kmalloc(self->rx_buff.truesize, GFP_KERNEL | GFP_DMA);
+		dma_alloc_coherent(NULL, self->rx_buff.truesize,
+				   &self->rx_buff_dma, GFP_KERNEL);
 	if (self->rx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out2;
@@ -391,7 +393,8 @@
 	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 
 	self->tx_buff.head =
-	    (__u8 *) kmalloc(self->tx_buff.truesize, GFP_KERNEL | GFP_DMA);
+		dma_alloc_coherent(NULL, self->tx_buff.truesize,
+				   &self->tx_buff_dma, GFP_KERNEL);
 	if (self->tx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out3;
@@ -432,9 +435,11 @@
 
 	return 0;
  err_out4:
-	kfree(self->tx_buff.head);
+	dma_free_coherent(NULL, self->tx_buff.truesize,
+			  self->tx_buff.head, self->tx_buff_dma);
  err_out3:
-	kfree(self->rx_buff.head);
+	dma_free_coherent(NULL, self->rx_buff.truesize,
+			  self->rx_buff.head, self->rx_buff_dma);
  err_out2:
 	release_region(self->io.fir_base, self->io.fir_ext);
  err_out1:
@@ -468,9 +473,11 @@
 		   __FUNCTION__, self->io.fir_base);
 	release_region(self->io.fir_base, self->io.fir_ext);
 	if (self->tx_buff.head)
-		kfree(self->tx_buff.head);
+		dma_free_coherent(NULL, self->tx_buff.truesize,
+				  self->tx_buff.head, self->tx_buff_dma);
 	if (self->rx_buff.head)
-		kfree(self->rx_buff.head);
+		dma_free_coherent(NULL, self->rx_buff.truesize,
+				  self->rx_buff.head, self->rx_buff_dma);
 	dev_self[self->index] = NULL;
 
 	free_netdev(self->netdev);
@@ -816,7 +823,7 @@
 	EnTXDMA(iobase, ON);
 	EnRXDMA(iobase, OFF);
 
-	irda_setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len,
+	irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len,
 		       DMA_TX_MODE);
 
 	SetSendByte(iobase, self->tx_buff.len);
@@ -897,7 +904,8 @@
 	EnTXDMA(iobase, ON);
 	EnRXDMA(iobase, OFF);
 	irda_setup_dma(self->io.dma,
-		       self->tx_fifo.queue[self->tx_fifo.ptr].start,
+		       ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start -
+			self->tx_buff.head) + self->tx_buff_dma,
 		       self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE);
 #ifdef	DBGMSG
 	DBG(printk
@@ -1022,8 +1030,8 @@
 	EnAllInt(iobase, ON);
 	EnTXDMA(iobase, OFF);
 	EnRXDMA(iobase, ON);
-	irda_setup_dma(self->io.dma2, self->rx_buff.data,
-		       self->rx_buff.truesize, DMA_RX_MODE);
+	irda_setup_dma(self->io.dma2, self->rx_buff_dma,
+		  self->rx_buff.truesize, DMA_RX_MODE);
 	TXStart(iobase, OFF);
 	RXStart(iobase, ON);
 
diff -Nru a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h
--- a/drivers/net/irda/via-ircc.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/irda/via-ircc.h	2004-06-23 19:04:28 -07:00
@@ -33,6 +33,7 @@
 #include <linux/time.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
+#include <linux/types.h>
 #include <asm/io.h>
 
 #define MAX_TX_WINDOW 7
@@ -102,6 +103,8 @@
 	chipio_t io;		/* IrDA controller information */
 	iobuff_t tx_buff;	/* Transmit buffer */
 	iobuff_t rx_buff;	/* Receive buffer */
+	dma_addr_t tx_buff_dma;
+	dma_addr_t rx_buff_dma;
 
 	__u8 ier;		/* Interrupt enable register */
 
diff -Nru a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
--- a/drivers/net/irda/w83977af_ir.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/irda/w83977af_ir.c	2004-06-23 19:04:26 -07:00
@@ -50,6 +50,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/rtnetlink.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -207,8 +208,9 @@
 	self->tx_buff.truesize = 4000;
 	
 	/* Allocate memory if needed */
-	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-					      GFP_KERNEL|GFP_DMA);
+	self->rx_buff.head =
+		dma_alloc_coherent(NULL, self->rx_buff.truesize,
+				   &self->rx_buff_dma, GFP_KERNEL);
 	if (self->rx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out1;
@@ -216,8 +218,9 @@
 
 	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 	
-	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-					      GFP_KERNEL|GFP_DMA);
+	self->tx_buff.head =
+		dma_alloc_coherent(NULL, self->tx_buff.truesize,
+				   &self->tx_buff_dma, GFP_KERNEL);
 	if (self->tx_buff.head == NULL) {
 		err = -ENOMEM;
 		goto err_out2;
@@ -252,9 +255,11 @@
 	
 	return 0;
 err_out3:
-	kfree(self->tx_buff.head);
+	dma_free_coherent(NULL, self->tx_buff.truesize,
+			  self->tx_buff.head, self->tx_buff_dma);
 err_out2:	
-	kfree(self->rx_buff.head);
+	dma_free_coherent(NULL, self->rx_buff.truesize,
+			  self->rx_buff.head, self->rx_buff_dma);
 err_out1:
 	free_netdev(dev);
 err_out:
@@ -297,10 +302,12 @@
 	release_region(self->io.fir_base, self->io.fir_ext);
 
 	if (self->tx_buff.head)
-		kfree(self->tx_buff.head);
+		dma_free_coherent(NULL, self->tx_buff.truesize,
+				  self->tx_buff.head, self->tx_buff_dma);
 	
 	if (self->rx_buff.head)
-		kfree(self->rx_buff.head);
+		dma_free_coherent(NULL, self->rx_buff.truesize,
+				  self->rx_buff.head, self->rx_buff_dma);
 
 	free_netdev(self->netdev);
 
@@ -606,10 +613,10 @@
 	disable_dma(self->io.dma);
 	clear_dma_ff(self->io.dma);
 	set_dma_mode(self->io.dma, DMA_MODE_READ);
-	set_dma_addr(self->io.dma, isa_virt_to_bus(self->tx_buff.data));
+	set_dma_addr(self->io.dma, self->tx_buff_dma);
 	set_dma_count(self->io.dma, self->tx_buff.len);
 #else
-	irda_setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
+	irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len,
 		       DMA_MODE_WRITE);	
 #endif
 	self->io.direction = IO_XMIT;
@@ -763,10 +770,10 @@
 	disable_dma(self->io.dma);
 	clear_dma_ff(self->io.dma);
 	set_dma_mode(self->io.dma, DMA_MODE_READ);
-	set_dma_addr(self->io.dma, isa_virt_to_bus(self->rx_buff.data));
+	set_dma_addr(self->io.dma, self->rx_buff_dma);
 	set_dma_count(self->io.dma, self->rx_buff.truesize);
 #else
-	irda_setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
+	irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,
 		       DMA_MODE_READ);
 #endif
 	/* 
diff -Nru a/drivers/net/irda/w83977af_ir.h b/drivers/net/irda/w83977af_ir.h
--- a/drivers/net/irda/w83977af_ir.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/irda/w83977af_ir.h	2004-06-23 19:04:25 -07:00
@@ -26,6 +26,7 @@
 #define W83977AF_IR_H
 
 #include <asm/io.h>
+#include <linux/types.h>
 
 /* Flags for configuration register CRF0 */
 #define ENBNKSEL	0x01
@@ -179,6 +180,8 @@
 	chipio_t io;               /* IrDA controller information */
 	iobuff_t tx_buff;          /* Transmit buffer */
 	iobuff_t rx_buff;          /* Receive buffer */
+	dma_addr_t tx_buff_dma;
+	dma_addr_t rx_buff_dma;
 
 	/* Note : currently locking is *very* incomplete, but this
 	 * will get you started. Check in nsc-ircc.c for a proper
diff -Nru a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c
--- a/drivers/net/isa-skeleton.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/isa-skeleton.c	2004-06-23 19:04:28 -07:00
@@ -161,6 +161,7 @@
 	release_region(dev->base_addr, NETCARD_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init netcard_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
@@ -185,6 +186,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 /*
  * This is the real probe routine. Linux has a history of friendly device
diff -Nru a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
--- a/drivers/net/ixgb/ixgb_main.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/ixgb/ixgb_main.c	2004-06-23 19:04:25 -07:00
@@ -1876,7 +1876,6 @@
 	struct ixgb_rx_desc *rx_desc;
 	struct ixgb_buffer *buffer_info;
 	struct sk_buff *skb;
-	int reserve_len = 2;
 	unsigned int i;
 	int num_group_tail_writes;
 	long cleancount;
@@ -1895,7 +1894,7 @@
 	while (--cleancount > 0) {
 		rx_desc = IXGB_RX_DESC(*rx_ring, i);
 
-		skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len);
+		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
 
 		if (unlikely(!skb)) {
 			/* Better luck next round */
@@ -1906,7 +1905,7 @@
 		 * this will result in a 16 byte aligned IP header after
 		 * the 14 byte MAC header is removed
 		 */
-		skb_reserve(skb, reserve_len);
+		skb_reserve(skb, NET_IP_ALIGN);
 
 		skb->dev = netdev;
 
diff -Nru a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
--- a/drivers/net/jazzsonic.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/jazzsonic.c	2004-06-23 19:04:26 -07:00
@@ -37,6 +37,8 @@
 #include <asm/jazz.h>
 #include <asm/jazzdma.h>
 
+#define DRV_NAME "jazzsonic"
+
 #define SREGS_PAD(n)    u16 n;
 
 #include "sonic.h"
@@ -151,7 +153,7 @@
 	int err = -ENODEV;
 	int i;
 
-	if (!request_region(base_addr, 0x100, dev->name))
+	if (!request_region(base_addr, 0x100, DRV_NAME))
 		return -EBUSY;
 	/*
 	 * get the Silicon Revision ID. If this is one of the known
diff -Nru a/drivers/net/lance.c b/drivers/net/lance.c
--- a/drivers/net/lance.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/lance.c	2004-06-23 19:04:25 -07:00
@@ -432,6 +432,7 @@
 	return -ENODEV;
 }
 
+#ifndef MODULE
 struct net_device * __init lance_probe(int unit)
 {
 	struct net_device *dev = alloc_etherdev(0);
@@ -456,6 +457,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options)
 {
diff -Nru a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
--- a/drivers/net/lasi_82596.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/lasi_82596.c	2004-06-23 19:04:25 -07:00
@@ -87,7 +87,6 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/pgalloc.h>
 #include <asm/irq.h>
 #include <asm/pdc.h>
 #include <asm/cache.h>
diff -Nru a/drivers/net/lne390.c b/drivers/net/lne390.c
--- a/drivers/net/lne390.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/lne390.c	2004-06-23 19:04:28 -07:00
@@ -49,6 +49,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "lne390"
+
 static int lne390_probe1(struct net_device *dev, int ioaddr);
 
 static int lne390_open(struct net_device *dev);
@@ -112,7 +114,7 @@
 	SET_MODULE_OWNER(dev);
 
 	if (ioaddr > 0x1ff) {		/* Check a single specified location. */
-		if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name))
+		if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME))
 			return -EBUSY;
 		ret = lne390_probe1(dev, ioaddr);
 		if (ret)
@@ -131,7 +133,7 @@
 
 	/* EISA spec allows for up to 16 slots, but 8 is typical. */
 	for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
-		if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name))
+		if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME))
 			continue;
 		if (lne390_probe1(dev, ioaddr) == 0)
 			return 0;
@@ -151,6 +153,7 @@
 		iounmap((void *)dev->mem_start);
 }
 
+#ifndef MODULE
 struct net_device * __init lne390_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -175,6 +178,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init lne390_probe1(struct net_device *dev, int ioaddr)
 {
@@ -228,7 +232,7 @@
 	}
 	printk(" IRQ %d,", dev->irq);
 
-	if ((ret = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) {
+	if ((ret = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev))) {
 		printk (" unable to get IRQ %d.\n", dev->irq);
 		return ret;
 	}
diff -Nru a/drivers/net/loopback.c b/drivers/net/loopback.c
--- a/drivers/net/loopback.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/loopback.c	2004-06-23 19:04:25 -07:00
@@ -55,7 +55,9 @@
 #include <linux/if_arp.h>	/* For ARPHRD_ETHER */
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/percpu.h>
 
+static DEFINE_PER_CPU(struct net_device_stats, loopback_stats);
 
 #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
 
@@ -123,7 +125,7 @@
  */
 static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net_device_stats *stats = dev->priv;
+	struct net_device_stats *lb_stats;
 
 	skb_orphan(skb);
 
@@ -142,12 +144,13 @@
 	}
 
 	dev->last_rx = jiffies;
-	if (likely(stats)) {
-		stats->rx_bytes+=skb->len;
-		stats->tx_bytes+=skb->len;
-		stats->rx_packets++;
-		stats->tx_packets++;
-	}
+
+	lb_stats = &per_cpu(loopback_stats, get_cpu());
+	lb_stats->rx_bytes += skb->len;
+	lb_stats->tx_bytes += skb->len;
+	lb_stats->rx_packets++;
+	lb_stats->tx_packets++;
+	put_cpu();
 
 	netif_rx(skb);
 
@@ -156,7 +159,28 @@
 
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
-	return (struct net_device_stats *)dev->priv;
+	struct net_device_stats *stats = dev->priv;
+	int i;
+
+	if (!stats) {
+		return NULL;
+	}
+
+	memset(stats, 0, sizeof(struct net_device_stats));
+
+	for (i=0; i < NR_CPUS; i++) {
+		struct net_device_stats *lb_stats;
+
+		if (!cpu_possible(i)) 
+			continue;
+		lb_stats = &per_cpu(loopback_stats, i);
+		stats->rx_bytes   += lb_stats->rx_bytes;
+		stats->tx_bytes   += lb_stats->tx_bytes;
+		stats->rx_packets += lb_stats->rx_packets;
+		stats->tx_packets += lb_stats->tx_packets;
+	}
+				
+	return stats;
 }
 
 struct net_device loopback_dev = {
@@ -173,7 +197,8 @@
 	.rebuild_header		= eth_rebuild_header,
 	.flags			= IFF_LOOPBACK,
 	.features 		= NETIF_F_SG|NETIF_F_FRAGLIST
-				  |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA,
+				  |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA
+				  |NETIF_F_LLTX,
 };
 
 /* Setup and register the of the LOOPBACK device. */
diff -Nru a/drivers/net/lp486e.c b/drivers/net/lp486e.c
--- a/drivers/net/lp486e.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/lp486e.c	2004-06-23 19:04:26 -07:00
@@ -75,6 +75,8 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 
+#define DRV_NAME "lp486e"
+
 /* debug print flags */
 #define LOG_SRCDST    0x80000000
 #define LOG_STATINT   0x40000000
@@ -970,7 +972,7 @@
 		return -ENODEV;
 	probed++;
 
-	if (!request_region(IOADDR, LP486E_TOTAL_SIZE, dev->name)) {
+	if (!request_region(IOADDR, LP486E_TOTAL_SIZE, DRV_NAME)) {
 		printk(KERN_ERR "lp486e: IO address 0x%x in use\n", IOADDR);
 		return -EBUSY;
 	}
diff -Nru a/drivers/net/macsonic.c b/drivers/net/macsonic.c
--- a/drivers/net/macsonic.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/macsonic.c	2004-06-23 19:04:25 -07:00
@@ -53,7 +53,6 @@
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_via.h>
-#include <asm/pgalloc.h>
 
 #define SREGS_PAD(n)    u16 n;
 
@@ -613,7 +612,6 @@
 
 MODULE_PARM(sonic_debug, "i");
 MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
-MODULE_LICENSE("GPL");
 
 int
 init_module(void)
diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c
--- a/drivers/net/natsemi.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/natsemi.c	2004-06-23 19:04:25 -07:00
@@ -766,7 +766,7 @@
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	i = pci_request_regions(pdev, dev->name);
+	i = pci_request_regions(pdev, DRV_NAME);
 	if (i)
 		goto err_pci_request_regions;
 
@@ -1798,14 +1798,9 @@
 					np->rx_dma[entry],
 					buflen,
 					PCI_DMA_FROMDEVICE);
-#if HAS_IP_COPYSUM
 				eth_copy_and_sum(skb,
 					np->rx_skbuff[entry]->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
-#else
-				memcpy(skb_put(skb, pkt_len),
-					np->rx_skbuff[entry]->tail, pkt_len);
-#endif
 				pci_dma_sync_single_for_device(np->pci_dev,
 					np->rx_dma[entry],
 					buflen,
diff -Nru a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
--- a/drivers/net/ne-h8300.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/ne-h8300.c	2004-06-23 19:04:26 -07:00
@@ -34,6 +34,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "ne-h8300"
+
 /* Some defines that people can play with if so inclined. */
 
 /* Do we perform extra sanity checks on stuff ? */
@@ -156,6 +158,7 @@
 	release_region(dev->base_addr, NE_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init ne_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -187,6 +190,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init ne_probe1(struct net_device *dev, int ioaddr)
 {
@@ -200,7 +204,7 @@
 	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
 	unsigned char bus_width;
 
-	if (!request_region(ioaddr, NE_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	reg0 = inb_p(ioaddr);
diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c
--- a/drivers/net/ne.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/ne.c	2004-06-23 19:04:26 -07:00
@@ -55,6 +55,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "ne"
+
 /* Some defines that people can play with if so inclined. */
 
 /* Do we support clones that don't adhere to 14,15 of the SAprom ? */
@@ -203,6 +205,7 @@
 	release_region(dev->base_addr, NE_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init ne_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -227,6 +230,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init ne_probe_isapnp(struct net_device *dev)
 {
@@ -284,7 +288,7 @@
 	int reg0, ret;
 	static unsigned version_printed;
 
-	if (!request_region(ioaddr, NE_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	reg0 = inb_p(ioaddr);
diff -Nru a/drivers/net/ne2.c b/drivers/net/ne2.c
--- a/drivers/net/ne2.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/net/ne2.c	2004-06-23 19:04:29 -07:00
@@ -82,6 +82,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "ne2"
+
 /* Some defines that people can play with if so inclined. */
 
 /* Do we perform extra sanity checks on stuff ? */
@@ -284,6 +286,7 @@
 	release_region(dev->base_addr, NE_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init ne2_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -308,6 +311,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int ne2_procinfo(char *buf, int slot, struct net_device *dev)
 {
@@ -368,7 +372,7 @@
 		irq = irqs[(POS & 0x60)>>5];
 	}
 
-	if (!request_region(base_addr, NE_IO_EXTENT, dev->name))
+	if (!request_region(base_addr, NE_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 #ifdef DEBUG
@@ -470,7 +474,7 @@
 
 	/* Snarf the interrupt now.  There's no point in waiting since we cannot
 	   share and the board will usually be enabled. */
-	retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
+	retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
 	if (retval) {
 		printk (" unable to get IRQ %d (irqval=%d).\n", 
 				dev->irq, retval);
diff -Nru a/drivers/net/ne2k_cbus.c b/drivers/net/ne2k_cbus.c
--- a/drivers/net/ne2k_cbus.c	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,887 +0,0 @@
-/*
-
-  ne2k_cbus.c: A driver for the NE2000 like ethernet on NEC PC-9800.
-
-	This is a copy of the 2.5.66 Linux ISA NE2000 driver "ne.c" 
-	(Donald Becker/Paul Gortmaker) with the NEC PC-9800 specific
-	changes added by Osamu Tomita. 
-
-From ne.c:
------------
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.
-
-    This software may be used and distributed according to the terms
-    of the GNU General Public License, incorporated herein by reference.
------------
-
-*/
-
-/* Routines for the NatSemi-based designs (NE[12]000). */
-
-static const char version[] =
-"ne2k_cbus.c:v1.0 3/24/03 Osamu Tomita\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/isapnp.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "8390.h"
-
-/* Some defines that people can play with if so inclined. */
-
-/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
-#define SUPPORT_NE_BAD_CLONES
-
-/* Do we perform extra sanity checks on stuff ? */
-/* #define NE_SANITY_CHECK */
-
-/* Do we implement the read before write bugfix ? */
-/* #define NE_RW_BUGFIX */
-
-/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
-/* #define PACKETBUF_MEMSIZE	0x40 */
-
-#ifdef SUPPORT_NE_BAD_CLONES
-/* A list of bad clones that we none-the-less recognize. */
-static struct { const char *name8, *name16; unsigned char SAprefix[4];}
-bad_clone_list[] __initdata = {
-    {"LA/T-98?", "LA/T-98", {0x00, 0xa0, 0xb0}},	/* I/O Data */
-    {"EGY-98?", "EGY-98", {0x00, 0x40, 0x26}},		/* Melco EGY98 */
-    {"ICM?", "ICM-27xx-ET", {0x00, 0x80, 0xc8}},	/* ICM IF-27xx-ET */
-    {"CNET-98/EL?", "CNET(98)E/L", {0x00, 0x80, 0x4C}},	/* Contec CNET-98/EL */
-    {0,}
-};
-#endif
-
-/* ---- No user-serviceable parts below ---- */
-
-#define NE_BASE	 (dev->base_addr)
-#define NE_CMD	 	EI_SHIFT(0x00)
-#define NE_DATAPORT	EI_SHIFT(0x10)	/* NatSemi-defined port window offset. */
-#define NE_RESET	EI_SHIFT(0x1f) /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT	0x20
-
-#define NE1SM_START_PG	0x20	/* First page of TX buffer */
-#define NE1SM_STOP_PG 	0x40	/* Last page +1 of RX ring */
-#define NESM_START_PG	0x40	/* First page of TX buffer */
-#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
-
-#include "ne2k_cbus.h"
-
-static int ne_probe1(struct net_device *dev, int ioaddr);
-static int ne_open(struct net_device *dev);
-static int ne_close(struct net_device *dev);
-
-static void ne_reset_8390(struct net_device *dev);
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-			  int ring_page);
-static void ne_block_input(struct net_device *dev, int count,
-			  struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct net_device *dev, const int count,
-		const unsigned char *buf, const int start_page);
-
-
-/*  Probe for various non-shared-memory ethercards.
-
-   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
-   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
-   the SAPROM, while other supposed NE2000 clones must be detected by their
-   SA prefix.
-
-   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
-   mode results in doubled values, which can be detected and compensated for.
-
-   The probe is also responsible for initializing the card and filling
-   in the 'dev' and 'ei_status' structures.
-
-   We use the minimum memory size for some ethercard product lines, iff we can't
-   distinguish models.  You can increase the packet buffer size by setting
-   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
-	E1010   starts at 0x100 and ends at 0x2000.
-	E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
-	E2010	 starts at 0x100 and ends at 0x4000.
-	E2010-x starts at 0x100 and ends at 0xffff.  */
-
-static int __init do_ne_probe(struct net_device *dev)
-{
-	unsigned int base_addr = dev->base_addr;
-	int irq = dev->irq;
-
-	SET_MODULE_OWNER(dev);
-
-	if (ei_debug > 2)
-		printk(KERN_DEBUG "ne_probe(): entered.\n");
-
-	/* If CONFIG_NET_CBUS,
-	   we need dev->priv->reg_offset BEFORE to probe */
-	if (ne2k_cbus_init(dev) != 0)
-		return -ENOMEM;
-
-	/* First check any supplied i/o locations. User knows best. <cough> */
-	if (base_addr > 0) {
-		int result;
-		const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
-
-		if (ei_debug > 2)
-			printk(KERN_DEBUG "ne_probe(): call ne_probe_cbus(base_addr=0x%x)\n", base_addr);
-
-		result = ne_probe_cbus(dev, hw, base_addr, irq);
-		if (result != 0)
-			ne2k_cbus_destroy(dev);
-
-		return result;
-	}
-
-	if (ei_debug > 2)
-		printk(KERN_DEBUG "ne_probe(): base_addr is not specified.\n");
-
-#ifndef MODULE
-	/* Last resort. The semi-risky C-Bus auto-probe. */
-	if (ei_debug > 2)
-		printk(KERN_DEBUG "ne_probe(): auto-probe start.\n");
-
-	{
-		const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
-
-		if (hw && hw->hwtype) {
-			const unsigned short *plist;
-			for (plist = hw->portlist; *plist; plist++)
-				if (ne_probe_cbus(dev, hw, *plist, irq) == 0)
-					return 0;
-		} else {
-			for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
-				const unsigned short *plist;
-				for (plist = hw->portlist; *plist; plist++)
-					if (ne_probe_cbus(dev, hw, *plist, irq) == 0)
-						return 0;
-			}
-		}
-	}
-#endif
-
-	ne2k_cbus_destroy(dev);
-
-	return -ENODEV;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-	const struct ne2k_cbus_region *rlist;
-	const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
-
-	free_irq(dev->irq, dev);
-	for (rlist = hw->regionlist; rlist->range; rlist++) {
-		release_region(dev->base_addr + rlist->start,
-				rlist->range);
-	}
-	ne2k_cbus_destroy(dev);
-}
-
-struct net_device * __init ne_probe(int unit)
-{
-	struct net_device *dev = alloc_ei_netdev();
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = do_ne_probe(dev);
-	if (err)
-		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
-	return dev;
-out1:
-	cleanup_card(dev);
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr, int irq)
-{
-	if (ei_debug > 2)
-		printk(KERN_DEBUG "ne_probe_cbus(): entered. (called from %p)\n",
-		       __builtin_return_address(0));
-
-	if (hw && hw->hwtype) {
-		ne2k_cbus_set_hwtype(dev, hw, ioaddr);
-		dev->irq = irq;
-		return ne_probe1(dev, ioaddr);
-	} else {
-		/* auto detect */
-
-		printk(KERN_DEBUG "ne_probe_cbus(): try to determine hardware types.\n");
-		for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
-			ne2k_cbus_set_hwtype(dev, hw, ioaddr);
-			dev->irq = irq;
-			if (ne_probe1(dev, ioaddr) == 0)
-				return 0;
-		}
-	}
-	return -ENODEV;
-}
-
-static int __init ne_probe1(struct net_device *dev, int ioaddr)
-{
-	int i;
-	unsigned char SA_prom[32];
-	int wordlength = 2;
-	const char *name = NULL;
-	int start_page, stop_page;
-	int neX000, bad_card;
-	int reg0, ret;
-	static unsigned version_printed;
-	const struct ne2k_cbus_region *rlist;
-	const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
-	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
-
-#ifdef CONFIG_NE2K_CBUS_CNET98EL
-	if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) {
-		outb_p(0, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE);
-		/* udelay(5000);	*/
-		outb_p(1, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE);
-		/* udelay(5000);	*/
-		outb_p((ioaddr & 0xf000) >> 8 | 0x08 | 0x01, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE + 2);
-		/* udelay(5000); */
-	}
-#endif
-
-	for (rlist = hw->regionlist; rlist->range; rlist++)
-		if (!request_region(ioaddr + rlist->start,
-					rlist->range, dev->name)) {
-			ret = -EBUSY;
-			goto err_out;
-		}
-
-	reg0 = inb_p(ioaddr + EI_SHIFT(0));
-	if (reg0 == 0xFF) {
-		ret = -ENODEV;
-		goto err_out;
-	}
-
-	/* Do a preliminary verification that we have a 8390. */
-#ifdef CONFIG_NE2K_CBUS_CNET98EL
-	if (hw->hwtype != NE2K_CBUS_HARDWARE_TYPE_CNET98EL)
-#endif
-	{
-		int regd;
-		outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
-		regd = inb_p(ioaddr + EI_SHIFT(0x0d));
-		outb_p(0xff, ioaddr + EI_SHIFT(0x0d));
-		outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
-		inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
-		if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
-			outb_p(reg0, ioaddr);
-			outb_p(regd, ioaddr + EI_SHIFT(0x0d));	/* Restore the old values. */
-			ret = -ENODEV;
-			goto err_out;
-		}
-	}
-
-	if (ei_debug  &&  version_printed++ == 0)
-		printk(KERN_INFO "%s", version);
-
-	printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);
-
-	/* A user with a poor card that fails to ack the reset, or that
-	   does not have a valid 0x57,0x57 signature can still use this
-	   without having to recompile. Specifying an i/o address along
-	   with an otherwise unused dev->mem_end value of "0xBAD" will
-	   cause the driver to skip these parts of the probe. */
-
-	bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
-
-	/* Reset card. Who knows what dain-bramaged state it was left in. */
-
-	{
-		unsigned long reset_start_time = jiffies;
-
-		/* derived from CNET98EL-patch for bad clones */
-		outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD);
-
-		/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
-		outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
-		while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
-		if (jiffies - reset_start_time > 2*HZ/100) {
-			if (bad_card) {
-				printk(" (warning: no reset ack)");
-				break;
-			} else {
-				printk(" not found (no reset ack).\n");
-				ret = -ENODEV;
-				goto err_out;
-			}
-		}
-
-		outb_p(0xff, ioaddr + EN0_ISR);		/* Ack all intr. */
-	}
-
-#ifdef CONFIG_NE2K_CBUS_CNET98EL
-	if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) {
-		static const char pat[32] ="AbcdeFghijKlmnoPqrstUvwxyZ789012";
-		char buf[32];
-		int maxwait = 200;
-
-		if (ei_debug > 2)
-			printk(" [CNET98EL-specific initialize...");
-		outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD); /* 0x20|0x1 */
-		ret = -ENODEV;
-		i = inb(ioaddr);
-		if ((i & ~0x2) != (0x20 | 0x01))
-			goto err_out;
-		if ((inb(ioaddr + 0x7) & 0x80) != 0x80)
-			goto err_out;
-		outb_p(E8390_RXOFF, ioaddr + EN0_RXCR); /* out(ioaddr+0xc, 0x20) */
-		/* outb_p(ENDCFG_WTS|ENDCFG_FT1|ENDCFG_LS, ioaddr+EN0_DCFG); */
-		outb_p(ENDCFG_WTS | 0x48, ioaddr + EN0_DCFG); /* 0x49 */
-		outb_p(CNET98EL_START_PG, ioaddr + EN0_STARTPG);
-		outb_p(CNET98EL_STOP_PG, ioaddr + EN0_STOPPG);
-		if (ei_debug > 2)
-			printk("memory check");
-		for (i = 0; i < 65536; i += 1024) {
-			if (ei_debug > 2)
-				printk(" %04x", i);
-			ne2k_cbus_writemem(dev, ioaddr, i, pat, 32);
-			while (((inb(ioaddr + EN0_ISR) & ENISR_RDC) != ENISR_RDC) && --maxwait)
-				;
-			ne2k_cbus_readmem(dev, ioaddr, i, buf, 32);
-			if (memcmp(pat, buf, 32)) {
-				if (ei_debug > 2)
-					printk(" failed.");
-				break;
-			}
-		}
-		if (i != 16384) {
-			if (ei_debug > 2)
-				printk("] ");
-			printk("memory failure at %x\n", i);
-			goto err_out;
-		}
-		if (ei_debug > 2)
-			printk(" good...");
-		if (!dev->irq) {
-			if (ei_debug > 2)
-				printk("] ");
-			printk("IRQ must be specified for C-NET(98)E/L. probe failed.\n");
-			goto err_out;
-		}
-		outb((dev->irq > 5) ? (dev->irq & 4):(dev->irq >> 1), ioaddr + (0x2 | 0x400));
-		outb(0x7e, ioaddr + (0x4 | 0x400));
-		ne2k_cbus_readmem(dev, ioaddr, 16384, SA_prom, 32);
-		outb(0xff, ioaddr + EN0_ISR);
-		if (ei_debug > 2)
-			printk("done]");
-	} else
-#endif /* CONFIG_NE2K_CBUS_CNET98EL */
-	/* Read the 16 bytes of station address PROM.
-	   We must first initialize registers, similar to NS8390_init(eifdev, 0).
-	   We can't reliably read the SAPROM address without this.
-	   (I learned the hard way!). */
-	{
-		struct {unsigned char value; unsigned short offset;} program_seq[] = 
-		{
-			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
-			/* NEC PC-9800: some board can only handle word-wide access? */
-			{0x48 | ENDCFG_WTS,	EN0_DCFG},	/* Set word-wide (0x48) access. */
-			{16384 / 256, EN0_STARTPG},
-			{32768 / 256, EN0_STOPPG},
-			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
-			{0x00,	EN0_RCNTHI},
-			{0x00,	EN0_IMR},	/* Mask completion irq. */
-			{0xFF,	EN0_ISR},
-			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
-			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
-			{32,	EN0_RCNTLO},
-			{0x00,	EN0_RCNTHI},
-			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
-			{0x00,	EN0_RSARHI},
-			{E8390_RREAD+E8390_START, E8390_CMD},
-		};
-
-		for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
-			outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-		insw(ioaddr + NE_DATAPORT, SA_prom, 32 >> 1);
-
-	}
-
-	if (wordlength == 2)
-	{
-		for (i = 0; i < 16; i++)
-			SA_prom[i] = SA_prom[i+i];
-		start_page = NESM_START_PG;
-		stop_page = NESM_STOP_PG;
-#ifdef CONFIG_NE2K_CBUS_CNET98EL
-		if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) {
-			start_page = CNET98EL_START_PG;
-			stop_page = CNET98EL_STOP_PG;
-		}
-#endif
-	} else {
-		start_page = NE1SM_START_PG;
-		stop_page = NE1SM_STOP_PG;
-	}
-
-	neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
-	if (neX000) {
-		name = "C-Bus-NE2K-compat";
-	}
-	else
-	{
-#ifdef SUPPORT_NE_BAD_CLONES
-		/* Ack!  Well, there might be a *bad* NE*000 clone there.
-		   Check for total bogus addresses. */
-		for (i = 0; bad_clone_list[i].name8; i++)
-		{
-			if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
-				SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
-				SA_prom[2] == bad_clone_list[i].SAprefix[2])
-			{
-				if (wordlength == 2)
-				{
-					name = bad_clone_list[i].name16;
-				} else {
-					name = bad_clone_list[i].name8;
-				}
-				break;
-			}
-		}
-		if (bad_clone_list[i].name8 == NULL)
-		{
-			printk(" not found (invalid signature %2.2x %2.2x).\n",
-				SA_prom[14], SA_prom[15]);
-			ret = -ENXIO;
-			goto err_out;
-		}
-#else
-		printk(" not found.\n");
-		ret = -ENXIO;
-		goto err_out;
-#endif
-	}
-
-	if (dev->irq < 2)
-	{
-		unsigned long cookie = probe_irq_on();
-		outb_p(0x50, ioaddr + EN0_IMR);	/* Enable one interrupt. */
-		outb_p(0x00, ioaddr + EN0_RCNTLO);
-		outb_p(0x00, ioaddr + EN0_RCNTHI);
-		outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
-		mdelay(10);		/* wait 10ms for interrupt to propagate */
-		outb_p(0x00, ioaddr + EN0_IMR); 		/* Mask it again. */
-		dev->irq = probe_irq_off(cookie);
-		if (ei_debug > 2)
-			printk(" autoirq is %d\n", dev->irq);
-	} else if (dev->irq == 7)
-		/* Fixup for users that don't know that IRQ 7 is really IRQ 11,
-		   or don't know which one to set. */
-		dev->irq = 11;
-
-	if (! dev->irq) {
-		printk(" failed to detect IRQ line.\n");
-		ret = -EAGAIN;
-		goto err_out;
-	}
-
-	/* Snarf the interrupt now.  There's no point in waiting since we cannot
-	   share and the board will usually be enabled. */
-	ret = request_irq(dev->irq, ei_interrupt, 0, name, dev);
-	if (ret) {
-		printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
-		goto err_out_kfree;
-	}
-
-	dev->base_addr = ioaddr;
-
-	for(i = 0; i < ETHER_ADDR_LEN; i++) {
-		printk(" %2.2x", SA_prom[i]);
-		dev->dev_addr[i] = SA_prom[i];
-	}
-
-	printk("\n%s: %s found at %#x, hardware type %d(%s), using IRQ %d.\n",
-		   dev->name, name, ioaddr, hw->hwtype, hw->hwident, dev->irq);
-
-	ei_status.name = name;
-	ei_status.tx_start_page = start_page;
-	ei_status.stop_page = stop_page;
-	ei_status.word16 = (wordlength == 2);
-
-	ei_status.rx_start_page = start_page + TX_PAGES;
-#ifdef PACKETBUF_MEMSIZE
-	 /* Allow the packet buffer size to be overridden by know-it-alls. */
-	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
-	ei_status.reset_8390 = &ne_reset_8390;
-	ei_status.block_input = &ne_block_input;
-	ei_status.block_output = &ne_block_output;
-	ei_status.get_8390_hdr = &ne_get_8390_hdr;
-	ei_status.priv = 0;
-	dev->open = &ne_open;
-	dev->stop = &ne_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = ei_poll;
-#endif
-	NS8390_init(dev, 0);
-	return 0;
-
-err_out_kfree:
-	ne2k_cbus_destroy(dev);
-err_out:
-	while (rlist > hw->regionlist) {
-		rlist --;
-		release_region(ioaddr + rlist->start, rlist->range);
-	}
-	return ret;
-}
-
-static int ne_open(struct net_device *dev)
-{
-	ei_open(dev);
-	return 0;
-}
-
-static int ne_close(struct net_device *dev)
-{
-	if (ei_debug > 1)
-		printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
-	ei_close(dev);
-	return 0;
-}
-
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-
-static void ne_reset_8390(struct net_device *dev)
-{
-	unsigned long reset_start_time = jiffies;
-	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
-
-	if (ei_debug > 1)
-		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
-
-	/* derived from CNET98EL-patch for bad clones... */
-	outb_p(E8390_NODMA | E8390_STOP, NE_BASE + E8390_CMD);  /* 0x20 | 0x1 */
-
-	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
-	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-	ei_status.txing = 0;
-	ei_status.dmaing = 0;
-
-	/* This check _should_not_ be necessary, omit eventually. */
-	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-		if (jiffies - reset_start_time > 2*HZ/100) {
-			printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
-			break;
-		}
-	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-	int nic_base = dev->base_addr;
-	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
-
-	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-
-	if (ei_status.dmaing)
-	{
-		printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
-			"[DMAstat:%d][irqlock:%d].\n",
-			dev->name, ei_status.dmaing, ei_status.irqlock);
-		return;
-	}
-
-	ei_status.dmaing |= 0x01;
-	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-	outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
-	outb_p(0, nic_base + EN0_RCNTHI);
-	outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
-	outb_p(ring_page, nic_base + EN0_RSARHI);
-	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-	if (ei_status.word16)
-		insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-	else
-		insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
-
-	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
-
-	le16_to_cpus(&hdr->count);
-}
-
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for hints.
-   The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using outb. */
-
-static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-#ifdef NE_SANITY_CHECK
-	int xfer_count = count;
-#endif
-	int nic_base = dev->base_addr;
-	char *buf = skb->data;
-	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
-
-	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-	if (ei_status.dmaing)
-	{
-		printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
-			"[DMAstat:%d][irqlock:%d].\n",
-			dev->name, ei_status.dmaing, ei_status.irqlock);
-		return;
-	}
-	ei_status.dmaing |= 0x01;
-
-	/* round up count to a word (derived from ICM-patch) */
-	count = (count + 1) & ~1;
-
-	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-	outb_p(count >> 8, nic_base + EN0_RCNTHI);
-	outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
-	outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
-	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-	if (ei_status.word16)
-	{
-		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
-		if (count & 0x01)
-		{
-			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-#ifdef NE_SANITY_CHECK
-			xfer_count++;
-#endif
-		}
-	} else {
-		insb(NE_BASE + NE_DATAPORT, buf, count);
-	}
-
-#ifdef NE_SANITY_CHECK
-	/* This was for the ALPHA version only, but enough people have
-	   been encountering problems so it is still here.  If you see
-	   this message you either 1) have a slightly incompatible clone
-	   or 2) have noise/speed problems with your bus. */
-
-	if (ei_debug > 1)
-	{
-		/* DMA termination address check... */
-		int addr, tries = 20;
-		do {
-			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
-			   -- it's broken for Rx on some cards! */
-			int high = inb_p(nic_base + EN0_RSARHI);
-			int low = inb_p(nic_base + EN0_RSARLO);
-			addr = (high << 8) + low;
-			if (((ring_offset + xfer_count) & 0xff) == low)
-				break;
-		} while (--tries > 0);
-	 	if (tries <= 0)
-			printk(KERN_WARNING "%s: RX transfer address mismatch,"
-				"%#4.4x (expected) vs. %#4.4x (actual).\n",
-				dev->name, ring_offset + xfer_count, addr);
-	}
-#endif
-	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
-}
-
-static void ne_block_output(struct net_device *dev, int count,
-		const unsigned char *buf, const int start_page)
-{
-	int nic_base = NE_BASE;
-	unsigned long dma_start;
-#ifdef NE_SANITY_CHECK
-	int retries = 0;
-#endif
-	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
-
-	/* Round the count up for word writes.  Do we need to do this?
-	   What effect will an odd byte count have on the 8390?
-	   I should check someday. */
-
-	if (ei_status.word16 && (count & 0x01))
-		count++;
-
-	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-	if (ei_status.dmaing)
-	{
-		printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
-			"[DMAstat:%d][irqlock:%d]\n",
-			dev->name, ei_status.dmaing, ei_status.irqlock);
-		return;
-	}
-	ei_status.dmaing |= 0x01;
-	/* We should already be in page 0, but to be safe... */
-	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-#ifdef NE_SANITY_CHECK
-retry:
-#endif
-
-#ifdef NE8390_RW_BUGFIX
-	/* Handle the read-before-write bug the same way as the
-	   Crynwr packet driver -- the NatSemi method doesn't work.
-	   Actually this doesn't always work either, but if you have
-	   problems with your NEx000 this is better than nothing! */
-
-	outb_p(0x42, nic_base + EN0_RCNTLO);
-	outb_p(0x00,   nic_base + EN0_RCNTHI);
-	outb_p(0x42, nic_base + EN0_RSARLO);
-	outb_p(0x00, nic_base + EN0_RSARHI);
-	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-	/* Make certain that the dummy read has occurred. */
-	udelay(6);
-#endif
-
-	outb_p(ENISR_RDC, nic_base + EN0_ISR);
-
-	/* Now the normal output. */
-	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-	outb_p(count >> 8,   nic_base + EN0_RCNTHI);
-	outb_p(0x00, nic_base + EN0_RSARLO);
-	outb_p(start_page, nic_base + EN0_RSARHI);
-
-	outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-	if (ei_status.word16) {
-		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
-	} else {
-		outsb(NE_BASE + NE_DATAPORT, buf, count);
-	}
-
-	dma_start = jiffies;
-
-#ifdef NE_SANITY_CHECK
-	/* This was for the ALPHA version only, but enough people have
-	   been encountering problems so it is still here. */
-
-	if (ei_debug > 1)
-	{
-		/* DMA termination address check... */
-		int addr, tries = 20;
-		do {
-			int high = inb_p(nic_base + EN0_RSARHI);
-			int low = inb_p(nic_base + EN0_RSARLO);
-			addr = (high << 8) + low;
-			if ((start_page << 8) + count == addr)
-				break;
-		} while (--tries > 0);
-
-		if (tries <= 0)
-		{
-			printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
-				"%#4.4x (expected) vs. %#4.4x (actual).\n",
-				dev->name, (start_page << 8) + count, addr);
-			if (retries++ == 0)
-				goto retry;
-		}
-	}
-#endif
-
-	while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
-		if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
-			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
-			ne_reset_8390(dev);
-			NS8390_init(dev,1);
-			break;
-		}
-
-	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
-	return;
-}
-
-
-#ifdef MODULE
-#define MAX_NE_CARDS	4	/* Max number of NE cards per module */
-static struct net_device *dev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS];	/* 0xbad = bad sig or no reset ack */
-static int hwtype[MAX_NE_CARDS] = { 0, }; /* board type */
-
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
-MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
-MODULE_PARM(hwtype, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
-MODULE_PARM_DESC(io, "I/O base address(es),required");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
-MODULE_PARM_DESC(hwtype, "Board type of PC-9800 C-Bus NIC");
-MODULE_DESCRIPTION("NE1000/NE2000 PC-9800 C-bus Ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that no ISA autoprobe takes place. We can't guarantee
-that the ne2k probe is the last 8390 based probe to take place (as it
-is at boot) and so the probe will get confused by any other 8390 cards.
-ISA device autoprobes on a running machine are not recommended anyway. */
-
-int init_module(void)
-{
-	int this_dev, found = 0;
-
-	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct net_device *dev = alloc_ei_netdev();
-		if (!dev)
-			break;
-		dev->irq = irq[this_dev];
-		dev->mem_end = bad[this_dev];
-		dev->base_addr = io[this_dev];
-		dev->mem_start = hwtype[this_dev];
-		if (do_ne_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_ne[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
-		}
-		free_netdev(dev);
-		if (found)
-			break;
-		if (io[this_dev] != 0)
-			printk(KERN_WARNING "ne2k_cbus: No NE*000 card found at i/o = %#x\n", io[this_dev]);
-		else
-			printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
-		return -ENXIO;
-	}
-	if (found)
-		return 0;
- 	return -ENODEV;
-}
-
-void cleanup_module(void)
-{
-	int this_dev;
-
-	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct net_device *dev = dev_ne[this_dev];
-		if (dev) {
-			unregister_netdev(dev);
-			cleanup_card(dev);
-			free_netdev(dev);
-		}
-	}
-}
-#endif /* MODULE */
-
diff -Nru a/drivers/net/ne2k_cbus.h b/drivers/net/ne2k_cbus.h
--- a/drivers/net/ne2k_cbus.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,481 +0,0 @@
-/* ne2k_cbus.h: 
-   vender-specific information definition for NEC PC-9800
-   C-bus Ethernet Cards
-   Used in ne.c 
-
-   (C)1998,1999 KITAGWA Takurou & Linux/98 project
-*/
-
-#include <linux/config.h>
-
-#undef NE_RESET
-#define NE_RESET EI_SHIFT(0x11) /* Issue a read to reset, a write to clear. */
-
-#ifdef CONFIG_NE2K_CBUS_CNET98EL
-#ifndef CONFIG_NE2K_CBUS_CNET98EL_IO_BASE
-#warning CONFIG_NE2K_CBUS_CNET98EL_IO_BASE is not defined(config error?)
-#warning use 0xaaed as default
-#define CONFIG_NE2K_CBUS_CNET98EL_IO_BASE 0xaaed /* or 0x55ed */
-#endif
-#define CNET98EL_START_PG 0x00
-#define CNET98EL_STOP_PG 0x40
-#endif
-
-/* Hardware type definition (derived from *BSD) */
-#define NE2K_CBUS_HARDWARE_TYPE_MASK 0xff
-
-/* 0: reserved for auto-detect */
-/* 1: (not tested)
-   Allied Telesis CentreCom LA-98-T */
-#define NE2K_CBUS_HARDWARE_TYPE_ATLA98 1
-/* 2: (not tested)
-   ELECOM Laneed
-   LD-BDN[123]A
-   PLANET SMART COM 98 EN-2298-C
-   MACNICA ME98 */
-#define NE2K_CBUS_HARDWARE_TYPE_BDN 2
-/* 3:
-   Melco EGY-98
-   Contec C-NET(98)E*A/L*A,C-NET(98)P */
-#define NE2K_CBUS_HARDWARE_TYPE_EGY98 3
-/* 4:
-   Melco LGY-98,IND-SP,IND-SS
-   MACNICA NE2098 */
-#define NE2K_CBUS_HARDWARE_TYPE_LGY98 4
-/* 5:
-   ICM DT-ET-25,DT-ET-T5,IF-2766ET,IF-2771ET
-   PLANET SMART COM 98 EN-2298-T,EN-2298P-T
-   D-Link DE-298PT,DE-298PCAT
-   ELECOM Laneed LD-98P */
-#define NE2K_CBUS_HARDWARE_TYPE_ICM 5
-/* 6: (reserved for SIC-98, which is not supported in this driver.) */
-/* 7: (unused in *BSD?)
-   <Original NE2000 compatible>
-   <for PCI/PCMCIA cards>
-*/
-#define NE2K_CBUS_HARDWARE_TYPE_NE2K 7
-/* 8:
-   NEC PC-9801-108 */
-#define NE2K_CBUS_HARDWARE_TYPE_NEC108 8
-/* 9:
-   I-O DATA LA-98,LA/T-98 */
-#define NE2K_CBUS_HARDWARE_TYPE_IOLA98 9
-/* 10: (reserved for C-NET(98), which is not supported in this driver.) */
-/* 11:
-   Contec C-NET(98)E,L */
-#define NE2K_CBUS_HARDWARE_TYPE_CNET98EL 11
-
-#define NE2K_CBUS_HARDWARE_TYPE_MAX 11
-
-/* HARDWARE TYPE ID 12-31: reserved */
-
-struct ne2k_cbus_offsetinfo {
-	unsigned short skip;
-	unsigned short offset8; /* +0x8 - +0xf */
-	unsigned short offset10; /* +0x10 */
-	unsigned short offset1f; /* +0x1f */
-};
-
-struct ne2k_cbus_region {
-	unsigned short start;
-	short range;
-};
-
-struct ne2k_cbus_hwinfo {
-	const unsigned short hwtype;
-	const unsigned char *hwident;
-#ifndef MODULE
-	const unsigned short *portlist;
-#endif
-	const struct ne2k_cbus_offsetinfo *offsetinfo;
-	const struct ne2k_cbus_region *regionlist;
-};
-
-#ifdef CONFIG_NE2K_CBUS_ATLA98
-#ifndef MODULE
-static unsigned short atla98_portlist[] __initdata = {
-	0xd0,
-	0
-};
-#endif
-#define atla98_offsetinfo ne2k_offsetinfo
-#define atla98_regionlist ne2k_regionlist
-#endif /* CONFIG_NE2K_CBUS_ATLA98 */
-
-#ifdef CONFIG_NE2K_CBUS_BDN
-#ifndef MODULE
-static unsigned short bdn_portlist[] __initdata = {
-	0xd0,
-	0
-};
-#endif
-static struct ne2k_cbus_offsetinfo bdn_offsetinfo __initdata = {
-#if 0
-	/* comes from FreeBSD(98) ed98.h */
-	0x1000, 0x8000, 0x100, 0xc200 /* ??? */
-#else
-	/* comes from NetBSD/pc98 if_ne_isa.c */
-	0x1000, 0x8000, 0x100, 0x7f00 /* ??? */
-#endif
-};
-static struct ne2k_cbus_region bdn_regionlist[] __initdata = {
-	{0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000,1},
-	{0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1},
-	{0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1},
-	{0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1},
-	{0x100, 1}, {0x7f00, 1},
-	{0x0, 0}
-};
-#endif /* CONFIG_NE2K_CBUS_BDN */
-
-#ifdef CONFIG_NE2K_CBUS_EGY98
-#ifndef MODULE
-static unsigned short egy98_portlist[] __initdata = {
-	0xd0,
-	0
-};
-#endif
-static struct ne2k_cbus_offsetinfo egy98_offsetinfo __initdata = {
-	0x02, 0x100, 0x200, 0x300
-};
-static struct ne2k_cbus_region egy98_regionlist[] __initdata = {
-	{0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1},
-	{0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1},
-	{0x100, 1}, {0x102, 1}, {0x104, 1}, {0x106, 1},
-	{0x108, 1}, {0x10a, 1}, {0x10c, 1}, {0x10e, 1},
-	{0x200, 1}, {0x300, 1},
-	{0x0, 0}
-};
-#endif /* CONFIG_NE2K_CBUS_EGY98 */
-
-#ifdef CONFIG_NE2K_CBUS_LGY98
-#ifndef MODULE
-static unsigned short lgy98_portlist[] __initdata = {
-	0xd0, 0x10d0, 0x20d0, 0x30d0, 0x40d0, 0x50d0, 0x60d0, 0x70d0,
-	0
-};
-#endif
-static struct ne2k_cbus_offsetinfo lgy98_offsetinfo __initdata = {
-	0x01, 0x08, 0x200, 0x300
-};
-static struct ne2k_cbus_region lgy98_regionlist[] __initdata = {
-	{0x0, 16}, {0x200, 1}, {0x300, 1},
-	{0x0, 0}
-};
-#endif /* CONFIG_NE2K_CBUS_LGY98 */
-
-#ifdef CONFIG_NE2K_CBUS_ICM
-#ifndef MODULE
-static unsigned short icm_portlist[] __initdata = {
-	/* ICM */
-	0x56d0,
-	/* LD-98PT */
-	0x46d0, 0x66d0, 0x76d0, 0x86d0, 0x96d0, 0xa6d0, 0xb6d0, 0xc6d0,
-	0
-};
-#endif
-static struct ne2k_cbus_offsetinfo icm_offsetinfo __initdata = {
-	0x01, 0x08, 0x100, 0x10f
-};
-static struct ne2k_cbus_region icm_regionlist[] __initdata = {
-	{0x0, 16}, {0x100, 16},
-	{0x0, 0}
-};
-#endif /* CONFIG_NE2K_CBUS_ICM */
-
-#if defined(CONFIG_NE2K_CBUS_NE2K) && !defined(MODULE)
-static unsigned short ne2k_portlist[] __initdata = {
-	0xd0, 0x300, 0x280, 0x320, 0x340, 0x360, 0x380,
-	0
-};
-#endif
-#if defined(CONFIG_NE2K_CBUS_NE2K) || defined(CONFIG_NE2K_CBUS_ATLA98)
-static struct ne2k_cbus_offsetinfo ne2k_offsetinfo __initdata = {
-	0x01, 0x08, 0x10, 0x1f
-};
-static struct ne2k_cbus_region ne2k_regionlist[] __initdata = {
-	{0x0, 32},
-	{0x0, 0}
-};
-#endif
-
-#ifdef CONFIG_NE2K_CBUS_NEC108
-#ifndef MODULE
-static unsigned short nec108_portlist[] __initdata = {
-	0x770, 0x2770, 0x4770, 0x6770,
-	0
-};
-#endif
-static struct ne2k_cbus_offsetinfo nec108_offsetinfo __initdata = {
-	0x02, 0x1000, 0x888, 0x88a
-};
-static struct ne2k_cbus_region nec108_regionlist[] __initdata = {
-	{0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1},
-	{0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1},
-	{0x1000, 1}, {0x1002, 1}, {0x1004, 1}, {0x1006, 1},
-	{0x1008, 1}, {0x100a, 1}, {0x100c, 1}, {0x100e, 1},
-	{0x888, 1}, {0x88a, 1}, {0x88c, 1}, {0x88e, 1},
-	{0x0, 0}
-};
-#endif
-
-#ifdef CONFIG_NE2K_CBUS_IOLA98
-#ifndef MODULE
-static unsigned short iola98_portlist[] __initdata = {
-	0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
-	0
-};
-#endif
-static struct ne2k_cbus_offsetinfo iola98_offsetinfo __initdata = {
-	0x1000, 0x8000, 0x100, 0xf100
-};
-static struct ne2k_cbus_region iola98_regionlist[] __initdata = {
-	{0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000, 1},
-	{0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1},
-	{0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1},
-	{0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1},
-	{0x100, 1}, {0xf100, 1},
-	{0x0,0}
-};
-#endif /* CONFIG_NE2K_CBUS_IOLA98 */
-
-#ifdef CONFIG_NE2K_CBUS_CNET98EL
-#ifndef MODULE
-static unsigned short cnet98el_portlist[] __initdata = {
-	0x3d0, 0x13d0, 0x23d0, 0x33d0, 0x43d0, 0x53d0, 0x60d0, 0x70d0,
-	0
-};
-#endif
-static struct ne2k_cbus_offsetinfo cnet98el_offsetinfo __initdata = {
-	0x01, 0x08, 0x40e, 0x400
-};
-static struct ne2k_cbus_region cnet98el_regionlist[] __initdata = {
-	{0x0, 16}, {0x400, 16},
-	{0x0, 0}
-};
-#endif
-
-
-/* port information table (for ne.c initialize/probe process) */
-
-static struct ne2k_cbus_hwinfo ne2k_cbus_hwinfo_list[] __initdata = {
-#ifdef CONFIG_NE2K_CBUS_ATLA98
-/* NOT TESTED */
-	{
-		NE2K_CBUS_HARDWARE_TYPE_ATLA98,
-		"LA-98-T",
-#ifndef MODULE
-		atla98_portlist,
-#endif
-		&atla98_offsetinfo, atla98_regionlist
-	},
-#endif
-#ifdef CONFIG_NE2K_CBUS_BDN
-/* NOT TESTED */
-	{
-		NE2K_CBUS_HARDWARE_TYPE_BDN,
-		"LD-BDN[123]A",
-#ifndef MODULE
-		bdn_portlist,
-#endif
-		&bdn_offsetinfo, bdn_regionlist
-	},
-#endif
-#ifdef CONFIG_NE2K_CBUS_ICM
-	{
-		NE2K_CBUS_HARDWARE_TYPE_ICM,
-		"IF-27xxET",
-#ifndef MODULE
-		icm_portlist,
-#endif
-		&icm_offsetinfo, icm_regionlist
-	},
-#endif
-#ifdef CONFIG_NE2K_CBUS_NE2K
-	{
-		NE2K_CBUS_HARDWARE_TYPE_NE2K,
-		"NE2000 compat.",
-#ifndef MODULE
-		ne2k_portlist,
-#endif
-		&ne2k_offsetinfo, ne2k_regionlist
-	},
-#endif
-#ifdef CONFIG_NE2K_CBUS_NEC108
-	{
-		NE2K_CBUS_HARDWARE_TYPE_NEC108,
-		"PC-9801-108",
-#ifndef MODULE
-		nec108_portlist,
-#endif
-		&nec108_offsetinfo, nec108_regionlist
-	},
-#endif
-#ifdef CONFIG_NE2K_CBUS_IOLA98
-	{
-		NE2K_CBUS_HARDWARE_TYPE_IOLA98,
-		"LA-98",
-#ifndef MODULE
-		iola98_portlist,
-#endif
-		&iola98_offsetinfo, iola98_regionlist
-	},
-#endif
-#ifdef CONFIG_NE2K_CBUS_CNET98EL
-	{
-		NE2K_CBUS_HARDWARE_TYPE_CNET98EL,
-		"C-NET(98)E/L",
-#ifndef MODULE
-		cnet98el_portlist,
-#endif
-		&cnet98el_offsetinfo, cnet98el_regionlist
-	},
-#endif
-/* NOTE: LGY98 must be probed before EGY98, or system stalled!? */
-#ifdef CONFIG_NE2K_CBUS_LGY98
-	{
-		NE2K_CBUS_HARDWARE_TYPE_LGY98,
-		"LGY-98",
-#ifndef MODULE
-		lgy98_portlist,
-#endif
-		&lgy98_offsetinfo, lgy98_regionlist
-	},
-#endif
-#ifdef CONFIG_NE2K_CBUS_EGY98
-	{
-		NE2K_CBUS_HARDWARE_TYPE_EGY98,
-		"EGY-98",
-#ifndef MODULE
-		egy98_portlist,
-#endif
-		&egy98_offsetinfo, egy98_regionlist
-	},
-#endif
-	{
-		0,
-		"unsupported hardware",
-#ifndef MODULE
-		NULL,
-#endif
-		NULL, NULL
-	}
-};
-
-static int __init ne2k_cbus_init(struct net_device *dev)
-{
-	struct ei_device *ei_local;
-	if (dev->priv == NULL) {
-		ei_local = kmalloc(sizeof(struct ei_device), GFP_KERNEL);
-		if (ei_local == NULL)
-			return -ENOMEM;
-		memset(ei_local, 0, sizeof(struct ei_device));
-		ei_local->reg_offset = kmalloc(sizeof(typeof(*ei_local->reg_offset))*18, GFP_KERNEL);
-		if (ei_local->reg_offset == NULL) {
-			kfree(ei_local);
-			return -ENOMEM;
-		}
-		spin_lock_init(&ei_local->page_lock);
-		dev->priv = ei_local;
-	}
-	return 0;
-}
-
-static void ne2k_cbus_destroy(struct net_device *dev)
-{
-	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
-	if (ei_local != NULL) {
-		if (ei_local->reg_offset)
-			kfree(ei_local->reg_offset);
-		kfree(dev->priv);
-		dev->priv = NULL;
-	}
-}
-
-static const struct ne2k_cbus_hwinfo * __init ne2k_cbus_get_hwinfo(int hwtype)
-{
-	const struct ne2k_cbus_hwinfo *hw;
-
-	for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
-		if (hw->hwtype == hwtype) break;
-	}
-	return hw;
-}
-
-static void __init ne2k_cbus_set_hwtype(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr)
-{
-	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
-	int i;
-	int hwtype_old = dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK;
-
-	if (!ei_local)
-		panic("Gieee! ei_local == NULL!! (from %p)",
-		       __builtin_return_address(0));
-
-	dev->mem_start &= ~NE2K_CBUS_HARDWARE_TYPE_MASK;
-	dev->mem_start |= hw->hwtype & NE2K_CBUS_HARDWARE_TYPE_MASK;
-
-	if (ei_debug > 2) {
-		printk(KERN_DEBUG "hwtype changed: %d -> %d\n",hwtype_old,(int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
-	}
-
-	if (hw->offsetinfo) {
-		for (i = 0; i < 8; i++) {
-			ei_local->reg_offset[i] = hw->offsetinfo->skip * i;
-		}
-		for (i = 8; i < 16; i++) {
-			ei_local->reg_offset[i] =
-				hw->offsetinfo->skip*(i-8) + hw->offsetinfo->offset8;
-		}
-#ifdef CONFIG_NE2K_CBUS_NEC108
-		if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_NEC108) {
-			int adj = (ioaddr & 0xf000) /2;
-			ei_local->reg_offset[16] = 
-				(hw->offsetinfo->offset10 | adj) - ioaddr;
-			ei_local->reg_offset[17] = 
-				(hw->offsetinfo->offset1f | adj) - ioaddr;
-		} else {
-#endif /* CONFIG_NE2K_CBUS_NEC108 */
-			ei_local->reg_offset[16] = hw->offsetinfo->offset10;
-			ei_local->reg_offset[17] = hw->offsetinfo->offset1f;
-#ifdef CONFIG_NE2K_CBUS_NEC108
-		}
-#endif
-	} else {
-		/* make dummmy offset list */
-		for (i = 0; i < 16; i++) {
-			ei_local->reg_offset[i] = i;
-		}
-		ei_local->reg_offset[16] = 0x10;
-		ei_local->reg_offset[17] = 0x1f;
-	}
-}
-
-#if defined(CONFIG_NE2K_CBUS_ICM) || defined(CONFIG_NE2K_CBUS_CNET98EL)
-static void __init ne2k_cbus_readmem(struct net_device *dev, int ioaddr, unsigned short memaddr, char *buf, unsigned short len)
-{
-	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
-	outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD);
-	outb_p(len & 0xff, ioaddr+EN0_RCNTLO);
-	outb_p(len >> 8, ioaddr+EN0_RCNTHI);
-	outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO);
-	outb_p(memaddr >> 8, ioaddr+EN0_RSARHI);
-	outb_p(E8390_RREAD | E8390_START, ioaddr+E8390_CMD);
-	insw(ioaddr+NE_DATAPORT, buf, len >> 1);
-}
-static void __init ne2k_cbus_writemem(struct net_device *dev, int ioaddr, unsigned short memaddr, const char *buf, unsigned short len)
-{
-	struct ei_device *ei_local = (struct ei_device *)(dev->priv);
-	outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD);
-	outb_p(ENISR_RDC, ioaddr+EN0_ISR);
-	outb_p(len & 0xff, ioaddr+EN0_RCNTLO);
-	outb_p(len >> 8, ioaddr+EN0_RCNTHI);
-	outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO);
-	outb_p(memaddr >> 8, ioaddr+EN0_RSARHI);
-	outb_p(E8390_RWRITE | E8390_START, ioaddr+E8390_CMD);
-	outsw(ioaddr+NE_DATAPORT, buf, len >> 1);
-}
-#endif
-
-static int ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr, int irq);
-/* End of ne2k_cbus.h */
diff -Nru a/drivers/net/ne3210.c b/drivers/net/ne3210.c
--- a/drivers/net/ne3210.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/ne3210.c	2004-06-23 19:04:26 -07:00
@@ -45,6 +45,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "ne3210"
+
 static int ne3210_open(struct net_device *dev);
 static int ne3210_close(struct net_device *dev);
 
@@ -111,13 +113,13 @@
 	device->driver_data = dev;
 	ioaddr = edev->base_addr;
 
-	if (!request_region(ioaddr, NE3210_IO_EXTENT, dev->name)) {
+	if (!request_region(ioaddr, NE3210_IO_EXTENT, DRV_NAME)) {
 		retval = -EBUSY;
 		goto out;
 	}
 
 	if (!request_region(ioaddr + NE3210_CFG1,
-			    NE3210_CFG_EXTENT, dev->name)) {
+			    NE3210_CFG_EXTENT, DRV_NAME)) {
 		retval = -EBUSY;
 		goto out1;
 	}
@@ -140,7 +142,7 @@
 	dev->irq = irq_map[(inb(ioaddr + NE3210_CFG2) >> 3) & 0x07];
 	printk(".\nne3210.c: using IRQ %d, ", dev->irq);
 
-	retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
+	retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
 	if (retval) {
 		printk (" unable to get IRQ %d.\n", dev->irq);
 		goto out2;
@@ -163,7 +165,7 @@
 		}
 	}
 	
-	if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, dev->name)) {
+	if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, DRV_NAME)) {
 		printk ("ne3210.c: Unable to request shared memory at physical address %#lx\n",
 			phys_mem);
 		goto out3;
diff -Nru a/drivers/net/ni52.c b/drivers/net/ni52.c
--- a/drivers/net/ni52.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/ni52.c	2004-06-23 19:04:27 -07:00
@@ -124,6 +124,8 @@
 
 #include "ni52.h"
 
+#define DRV_NAME "ni52"
+
 #define DEBUG       /* debug on */
 #define SYSBUSVAL 1 /* 8 Bit */
 
@@ -424,7 +426,7 @@
 	dev->mem_start = memstart;
 	dev->mem_end = memend;
 
-	if (!request_region(ioaddr, NI52_TOTAL_SIZE, dev->name))
+	if (!request_region(ioaddr, NI52_TOTAL_SIZE, DRV_NAME))
 		return -EBUSY;
 
 	if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) ||
diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c
--- a/drivers/net/ns83820.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/ns83820.c	2004-06-23 19:04:28 -07:00
@@ -113,6 +113,8 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#define DRV_NAME "ns83820"
+
 /* Global parameters.  See MODULE_PARM near the bottom. */
 static int ihr = 2;
 static int reset_phy = 0;
@@ -1851,7 +1853,7 @@
 		0);
 
 	err = request_irq(pci_dev->irq, ns83820_irq, SA_SHIRQ,
-			  ndev->name, ndev);
+			  DRV_NAME, ndev);
 	if (err) {
 		printk(KERN_INFO "ns83820: unable to register irq %d\n",
 			pci_dev->irq);
diff -Nru a/drivers/net/oaknet.c b/drivers/net/oaknet.c
--- a/drivers/net/oaknet.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/oaknet.c	2004-06-23 19:04:28 -07:00
@@ -164,7 +164,7 @@
 	ret = -EAGAIN;
 	if (request_irq(dev->irq, ei_interrupt, 0, name, dev)) {
 		printk("%s: unable to request interrupt %d.\n",
-		       dev->name, dev->irq);
+		       name, dev->irq);
 		goto out_region;
 	}
 
diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
--- a/drivers/net/pcnet32.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/pcnet32.c	2004-06-23 19:04:26 -07:00
@@ -22,8 +22,8 @@
  *************************************************************************/
 
 #define DRV_NAME	"pcnet32"
-#define DRV_VERSION	"1.30c"
-#define DRV_RELDATE	"05.25.2004"
+#define DRV_VERSION	"1.30f"
+#define DRV_RELDATE	"06.16.2004"
 #define PFX		DRV_NAME ": "
 
 static const char *version =
@@ -245,6 +245,11 @@
  * v1.30b  24 May 2004 Don Fry fix bogus tx carrier errors with 79c973,
  *	   assisted by Bruce Penrod <bmpenrod@endruntechnologies.com>.
  * v1.30c  25 May 2004 Don Fry added netif_wake_queue after pcnet32_restart.
+ * v1.30d  01 Jun 2004 Don Fry discard oversize rx packets.
+ * v1.30e  11 Jun 2004 Don Fry recover after fifo error and rx hang.
+ * v1.30f  16 Jun 2004 Don Fry cleanup IRQ to allow 0 and 1 for PCI,
+ * 	   expanding on suggestions from Ralf Baechle <ralf@linux-mips.org>,
+ * 	   and Brian Murphy <brian@murphy.dk>.
  */
 
 
@@ -360,7 +365,7 @@
 
 static void pcnet32_probe_vlbus(void);
 static int  pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
-static int  pcnet32_probe1(unsigned long, unsigned int, int, struct pci_dev *);
+static int  pcnet32_probe1(unsigned long, int, struct pci_dev *);
 static int  pcnet32_open(struct net_device *);
 static int  pcnet32_init_ring(struct net_device *);
 static int  pcnet32_start_xmit(struct sk_buff *, struct net_device *);
@@ -958,7 +963,7 @@
 	if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) {
 	    /* check if there is really a pcnet chip on that ioaddr */
 	    if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) {
-		pcnet32_probe1(ioaddr, 0, 0, NULL);
+		pcnet32_probe1(ioaddr, 0, NULL);
 	    } else {
 		release_region(ioaddr, PCNET32_TOTAL_SIZE);
 	    }
@@ -999,7 +1004,7 @@
 	return -EBUSY;
     }
 
-    return pcnet32_probe1(ioaddr, pdev->irq, 1, pdev);
+    return pcnet32_probe1(ioaddr, 1, pdev);
 }
 
 
@@ -1008,8 +1013,7 @@
  *  pdev will be NULL when called from pcnet32_probe_vlbus.
  */
 static int __devinit
-pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
-		struct pci_dev *pdev)
+pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 {
     struct pcnet32_private *lp;
     dma_addr_t lp_dma_addr;
@@ -1270,11 +1274,8 @@
     a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private,
 		    init_block)) >> 16);
 
-    if (irq_line) {
-	dev->irq = irq_line;
-    }
-
-    if (dev->irq >= 2) {
+    if (pdev) {		/* use the IRQ provided by PCI */
+	dev->irq = pdev->irq;
 	if (pcnet32_debug & NETIF_MSG_PROBE)
 	    printk(" assigned IRQ %d.\n", dev->irq);
     } else {
@@ -1362,8 +1363,7 @@
     int rc;
     unsigned long flags;
 
-    if (dev->irq == 0 ||
-	request_irq(dev->irq, &pcnet32_interrupt,
+    if (request_irq(dev->irq, &pcnet32_interrupt,
 		    lp->shared_irq ? SA_SHIRQ : 0, dev->name, (void *)dev)) {
 	return -EAGAIN;
     }
@@ -1531,13 +1531,15 @@
     int i;
 
     for (i = 0; i < TX_RING_SIZE; i++) {
+	lp->tx_ring[i].status = 0;	/* CPU owns buffer */
+	wmb();	/* Make sure adapter sees owner change */
 	if (lp->tx_skbuff[i]) {
 	    pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
 		    lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE);
 	    dev_kfree_skb_any(lp->tx_skbuff[i]);
-	    lp->tx_skbuff[i] = NULL;
-	    lp->tx_dma_addr[i] = 0;
 	}
+	lp->tx_skbuff[i] = NULL;
+	lp->tx_dma_addr[i] = 0;
     }
 }
 
@@ -1566,21 +1568,23 @@
 	    skb_reserve (rx_skbuff, 2);
 	}
 
+	rmb();
 	if (lp->rx_dma_addr[i] == 0)
 	    lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail,
 		    PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 	lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]);
 	lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
+	wmb();	/* Make sure owner changes after all others are visible */
 	lp->rx_ring[i].status = le16_to_cpu(0x8000);
     }
     /* The Tx buffer address is filled in as needed, but we do need to clear
      * the upper ownership bit. */
     for (i = 0; i < TX_RING_SIZE; i++) {
+	lp->tx_ring[i].status = 0;	/* CPU owns buffer */
+	wmb();	/* Make sure adapter sees owner change */
 	lp->tx_ring[i].base = 0;
-	lp->tx_ring[i].status = 0;
 	lp->tx_dma_addr[i] = 0;
     }
-    wmb(); /* Make sure all changes are visible */
 
     lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
     for (i = 0; i < 6; i++)
@@ -1589,9 +1593,14 @@
 	    offsetof(struct pcnet32_private, rx_ring));
     lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
 	    offsetof(struct pcnet32_private, tx_ring));
+    wmb();	/* Make sure all changes are visible */
     return 0;
 }
 
+/* the pcnet32 has been issued a stop or reset.  Wait for the stop bit
+ * then flush the pending transmit operations, re-initialize the ring,
+ * and tell the chip to initialize.
+ */
 static void
 pcnet32_restart(struct net_device *dev, unsigned int csr0_bits)
 {
@@ -1599,6 +1608,15 @@
     unsigned long ioaddr = dev->base_addr;
     int i;
 
+    /* wait for stop */
+    for (i=0; i<100; i++)
+	if (lp->a.read_csr(ioaddr, 0) & 0x0004)
+	   break;
+
+    if (i >= 100 && netif_msg_drv(lp))
+	printk(KERN_ERR "%s: pcnet32_restart timed out waiting for stop.\n",
+		dev->name);
+
     pcnet32_purge_tx_ring(dev);
     if (pcnet32_init_ring(dev))
 	return;
@@ -1857,15 +1875,16 @@
 	}
 
 	if (must_restart) {
-	    /* stop the chip to clear the error condition, then restart */
-	    lp->a.write_csr (ioaddr, 0, 0x0004);
+	    /* reset the chip to clear the error condition, then restart */
+	    lp->a.reset(ioaddr);
+	    lp->a.write_csr(ioaddr, 4, 0x0915);
 	    pcnet32_restart(dev, 0x0002);
 	    netif_wake_queue(dev);
 	}
     }
 
-    /* Clear any other interrupt, and set interrupt enable. */
-    lp->a.write_csr (ioaddr, 0, 0x7940);
+    /* Set interrupt enable. */
+    lp->a.write_csr (ioaddr, 0, 0x0040);
     lp->a.write_rap (ioaddr,rap);
 
     if (netif_msg_intr(lp))
@@ -1907,7 +1926,13 @@
 	    short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4;
 	    struct sk_buff *skb;
 
-	    if (pkt_len < 60) {
+	    /* Discard oversize frames. */
+	    if (unlikely(pkt_len > PKT_BUF_SZ - 2)) {
+		if (netif_msg_drv(lp))
+		    printk(KERN_ERR "%s: Impossible packet size %d!\n",
+			    dev->name, pkt_len);
+		lp->stats.rx_errors++;
+	    } else if (pkt_len < 60) {
 		if (netif_msg_rx_err(lp))
 		    printk(KERN_ERR "%s: Runt packet!\n", dev->name);
 		lp->stats.rx_errors++;
diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
--- a/drivers/net/ppp_generic.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/ppp_generic.c	2004-06-23 19:04:28 -07:00
@@ -129,8 +129,9 @@
 #endif /* CONFIG_PPP_MULTILINK */
 	struct net_device_stats stats;	/* statistics */
 #ifdef CONFIG_PPP_FILTER
-	struct sock_fprog pass_filter;	/* filter for packets to pass */
-	struct sock_fprog active_filter;/* filter for pkts to reset idle */
+	struct sock_filter *pass_filter;	/* filter for packets to pass */
+	struct sock_filter *active_filter;/* filter for pkts to reset idle */
+	unsigned pass_len, active_len;
 #endif /* CONFIG_PPP_FILTER */
 };
 
@@ -493,6 +494,43 @@
 	return mask;
 }
 
+static int get_filter(void __user *arg, struct sock_filter **p)
+{
+	struct sock_fprog uprog;
+	struct sock_filter *code = NULL;
+	int len, err;
+
+	if (copy_from_user(&uprog, arg, sizeof(uprog)))
+		return -EFAULT;
+
+	if (uprog.len > BPF_MAXINSNS)
+		return -EINVAL;
+
+	if (!uprog.len) {
+		*p = NULL;
+		return 0;
+	}
+
+	len = uprog.len * sizeof(struct sock_filter);
+	code = kmalloc(len, GFP_KERNEL);
+	if (code == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(code, uprog.filter, len)) {
+		kfree(code);
+		return -EFAULT;
+	}
+
+	err = sk_chk_filter(code, uprog.len);
+	if (err) {
+		kfree(code);
+		return err;
+	}
+
+	*p = code;
+	return uprog.len;
+}
+
 static int ppp_ioctl(struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
@@ -503,6 +541,8 @@
 	struct npioctl npi;
 	int unit, cflags;
 	struct slcompress *vj;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
 
 	if (pf == 0)
 		return ppp_unattached_ioctl(pf, file, cmd, arg);
@@ -540,7 +580,7 @@
 
 		switch (cmd) {
 		case PPPIOCCONNECT:
-			if (get_user(unit, (int *) arg))
+			if (get_user(unit, p))
 				break;
 			err = ppp_connect_channel(pch, unit);
 			break;
@@ -569,14 +609,14 @@
 	ppp = PF_TO_PPP(pf);
 	switch (cmd) {
 	case PPPIOCSMRU:
-		if (get_user(val, (int *) arg))
+		if (get_user(val, p))
 			break;
 		ppp->mru = val;
 		err = 0;
 		break;
 
 	case PPPIOCSFLAGS:
-		if (get_user(val, (int *) arg))
+		if (get_user(val, p))
 			break;
 		ppp_lock(ppp);
 		cflags = ppp->flags & ~val;
@@ -589,7 +629,7 @@
 
 	case PPPIOCGFLAGS:
 		val = ppp->flags | ppp->xstate | ppp->rstate;
-		if (put_user(val, (int *) arg))
+		if (put_user(val, p))
 			break;
 		err = 0;
 		break;
@@ -599,20 +639,20 @@
 		break;
 
 	case PPPIOCGUNIT:
-		if (put_user(ppp->file.index, (int *) arg))
+		if (put_user(ppp->file.index, p))
 			break;
 		err = 0;
 		break;
 
 	case PPPIOCSDEBUG:
-		if (get_user(val, (int *) arg))
+		if (get_user(val, p))
 			break;
 		ppp->debug = val;
 		err = 0;
 		break;
 
 	case PPPIOCGDEBUG:
-		if (put_user(ppp->debug, (int *) arg))
+		if (put_user(ppp->debug, p))
 			break;
 		err = 0;
 		break;
@@ -620,13 +660,13 @@
 	case PPPIOCGIDLE:
 		idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
 		idle.recv_idle = (jiffies - ppp->last_recv) / HZ;
-		if (copy_to_user((void __user *) arg, &idle, sizeof(idle)))
+		if (copy_to_user(argp, &idle, sizeof(idle)))
 			break;
 		err = 0;
 		break;
 
 	case PPPIOCSMAXCID:
-		if (get_user(val, (int *) arg))
+		if (get_user(val, p))
 			break;
 		val2 = 15;
 		if ((val >> 16) != 0) {
@@ -649,7 +689,7 @@
 
 	case PPPIOCGNPMODE:
 	case PPPIOCSNPMODE:
-		if (copy_from_user(&npi, (void __user *) arg, sizeof(npi)))
+		if (copy_from_user(&npi, argp, sizeof(npi)))
 			break;
 		err = proto_to_npindex(npi.protocol);
 		if (err < 0)
@@ -658,7 +698,7 @@
 		if (cmd == PPPIOCGNPMODE) {
 			err = -EFAULT;
 			npi.mode = ppp->npmode[i];
-			if (copy_to_user((void __user *) arg, &npi, sizeof(npi)))
+			if (copy_to_user(argp, &npi, sizeof(npi)))
 				break;
 		} else {
 			ppp->npmode[i] = npi.mode;
@@ -670,49 +710,38 @@
 
 #ifdef CONFIG_PPP_FILTER
 	case PPPIOCSPASS:
+	{
+		struct sock_filter *code;
+		err = get_filter(argp, &code);
+		if (err >= 0) {
+			ppp_lock(ppp);
+			kfree(ppp->pass_filter);
+			ppp->pass_filter = code;
+			ppp->pass_len = err;
+			ppp_unlock(ppp);
+			err = 0;
+		}
+		break;
+	}
 	case PPPIOCSACTIVE:
 	{
-		struct sock_fprog uprog, *filtp;
-		struct sock_filter *code = NULL;
-		int len;
-
-		if (copy_from_user(&uprog, (void __user *) arg, sizeof(uprog)))
-			break;
-		err = -EINVAL;
-		if (uprog.len > BPF_MAXINSNS)
-			break;
-		err = -ENOMEM;
-		if (uprog.len > 0) {
-			len = uprog.len * sizeof(struct sock_filter);
-			code = kmalloc(len, GFP_KERNEL);
-			if (code == NULL)
-				break;
-			err = -EFAULT;
-			if (copy_from_user(code, (void __user *) uprog.filter, len)) {
-				kfree(code);
-				break;
-			}
-			err = sk_chk_filter(code, uprog.len);
-			if (err) {
-				kfree(code);
-				break;
-			}
+		struct sock_filter *code;
+		err = get_filter(argp, &code);
+		if (err >= 0) {
+			ppp_lock(ppp);
+			kfree(ppp->active_filter);
+			ppp->active_filter = code;
+			ppp->active_len = err;
+			ppp_unlock(ppp);
+			err = 0;
 		}
-		filtp = (cmd == PPPIOCSPASS)? &ppp->pass_filter: &ppp->active_filter;
-		ppp_lock(ppp);
-		if (filtp->filter)
-			kfree(filtp->filter);
-		filtp->filter = code;
-		filtp->len = uprog.len;
-		ppp_unlock(ppp);
-		err = 0;
 		break;
 	}
 #endif /* CONFIG_PPP_FILTER */
 
 #ifdef CONFIG_PPP_MULTILINK
 	case PPPIOCSMRRU:
-		if (get_user(val, (int *) arg))
+		if (get_user(val, p))
 			break;
 		ppp_recv_lock(ppp);
 		ppp->mrru = val;
@@ -734,11 +763,12 @@
 	int unit, err = -EFAULT;
 	struct ppp *ppp;
 	struct channel *chan;
+	int __user *p = (int __user *)arg;
 
 	switch (cmd) {
 	case PPPIOCNEWUNIT:
 		/* Create a new ppp unit */
-		if (get_user(unit, (int *) arg))
+		if (get_user(unit, p))
 			break;
 		ppp = ppp_create_interface(unit, &err);
 		if (ppp == 0)
@@ -746,14 +776,14 @@
 		file->private_data = &ppp->file;
 		ppp->owner = file;
 		err = -EFAULT;
-		if (put_user(ppp->file.index, (int *) arg))
+		if (put_user(ppp->file.index, p))
 			break;
 		err = 0;
 		break;
 
 	case PPPIOCATTACH:
 		/* Attach to an existing ppp unit */
-		if (get_user(unit, (int *) arg))
+		if (get_user(unit, p))
 			break;
 		down(&all_ppp_sem);
 		err = -ENXIO;
@@ -767,7 +797,7 @@
 		break;
 
 	case PPPIOCATTCHAN:
-		if (get_user(unit, (int *) arg))
+		if (get_user(unit, p))
 			break;
 		spin_lock_bh(&all_channels_lock);
 		err = -ENXIO;
@@ -999,18 +1029,18 @@
 
 			*p = htons(4); /* indicate outbound in DLT_LINUX_SLL */;
 		}
-		if (ppp->pass_filter.filter
-		    && sk_run_filter(skb, ppp->pass_filter.filter,
-				     ppp->pass_filter.len) == 0) {
+		if (ppp->pass_filter
+		    && sk_run_filter(skb, ppp->pass_filter,
+				     ppp->pass_len) == 0) {
 			if (ppp->debug & 1)
 				printk(KERN_DEBUG "PPP: outbound frame not passed\n");
 			kfree_skb(skb);
 			return;
 		}
 		/* if this packet passes the active filter, record the time */
-		if (!(ppp->active_filter.filter
-		      && sk_run_filter(skb, ppp->active_filter.filter,
-				       ppp->active_filter.len) == 0))
+		if (!(ppp->active_filter
+		      && sk_run_filter(skb, ppp->active_filter,
+				       ppp->active_len) == 0))
 			ppp->last_xmit = jiffies;
 		skb_pull(skb, 2);
 #else
@@ -1546,17 +1576,17 @@
 
 			*p = 0; /* indicate inbound in DLT_LINUX_SLL */
 		}
-		if (ppp->pass_filter.filter
-		    && sk_run_filter(skb, ppp->pass_filter.filter,
-				     ppp->pass_filter.len) == 0) {
+		if (ppp->pass_filter
+		    && sk_run_filter(skb, ppp->pass_filter,
+				     ppp->pass_len) == 0) {
 			if (ppp->debug & 1)
 				printk(KERN_DEBUG "PPP: inbound frame not passed\n");
 			kfree_skb(skb);
 			return;
 		}
-		if (!(ppp->active_filter.filter
-		      && sk_run_filter(skb, ppp->active_filter.filter,
-				       ppp->active_filter.len) == 0))
+		if (!(ppp->active_filter
+		      && sk_run_filter(skb, ppp->active_filter,
+				       ppp->active_len) == 0))
 			ppp->last_recv = jiffies;
 		skb_pull(skb, 2);
 #else
@@ -2423,13 +2453,13 @@
 	skb_queue_purge(&ppp->mrq);
 #endif /* CONFIG_PPP_MULTILINK */
 #ifdef CONFIG_PPP_FILTER
-	if (ppp->pass_filter.filter) {
-		kfree(ppp->pass_filter.filter);
-		ppp->pass_filter.filter = NULL;
-	}
-	if (ppp->active_filter.filter) {
-		kfree(ppp->active_filter.filter);
-		ppp->active_filter.filter = 0;
+	if (ppp->pass_filter) {
+		kfree(ppp->pass_filter);
+		ppp->pass_filter = NULL;
+	}
+	if (ppp->active_filter) {
+		kfree(ppp->active_filter);
+		ppp->active_filter = 0;
 	}
 #endif /* CONFIG_PPP_FILTER */
 
diff -Nru a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
--- a/drivers/net/ppp_synctty.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/ppp_synctty.c	2004-06-23 19:04:26 -07:00
@@ -29,7 +29,7 @@
  * PPP driver, written by Michael Callahan and Al Longyear, and
  * subsequently hacked by Paul Mackerras.
  *
- * ==FILEVERSION 20020125==
+ * ==FILEVERSION 20040616==
  */
 
 #include <linux/module.h>
@@ -65,7 +65,9 @@
 	struct sk_buff	*tpkt;
 	unsigned long	last_xmit;
 
-	struct sk_buff	*rpkt;
+	struct sk_buff_head rqueue;
+
+	struct tasklet_struct tsk;
 
 	atomic_t	refcnt;
 	struct semaphore dead_sem;
@@ -88,6 +90,7 @@
 static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb);
 static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd,
 			  unsigned long arg);
+static void ppp_sync_process(unsigned long arg);
 static int ppp_sync_push(struct syncppp *ap);
 static void ppp_sync_flush_output(struct syncppp *ap);
 static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
@@ -217,6 +220,9 @@
 	ap->xaccm[3] = 0x60000000U;
 	ap->raccm = ~0U;
 
+	skb_queue_head_init(&ap->rqueue);
+	tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap);
+
 	atomic_set(&ap->refcnt, 1);
 	init_MUTEX_LOCKED(&ap->dead_sem);
 
@@ -267,10 +273,10 @@
 	 */
 	if (!atomic_dec_and_test(&ap->refcnt))
 		down(&ap->dead_sem);
+	tasklet_kill(&ap->tsk);
 
 	ppp_unregister_channel(&ap->chan);
-	if (ap->rpkt != 0)
-		kfree_skb(ap->rpkt);
+	skb_queue_purge(&ap->rqueue);
 	if (ap->tpkt != 0)
 		kfree_skb(ap->tpkt);
 	kfree(ap);
@@ -369,17 +375,24 @@
 	return 65535;
 }
 
+/*
+ * This can now be called from hard interrupt level as well
+ * as soft interrupt level or mainline.
+ */
 static void
 ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
-		  char *flags, int count)
+		  char *cflags, int count)
 {
 	struct syncppp *ap = sp_get(tty);
+	unsigned long flags;
 
 	if (ap == 0)
 		return;
-	spin_lock_bh(&ap->recv_lock);
-	ppp_sync_input(ap, buf, flags, count);
-	spin_unlock_bh(&ap->recv_lock);
+	spin_lock_irqsave(&ap->recv_lock, flags);
+	ppp_sync_input(ap, buf, cflags, count);
+	spin_unlock_irqrestore(&ap->recv_lock, flags);
+	if (skb_queue_len(&ap->rqueue))
+		tasklet_schedule(&ap->tsk);
 	sp_put(ap);
 	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
 	    && tty->driver->unthrottle)
@@ -394,8 +407,8 @@
 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 	if (ap == 0)
 		return;
-	if (ppp_sync_push(ap))
-		ppp_output_wakeup(&ap->chan);
+	set_bit(XMIT_WAKEUP, &ap->xmit_flags);
+	tasklet_schedule(&ap->tsk);
 	sp_put(ap);
 }
 
@@ -449,9 +462,9 @@
 		if (get_user(val, (int *) arg))
 			break;
 		ap->flags = val & ~SC_RCV_BITS;
-		spin_lock_bh(&ap->recv_lock);
+		spin_lock_irq(&ap->recv_lock);
 		ap->rbits = val & SC_RCV_BITS;
-		spin_unlock_bh(&ap->recv_lock);
+		spin_unlock_irq(&ap->recv_lock);
 		err = 0;
 		break;
 
@@ -512,6 +525,32 @@
 }
 
 /*
+ * This is called at softirq level to deliver received packets
+ * to the ppp_generic code, and to tell the ppp_generic code
+ * if we can accept more output now.
+ */
+static void ppp_sync_process(unsigned long arg)
+{
+	struct syncppp *ap = (struct syncppp *) arg;
+	struct sk_buff *skb;
+
+	/* process received packets */
+	while ((skb = skb_dequeue(&ap->rqueue)) != NULL) {
+		if (skb->len == 0) {
+			/* zero length buffers indicate error */
+			ppp_input_error(&ap->chan, 0);
+			kfree_skb(skb);
+		}
+		else
+			ppp_input(&ap->chan, skb);
+	}
+
+	/* try to push more stuff out */
+	if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_sync_push(ap))
+		ppp_output_wakeup(&ap->chan);
+}
+
+/*
  * Procedures for encapsulation and framing.
  */
 
@@ -600,7 +639,6 @@
 	struct tty_struct *tty = ap->tty;
 	int tty_stuffed = 0;
 
-	set_bit(XMIT_WAKEUP, &ap->xmit_flags);
 	if (!spin_trylock_bh(&ap->xmit_lock))
 		return 0;
 	for (;;) {
@@ -667,15 +705,44 @@
  * Receive-side routines.
  */
 
-static inline void
-process_input_packet(struct syncppp *ap)
+/* called when the tty driver has data for us.
+ *
+ * Data is frame oriented: each call to ppp_sync_input is considered
+ * a whole frame. If the 1st flag byte is non-zero then the whole
+ * frame is considered to be in error and is tossed.
+ */
+static void
+ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
+		char *flags, int count)
 {
 	struct sk_buff *skb;
 	unsigned char *p;
-	int code = 0;
 
-	skb = ap->rpkt;
-	ap->rpkt = 0;
+	if (count == 0)
+		return;
+
+	if (ap->flags & SC_LOG_INPKT)
+		ppp_print_buffer ("receive buffer", buf, count);
+
+	/* stuff the chars in the skb */
+	if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) {
+		printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
+		goto err;
+	}
+	/* Try to get the payload 4-byte aligned */
+	if (buf[0] != PPP_ALLSTATIONS)
+		skb_reserve(skb, 2 + (buf[0] & 1));
+
+	if (flags != 0 && *flags) {
+		/* error flag set, ignore frame */
+		goto err;
+	} else if (count > skb_tailroom(skb)) {
+		/* packet overflowed MRU */
+		goto err;
+	}
+
+	p = skb_put(skb, count);
+	memcpy(p, buf, count);
 
 	/* strip address/control field if present */
 	p = skb->data;
@@ -693,59 +760,15 @@
 	} else if (skb->len < 2)
 		goto err;
 
-	/* pass to generic layer */
-	ppp_input(&ap->chan, skb);
+	/* queue the frame to be processed */
+	skb_queue_tail(&ap->rqueue, skb);
 	return;
 
- err:
-	kfree_skb(skb);
-	ppp_input_error(&ap->chan, code);
-}
-
-/* called when the tty driver has data for us. 
- *
- * Data is frame oriented: each call to ppp_sync_input is considered
- * a whole frame. If the 1st flag byte is non-zero then the whole
- * frame is considered to be in error and is tossed.
- */
-static void
-ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
-		char *flags, int count)
-{
-	struct sk_buff *skb;
-	unsigned char *sp;
-
-	if (count == 0)
-		return;
-
-	/* if flag set, then error, ignore frame */
-	if (flags != 0 && *flags) {
-		ppp_input_error(&ap->chan, *flags);
-		return;
-	}
-
-	if (ap->flags & SC_LOG_INPKT)
-		ppp_print_buffer ("receive buffer", buf, count);
-
-	/* stuff the chars in the skb */
-	if ((skb = ap->rpkt) == 0) {
-		if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) {
-			printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
-			ppp_input_error(&ap->chan, 0);
-			return;
-		}
-		/* Try to get the payload 4-byte aligned */
-		if (buf[0] != PPP_ALLSTATIONS)
-			skb_reserve(skb, 2 + (buf[0] & 1));
-		ap->rpkt = skb;
-	}
-	if (count > skb_tailroom(skb)) {
-		/* packet overflowed MRU */
-		ppp_input_error(&ap->chan, 1);
-	} else {
-		sp = skb_put(skb, count);
-		memcpy(sp, buf, count);
-		process_input_packet(ap);
+err:
+	/* queue zero length packet as error indication */
+	if (skb || (skb = dev_alloc_skb(0))) {
+		skb_trim(skb, 0);
+		skb_queue_tail(&ap->rqueue, skb);
 	}
 }
 
diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c
--- a/drivers/net/r8169.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/r8169.c	2004-06-23 19:04:27 -07:00
@@ -716,7 +716,7 @@
 		goto err_out_disable;
 	}
 
-	rc = pci_request_regions(pdev, dev->name);
+	rc = pci_request_regions(pdev, MODULENAME);
 	if (rc) {
 		printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name);
 		goto err_out_disable;
diff -Nru a/drivers/net/s2io.c b/drivers/net/s2io.c
--- a/drivers/net/s2io.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/s2io.c	2004-06-23 19:04:27 -07:00
@@ -1425,13 +1425,13 @@
 			goto end;
 		}
 
-		skb = dev_alloc_skb(size + HEADER_ALIGN_LAYER_3);
+		skb = dev_alloc_skb(size + NET_IP_ALIGN);
 		if (!skb) {
 			DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
 			DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
 			return -ENOMEM;
 		}
-		skb_reserve(skb, HEADER_ALIGN_LAYER_3);
+		skb_reserve(skb, NET_IP_ALIGN);
 		memset(rxdp, 0, sizeof(RxD_t));
 		rxdp->Buffer0_ptr = pci_map_single
 		    (nic->pdev, skb->data, size, PCI_DMA_FROMDEVICE);
diff -Nru a/drivers/net/s2io.h b/drivers/net/s2io.h
--- a/drivers/net/s2io.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/s2io.h	2004-06-23 19:04:26 -07:00
@@ -411,7 +411,6 @@
 #define HEADER_802_2_SIZE              3
 #define HEADER_SNAP_SIZE               5
 #define HEADER_VLAN_SIZE               4
-#define HEADER_ALIGN_LAYER_3           2
 
 #define MIN_MTU                       46
 #define MAX_PYLD                    1500
diff -Nru a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
--- a/drivers/net/sb1250-mac.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/sb1250-mac.c	2004-06-23 19:04:28 -07:00
@@ -2900,15 +2900,15 @@
 sbmac_cleanup_module(void)
 {
 	struct net_device *dev;
-	sbmac_port_t port;
 	int idx;
 
 	for (idx = 0; idx < MAX_UNITS; idx++) {
+		struct sbmac_softc *sc;
 		dev = dev_sbmac[idx];
 		if (!dev)
 			continue;
 
-		struct sbmac_softc *sc = netdev_priv(dev);
+		sc = netdev_priv(dev);
 		unregister_netdev(dev);
 		sbmac_uninitctx(sc);
 		free_netdev(dev);
diff -Nru a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
--- a/drivers/net/sgiseeq.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/sgiseeq.c	2004-06-23 19:04:28 -07:00
@@ -64,13 +64,13 @@
 #define DEBUG
 
 struct sgiseeq_rx_desc {
-	struct hpc_dma_desc rdma;
-	signed int buf_vaddr;
+	volatile struct hpc_dma_desc rdma;
+	volatile signed int buf_vaddr;
 };
 
 struct sgiseeq_tx_desc {
-	struct hpc_dma_desc tdma;
-	signed int buf_vaddr;
+	volatile struct hpc_dma_desc tdma;
+	volatile signed int buf_vaddr;
 };
 
 /*
@@ -79,17 +79,17 @@
  *          some care.
  */
 struct sgiseeq_init_block { /* Note the name ;-) */
-	/* Ptrs to the descriptors in KSEG1 uncached space. */
-	struct sgiseeq_rx_desc *rx_desc;
-	struct sgiseeq_tx_desc *tx_desc;
-	unsigned int _padding[30]; /* Pad out to largest cache line size. */
-
 	struct sgiseeq_rx_desc rxvector[SEEQ_RX_BUFFERS];
 	struct sgiseeq_tx_desc txvector[SEEQ_TX_BUFFERS];
 };
 
 struct sgiseeq_private {
-	volatile struct sgiseeq_init_block srings;
+	struct sgiseeq_init_block *srings;
+
+	/* Ptrs to the descriptors in uncached space. */
+	struct sgiseeq_rx_desc *rx_desc;
+	struct sgiseeq_tx_desc *tx_desc;
+
 	char *name;
 	struct hpc3_ethregs *hregs;
 	struct sgiseeq_regs *sregs;
@@ -152,8 +152,7 @@
 
 static int seeq_init_ring(struct net_device *dev)
 {
-	struct sgiseeq_private *sp = dev->priv;
-	volatile struct sgiseeq_init_block *ib = &sp->srings;
+	struct sgiseeq_private *sp = netdev_priv(dev);
 	int i;
 
 	netif_stop_queue(dev);
@@ -170,32 +169,32 @@
 
 	/* Setup tx ring. */
 	for(i = 0; i < SEEQ_TX_BUFFERS; i++) {
-		if (!ib->tx_desc[i].tdma.pbuf) {
+		if (!sp->tx_desc[i].tdma.pbuf) {
 			unsigned long buffer;
 
 			buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
 			if (!buffer)
 				return -ENOMEM;
-			ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
-			ib->tx_desc[i].tdma.pbuf = CPHYSADDR(buffer);
+			sp->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
+			sp->tx_desc[i].tdma.pbuf = CPHYSADDR(buffer);
 		}
-		ib->tx_desc[i].tdma.cntinfo = TCNTINFO_INIT;
+		sp->tx_desc[i].tdma.cntinfo = TCNTINFO_INIT;
 	}
 
 	/* And now the rx ring. */
 	for (i = 0; i < SEEQ_RX_BUFFERS; i++) {
-		if (!ib->rx_desc[i].rdma.pbuf) {
+		if (!sp->rx_desc[i].rdma.pbuf) {
 			unsigned long buffer;
 
 			buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
 			if (!buffer)
 				return -ENOMEM;
-			ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
-			ib->rx_desc[i].rdma.pbuf = CPHYSADDR(buffer);
+			sp->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
+			sp->rx_desc[i].rdma.pbuf = CPHYSADDR(buffer);
 		}
-		ib->rx_desc[i].rdma.cntinfo = RCNTINFO_INIT;
+		sp->rx_desc[i].rdma.cntinfo = RCNTINFO_INIT;
 	}
-	ib->rx_desc[i - 1].rdma.cntinfo |= HPCDMA_EOR;
+	sp->rx_desc[i - 1].rdma.cntinfo |= HPCDMA_EOR;
 	return 0;
 }
 
@@ -206,8 +205,8 @@
 void sgiseeq_dump_rings(void)
 {
 	static int once;
-	struct sgiseeq_rx_desc *r = gpriv->srings.rx_desc;
-	struct sgiseeq_tx_desc *t = gpriv->srings.tx_desc;
+	struct sgiseeq_rx_desc *r = gpriv->rx_desc;
+	struct sgiseeq_tx_desc *t = gpriv->tx_desc;
 	struct hpc3_ethregs *hregs = gpriv->hregs;
 	int i;
 
@@ -268,8 +267,8 @@
 
 	hregs->rx_dconfig |= RDMACFG_INIT;
 
-	hregs->rx_ndptr = CPHYSADDR(sp->srings.rx_desc);
-	hregs->tx_ndptr = CPHYSADDR(sp->srings.tx_desc);
+	hregs->rx_ndptr = CPHYSADDR(sp->rx_desc);
+	hregs->tx_ndptr = CPHYSADDR(sp->tx_desc);
 
 	seeq_go(sp, hregs, sregs);
 	return 0;
@@ -294,14 +293,14 @@
 				    struct sgiseeq_regs *sregs)
 {
 	if (!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) {
-		hregs->rx_ndptr = CPHYSADDR(sp->srings.rx_desc + sp->rx_new);
+		hregs->rx_ndptr = CPHYSADDR(sp->rx_desc + sp->rx_new);
 		seeq_go(sp, hregs, sregs);
 	}
 }
 
-#define for_each_rx(rd, sp) for((rd) = &(sp)->srings.rx_desc[(sp)->rx_new]; \
+#define for_each_rx(rd, sp) for((rd) = &(sp)->rx_desc[(sp)->rx_new]; \
 				!((rd)->rdma.cntinfo & HPCDMA_OWN); \
-				(rd) = &(sp)->srings.rx_desc[(sp)->rx_new])
+				(rd) = &(sp)->rx_desc[(sp)->rx_new])
 
 static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp,
 			      struct hpc3_ethregs *hregs,
@@ -349,8 +348,8 @@
 		rd->rdma.cntinfo = RCNTINFO_INIT;
 		sp->rx_new = NEXT_RX(sp->rx_new);
 	}
-	sp->srings.rx_desc[orig_end].rdma.cntinfo &= ~(HPCDMA_EOR);
-	sp->srings.rx_desc[PREV_RX(sp->rx_new)].rdma.cntinfo |= HPCDMA_EOR;
+	sp->rx_desc[orig_end].rdma.cntinfo &= ~(HPCDMA_EOR);
+	sp->rx_desc[PREV_RX(sp->rx_new)].rdma.cntinfo |= HPCDMA_EOR;
 	rx_maybe_restart(sp, hregs, sregs);
 }
 
@@ -403,7 +402,7 @@
 
 	/* Ack 'em... */
 	for (j = sp->tx_old; j != sp->tx_new; j = NEXT_TX(j)) {
-		td = &sp->srings.tx_desc[j];
+		td = &sp->tx_desc[j];
 
 		if (!(td->tdma.cntinfo & (HPCDMA_XIU)))
 			break;
@@ -424,7 +423,7 @@
 static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
-	struct sgiseeq_private *sp = dev->priv;
+	struct sgiseeq_private *sp = netdev_priv(dev);
 	struct hpc3_ethregs *hregs = sp->hregs;
 	struct sgiseeq_regs *sregs = sp->sregs;
 
@@ -450,21 +449,33 @@
 
 static int sgiseeq_open(struct net_device *dev)
 {
-	struct sgiseeq_private *sp = dev->priv;
+	struct sgiseeq_private *sp = netdev_priv(dev);
 	struct sgiseeq_regs *sregs = sp->sregs;
+	unsigned int irq = dev->irq;
+	int err;
 
-	int err = init_seeq(dev, sp, sregs);
+	if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) {
+		printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq);
+		err = -EAGAIN;
+	}
+
+	err = init_seeq(dev, sp, sregs);
 	if (err)
-		return err;
+		goto out_free_irq;
 
 	netif_start_queue(dev);
 
 	return 0;
+
+out_free_irq:
+	free_irq(irq, dev);
+
+	return err;
 }
 
 static int sgiseeq_close(struct net_device *dev)
 {
-	struct sgiseeq_private *sp = dev->priv;
+	struct sgiseeq_private *sp = netdev_priv(dev);
 	struct sgiseeq_regs *sregs = sp->sregs;
 
 	netif_stop_queue(dev);
@@ -477,7 +488,7 @@
 
 static inline int sgiseeq_reset(struct net_device *dev)
 {
-	struct sgiseeq_private *sp = dev->priv;
+	struct sgiseeq_private *sp = netdev_priv(dev);
 	struct sgiseeq_regs *sregs = sp->sregs;
 	int err;
 
@@ -499,7 +510,7 @@
 
 static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct sgiseeq_private *sp = dev->priv;
+	struct sgiseeq_private *sp = netdev_priv(dev);
 	struct hpc3_ethregs *hregs = sp->hregs;
 	unsigned long flags;
 	struct sgiseeq_tx_desc *td;
@@ -512,7 +523,7 @@
 	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
 	sp->stats.tx_bytes += len;
 	entry = sp->tx_new;
-	td = &sp->srings.tx_desc[entry];
+	td = &sp->tx_desc[entry];
 
 	/* Create entry.  There are so many races with adding a new
 	 * descriptor to the chain:
@@ -535,14 +546,14 @@
 	if (sp->tx_old != sp->tx_new) {
 		struct sgiseeq_tx_desc *backend;
 
-		backend = &sp->srings.tx_desc[PREV_TX(sp->tx_new)];
+		backend = &sp->tx_desc[PREV_TX(sp->tx_new)];
 		backend->tdma.cntinfo &= ~HPCDMA_EOX;
 	}
 	sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */
 
 	/* Maybe kick the HPC back into motion. */
 	if (!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE))
-		kick_tx(&sp->srings.tx_desc[sp->tx_old], hregs);
+		kick_tx(&sp->tx_desc[sp->tx_old], hregs);
 
 	dev->trans_start = jiffies;
 	dev_kfree_skb(skb);
@@ -565,7 +576,7 @@
 
 static struct net_device_stats *sgiseeq_get_stats(struct net_device *dev)
 {
-	struct sgiseeq_private *sp = dev->priv;
+	struct sgiseeq_private *sp = netdev_priv(dev);
 
 	return &sp->stats;
 }
@@ -601,31 +612,29 @@
 
 #define ALIGNED(x)  ((((unsigned long)(x)) + 0xf) & ~(0xf))
 
-int sgiseeq_init(struct hpc3_regs* regs, int irq)
+static int sgiseeq_init(struct hpc3_regs* regs, int irq)
 {
-	struct net_device *dev;
+	struct sgiseeq_init_block *sr;
 	struct sgiseeq_private *sp;
+	struct net_device *dev;
 	int err, i;
 
-	dev = alloc_etherdev(0);
+	dev = alloc_etherdev(sizeof (struct sgiseeq_private));
 	if (!dev) {
 		printk(KERN_ERR "Sgiseeq: Etherdev alloc failed, aborting.\n");
 		err = -ENOMEM;
 		goto err_out;
 	}
+	sp = netdev_priv(dev);
+
 	/* Make private data page aligned */
-	sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL); 	 
-	if (!sp) {
+	sr = (struct sgiseeq_init_block *) get_zeroed_page(GFP_KERNEL);
+	if (!sr) {
 		printk(KERN_ERR "Sgiseeq: Page alloc failed, aborting.\n");
 		err = -ENOMEM;
 		goto err_out_free_dev;
 	}
-
-	if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) {
-		printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq);
-		err = -EAGAIN;
-		goto err_out_free_page;
-	}
+	sp->srings = sr;
 
 #define EADDR_NVOFS     250
 	for (i = 0; i < 3; i++) {
@@ -643,18 +652,18 @@
 	sp->hregs = &hpc3c0->ethregs;
 	sp->name = sgiseeqstr;
 
-	sp->srings.rx_desc = (struct sgiseeq_rx_desc *)
-	                     KSEG1ADDR(ALIGNED(&sp->srings.rxvector[0]));
-	dma_cache_wback_inv((unsigned long)&sp->srings.rxvector,
-	                    sizeof(sp->srings.rxvector));
-	sp->srings.tx_desc = (struct sgiseeq_tx_desc *)
-	                     KSEG1ADDR(ALIGNED(&sp->srings.txvector[0]));
-	dma_cache_wback_inv((unsigned long)&sp->srings.txvector,
-	                    sizeof(sp->srings.txvector));
+	sp->rx_desc = (struct sgiseeq_rx_desc *)
+	              KSEG1ADDR(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]));
+	dma_cache_wback_inv((unsigned long)&sp->srings->txvector,
+	                    sizeof(sp->srings->txvector));
 
 	/* A couple calculations now, saves many cycles later. */
-	setup_rx_ring(sp->srings.rx_desc, SEEQ_RX_BUFFERS);
-	setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS);
+	setup_rx_ring(sp->rx_desc, SEEQ_RX_BUFFERS);
+	setup_tx_ring(sp->tx_desc, SEEQ_TX_BUFFERS);
 
 	/* Reset the chip. */
 	hpc3_eth_reset(sp->hregs);
@@ -673,14 +682,12 @@
 	dev->get_stats		= sgiseeq_get_stats;
 	dev->set_multicast_list	= sgiseeq_set_multicast;
 	dev->irq		= irq;
-	dev->dma		= 0;
-	dev->priv		= sp;
 
 	if (register_netdev(dev)) {
 		printk(KERN_ERR "Sgiseeq: Cannot register net device, "
 		       "aborting.\n");
 		err = -ENODEV;
-		goto err_out_free_irq;
+		goto err_out_free_page;
 	}
 
 	printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
@@ -692,8 +699,6 @@
 
 	return 0;
 
-err_out_free_irq:
-	free_irq(irq, dev);
 err_out_free_page:
 	free_page((unsigned long) sp);
 err_out_free_dev:
@@ -718,12 +723,12 @@
 	int irq;
 
 	for (dev = root_sgiseeq_dev; dev; dev = next) {
-		sp = (struct sgiseeq_private *) dev->priv;
+		sp = (struct sgiseeq_private *) netdev_priv(dev);
 		next = sp->next_module;
 		irq = dev->irq;
 		unregister_netdev(dev);
 		free_irq(irq, dev);
-		free_page((unsigned long) dev->priv);
+		free_page((unsigned long) sp);
 		free_netdev(dev);
 	}
 }
diff -Nru a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
--- a/drivers/net/sk98lin/h/skdrv2nd.h	2004-06-23 19:04:29 -07:00
+++ b/drivers/net/sk98lin/h/skdrv2nd.h	2004-06-23 19:04:29 -07:00
@@ -58,7 +58,8 @@
     /* 3Com (0x10b7) */     \
     if (pdev->vendor == 0x10b7) {     \
         /* Gigabit Ethernet Adapter (0x1700) */     \
-        if ((pdev->device == 0x1700)) { \
+        if ((pdev->device == 0x1700) || \
+            (pdev->device == 0x80eb)) { \
             result = SK_TRUE;     \
         }     \
     /* SysKonnect (0x1148) */     \
diff -Nru a/drivers/net/skfp/cfm.c b/drivers/net/skfp/cfm.c
--- a/drivers/net/skfp/cfm.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/skfp/cfm.c	2004-06-23 19:04:27 -07:00
@@ -96,14 +96,13 @@
 /*
  * function declarations
  */
-static void cfm_fsm() ;
+static void cfm_fsm(struct s_smc *smc, int cmd);
 
 /*
 	init CFM state machine
 	clear all CFM vars and flags
 */
-void cfm_init(smc)
-struct s_smc *smc ;
+void cfm_init(struct s_smc *smc)
 {
 	smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ;
 	smc->r.rm_join = 0 ;
@@ -118,9 +117,7 @@
 #define THRU_ENABLED(smc)	(smc->y[PA].pc_mode != PM_TREE && \
 				 smc->y[PB].pc_mode != PM_TREE)
 /* Selection criteria for the ports */
-static void	selection_criteria (smc,phy)
-struct s_smc	*smc ;
-struct s_phy	*phy ;
+static void selection_criteria (struct s_smc *smc, struct s_phy *phy)
 {
 
 	switch (phy->mib->fddiPORTMy_Type) {
@@ -146,8 +143,7 @@
 
 }
 
-void	all_selection_criteria (smc)
-struct s_smc *smc ;
+void all_selection_criteria(struct s_smc *smc)
 {
 	struct s_phy	*phy ;
 	int		p ;
@@ -158,9 +154,7 @@
 	}
 }
 
-static void	cem_priv_state (smc, event)
-struct s_smc *smc ;
-int event ;
+static void cem_priv_state(struct s_smc *smc, int event)
 /* State machine for private PORT states: used to optimize dual homing */
 {
 	int	np;	/* Number of the port */
@@ -216,9 +210,7 @@
 		process event
 	until SM is stable
 */
-void cfm(smc,event)
-struct s_smc *smc ;
-int event ;
+void cfm(struct s_smc *smc, int event)
 {
 	int	state ;		/* remember last state */
 	int	cond ;
@@ -290,9 +282,7 @@
 	process CFM event
 */
 /*ARGSUSED1*/
-static void cfm_fsm(smc,cmd)
-struct s_smc *smc ;
-int cmd ;
+static void cfm_fsm(struct s_smc *smc, int cmd)
 {
 	switch(smc->mib.fddiSMTCF_State) {
 	case ACTIONS(SC0_ISOLATED) :
@@ -550,8 +540,7 @@
  *	return :
  *		PA or PB
  */
-int cfm_get_mac_input(smc)
-struct s_smc *smc ;
+int cfm_get_mac_input(struct s_smc *smc)
 {
 	return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
 		smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA) ;
@@ -562,8 +551,7 @@
  *	return :
  *		PA or PB
  */
-int cfm_get_mac_output(smc)
-struct s_smc *smc ;
+int cfm_get_mac_output(struct s_smc *smc)
 {
 	return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
 		smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA) ;
@@ -603,10 +591,7 @@
 	0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_ISO,
 } ;
 
-int cem_build_path(smc,to,path_index)
-struct s_smc *smc ;
-char *to ;
-int path_index ;
+int cem_build_path(struct s_smc *smc, char *to, int path_index)
 {
 	char	*path ;
 	int	len ;
diff -Nru a/drivers/net/skfp/drvfbi.c b/drivers/net/skfp/drvfbi.c
--- a/drivers/net/skfp/drvfbi.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/skfp/drvfbi.c	2004-06-23 19:04:25 -07:00
@@ -100,14 +100,13 @@
 #endif	/* MULT_OEM */
 
 /* Prototypes of external functions */
-extern void hwt_restart() ;
 #ifdef AIX
 extern int AIX_vpdReadByte() ;
 #endif
 
 
 /* Prototypes of local functions. */
-void smt_stop_watchdog() ;
+void smt_stop_watchdog(struct s_smc *smc);
 
 #ifdef MCA
 static int read_card_id() ;
@@ -129,8 +128,7 @@
 /*
  * FDDI card reset
  */
-static void card_start(smc)
-struct s_smc *smc ;
+static void card_start(struct s_smc *smc)
 {
 	int i ;
 #ifdef	PCI
@@ -250,8 +248,7 @@
 	GET_PAGE(0) ;		/* necessary for BOOT */
 }
 
-void card_stop(smc)
-struct s_smc *smc ;
+void card_stop(struct s_smc *smc)
 {
 	smt_stop_watchdog(smc) ;
 	smc->hw.mac_ring_is_up = 0 ;		/* ring down */
@@ -282,14 +279,11 @@
 }
 /*--------------------------- ISR handling ----------------------------------*/
 
-#ifndef PCI
-void mac1_irq(smc,stu, stl)
-struct s_smc *smc ;
-u_short stu;
-u_short stl;
+void mac1_irq(struct s_smc *smc, u_short stu, u_short stl)
 {
 	int	restart_tx = 0 ;
 again:
+#ifndef PCI
 #ifndef ISA
 /*
  * FORMAC+ bug modified the queue pointer if many read/write accesses happens!?
@@ -344,14 +338,6 @@
 }
 #else	/* PCI */
 
-void mac1_irq(smc,stu, stl)
-struct s_smc *smc ;
-u_short stu;
-u_short stl;
-{
-	int	restart_tx = 0 ;
-again:
-
 	/*
 	 * parity error: note encoding error is not possible in tag mode
 	 */
@@ -396,8 +382,7 @@
  * interrupt source= plc1
  * this function is called in nwfbisr.asm
  */
-void plc1_irq(smc)
-struct s_smc *smc ;
+void plc1_irq(struct s_smc *smc)
 {
 	u_short	st = inpw(PLC(PB,PL_INTR_EVENT)) ;
 
@@ -412,8 +397,7 @@
  * interrupt source= plc2
  * this function is called in nwfbisr.asm
  */
-void plc2_irq(smc)
-struct s_smc *smc ;
+void plc2_irq(struct s_smc *smc)
 {
 	u_short	st = inpw(PLC(PA,PL_INTR_EVENT)) ;
 
@@ -428,8 +412,7 @@
 /*
  * interrupt source= timer
  */
-void timer_irq(smc)
-struct s_smc *smc ;
+void timer_irq(struct s_smc *smc)
 {
 	hwt_restart(smc);
 	smc->hw.t_stop = smc->hw.t_start;
@@ -439,8 +422,7 @@
 /*
  * return S-port (PA or PB)
  */
-int pcm_get_s_port(smc)
-struct s_smc *smc ;
+int pcm_get_s_port(struct s_smc *smc)
 {
 	SK_UNUSED(smc) ;
 	return(PS) ;
@@ -457,9 +439,7 @@
 #define STATION_LABEL_PMD_OFFSET	6
 #define STATION_LABEL_PORT_OFFSET	7
 
-void read_address(smc,mac_addr)
-struct s_smc *smc ;
-u_char *mac_addr ;
+void read_address(struct s_smc *smc, u_char *mac_addr)
 {
 	char ConnectorType ;
 	char PmdType ;
@@ -528,9 +508,7 @@
 /*
  * FDDI card soft reset
  */
-void init_board(smc,mac_addr)
-struct s_smc *smc ;
-u_char *mac_addr ;
+void init_board(struct s_smc *smc, u_char *mac_addr)
 {
 	card_start(smc) ;
 	read_address(smc,mac_addr) ;
@@ -559,9 +537,7 @@
 /*
  * insert or deinsert optical bypass (called by ECM)
  */
-void sm_pm_bypass_req(smc,mode)
-struct s_smc *smc ;
-int mode;
+void sm_pm_bypass_req(struct s_smc *smc, int mode)
 {
 #if	(defined(ISA) || defined(EISA))
 	int csra_v ;
@@ -614,8 +590,7 @@
 /*
  * check if bypass connected
  */
-int sm_pm_bypass_present(smc)
-struct s_smc *smc ;
+int sm_pm_bypass_present(struct s_smc *smc)
 {
 #ifndef	PCI
 	return(	(inpw(CSR_A) & CS_BYSTAT) ? FALSE : TRUE ) ;
@@ -624,9 +599,7 @@
 #endif
 }
 
-void plc_clear_irq(smc,p)
-struct s_smc *smc ;
-int p ;
+void plc_clear_irq(struct s_smc *smc, int p)
 {
 	SK_UNUSED(p) ;
 
@@ -658,9 +631,7 @@
  *	LED_Y_OFF	just switch yellow LED off
  *	LED_Y_ON	just switch yello LED on
  */
-void led_indication(smc,led_event)
-struct s_smc	*smc ;
-int		led_event;
+void led_indication(struct s_smc *smc, int led_event)
 {
 	/* use smc->hw.mac_ring_is_up == TRUE 
 	 * as indication for Ring Operational
@@ -754,10 +725,7 @@
 }
 
 
-void pcm_state_change(smc,plc,p_state)
-struct s_smc *smc;
-int plc;
-int p_state;
+void pcm_state_change(struct s_smc *smc, int plc, int p_state)
 {
 	/*
 	 * the current implementation of pcm_state_change() in the driver
@@ -770,9 +738,7 @@
 }
 
 
-void rmt_indication(smc,i)
-struct s_smc *smc ;
-int i;
+void rmt_indication(struct s_smc *smc, int i)
 {
 	/* Call a driver special function if defined */
 	DRV_RMT_INDICATION(smc,i) ;
@@ -784,8 +750,7 @@
 /*
  * llc_recover_tx called by init_tx (fplus.c)
  */
-void llc_recover_tx(smc)
-struct s_smc *smc ;
+void llc_recover_tx(struct s_smc *smc)
 {
 #ifdef	LOAD_GEN
 	extern	int load_gen_flag ;
@@ -805,9 +770,7 @@
 /*
  * init DMA
  */
-void init_dma(smc,dma)
-struct s_smc *smc;
-int	dma;
+void init_dma(struct s_smc *smc, int dma)
 {
 	SK_UNUSED(smc) ;
 
@@ -828,9 +791,7 @@
 /*
  * disable DMA
  */
-void dis_dma(smc,dma)
-struct s_smc *smc ;
-int	dma;
+void dis_dma(struct s_smc *smc, int dma)
 {
 	SK_UNUSED(smc) ;
 
@@ -854,9 +815,7 @@
 static const int base[8] = { 0x000,0x002,0x004,0x006,0,0x0c4,0x0c8,0x0cc } ;
 static const int page[8] = { 0x087,0x083,0x081,0x082,0,0x08b,0x089,0x08a } ;
 
-void init_dma(smc,dma)
-struct s_smc *smc ;
-int	dma;
+void init_dma(struct s_smc *smc, int dma)
 {
 	/*
 	 * extended mode register
@@ -885,9 +844,7 @@
 
 }
 
-void dis_dma(smc,dma)
-struct s_smc *smc ;
-int	dma;
+void dis_dma(struct s_smc *smc, int dma)
 {
 	SK_UNUSED(smc) ;
 
@@ -896,16 +853,13 @@
 #endif	/* EISA */
 
 #ifdef	MCA
-void init_dma(smc,dma)
-struct s_smc *smc;
-int	dma;
+void init_dma(struct s_smc *smc, int dma)
 {
 	SK_UNUSED(smc) ;
 	SK_UNUSED(dma) ;
 }
-void dis_dma(smc,dma)
-struct s_smc *smc;
-int	dma;
+
+void dis_dma(struct s_smc *smc, int dma)
 {
 	SK_UNUSED(smc) ;
 	SK_UNUSED(dma) ;
@@ -913,16 +867,13 @@
 #endif
 
 #ifdef	PCI
-void init_dma(smc,dma)
-struct s_smc *smc;
-int	dma;
+void init_dma(struct s_smc *smc, int dma)
 {
 	SK_UNUSED(smc) ;
 	SK_UNUSED(dma) ;
 }
-void dis_dma(smc,dma)
-struct s_smc *smc;
-int	dma;
+
+void dis_dma(struct s_smc *smc, int dma)
 {
 	SK_UNUSED(smc) ;
 	SK_UNUSED(dma) ;
@@ -930,10 +881,7 @@
 #endif
 
 #ifdef MULT_OEM
-static int is_equal_num(comp1,comp2,num)
-char comp1[] ;
-char comp2[] ;
-int num ;
+static int is_equal_num(char comp1[], char comp2[], int num)
 {
 	int i ;
 
@@ -954,8 +902,7 @@
  *		2	data base empty
  *		3	no active entry	
  */
-int set_oi_id_def(smc)
-struct s_smc *smc ;
+int set_oi_id_def(struct s_smc *smc)
 {
 	int sel_id ;
 	int i ;
@@ -1029,9 +976,7 @@
  *
  ************************/
 #define LONG_CARD_ID(lo, hi)	((((hi) & 0xff) << 8) | ((lo) & 0xff))
-int exist_board(smc,slot)
-struct s_smc *smc ;
-int	slot ;
+int exist_board(struct s_smc *smc, int slot)
 {
 #ifdef MULT_OEM
 	SK_LOC_DECL(u_char,id[2]) ;
@@ -1081,9 +1026,8 @@
  *	number is specified, the function returns zero.
  *
  ************************/
-static int read_card_id(smc,slot)
-struct s_smc *smc ;	/* Do not use. */
-int slot ;
+static int read_card_id(struct s_smc *smc, int slot)
+/* struct s_smc *smc ;	Do not use. */
 {
 	int card_id ;
 
@@ -1126,9 +1070,7 @@
  * END_MANUAL_ENTRY()
  *
  ************************/
-int get_board_para(smc,slot)
-struct s_smc *smc ;
-int slot ;
+int get_board_para(struct s_smc *smc, int slot)
 {
 	int val ;
 	int i ;
@@ -1175,9 +1117,7 @@
 }
 
 /* Enable access to specified MCA slot. */
-static void EnableSlotAccess(smc,slot)
-struct s_smc *smc ;
-int slot ;
+static void EnableSlotAccess(struct s_smc *smc, int slot)
 {
 	SK_UNUSED(slot) ;
 
@@ -1195,8 +1135,7 @@
 }
 
 /* Disable access to MCA slot formerly enabled via EnableSlotAccess(). */
-static void DisableSlotAccess(smc)
-struct s_smc *smc ;
+static void DisableSlotAccess(struct s_smc *smc)
 {
 #ifndef AIX
 	SK_UNUSED(smc) ;
@@ -1245,9 +1184,7 @@
  *	The smc pointer must be valid now.
  *
  ************************/
-int exist_board(smc,slot)
-struct s_smc *smc ;
-int	slot ;
+int exist_board(struct s_smc *smc, int slot)
 {
 	int i ;
 #ifdef MULT_OEM
@@ -1284,9 +1221,7 @@
 }
 
 
-int get_board_para(smc,slot)
-struct s_smc *smc ;
-int	slot ;
+int get_board_para(struct s_smc *smc, int slot)
 {
 	int	i ;
 
@@ -1327,9 +1262,7 @@
 #endif	/* MULT_OEM */
 
 
-int exist_board(smc,port)
-struct s_smc *smc ;
-HW_PTR	port ;
+int exist_board(struct s_smc *smc, HW_PTR port)
 {
 	int	i ;
 #ifdef MULT_OEM
@@ -1400,9 +1333,7 @@
 #endif	/* MULT_OEM */
 }
 
-int get_board_para(smc,slot)
-struct s_smc *smc ;
-int	slot ;
+int get_board_para(struct s_smc *smc, int slot)
 {
 	SK_UNUSED(smc) ;
 	SK_UNUSED(slot) ;
@@ -1412,9 +1343,7 @@
 
 #ifdef PCI
 #ifdef USE_BIOS_FUN
-int exist_board(smc,slot)
-struct s_smc *smc ;
-int	slot ;
+int exist_board(struct s_smc *smc, int slot)
 {
 	u_short dev_id ;
 	u_short ven_id ;
@@ -1452,9 +1381,7 @@
 #endif	/* PCI */
 #endif	/* USE_BIOS_FUNC */
 
-void driver_get_bia(smc, bia_addr)
-struct s_smc *smc ;
-struct fddi_addr *bia_addr ;
+void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr)
 {
 	int i ;
 
@@ -1465,8 +1392,7 @@
 	}
 }
 
-void smt_start_watchdog(smc)
-struct s_smc *smc ;
+void smt_start_watchdog(struct s_smc *smc)
 {
 	SK_UNUSED(smc) ;	/* Make LINT happy. */
 
@@ -1481,8 +1407,7 @@
 #endif	/* DEBUG */
 }
 
-void smt_stop_watchdog(smc)
-struct s_smc *smc ;
+void smt_stop_watchdog(struct s_smc *smc)
 {
 	SK_UNUSED(smc) ;	/* Make LINT happy. */
 #ifndef	DEBUG
@@ -1497,9 +1422,7 @@
 }
 
 #ifdef	PCI
-static char get_rom_byte(smc,addr)
-struct s_smc *smc ;
-u_short	addr ;
+static char get_rom_byte(struct s_smc *smc, u_short addr)
 {
 	GET_PAGE(addr) ;
 	return (READ_PROM(ADDR(B2_FDP))) ;
@@ -1544,11 +1467,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-int mac_drv_vpd_read(smc,buf,size,image)
-struct s_smc *smc ;
-char *buf ;
-int size ;
-char image ;
+int mac_drv_vpd_read(struct s_smc *smc, char *buf, int size, char image)
 {
 	u_short	ibase ;
 	u_short pci_base ;
@@ -1597,16 +1516,14 @@
 	return(len) ;
 }
 
-void mac_drv_pci_fix(smc,fix_value)
-struct s_smc *smc ;
-u_long fix_value ;
+void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value)
 {
 	smc->hw.pci_fix_value = fix_value ;
 }
 
-void mac_do_pci_fix(smc)
-struct s_smc *smc ;
+void mac_do_pci_fix(struct s_smc *smc)
 {
 	SK_UNUSED(smc) ;
 }
 #endif	/* PCI */
+
diff -Nru a/drivers/net/skfp/ecm.c b/drivers/net/skfp/ecm.c
--- a/drivers/net/skfp/ecm.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/skfp/ecm.c	2004-06-23 19:04:26 -07:00
@@ -94,17 +94,16 @@
  * function declarations
  */
 
-static void ecm_fsm() ;
-static void start_ecm_timer() ;
-static void stop_ecm_timer() ;
-static void prop_actions() ;
+static void ecm_fsm(struct s_smc *smc, int cmd);
+static void start_ecm_timer(struct s_smc *smc, u_long value, int event);
+static void stop_ecm_timer(struct s_smc *smc);
+static void prop_actions(struct s_smc *smc);
 
 /*
 	init ECM state machine
 	clear all ECM vars and flags
 */
-void ecm_init(smc)
-struct s_smc *smc ;
+void ecm_init(struct s_smc *smc)
 {
 	smc->e.path_test = PT_PASSED ;
 	smc->e.trace_prop = 0 ;
@@ -122,9 +121,7 @@
 		process event
 	until SM is stable
 */
-void ecm(smc,event)
-struct s_smc *smc ;
-int event ;
+void ecm(struct s_smc *smc, int event)
 {
 	int	state ;
 
@@ -143,9 +140,7 @@
 /*
 	process ECM event
 */
-static void ecm_fsm(smc,cmd)
-struct s_smc *smc ;
-int cmd ;
+static void ecm_fsm(struct s_smc *smc, int cmd)
 {
 	int ls_a ;			/* current line state PHY A */
 	int ls_b ;			/* current line state PHY B */
@@ -429,8 +424,7 @@
 /*
  * trace propagation actions for SAS & DAS
  */
-static void prop_actions(smc)
-struct s_smc *smc ;
+static void prop_actions(struct s_smc *smc)
 {
 	int	port_in = 0 ;
 	int	port_out = 0 ;
@@ -480,8 +474,7 @@
 /*
  * trace propagation actions for Concentrator
  */
-static void prop_actions(smc)
-struct s_smc *smc ;
+static void prop_actions(struct s_smc *smc)
 {
 	int	initiator ;
 	int	upstream ;
@@ -527,10 +520,7 @@
  * SMT timer interface
  *	start ECM timer
  */
-static void start_ecm_timer(smc,value,event)
-struct s_smc *smc ;
-u_long value;
-int event ;
+static void start_ecm_timer(struct s_smc *smc, u_long value, int event)
 {
 	smt_timer_start(smc,&smc->e.ecm_timer,value,EV_TOKEN(EVENT_ECM,event));
 }
@@ -539,8 +529,7 @@
  * SMT timer interface
  *	stop ECM timer
  */
-static void stop_ecm_timer(smc)
-struct s_smc *smc ;
+static void stop_ecm_timer(struct s_smc *smc)
 {
 	if (smc->e.ecm_timer.tm_active)
 		smt_timer_stop(smc,&smc->e.ecm_timer) ;
diff -Nru a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c
--- a/drivers/net/skfp/ess.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/skfp/ess.c	2004-06-23 19:04:26 -07:00
@@ -80,8 +80,11 @@
 	-------------------------------------------------------------
 */
 
-static	void	ess_send_response(),		ess_config_fifo(),
-		ess_send_alc_req(),		ess_send_frame() ;
+static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
+			      int sba_cmd);
+static void ess_config_fifo(struct s_smc *smc);
+static void ess_send_alc_req(struct s_smc *smc);
+static void ess_send_frame(struct s_smc *smc, SMbuf *mb);
 
 /*
 	-------------------------------------------------------------
@@ -89,26 +92,17 @@
 	-------------------------------------------------------------
 */
 
-extern	void	*sm_to_para() ;
-
-extern	void	smt_send_frame(),	smt_free_mbuf(),
-		set_formac_tsync(),	formac_reinit_tx() ;
-
-extern	int	smt_check_para() ;
-
-extern	SMbuf	*smt_get_mbuf(),	*smt_build_frame() ;
-
-extern	u_long	smt_get_tid() ;
-
 /*
 	-------------------------------------------------------------
 	PUBLIC FUNCTIONS:
 	-------------------------------------------------------------
 */
 
-	void	ess_timer_poll(),		ess_para_change() ;
-
-	int	ess_raf_received_pack(),	process_bw_alloc() ;
+void ess_timer_poll(struct s_smc *smc);
+void ess_para_change(struct s_smc *smc);
+int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
+			  int fs);
+int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead);
 
 
 /*
@@ -120,11 +114,8 @@
 /*
  * evaluate the RAF frame
  */
-int ess_raf_received_pack(smc,mb,sm,fs)
-struct s_smc *smc ;
-SMbuf *mb ;
-struct smt_header *sm ;
-int fs ;
+int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
+			  int fs)
 {
 	void			*p ;		/* universal pointer */
 	struct smt_p_0016	*cmd ;		/* para: command for the ESS */
@@ -384,10 +375,7 @@
  * determines the synchronous bandwidth, set the TSYNC register and the
  * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG.
  */
-int process_bw_alloc(smc,payload,overhead)
-struct s_smc *smc ;
-long payload ;
-long overhead ;
+int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead)
 {
 	/*
 	 * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG,
@@ -483,10 +471,8 @@
 	return(TRUE) ;
 }
 
-static void ess_send_response(smc,sm,sba_cmd)
-struct s_smc *smc ;
-struct smt_header *sm ;
-int sba_cmd ;
+static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
+			      int sba_cmd)
 {
 	struct smt_sba_chg	*chg ;
 	SMbuf			*mb ;
@@ -550,9 +536,7 @@
 	ess_send_frame(smc,mb) ;
 }
 
-
-void ess_timer_poll(smc)
-struct s_smc *smc ;
+void ess_timer_poll(struct s_smc *smc)
 {
 	if (!smc->ess.raf_act_timer_poll)
 		return ;
@@ -566,8 +550,7 @@
 	}
 }
 
-static void ess_send_alc_req(smc)
-struct s_smc *smc ;
+static void ess_send_alc_req(struct s_smc *smc)
 {
 	struct smt_sba_alc_req *req ;
 	SMbuf	*mb ;
@@ -675,9 +658,7 @@
 	ess_send_frame(smc,mb) ;
 }
 
-static void ess_send_frame(smc,mb)
-struct s_smc *smc ;
-SMbuf *mb ;
+static void ess_send_frame(struct s_smc *smc, SMbuf *mb)
 {
 	/*
 	 * check if the frame must be send to the own ESS
@@ -703,15 +684,13 @@
 	}
 }
 
-void ess_para_change(smc)
-struct s_smc *smc ;
+void ess_para_change(struct s_smc *smc)
 {
 	(void)process_bw_alloc(smc,(long)smc->mib.a[PATH0].fddiPATHSbaPayload,
 		(long)smc->mib.a[PATH0].fddiPATHSbaOverhead) ;
 }
 
-static void ess_config_fifo(smc)
-struct s_smc *smc ;
+static void ess_config_fifo(struct s_smc *smc)
 {
 	/*
 	 * if nothing to do exit 
@@ -738,3 +717,4 @@
 #endif /* ESS */
 
 #endif	/* no SLIM_SMT */
+
diff -Nru a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c
--- a/drivers/net/skfp/fplustm.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/skfp/fplustm.c	2004-06-23 19:04:26 -07:00
@@ -43,10 +43,10 @@
 /*
  * prototypes for static function
  */
-static void build_claim_beacon() ;
-static int init_mac() ;
-static void rtm_init() ;
-static void smt_split_up_fifo() ;
+static void build_claim_beacon(struct s_smc *smc, u_long t_request);
+static int init_mac(struct s_smc *smc, int all);
+static void rtm_init(struct s_smc *smc);
+static void smt_split_up_fifo(struct s_smc *smc);
 
 #if (!defined(NO_SMT_PANIC) || defined(DEBUG))
 static	char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n";
@@ -107,8 +107,7 @@
 			FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;
 
 
-static u_long mac_get_tneg(smc)
-struct s_smc *smc ;
+static u_long mac_get_tneg(struct s_smc *smc)
 {
 	u_long	tneg ;
 
@@ -117,8 +116,7 @@
 		0xffe00000L)) ;
 }
 
-void mac_update_counter(smc)
-struct s_smc *smc ;
+void mac_update_counter(struct s_smc *smc)
 {
 	smc->mib.m[MAC0].fddiMACFrame_Ct =
 		(smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L)
@@ -143,9 +141,7 @@
 /*
  * write long value into buffer memory over memory data register (MDR),
  */
-void	write_mdr(smc,val)
-struct s_smc *smc ;
-u_long val;
+void	write_mdr(struct s_smc *smc, u_long val)
 {
 	CHECK_NPP() ;
 	MDRW(val) ;
@@ -154,9 +150,7 @@
 /*
  * read long value from buffer memory over memory data register (MDR),
  */
-u_long read_mdr(smc,addr)
-struct s_smc *smc ;
-unsigned int addr;
+u_long read_mdr(struct s_smc *smc, unsigned int addr)
 {
 	long p ;
 	CHECK_NPP() ;
@@ -173,8 +167,7 @@
 /*
  * clear buffer memory
  */
-static void init_ram(smc)
-struct s_smc *smc ;
+static void init_ram(struct s_smc *smc)
 {
 	u_short i ;
 
@@ -193,8 +186,7 @@
 /*
  * set receive FIFO pointer
  */
-static void set_recvptr(smc)
-struct s_smc *smc ;
+static void set_recvptr(struct s_smc *smc)
 {
 	/*
 	 * initialize the pointer for receive queue 1
@@ -224,8 +216,7 @@
 /*
  * set transmit FIFO pointer
  */
-static void set_txptr(smc)
-struct s_smc *smc ;
+static void set_txptr(struct s_smc *smc)
 {
 	outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ;	/* reset transmit queues */
 
@@ -257,8 +248,7 @@
 /*
  * init memory buffer management registers
  */
-static void init_rbc(smc)
-struct s_smc *smc ;
+static void init_rbc(struct s_smc *smc)
 {
 	u_short	rbc_ram_addr ;
 
@@ -279,8 +269,7 @@
 /*
  * init rx pointer
  */
-static void init_rx(smc)
-struct s_smc *smc ;
+static void init_rx(struct s_smc *smc)
 {
 	struct s_smt_rx_queue	*queue ;
 
@@ -302,9 +291,7 @@
 /*
  * set the TSYNC register of the FORMAC to regulate synchronous transmission
  */
-void set_formac_tsync(smc,sync_bw)
-struct s_smc *smc ;
-long sync_bw ;
+void set_formac_tsync(struct s_smc *smc, long sync_bw)
 {
 	outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ;
 }
@@ -312,8 +299,7 @@
 /*
  * init all tx data structures
  */
-static void init_tx(smc)
-struct s_smc *smc ;
+static void init_tx(struct s_smc *smc)
 {
 	struct s_smt_tx_queue	*queue ;
 
@@ -339,8 +325,7 @@
 	llc_recover_tx(smc) ;
 }
 
-static void mac_counter_init(smc)
-struct s_smc *smc ;
+static void mac_counter_init(struct s_smc *smc)
 {
 	int i ;
 	u_long *ec ;
@@ -363,8 +348,7 @@
 /*
  * set FORMAC address, and t_request
  */
-static	void set_formac_addr(smc)
-struct s_smc *smc ;
+static	void set_formac_addr(struct s_smc *smc)
 {
 	long	t_requ = smc->mib.m[MAC0].fddiMACT_Req ;
 
@@ -390,9 +374,7 @@
 	outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ;
 }
 
-static void set_int(p,l)
-char *p;
-int l;
+static void set_int(char *p, int l)
 {
 	p[0] = (char)(l >> 24) ;
 	p[1] = (char)(l >> 16) ;
@@ -408,12 +390,12 @@
  * else
  *	append 'end of chain' pointer
  */
-static void copy_tx_mac(smc,td,mac,off,len)
-struct s_smc *smc ;
-u_long td;		/* transmit descriptor */
-struct fddi_mac *mac;	/* mac frame pointer */
-unsigned off;		/* start address within buffer memory */
-int len ;		/* lenght of the frame including the FC */
+static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
+			unsigned off, int len)
+/* u_long td;		 transmit descriptor */
+/* struct fddi_mac *mac; mac frame pointer */
+/* unsigned off;	 start address within buffer memory */
+/* int len ;		 lenght of the frame including the FC */
 {
 	int	i ;
 	u_int	*p ;
@@ -457,8 +439,7 @@
 
 	END_MANUAL_ENTRY
  */
-static void directed_beacon(smc)
-struct s_smc *smc ;
+static void directed_beacon(struct s_smc *smc)
 {
 	SK_LOC_DECL(u_int,a[2]) ;
 
@@ -487,9 +468,7 @@
 		special frame packets end with a pointer to their own
 		descriptor, and the MORE bit is set in the descriptor
 */
-static void build_claim_beacon(smc,t_request)
-struct s_smc *smc ;
-u_long t_request;
+static void build_claim_beacon(struct s_smc *smc, u_long t_request)
 {
 	u_int	td ;
 	int	len ;
@@ -550,8 +529,7 @@
 	outpw(FM_A(FM_RPXSF),0) ;
 }
 
-void formac_rcv_restart(smc)
-struct s_smc *smc ;
+void formac_rcv_restart(struct s_smc *smc)
 {
 	/* enable receive function */
 	SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
@@ -559,15 +537,13 @@
 	outpw(FM_A(FM_CMDREG1),FM_ICLLR) ;	/* clear receive lock */
 }
 
-void formac_tx_restart(smc)
-struct s_smc *smc ;
+void formac_tx_restart(struct s_smc *smc)
 {
 	outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;	/* clear s-frame lock */
 	outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ;	/* clear a-frame lock */
 }
 
-static void enable_formac(smc)
-struct s_smc *smc ;
+static void enable_formac(struct s_smc *smc)
 {
 	/* set formac IMSK : 0 enables irq */
 	outpw(FM_A(FM_IMSK1U),~mac_imsk1u) ;
@@ -607,9 +583,8 @@
 
 	END_MANUAL_ENTRY
  */
-void enable_tx_irq(smc, queue)
-struct s_smc *smc ;
-u_short	queue ;		/* 0 = synchronous queue, 1 = asynchronous queue 0 */
+void enable_tx_irq(struct s_smc *smc, u_short queue)
+/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
 {
 	u_short	imask ;
 
@@ -643,9 +618,8 @@
 
 	END_MANUAL_ENTRY
  */
-void disable_tx_irq(smc, queue)
-struct s_smc *smc ;
-u_short	queue ;		/* 0 = synchronous queue, 1 = asynchronous queue 0 */
+void disable_tx_irq(struct s_smc *smc, u_short queue)
+/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
 {
 	u_short	imask ;
 
@@ -660,8 +634,7 @@
 }
 #endif
 
-static void disable_formac(smc)
-struct s_smc *smc ;
+static void disable_formac(struct s_smc *smc)
 {
 	/* clear formac IMSK : 1 disables irq */
 	outpw(FM_A(FM_IMSK1U),MW) ;
@@ -673,9 +646,7 @@
 }
 
 
-static void mac_ring_up(smc,up)
-struct s_smc *smc ;
-int up;
+static void mac_ring_up(struct s_smc *smc, int up)
 {
 	if (up) {
 		formac_rcv_restart(smc) ;	/* enable receive function */
@@ -702,10 +673,7 @@
  * mac2_irq:	status bits for the receive queue 1, and ring status
  * 		ring status indication bits
  */
-void mac2_irq(smc,code_s2u,code_s2l)
-struct s_smc *smc ;
-u_short code_s2u ;
-u_short code_s2l ;
+void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l)
 {
 	u_short	change_s2l ;
 	u_short	change_s2u ;
@@ -831,10 +799,7 @@
 /*
  * mac3_irq:	receive queue 2 bits and address detection bits
  */
-void mac3_irq(smc,code_s3u,code_s3l)
-struct s_smc *smc ;
-u_short code_s3u ;
-u_short code_s3l ;
+void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l)
 {
 	UNUSED(code_s3l) ;
 
@@ -857,8 +822,7 @@
 /*
  * take formac offline
  */
-static void formac_offline(smc)
-struct s_smc *smc ;
+static void formac_offline(struct s_smc *smc)
 {
 	outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */
 
@@ -876,8 +840,7 @@
 /*
  * bring formac online
  */
-static void formac_online(smc)
-struct s_smc *smc ;
+static void formac_online(struct s_smc *smc)
 {
 	enable_formac(smc) ;
 	SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT |
@@ -887,8 +850,7 @@
 /*
  * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon)
  */
-int init_fplus(smc)
-struct s_smc *smc ;
+int init_fplus(struct s_smc *smc)
 {
 	smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
 	smc->hw.fp.rx_mode = FM_MDAMA ;
@@ -926,9 +888,7 @@
 	/* enable_formac(smc) ; */
 }
 
-static int init_mac(smc,all)
-struct s_smc *smc ;
-int all ;
+static int init_mac(struct s_smc *smc, int all)
 {
 	u_short	t_max,x ;
 	u_long	time=0 ;
@@ -1033,9 +993,7 @@
 /*
  * called by CFM
  */
-void config_mux(smc,mux)
-struct s_smc *smc ;
-int mux;
+void config_mux(struct s_smc *smc, int mux)
 {
 	plc_config_mux(smc,mux) ;
 
@@ -1049,8 +1007,7 @@
  * the interrupt must not be permanently enabled
  * RMT calls this function periodically (timer driven polling)
  */
-void sm_mac_check_beacon_claim(smc)
-struct s_smc *smc ;
+void sm_mac_check_beacon_claim(struct s_smc *smc)
 {
 	/* set formac IMSK : 0 enables irq */
 	outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ;
@@ -1063,9 +1020,7 @@
 /*
  * control ODL output
  */
-void sm_pm_control(smc,mode)
-struct s_smc *smc ;
-int mode;
+void sm_pm_control(struct s_smc *smc, int mode)
 {
 	SK_UNUSED(smc) ;
 
@@ -1084,9 +1039,7 @@
 /*
  * control MAC layer	(called by RMT)
  */
-void sm_ma_control(smc,mode)
-struct s_smc *smc ;
-int mode;
+void sm_ma_control(struct s_smc *smc, int mode)
 {
 	switch(mode) {
 	case MA_OFFLINE :
@@ -1110,8 +1063,7 @@
 	}
 }
 
-int sm_mac_get_tx_state(smc)
-struct s_smc *smc ;
+int sm_mac_get_tx_state(struct s_smc *smc)
 {
 	return((inpw(FM_A(FM_STMCHN))>>4)&7) ;
 }
@@ -1120,12 +1072,10 @@
  * multicast functions
  */
 
-static struct s_fpmc	*mac_get_mc_table(smc,user,own,del,can)
-struct s_smc *smc ;
-struct fddi_addr *user ;
-struct fddi_addr *own ;
-int del ;
-int can ;
+static struct s_fpmc* mac_get_mc_table(struct s_smc *smc,
+				       struct fddi_addr *user,
+				       struct fddi_addr *own,
+				       int del, int can)
 {
 	struct s_fpmc	*tb ;
 	struct s_fpmc	*slot ;
@@ -1166,8 +1116,7 @@
 
 	END_MANUAL_ENTRY()
  */
-void mac_clear_multicast(smc)
-struct s_smc *smc ;
+void mac_clear_multicast(struct s_smc *smc)
 {
 	struct s_fpmc	*tb ;
 	int i ;
@@ -1198,9 +1147,7 @@
 
 	END_MANUAL_ENTRY()
  */
-int mac_set_func_addr(smc,f_addr)
-struct s_smc *smc ;
-u_long f_addr ;
+int mac_set_func_addr(struct s_smc *smc, u_long f_addr)
 {
 	smc->hw.fp.func_addr = f_addr ;
 	return(0) ;
@@ -1235,10 +1182,7 @@
 
 	END_MANUAL_ENTRY()
  */
-int mac_add_multicast(smc,addr,can)
-struct s_smc *smc ;
-struct fddi_addr *addr ;
-int can ;
+int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
 {
 	SK_LOC_DECL(struct fddi_addr,own) ;
 	struct s_fpmc	*tb ;
@@ -1292,10 +1236,7 @@
 
 	END_MANUAL_ENTRY()
  */
-void mac_del_multicast(smc,addr,can)
-struct s_smc *smc ;
-struct fddi_addr *addr ;
-int can ;
+void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
 {
 	SK_LOC_DECL(struct fddi_addr,own) ;
 	struct s_fpmc	*tb ;
@@ -1341,8 +1282,7 @@
 
 	END_MANUAL_ENTRY()
  */
-void mac_update_multicast(smc)
-struct s_smc *smc ;
+void mac_update_multicast(struct s_smc *smc)
 {
 	struct s_fpmc	*tb ;
 	u_char	*fu ;
@@ -1418,9 +1358,7 @@
 
 	END_MANUAL_ENTRY
  */
-void mac_set_rx_mode(smc,mode)
-struct s_smc *smc ;
-int mode ;
+void mac_set_rx_mode(struct s_smc *smc, int mode)
 {
 	switch (mode) {
 	case RX_ENABLE_ALLMULTI :
@@ -1476,8 +1414,7 @@
 
 	END_MANUAL_ENTRY
  */
-void rtm_irq(smc)
-struct s_smc *smc ;
+void rtm_irq(struct s_smc *smc)
 {
 	outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ;		/* clear IRQ */
 	if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) {
@@ -1490,15 +1427,13 @@
 	outpw(ADDR(B2_RTM_CRTL),TIM_START) ;	/* enable RTM monitoring */
 }
 
-static void rtm_init(smc)
-struct s_smc *smc ;
+static void rtm_init(struct s_smc *smc)
 {
 	outpd(ADDR(B2_RTM_INI),0) ;		/* timer = 0 */
 	outpw(ADDR(B2_RTM_CRTL),TIM_START) ;	/* enable IRQ */
 }
 
-void rtm_set_timer(smc)
-struct s_smc *smc ;
+void rtm_set_timer(struct s_smc *smc)
 {
 	/*
 	 * MIB timer and hardware timer have the same resolution of 80nS
@@ -1508,8 +1443,7 @@
 	outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ;
 }
 
-static void smt_split_up_fifo(smc)
-struct s_smc *smc ;
+static void smt_split_up_fifo(struct s_smc *smc)
 {
 
 /*
@@ -1629,8 +1563,7 @@
 		smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start) ;
 }
 
-void formac_reinit_tx(smc)
-struct s_smc *smc ;
+void formac_reinit_tx(struct s_smc *smc)
 {
 	/*
 	 * Split up the FIFO and reinitialize the MAC if synchronous
@@ -1641,5 +1574,4 @@
 		(void)init_mac(smc,0) ;
 	}
 }
-
 
diff -Nru a/drivers/net/skfp/h/cmtdef.h b/drivers/net/skfp/h/cmtdef.h
--- a/drivers/net/skfp/h/cmtdef.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/skfp/h/cmtdef.h	2004-06-23 19:04:26 -07:00
@@ -418,7 +418,6 @@
 	void	*pc_p ;
 } ;
 
-
 /*
  * link error monitor
  */
@@ -444,7 +443,6 @@
 
 #define NUMBITS	10
 
-
 #ifdef	AMDPLC
 
 /*
@@ -480,216 +478,184 @@
  * function prototypes
  */
 #include "h/mbuf.h"	/* Type definitions for MBUFs */
-void hwt_restart(                       /* hwt.c */
-#ifdef ANSIC
-        struct s_smc *smc
-#endif
-	) ;
-
-SMbuf *smt_build_frame(                 /* smt.c */
-#ifdef ANSIC
-        struct s_smc *smc,
-        int class,
-        int type,
-        int length
-#endif
-	) ;
-
-SMbuf *smt_get_mbuf(                     /* drvsr.c */
-#ifdef ANSIC
-        struct s_smc *smc
-#endif
-	) ;
-
-void *sm_to_para(                       /* smt.c */
-#ifdef ANSIC
-	struct s_smc *smc,
-        struct smt_header *sm,
-        int para
-#endif
-	) ;
+#include "h/smtstate.h"	/* struct smt_state */
+
+void hwt_restart(struct s_smc *smc);	/* hwt.c */
+SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
+		       int length);	/* smt.c */
+SMbuf *smt_get_mbuf(struct s_smc *smc);	/* drvsr.c */
+void *sm_to_para(struct s_smc *smc, struct smt_header *sm,
+		 int para);		/* smt.c */
 
 #ifndef SK_UNUSED
 #define SK_UNUSED(var)		(void)(var)
 #endif
 
-void queue_event() ;
-void ecm() ;
-void ecm_init() ;
-void rmt() ;
-void rmt_init() ;
-void pcm() ;
-void pcm_init() ;
-void cfm() ;
-void cfm_init() ;
-void smt_timer_start() ;
-void smt_timer_stop() ;
-void pcm_status_state() ;
-void plc_config_mux() ;
-void sm_lem_evaluate() ;
-void smt_clear_una_dna() ;
-void mac_status_para() ;
-void mac_update_counter() ;
-void sm_pm_ls_latch() ;
-void sm_ma_control() ;
-void sm_mac_check_beacon_claim() ;
-void config_mux() ;
-void smt_agent_init() ;
-void smt_timer_init() ;
-void smt_received_pack() ;
-void smt_add_para() ;
-void smt_swap_para() ;
-void ev_init() ;
-void hwt_init() ;
-u_long hwt_read() ;
-void hwt_stop() ;
-void hwt_start() ;
-void smt_send_mbuf() ;
-void smt_free_mbuf() ;
-void sm_pm_bypass_req() ;
-void rmt_indication() ;
-void cfm_state_change() ;
-void rx_indication() ;
-void tx_indication() ;
-#ifndef NO_SMT_PANIC
-void smt_panic() ;
-#else
-#ifdef	DEBUG
-void smt_panic() ;
+void queue_event(struct s_smc *smc, int class, int event);
+void ecm(struct s_smc *smc, int event);
+void ecm_init(struct s_smc *smc);
+void rmt(struct s_smc *smc, int event);
+void rmt_init(struct s_smc *smc);
+void pcm(struct s_smc *smc, const int np, int event);
+void pcm_init(struct s_smc *smc);
+void cfm(struct s_smc *smc, int event);
+void cfm_init(struct s_smc *smc);
+void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
+		     u_long token);
+void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer);
+void pcm_status_state(struct s_smc *smc, int np, int *type, int *state,
+		      int *remote, int *mac);
+void plc_config_mux(struct s_smc *smc, int mux);
+void sm_lem_evaluate(struct s_smc *smc);
+void smt_clear_una_dna(struct s_smc *smc);
+void mac_update_counter(struct s_smc *smc);
+void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off);
+void sm_ma_control(struct s_smc *smc, int mode);
+void sm_mac_check_beacon_claim(struct s_smc *smc);
+void config_mux(struct s_smc *smc, int mux);
+void smt_agent_init(struct s_smc *smc);
+void smt_timer_init(struct s_smc *smc);
+void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs);
+void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
+		  int index, int local);
+void smt_swap_para(struct smt_header *sm, int len, int direction);
+void ev_init(struct s_smc *smc);
+void hwt_init(struct s_smc *smc);
+u_long hwt_read(struct s_smc *smc);
+void hwt_stop(struct s_smc *smc);
+void hwt_start(struct s_smc *smc, u_long time);
+void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc);
+void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
+void sm_pm_bypass_req(struct s_smc *smc, int mode);
+void rmt_indication(struct s_smc *smc, int i);
+void cfm_state_change(struct s_smc *smc, int c_state);
+
+#if defined(DEBUG) || !defined(NO_SMT_PANIC)
+void smt_panic(struct s_smc *smc, char *text);
 #else
 #define	smt_panic(smc,text)
-#endif	/* DEBUG */
-#endif	/* NO_SMT_PANIC */
-void smt_stat_counter() ;
-void smt_timer_poll() ;
-u_long smt_get_time() ;
-u_long smt_get_tid() ;
-void smt_timer_done() ;
-void smt_set_defaults() ;
-void smt_fixup_mib() ;
-void smt_reset_defaults() ;
-void smt_agent_task() ;
-void smt_please_reconnect() ;
-int smt_check_para() ;
-void driver_get_bia() ;
-#ifdef	SUPERNET_3
-void drv_reset_indication() ;
+#endif /* DEBUG || !NO_SMT_PANIC */
+
+void smt_stat_counter(struct s_smc *smc, int stat);
+void smt_timer_poll(struct s_smc *smc);
+u_long smt_get_time(void);
+u_long smt_get_tid(struct s_smc *smc);
+void smt_timer_done(struct s_smc *smc);
+void smt_set_defaults(struct s_smc *smc);
+void smt_fixup_mib(struct s_smc *smc);
+void smt_reset_defaults(struct s_smc *smc, int level);
+void smt_agent_task(struct s_smc *smc);
+void smt_please_reconnect(struct s_smc *smc, int reconn_time);
+int smt_check_para(struct s_smc *smc, struct smt_header *sm,
+		   const u_short list[]);
+void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr);
+
+#ifdef SUPERNET_3
+void drv_reset_indication(struct s_smc *smc);
 #endif	/* SUPERNET_3 */
-void smt_start_watchdog() ;
 
-void smt_event() ;
-void pcm_event() ;
-void rmt_event() ;
-void cfm_event() ;
-void timer_event() ;
-void ev_dispatcher() ;
-
-void smt_get_state() ;
-void ecm_get_state() ;
-void pcm_get_state() ;
-void rmt_get_state() ;
-
-void ecm_state_change() ;
-int sm_pm_bypass_present() ;
-void pcm_state_change() ;
-void rmt_state_change() ;
-int sm_pm_get_ls() ;
-int pcm_get_s_port() ;
-int pcm_rooted_station() ;
-int cfm_get_mac_input() ;
-int cfm_get_mac_output() ;
-int port_to_mib() ;
-int cem_build_path() ;
-int sm_mac_get_tx_state() ;
-int is_individual() ;
-int is_my_addr() ;
-int is_broadcast() ;
-int is_equal() ;
-char *get_pcmstate() ;
-
-int smt_action() ;
-u_short smt_online() ;
-void smt_force_irq() ;
-void smt_pmf_received_pack() ;
-void smt_send_frame() ;
-void smt_set_timestamp() ;
-void mac_set_rx_mode() ;
-int mac_add_multicast() ;
-int mac_set_func_addr() ;
-void mac_del_multicast() ;
-void mac_update_multicast() ;
-void mac_clear_multicast() ;
-void mac_rx_directed_beacon() ;
-void set_formac_tsync() ;
-void formac_reinit_tx() ;
-void formac_tx_restart() ;
-void process_receive() ;
-void init_driver_fplus() ;
-
-void rtm_irq() ;
-void rtm_set_timer() ;
-void ring_status_indication() ;
-void llc_recover_tx() ;
-void llc_restart_tx() ;
-void plc_clear_irq() ;
-void plc_irq() ;
-int smt_set_mac_opvalues() ;
-#ifdef	TAG_MODE
-void mac_drv_pci_fix() ;
-void mac_do_pci_fix() ;
-void mac_drv_clear_tx_queue() ;
-void mac_drv_repair_descr() ;
-u_long hwt_quick_read() ;
-void hwt_wait_time() ;
+void smt_start_watchdog(struct s_smc *smc);
+void smt_event(struct s_smc *smc, int event);
+void timer_event(struct s_smc *smc, u_long token);
+void ev_dispatcher(struct s_smc *smc);
+void pcm_get_state(struct s_smc *smc, struct smt_state *state);
+void ecm_state_change(struct s_smc *smc, int e_state);
+int sm_pm_bypass_present(struct s_smc *smc);
+void pcm_state_change(struct s_smc *smc, int plc, int p_state);
+void rmt_state_change(struct s_smc *smc, int r_state);
+int sm_pm_get_ls(struct s_smc *smc, int phy);
+int pcm_get_s_port(struct s_smc *smc);
+int pcm_rooted_station(struct s_smc *smc);
+int cfm_get_mac_input(struct s_smc *smc);
+int cfm_get_mac_output(struct s_smc *smc);
+int port_to_mib(struct s_smc *smc, int p);
+int cem_build_path(struct s_smc *smc, char *to, int path_index);
+int sm_mac_get_tx_state(struct s_smc *smc);
+int is_individual(struct fddi_addr *addr);
+int is_my_addr(struct s_smc *smc, struct fddi_addr *addr);
+int is_broadcast(struct fddi_addr *addr);
+int is_equal(struct fddi_addr *addr1, struct fddi_addr *addr2);
+char *get_pcmstate(struct s_smc *smc, int np);
+int smt_action(struct s_smc *smc, int class, int code, int index);
+u_short smt_online(struct s_smc *smc, int on);
+void smt_force_irq(struct s_smc *smc);
+void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local);
+void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local);
+void smt_set_timestamp(struct s_smc *smc, u_char *p);
+void mac_set_rx_mode(struct s_smc *smc,	int mode);
+int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can);
+int mac_set_func_addr(struct s_smc *smc, u_long f_addr);
+void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can);
+void mac_update_multicast(struct s_smc *smc);
+void mac_clear_multicast(struct s_smc *smc);
+void set_formac_tsync(struct s_smc *smc, long sync_bw);
+void formac_reinit_tx(struct s_smc *smc);
+void formac_tx_restart(struct s_smc *smc);
+void process_receive(struct s_smc *smc);
+void init_driver_fplus(struct s_smc *smc);
+void rtm_irq(struct s_smc *smc);
+void rtm_set_timer(struct s_smc *smc);
+void ring_status_indication(struct s_smc *smc, u_long status);
+void llc_recover_tx(struct s_smc *smc);
+void llc_restart_tx(struct s_smc *smc);
+void plc_clear_irq(struct s_smc *smc, int p);
+void plc_irq(struct s_smc *smc,	int np,	unsigned int cmd);
+int smt_set_mac_opvalues(struct s_smc *smc);
+
+#ifdef TAG_MODE
+void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value);
+void mac_do_pci_fix(struct s_smc *smc);
+void mac_drv_clear_tx_queue(struct s_smc *smc);
+void mac_drv_repair_descr(struct s_smc *smc);
+u_long hwt_quick_read(struct s_smc *smc);
+void hwt_wait_time(struct s_smc *smc, u_long start, long duration);
 #endif
 
 #ifdef SMT_PNMI
-#ifdef ANSIC
-int pnmi_init (struct s_smc* smc);
-int pnmi_process_ndis_id (struct s_smc* smc, u_long ndis_oid, void* buf,
-		int len, int* BytesAccessed, int* BytesNeeded, u_char action);
-#else
-int pnmi_init ();
-int pnmi_process_ndis_id ();
-#endif
+int pnmi_init(struct s_smc* smc);
+int pnmi_process_ndis_id(struct s_smc *smc, u_long ndis_oid, void *buf, int len,
+			 int *BytesAccessed, int *BytesNeeded, u_char action);
 #endif
 
 #ifdef	SBA
 #ifndef _H2INC
-void sba() ;
+void sba();
 #endif
-void sba_raf_received_pack() ;
-void sba_timer_poll() ;
-void smt_init_sba() ;
+void sba_raf_received_pack();
+void sba_timer_poll();
+void smt_init_sba();
 #endif
+
 #ifdef	ESS
-int ess_raf_received_pack() ;
-void ess_timer_poll() ;
-void ess_para_change() ;
+int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
+			  int fs);
+void ess_timer_poll(struct s_smc *smc);
+void ess_para_change(struct s_smc *smc);
 #endif
 
-#ifdef	BOOT
-#define smt_srf_event(a,b,c,d)
-#define smt_init_evc(a)
+#ifndef	BOOT
+void smt_init_evc(struct s_smc *smc);
+void smt_srf_event(struct s_smc *smc, int code, int index, int cond);
 #else
-void smt_init_evc() ;
-void smt_srf_event() ;
+#define smt_init_evc(smc)
+#define smt_srf_event(smc,code,index,cond)
 #endif
 
 #ifndef SMT_REAL_TOKEN_CT
-void smt_emulate_token_ct();
+void smt_emulate_token_ct(struct s_smc *smc, int mac_index);
 #endif
 
 #if defined(DEBUG) && !defined(BOOT)
-void dump_smt() ;
+void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text);
 #else
 #define	dump_smt(smc,sm,text)
 #endif
 
 #ifdef	DEBUG
-char	*addr_to_string() ;
-void	dump_hex() ;
+char* addr_to_string(struct fddi_addr *addr);
+void dump_hex(char *p, int len);
 #endif
+
 #endif	/* PROTOTYP_INC */
 
 /* PNMI default defines */
diff -Nru a/drivers/net/skfp/h/smtstate.h b/drivers/net/skfp/h/smtstate.h
--- a/drivers/net/skfp/h/smtstate.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/skfp/h/smtstate.h	2004-06-23 19:04:28 -07:00
@@ -12,6 +12,9 @@
  *
  ******************************************************************************/
 
+#ifndef _SKFP_H_SMTSTATE_H_
+#define _SKFP_H_SMTSTATE_H_
+
 /*
  *	SMT state definitions
  */
@@ -98,3 +101,6 @@
 struct smt_state {
 	struct pcm_state pcm_state[NUMPHYS] ;	/* port A & port B */
 } ;
+
+#endif
+
diff -Nru a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c
--- a/drivers/net/skfp/hwmtm.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/skfp/hwmtm.c	2004-06-23 19:04:27 -07:00
@@ -75,15 +75,17 @@
 	-------------------------------------------------------------
 */
 
-static	void	queue_llc_rx(),		smt_to_llc(),
-		init_txd_ring(),	init_rxd_ring(),
-		queue_txd_mb() ;
-
-static	u_long	init_descr_ring(),	repair_txd_ring(),
-		repair_rxd_ring() ;
-
-static	SMbuf	*get_llc_rx(),		*get_txd_mb() ;
-
+static void queue_llc_rx(struct s_smc *smc, SMbuf *mb);
+static void smt_to_llc(struct s_smc *smc, SMbuf *mb);
+static void init_txd_ring(struct s_smc *smc);
+static void init_rxd_ring(struct s_smc *smc);
+static void queue_txd_mb(struct s_smc *smc, SMbuf *mb);
+static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start,
+			      int count);
+static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue);
+static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue);
+static SMbuf* get_llc_rx(struct s_smc *smc);
+static SMbuf* get_txd_mb(struct s_smc *smc);
 
 /*
 	-------------------------------------------------------------
@@ -92,55 +94,81 @@
 */
 /*	The external SMT functions are listed in cmtdef.h */
 
-extern	void	*mac_drv_get_space(),	*mac_drv_get_desc_mem(),
-		init_board(),		mac_drv_fill_rxd(),
-		plc1_irq(),		mac_drv_tx_complete(),
-		plc2_irq(),		mac1_irq(),
-		mac2_irq(),		mac3_irq(),
-		timer_irq(),		mac_drv_rx_complete(),
-		mac_drv_requeue_rxd(),	init_plc(),
-		mac_drv_clear_rxd(),	llc_restart_tx(),
-		ev_dispatcher(),	smt_force_irq() ;
+extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size);
+extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size);
+extern void init_board(struct s_smc *smc, u_char *mac_addr);
+extern void mac_drv_fill_rxd(struct s_smc *smc);
+extern void plc1_irq(struct s_smc *smc);
+extern void mac_drv_tx_complete(struct s_smc *smc,
+				volatile struct s_smt_fp_txd *txd);
+extern void plc2_irq(struct s_smc *smc);
+extern void mac1_irq(struct s_smc *smc, u_short stu, u_short stl);
+extern void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l);
+extern void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l);
+extern void timer_irq(struct s_smc *smc);
+extern void mac_drv_rx_complete(struct s_smc *smc,
+				volatile struct s_smt_fp_rxd *rxd,
+				int frag_count, int len);
+extern void mac_drv_requeue_rxd(struct s_smc *smc, 
+				volatile struct s_smt_fp_rxd *rxd,
+				int frag_count);
+extern void init_plc(struct s_smc *smc);
+extern void mac_drv_clear_rxd(struct s_smc *smc,
+			      volatile struct s_smt_fp_rxd *rxd, int frag_count);
 
 #ifdef	USE_OS_CPY
-extern	void	hwm_cpy_rxd2mb(),	hwm_cpy_txd2mb() ;
+extern void hwm_cpy_rxd2mb(void);
+extern void hwm_cpy_txd2mb(void);
 #endif
+
 #ifdef	ALL_RX_COMPLETE
-extern	void	mac_drv_all_receives_complete() ;
+extern void mac_drv_all_receives_complete(void);
 #endif
 
-extern	u_long	mac_drv_virt2phys(),	dma_master() ;
+extern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt);
+extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag);
 
 #ifdef	NDIS_OS2
-extern	void	post_proc() ;
+extern void post_proc(void);
 #else
-extern	void	dma_complete() ;
+extern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
+			 int flag);
 #endif
 
-extern	int	init_fplus(),		mac_drv_rx_init() ;
+extern int init_fplus(struct s_smc *smc);
+extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
+			   int la_len);
 
 /*
 	-------------------------------------------------------------
 	PUBLIC FUNCTIONS:
 	-------------------------------------------------------------
 */
-	void	process_receive(),	smt_send_mbuf(),
-		fddi_isr(),		mac_drv_clear_txd(),
-		smt_free_mbuf(),	init_driver_fplus(),
-		mac_drv_rx_mode(),	init_fddi_driver(),
-		mac_drv_clear_tx_queue(),
-		mac_drv_clear_rx_queue(),
-		hwm_tx_frag(),		hwm_rx_frag() ;
-
-	int	mac_drv_rx_frag(),	mac_drv_init(),
-		hwm_tx_init() ;
+void process_receive(struct s_smc *smc);
+void fddi_isr(struct s_smc *smc);
+void mac_drv_clear_txd(struct s_smc *smc);
+void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
+void init_driver_fplus(struct s_smc *smc);
+void mac_drv_rx_mode(struct s_smc *smc, int mode);
+void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);
+void mac_drv_clear_tx_queue(struct s_smc *smc);
+void mac_drv_clear_rx_queue(struct s_smc *smc);
+void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+		 int frame_status);
+void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+		 int frame_status);
+
+int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len);
+int mac_drv_init(struct s_smc *smc);
+int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
+		int frame_status);
 
-	u_int	mac_drv_check_space() ;
+u_int mac_drv_check_space(void);
 
-	SMbuf 	*smt_get_mbuf() ;
+SMbuf* smt_get_mbuf(struct s_smc *smc);
 
 #ifdef DEBUG
-	void	mac_drv_debug_lev() ;
+	void mac_drv_debug_lev(void);
 #endif
 
 /*
@@ -208,7 +236,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-u_int mac_drv_check_space()
+u_int mac_drv_check_space(void)
 {
 #ifdef	MB_OUTSIDE_SMC
 #ifdef	COMMON_MB_POOL
@@ -238,8 +266,7 @@
  *			mac_drv_init once, after the adatper is detected.
  *	END_MANUAL_ENTRY
  */
-int mac_drv_init(smc)
-struct s_smc *smc ;
+int mac_drv_init(struct s_smc *smc)
 {
 	if (sizeof(struct s_smt_fp_rxd) % 16) {
 		SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ;
@@ -289,8 +316,7 @@
  *	 least significant byte etc.)
  *	END_MANUAL_ENTRY
  */
-void init_driver_fplus(smc)
-struct s_smc *smc ;
+void init_driver_fplus(struct s_smc *smc)
 {
 	smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ;
 
@@ -305,10 +331,9 @@
 #endif
 }
 
-static u_long init_descr_ring(smc,start,count)
-struct s_smc *smc ;
-union s_fp_descr volatile *start;
-int count ;
+static u_long init_descr_ring(struct s_smc *smc,
+			      union s_fp_descr volatile *start,
+			      int count)
 {
 	int i ;
 	union s_fp_descr volatile *d1 ;
@@ -337,8 +362,7 @@
 	return(phys) ;
 }
 
-static void init_txd_ring(smc)
-struct s_smc *smc ;
+static void init_txd_ring(struct s_smc *smc)
 {
 	struct s_smt_fp_txd volatile *ds ;
 	struct s_smt_tx_queue *queue ;
@@ -375,8 +399,7 @@
 	outpd(ADDR(B5_XS_DA),phys) ;
 }
 
-static void init_rxd_ring(smc)
-struct s_smc *smc ;
+static void init_rxd_ring(struct s_smc *smc)
 {
 	struct s_smt_fp_rxd volatile *ds ;
 	struct s_smt_rx_queue *queue ;
@@ -406,9 +429,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-void init_fddi_driver(smc,mac_addr)
-struct	s_smc	*smc ;
-u_char		*mac_addr ;	/* canonical address */
+void init_fddi_driver(struct s_smc *smc, u_char *mac_addr)
 {
 	SMbuf	*mb ;
 	int	i ;
@@ -472,8 +493,7 @@
 }
 
 
-SMbuf *smt_get_mbuf(smc)
-struct s_smc *smc ;
+SMbuf *smt_get_mbuf(struct s_smc *smc)
 {
 	register SMbuf	*mb ;
 
@@ -495,9 +515,7 @@
 	return (mb) ;	/* May be NULL */
 }
 
-void smt_free_mbuf(smc, mb)
-struct s_smc	*smc ;
-SMbuf		*mb;
+void smt_free_mbuf(struct s_smc *smc, SMbuf *mb)
 {
 
 	if (mb) {
@@ -543,8 +561,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-void mac_drv_repair_descr(smc)
-struct s_smc *smc ;
+void mac_drv_repair_descr(struct s_smc *smc)
 {
 	u_long	phys ;
 
@@ -576,9 +593,7 @@
 	outpd(ADDR(B0_R1_CSR),CSR_START) ;
 }
 
-static u_long repair_txd_ring(smc,queue)
-struct s_smc *smc ;
-struct s_smt_tx_queue *queue ;
+static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
 {
 	int i ;
 	int tx_used ;
@@ -630,9 +645,7 @@
  *	  RxDs with an OWN bit set but with a reset STF bit should be
  *	  skipped and owned by the driver (OWN = 0). 
  */
-static u_long repair_rxd_ring(smc,queue)
-struct s_smc *smc ;
-struct s_smt_rx_queue *queue ;
+static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
 {
 	int i ;
 	int rx_used ;
@@ -703,8 +716,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-void fddi_isr(smc)
-struct s_smc *smc ;
+void fddi_isr(struct s_smc *smc)
 {
 	u_long		is ;		/* ISR source */
 	u_short		stu, stl ;
@@ -987,9 +999,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-void mac_drv_rx_mode(smc,mode)
-struct s_smc *smc ;
-int mode ;
+void mac_drv_rx_mode(struct s_smc *smc, int mode)
 {
 	switch(mode) {
 	case RX_ENABLE_PASS_SMT:
@@ -1038,8 +1048,7 @@
 /*
  * process receive queue
  */
-void process_receive(smc)
-struct s_smc *smc ;
+void process_receive(struct s_smc *smc)
 {
 	int i ;
 	int n ;
@@ -1379,9 +1388,7 @@
 	return ;	/* lint bug: needs return detect end of function */
 }
 
-static void smt_to_llc(smc,mb)
-struct s_smc *smc ;
-SMbuf *mb ;
+static void smt_to_llc(struct s_smc *smc, SMbuf *mb)
 {
 	u_char	fc ;
 
@@ -1416,12 +1423,8 @@
  *
  *	END_MANUAL_ENTRY
  */
-void hwm_rx_frag(smc,virt,phys,len,frame_status)
-struct s_smc *smc ;
-char far *virt ;
-u_long phys ;
-int len ;
-int frame_status ;
+void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+		 int frame_status)
 {
 	struct s_smt_fp_rxd volatile *r ;
 	u_int	rbctrl ;
@@ -1460,10 +1463,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-int mac_drv_rx_frag(smc,virt,len)
-struct s_smc *smc ;
-void far *virt ;
-int len ;
+int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len)
 {
 	NDD_TRACE("RHSB",virt,len,smc->os.hwm.r.mb_pos) ;
 
@@ -1500,8 +1500,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-void mac_drv_clear_rx_queue(smc)
-struct s_smc *smc ;
+void mac_drv_clear_rx_queue(struct s_smc *smc)
 {
 	struct s_smt_fp_rxd volatile *r ;
 	struct s_smt_fp_rxd volatile *next_rxd ;
@@ -1588,12 +1587,8 @@
  *
  *	END_MANUAL_ENTRY
  */
-int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status)
-struct	s_smc *smc ;
-u_char fc ;
-int frag_count ;
-int frame_len ;
-int frame_status ;
+int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
+		int frame_status)
 {
 	NDD_TRACE("THiB",fc,frag_count,frame_len) ;
 	smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ;
@@ -1670,12 +1665,8 @@
  *
  *	END_MANUAL_ENTRY
  */
-void hwm_tx_frag(smc,virt,phys,len,frame_status)
-struct	s_smc *smc ;
-char far *virt ;
-u_long phys ;
-int len ;
-int frame_status ;
+void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+		 int frame_status)
 {
 	struct s_smt_fp_txd volatile *t ;
 	struct s_smt_tx_queue *queue ;
@@ -1780,9 +1771,7 @@
 /*
  * queues a receive for later send
  */
-static void queue_llc_rx(smc,mb)
-struct	s_smc *smc ;
-SMbuf	*mb ;
+static void queue_llc_rx(struct s_smc *smc, SMbuf *mb)
 {
 	DB_GEN("queue_llc_rx: mb = %x",(void *)mb,0,4) ;
 	smc->os.hwm.queued_rx_frames++ ;
@@ -1806,8 +1795,7 @@
 /*
  * get a SMbuf from the llc_rx_queue
  */
-static SMbuf *get_llc_rx(smc)
-struct	s_smc *smc ;
+static SMbuf *get_llc_rx(struct s_smc *smc)
 {
 	SMbuf	*mb ;
 
@@ -1823,9 +1811,7 @@
  * queues a transmit SMT MBuf during the time were the MBuf is
  * queued the TxD ring
  */
-static void queue_txd_mb(smc,mb)
-struct	s_smc *smc ;
-SMbuf	*mb ;
+static void queue_txd_mb(struct s_smc *smc, SMbuf *mb)
 {
 	DB_GEN("_rx: queue_txd_mb = %x",(void *)mb,0,4) ;
 	smc->os.hwm.queued_txd_mb++ ;
@@ -1842,8 +1828,7 @@
 /*
  * get a SMbuf from the txd_tx_queue
  */
-static SMbuf *get_txd_mb(smc)
-struct	s_smc *smc ;
+static SMbuf *get_txd_mb(struct s_smc *smc)
 {
 	SMbuf *mb ;
 
@@ -1858,10 +1843,7 @@
 /*
  *	SMT Send function
  */
-void smt_send_mbuf(smc,mb,fc)
-struct s_smc	*smc;
-SMbuf		*mb;
-int		fc;
+void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
 {
 	char far *data ;
 	int	len ;
@@ -1995,8 +1977,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-void mac_drv_clear_txd(smc)
-struct s_smc *smc ;
+void mac_drv_clear_txd(struct s_smc *smc)
 {
 	struct s_smt_tx_queue *queue ;
 	struct s_smt_fp_txd volatile *t1 ;
@@ -2087,8 +2068,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-void mac_drv_clear_tx_queue(smc)
-struct s_smc *smc ;
+void mac_drv_clear_tx_queue(struct s_smc *smc)
 {
 	struct s_smt_fp_txd volatile *t ;
 	struct s_smt_tx_queue *queue ;
@@ -2180,10 +2160,7 @@
  *
  *	END_MANUAL_ENTRY
  */
-void mac_drv_debug_lev(smc,flag,lev)
-struct s_smc *smc ;
-int flag ;
-int lev ;
+void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev)
 {
 	switch(flag) {
 	case (int)NULL:
diff -Nru a/drivers/net/skfp/hwt.c b/drivers/net/skfp/hwt.c
--- a/drivers/net/skfp/hwt.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/skfp/hwt.c	2004-06-23 19:04:25 -07:00
@@ -39,7 +39,7 @@
  * Prototypes of local functions.
  */
 /* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */
-/*static*/ void hwt_restart() ;
+/*static void hwt_restart() ; */
 
 /************************
  *
@@ -60,9 +60,7 @@
  ************************/
 #define	HWT_MAX	(65000)
 
-void hwt_start(smc, time)
-struct s_smc *smc ;
-u_long time ;
+void hwt_start(struct s_smc *smc, u_long time)
 {
 	u_short	cnt ;
 
@@ -115,8 +113,7 @@
  *	Nothing.
  *
  ************************/
-void hwt_stop(smc)
-struct s_smc *smc ;
+void hwt_stop(struct s_smc *smc)
 {
 #ifndef PCI
 	/* stop counter 0 by switching to mode 0 */
@@ -145,8 +142,7 @@
  *	Nothing.
  *
  ************************/
-void hwt_init(smc)
-struct s_smc *smc ;
+void hwt_init(struct s_smc *smc)
 {
 	smc->hw.t_start = 0 ;
 	smc->hw.t_stop	= 0 ;
@@ -169,8 +165,7 @@
  *	Nothing.
  *
  ************************/
-void hwt_restart(smc)
-struct s_smc *smc ;
+void hwt_restart(struct s_smc *smc)
 {
 	hwt_stop(smc) ;
 #ifndef	PCI
@@ -193,8 +188,7 @@
  *	The elapsed time since last start in units of 16us.
  *
  ************************/
-u_long hwt_read(smc)
-struct s_smc *smc ;
+u_long hwt_read(struct s_smc *smc)
 {
 	u_short	tr ;
 #ifndef	PCI
@@ -238,8 +232,7 @@
  *	current timer value in units of 80ns.
  *
  ************************/
-u_long hwt_quick_read(smc)
-struct s_smc *smc ;
+u_long hwt_quick_read(struct s_smc *smc)
 {
 	u_long interval ;
 	u_long time ;
@@ -267,10 +260,7 @@
  * NOTE: The fuction will return immediately, if the timer is not 
  *	 started
  ************************/
-void hwt_wait_time(smc,start,duration)
-struct s_smc *smc ;
-u_long	start ;
-long	duration ;
+void hwt_wait_time(struct s_smc *smc, u_long start, long int duration)
 {
 	long	diff ;
 	long	interval ;
@@ -312,3 +302,4 @@
 	}
 }
 #endif
+
diff -Nru a/drivers/net/skfp/lnkstat.c b/drivers/net/skfp/lnkstat.c
--- a/drivers/net/skfp/lnkstat.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/skfp/lnkstat.c	2004-06-23 19:04:27 -07:00
@@ -52,8 +52,7 @@
 
 	END_MANUAL_ENTRY()
  */
-u_long smt_get_error_word(smc)
-struct s_smc *smc ;
+u_long smt_get_error_word(struct s_smc *smc)
 {
 	u_long	st;
 
@@ -92,8 +91,7 @@
 
 	END_MANUAL_ENTRY()
  */
-u_long smt_get_event_word(smc)
-struct s_smc *smc ;
+u_long smt_get_event_word(struct s_smc *smc)
 {
 	return (u_long) 0;
 }
@@ -111,8 +109,7 @@
 
 	END_MANUAL_ENTRY()
  */
-u_long smt_get_port_event_word(smc)
-struct s_smc *smc ;
+u_long smt_get_port_event_word(struct s_smc *smc)
 {
 	return (u_long) 0;
 }
@@ -135,10 +132,7 @@
 
 	END_MANUAL_ENTRY()
  */
-int smt_read_errorlog(smc,p,len)
-struct s_smc *smc ;
-char _far *p ;
-int len ;
+int smt_read_errorlog(struct s_smc *smc, char _far *p, int len)
 {
 	int			i ;
 	int			st ;
@@ -207,3 +201,4 @@
 		er->ucode_version_level = 0x0101 ;
 	return(len) ;
 }
+
diff -Nru a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c
--- a/drivers/net/skfp/pcmplc.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/skfp/pcmplc.c	2004-06-23 19:04:25 -07:00
@@ -199,28 +199,25 @@
 			PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
 
 /* external functions */
-void	all_selection_criteria ();
+void all_selection_criteria(struct s_smc *smc);
 
 /* internal functions */
-static void pcm_fsm() ;
-static void pc_rcode_actions() ;
-static void pc_tcode_actions() ;
-static void reset_lem_struct() ;
-static void plc_init() ;
-static void sm_ph_lem_start() ;
-static void sm_ph_lem_stop() ;
-static void sm_ph_linestate() ;
-static void real_init_plc() ;
+static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd);
+static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy);
+static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy);
+static void reset_lem_struct(struct s_phy *phy);
+static void plc_init(struct s_smc *smc, int p);
+static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold);
+static void sm_ph_lem_stop(struct s_smc *smc, int np);
+static void sm_ph_linestate(struct s_smc *smc, int phy, int ls);
+static void real_init_plc(struct s_smc *smc);
 
 /*
  * SMT timer interface
  *      start PCM timer 0
  */
-static void start_pcm_timer0(smc,value,event,phy)
-struct s_smc *smc ;
-u_long value;
-int event;
-struct s_phy *phy;
+static void start_pcm_timer0(struct s_smc *smc, u_long value, int event,
+			     struct s_phy *phy)
 {
 	phy->timer0_exp = FALSE ;       /* clear timer event flag */
 	smt_timer_start(smc,&phy->pcm_timer0,value,
@@ -230,9 +227,7 @@
  * SMT timer interface
  *      stop PCM timer 0
  */
-static void stop_pcm_timer0(smc,phy)
-struct s_smc *smc ;
-struct s_phy *phy;
+static void stop_pcm_timer0(struct s_smc *smc, struct s_phy *phy)
 {
 	if (phy->pcm_timer0.tm_active)
 		smt_timer_stop(smc,&phy->pcm_timer0) ;
@@ -242,8 +237,7 @@
 	init PCM state machine (called by driver)
 	clear all PCM vars and flags
 */
-void pcm_init(smc)
-struct s_smc *smc ;
+void pcm_init(struct s_smc *smc)
 {
 	int		i ;
 	int		np ;
@@ -407,8 +401,7 @@
 	real_init_plc(smc) ;
 }
 
-void init_plc(smc)
-struct s_smc *smc ;
+void init_plc(struct s_smc *smc)
 {
 	SK_UNUSED(smc) ;
 
@@ -421,8 +414,7 @@
 	 */
 }
 
-static void real_init_plc(smc)
-struct s_smc *smc ;
+static void real_init_plc(struct s_smc *smc)
 {
 	int	p ;
 
@@ -430,9 +422,7 @@
 		plc_init(smc,p) ;
 }
 
-static void plc_init(smc,p)
-struct s_smc *smc ;
-int p;
+static void plc_init(struct s_smc *smc, int p)
 {
 	int	i ;
 #ifndef	MOT_ELM
@@ -495,10 +485,7 @@
 /*
  * control PCM state machine
  */
-static void plc_go_state(smc,p,state)
-struct s_smc *smc ;
-int p;
-int state;
+static void plc_go_state(struct s_smc *smc, int p, int state)
 {
 	HW_PTR port ;
 	int val ;
@@ -514,9 +501,7 @@
 /*
  * read current line state (called by ECM & PCM)
  */
-int sm_pm_get_ls(smc,phy)
-struct s_smc *smc ;
-int phy;
+int sm_pm_get_ls(struct s_smc *smc, int phy)
 {
 	int	state ;
 
@@ -549,10 +534,7 @@
 	return(state) ;
 }
 
-static int plc_send_bits(smc,phy,len)
-struct s_smc *smc ;
-struct s_phy *phy;
-int len;
+static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len)
 {
 	int np = phy->np ;		/* PHY index */
 	int	n ;
@@ -589,9 +571,7 @@
 /*
  * config plc muxes
  */
-void plc_config_mux(smc,mux)
-struct s_smc *smc ;
-int mux ;
+void plc_config_mux(struct s_smc *smc, int mux)
 {
 	if (smc->s.sas != SMT_DAS)
 		return ;
@@ -615,10 +595,7 @@
 		process event
 	until SM is stable
 */
-void pcm(smc,np,event)
-struct s_smc *smc ;
-const int np;
-int event;
+void pcm(struct s_smc *smc, const int np, int event)
 {
 	int	state ;
 	int	oldstate ;
@@ -697,10 +674,7 @@
 /*
  * PCM state machine
  */
-static void pcm_fsm(smc,phy,cmd)
-struct s_smc *smc ;
-struct s_phy *phy;
-int cmd;
+static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd)
 {
 	int	i ;
 	int	np = phy->np ;		/* PHY index */
@@ -1063,10 +1037,7 @@
 /*
  * force line state on a PHY output	(only in MAINT state)
  */
-static void sm_ph_linestate(smc,phy,ls)
-struct s_smc *smc ;
-int phy;
-int ls;
+static void sm_ph_linestate(struct s_smc *smc, int phy, int ls)
 {
 	int	cntrl ;
 
@@ -1095,9 +1066,7 @@
 	outpw(PLC(phy,PL_CNTRL_B),cntrl) ;
 }
 
-
-static void reset_lem_struct(phy)
-struct s_phy *phy;
+static void reset_lem_struct(struct s_phy *phy)
 {
 	struct lem_counter *lem = &phy->lem ;
 
@@ -1108,9 +1077,7 @@
 /*
  * link error monitor
  */
-static void lem_evaluate(smc,phy)
-struct s_smc *smc ;
-struct s_phy *phy;
+static void lem_evaluate(struct s_smc *smc, struct s_phy *phy)
 {
 	int ber ;
 	u_long errors ;
@@ -1210,8 +1177,7 @@
 /*
  * called by SMT to calculate LEM bit error rate
  */
-void sm_lem_evaluate(smc)
-struct s_smc *smc ;
+void sm_lem_evaluate(struct s_smc *smc)
 {
 	int np ;
 
@@ -1219,9 +1185,7 @@
 		lem_evaluate(smc,&smc->y[np]) ;
 }
 
-static void lem_check_lct(smc,phy)
-struct s_smc *smc ;
-struct s_phy	*phy ;
+static void lem_check_lct(struct s_smc *smc, struct s_phy *phy)
 {
 	struct lem_counter	*lem = &phy->lem ;
 	struct fddi_mib_p	*mib ;
@@ -1265,10 +1229,7 @@
 /*
  * LEM functions
  */
-static void sm_ph_lem_start(smc,np,threshold)
-struct s_smc *smc ;
-int np;
-int threshold;
+static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold)
 {
 	struct lem_counter *lem = &smc->y[np].lem ;
 
@@ -1286,9 +1247,7 @@
 	SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ;
 }
 
-static void sm_ph_lem_stop(smc,np)
-struct s_smc *smc ;
-int np;
+static void sm_ph_lem_stop(struct s_smc *smc, int np)
 {
 	struct lem_counter *lem = &smc->y[np].lem ;
 
@@ -1297,10 +1256,8 @@
 }
 
 /* ARGSUSED */
-void sm_pm_ls_latch(smc,phy,on_off)
-struct s_smc *smc ;
-int phy;
-int on_off;		/* en- or disable ident. ls */
+void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off)
+/* int on_off;	en- or disable ident. ls */
 {
 	SK_UNUSED(smc) ;
 
@@ -1317,10 +1274,7 @@
 /*
  * PCM pseudo code 5.1 .. 6.1
  */
-static void pc_rcode_actions(smc,bit,phy)
-struct s_smc *smc ;
-int bit;
-struct s_phy *phy;
+static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy)
 {
 	struct fddi_mib_p	*mib ;
 
@@ -1456,10 +1410,7 @@
 /*
  * PCM pseudo code 5.1 .. 6.1
  */
-static void pc_tcode_actions(smc,bit,phy)
-struct s_smc *smc ;
-const int bit;
-struct s_phy *phy;
+static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy)
 {
 	int	np = phy->np ;
 	struct fddi_mib_p	*mib ;
@@ -1638,8 +1589,7 @@
 /*
  * return status twisted (called by SMT)
  */
-int pcm_status_twisted(smc)
-struct s_smc *smc ;
+int pcm_status_twisted(struct s_smc *smc)
 {
 	int	twist = 0 ;
 	if (smc->s.sas != SMT_DAS)
@@ -1658,13 +1608,8 @@
  *	remote phy type
  *	remote mac yes/no
  */
-void pcm_status_state(smc,np,type,state,remote,mac)
-struct s_smc *smc ;
-int np;
-int *type;
-int *state;
-int *remote;
-int *mac;
+void pcm_status_state(struct s_smc *smc, int np, int *type, int *state,
+		      int *remote, int *mac)
 {
 	struct s_phy	*phy = &smc->y[np] ;
 	struct fddi_mib_p	*mib ;
@@ -1687,8 +1632,7 @@
 /*
  * return rooted station status (called by SMT)
  */
-int pcm_rooted_station(smc)
-struct s_smc *smc ;
+int pcm_rooted_station(struct s_smc *smc)
 {
 	int	n ;
 
@@ -1703,10 +1647,8 @@
 /*
  * Interrupt actions for PLC & PCM events
  */
-void plc_irq(smc,np,cmd)
-struct s_smc *smc ;
-int np;			/* PHY index */
-unsigned int cmd;
+void plc_irq(struct s_smc *smc, int np, unsigned int cmd)
+/* int np;	PHY index */
 {
 	struct s_phy *phy = &smc->y[np] ;
 	struct s_plc *plc = &phy->plc ;
@@ -1919,9 +1861,7 @@
 #endif
 }
 
-void pcm_set_lct_short(smc,n)
-struct s_smc *smc ;
-int n ;
+void pcm_set_lct_short(struct s_smc *smc, int n)
 {
 	if (n <= 0 || n > 1000)
 		return ;
@@ -1932,9 +1872,7 @@
 /*
  * fill state struct
  */
-void pcm_get_state(smc,state)
-struct s_smc *smc ;
-struct smt_state *state ;
+void pcm_get_state(struct s_smc *smc, struct smt_state *state)
 {
 	struct s_phy	*phy ;
 	struct pcm_state *pcs ;
@@ -1968,9 +1906,7 @@
 	}
 }
 
-int get_pcm_state(smc,np)
-struct s_smc *smc ;
-int np;
+int get_pcm_state(struct s_smc *smc, int np)
 {
 	int pcs ;
 
@@ -1992,9 +1928,7 @@
 	return(pcs) ;
 }
 
-char *get_linestate(smc,np)
-struct s_smc *smc ;
-int np;
+char *get_linestate(struct s_smc *smc, int np)
 {
 	char *ls = "" ;
 
@@ -2016,9 +1950,7 @@
 	return(ls) ;
 }
 
-char *get_pcmstate(smc,np)
-struct s_smc *smc ;
-int np;
+char *get_pcmstate(struct s_smc *smc, int np)
 {
 	char *pcs ;
 	
@@ -2040,8 +1972,7 @@
 	return(pcs) ;
 }
 
-void list_phy(smc)
-struct s_smc *smc ;
+void list_phy(struct s_smc *smc)
 {
 	struct s_plc *plc ;
 	int np ;
@@ -2069,8 +2000,7 @@
 
 
 #ifdef	CONCENTRATOR
-void pcm_lem_dump(smc)
-struct s_smc *smc ;
+void pcm_lem_dump(struct s_smc *smc)
 {
 	int		i ;
 	struct s_phy	*phy ;
diff -Nru a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c
--- a/drivers/net/skfp/pmf.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/skfp/pmf.c	2004-06-23 19:04:28 -07:00
@@ -32,12 +32,16 @@
 static const char ID_sccs[] = "@(#)pmf.c	1.37 97/08/04 (C) SK " ;
 #endif
 
-static int smt_authorize() ;
-static int smt_check_set_count() ;
-static const struct s_p_tab *smt_get_ptab() ;
-static int smt_mib_phys() ;
-int smt_set_para() ;
-void smt_add_para() ;
+static int smt_authorize(struct s_smc *smc, struct smt_header *sm);
+static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm);
+static const struct s_p_tab* smt_get_ptab(u_short para);
+static int smt_mib_phys(struct s_smc *smc);
+int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local,
+		 int set);
+void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
+		  int index, int local);
+static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
+				     int set, int local);
 
 #define MOFFSS(e)	((int)&(((struct fddi_mib *)0)->e))
 #define MOFFSA(e)	((int) (((struct fddi_mib *)0)->e))
@@ -280,13 +284,7 @@
 	{ 0 }
 } ;
 
-
-static SMbuf *smt_build_pmf_response() ;
-
-void smt_pmf_received_pack(smc,mb,local)
-struct s_smc *smc ;
-SMbuf *mb ;
-int local ;
+void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local)
 {
 	struct smt_header	*sm ;
 	SMbuf		*reply ;
@@ -316,13 +314,8 @@
 	}
 }
 
-extern	SMbuf	*smt_get_mbuf() ;
-
-static SMbuf *smt_build_pmf_response(smc,req,set,local)
-struct s_smc *smc ;
-struct smt_header *req ;
-int	set ;
-int	local ;
+static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
+				     int set, int local)
 {
 	SMbuf			*mb ;
 	struct smt_header	*smt ;
@@ -509,11 +502,7 @@
 	return(mb) ;
 }
 
-extern void *sm_to_para() ;
-
-static int smt_authorize(smc,sm)
-struct s_smc *smc ;
-struct smt_header *sm ;
+static int smt_authorize(struct s_smc *smc, struct smt_header *sm)
 {
 	struct smt_para	*pa ;
 	int		i ;
@@ -548,9 +537,7 @@
 	return(0) ;
 }
 
-static int smt_check_set_count(smc,sm)
-struct s_smc *smc ;
-struct smt_header *sm ;
+static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm)
 {
 	struct smt_para	*pa ;
 	struct smt_p_setcount	*sc ;
@@ -566,12 +553,8 @@
 	return(0) ;
 }
 
-void smt_add_para(smc,pcon,para,index,local)
-struct s_smc *smc ;
-struct s_pcon *pcon ;
-u_short para ;
-int index ;
-int local ;
+void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
+		  int index, int local)
 {
 	struct smt_para	*pa ;
 	const struct s_p_tab	*pt ;
@@ -1095,12 +1078,8 @@
 /*
  * set parameter
  */
-int smt_set_para(smc,pa,index,local,set)
-struct s_smc *smc ;
-struct smt_para	*pa ;
-int index ;
-int local ;
-int set ;
+int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local,
+		 int set)
 {
 #define IFSET(x)	if (set) (x)
 
@@ -1549,8 +1528,7 @@
 #endif
 }
 
-static const struct s_p_tab *smt_get_ptab(para)
-u_short para ;
+static const struct s_p_tab *smt_get_ptab(u_short para)
 {
 	const struct s_p_tab	*pt ;
 	for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++)
@@ -1558,8 +1536,7 @@
 	return(pt->p_num ? pt : 0) ;
 }
 
-static int smt_mib_phys(smc)
-struct s_smc *smc ;
+static int smt_mib_phys(struct s_smc *smc)
 {
 #ifdef	CONCENTRATOR
 	SK_UNUSED(smc) ;
@@ -1572,9 +1549,7 @@
 #endif
 }
 
-int port_to_mib(smc,p)
-struct s_smc *smc ;
-int p ;
+int port_to_mib(struct s_smc *smc, int p)
 {
 #ifdef	CONCENTRATOR
 	SK_UNUSED(smc) ;
@@ -1590,10 +1565,7 @@
 
 #ifdef	DEBUG
 #ifndef	BOOT
-void dump_smt(smc,sm,text)
-struct s_smc *smc ;
-struct smt_header *sm ;
-char *text ;
+void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text)
 {
 	int	len ;
 	struct smt_para	*pa ;
@@ -1680,9 +1652,7 @@
 	printf("-------------------------------------------------\n\n") ;
 }
 
-void dump_hex(p,len)
-char *p ;
-int len ;
+void dump_hex(char *p, int len)
 {
 	int	n = 0 ;
 	while (len--) {
diff -Nru a/drivers/net/skfp/queue.c b/drivers/net/skfp/queue.c
--- a/drivers/net/skfp/queue.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/skfp/queue.c	2004-06-23 19:04:28 -07:00
@@ -31,8 +31,7 @@
 /*
  * init event queue management
  */
-void ev_init(smc)
-struct s_smc *smc ;
+void ev_init(struct s_smc *smc)
 {
 	smc->q.ev_put = smc->q.ev_get = smc->q.ev_queue ;
 }
@@ -40,10 +39,7 @@
 /*
  * add event to queue
  */
-void queue_event(smc,class,event)
-struct s_smc *smc ;
-int class ;
-int event ;
+void queue_event(struct s_smc *smc, int class, int event)
 {
 	PRINTF("queue class %d event %d\n",class,event) ;
 	smc->q.ev_put->class = class ;
@@ -59,9 +55,7 @@
 /*
  * timer_event is called from HW timer package.
  */
-void timer_event(smc,token)
-struct s_smc *smc ;
-u_long token ;
+void timer_event(struct s_smc *smc, u_long token)
 {
 	PRINTF("timer event class %d token %d\n",
 		EV_T_CLASS(token),
@@ -76,8 +70,7 @@
  *		send command to state machine
  *	end
  */
-void ev_dispatcher(smc)
-struct s_smc *smc ;
+void ev_dispatcher(struct s_smc *smc)
 {
 	struct event_queue *ev ;	/* pointer into queue */
 	int		class ;
@@ -131,9 +124,7 @@
  *	on	0	disconnect
  *	on	1	connect
  */
-u_short smt_online(smc,on)
-struct s_smc *smc ;
-int on ;
+u_short smt_online(struct s_smc *smc, int on)
 {
 	queue_event(smc,EVENT_ECM,on ? EC_CONNECT : EC_DISCONNECT) ;
 	ev_dispatcher(smc) ;
@@ -147,10 +138,7 @@
  * dump current flag setting
  */
 #ifdef	CONCENTRATOR
-void do_smt_flag(smc,flag,value)
-struct s_smc *smc ;
-char *flag ;
-int value ;
+void do_smt_flag(struct s_smc *smc, char *flag, int value)
 {
 #ifdef	DEBUG
 	struct smt_debug	*deb;
diff -Nru a/drivers/net/skfp/rmt.c b/drivers/net/skfp/rmt.c
--- a/drivers/net/skfp/rmt.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/skfp/rmt.c	2004-06-23 19:04:28 -07:00
@@ -102,17 +102,17 @@
 /*
  * function declarations
  */
-static void rmt_fsm() ;
-static void start_rmt_timer0() ;
-static void start_rmt_timer1() ;
-static void start_rmt_timer2() ;
-static void stop_rmt_timer0() ;
-static void stop_rmt_timer1() ;
-static void stop_rmt_timer2() ;
-static void rmt_dup_actions() ;
-static void rmt_reinsert_actions() ;
-static void rmt_leave_actions() ;
-static void rmt_new_dup_actions() ;
+static void rmt_fsm(struct s_smc *smc, int cmd);
+static void start_rmt_timer0(struct s_smc *smc, u_long value, int event);
+static void start_rmt_timer1(struct s_smc *smc, u_long value, int event);
+static void start_rmt_timer2(struct s_smc *smc, u_long value, int event);
+static void stop_rmt_timer0(struct s_smc *smc);
+static void stop_rmt_timer1(struct s_smc *smc);
+static void stop_rmt_timer2(struct s_smc *smc);
+static void rmt_dup_actions(struct s_smc *smc);
+static void rmt_reinsert_actions(struct s_smc *smc);
+static void rmt_leave_actions(struct s_smc *smc);
+static void rmt_new_dup_actions(struct s_smc *smc);
 
 #ifndef SUPERNET_3
 extern void restart_trt_for_dbcn() ;
@@ -122,8 +122,7 @@
 	init RMT state machine
 	clear all RMT vars and flags
 */
-void rmt_init(smc)
-struct s_smc *smc ;
+void rmt_init(struct s_smc *smc)
 {
 	smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ;
 	smc->r.dup_addr_test = DA_NONE ;
@@ -145,9 +144,7 @@
 		process event
 	until SM is stable
 */
-void rmt(smc,event)
-struct s_smc *smc ;
-int event ;
+void rmt(struct s_smc *smc, int event)
 {
 	int	state ;
 
@@ -166,9 +163,7 @@
 /*
 	process RMT event
 */
-static void rmt_fsm(smc,cmd)
-struct s_smc *smc ;
-int cmd ;
+static void rmt_fsm(struct s_smc *smc, int cmd)
 {
 	/*
 	 * RM00-RM70 : from all states
@@ -535,8 +530,7 @@
  * (jd) RMT duplicate address actions
  * leave the ring or reinsert just as configured
  */
-static void rmt_dup_actions(smc)
-struct s_smc *smc ;
+static void rmt_dup_actions(struct s_smc *smc)
 {
 	if (smc->r.jm_flag) {
 	}
@@ -555,8 +549,7 @@
 /*
  * Reconnect to the Ring
  */
-static void rmt_reinsert_actions(smc)
-struct s_smc *smc ;
+static void rmt_reinsert_actions(struct s_smc *smc)
 {
 	queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
 	queue_event(smc,EVENT_ECM,EC_CONNECT) ;
@@ -565,8 +558,7 @@
 /*
  * duplicate address detected
  */
-static void rmt_new_dup_actions(smc)
-struct s_smc *smc ;
+static void rmt_new_dup_actions(struct s_smc *smc)
 {
 	smc->r.da_flag = TRUE ;
 	smc->r.bn_flag = FALSE ;
@@ -591,8 +583,7 @@
 /*
  * leave the ring
  */
-static void rmt_leave_actions(smc)
-struct s_smc *smc ;
+static void rmt_leave_actions(struct s_smc *smc)
 {
 	queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
 	/*
@@ -605,10 +596,7 @@
  * SMT timer interface
  *	start RMT timer 0
  */
-static void start_rmt_timer0(smc,value,event)
-struct s_smc *smc ;
-u_long value ;
-int event ;
+static void start_rmt_timer0(struct s_smc *smc, u_long value, int event)
 {
 	smc->r.timer0_exp = FALSE ;		/* clear timer event flag */
 	smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event));
@@ -618,10 +606,7 @@
  * SMT timer interface
  *	start RMT timer 1
  */
-static void start_rmt_timer1(smc,value,event)
-struct s_smc *smc ;
-u_long value ;
-int event ;
+static void start_rmt_timer1(struct s_smc *smc, u_long value, int event)
 {
 	smc->r.timer1_exp = FALSE ;	/* clear timer event flag */
 	smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event));
@@ -631,10 +616,7 @@
  * SMT timer interface
  *	start RMT timer 2
  */
-static void start_rmt_timer2(smc,value,event)
-struct s_smc *smc ;
-u_long value ;
-int event ;
+static void start_rmt_timer2(struct s_smc *smc, u_long value, int event)
 {
 	smc->r.timer2_exp = FALSE ;		/* clear timer event flag */
 	smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event));
@@ -644,8 +626,7 @@
  * SMT timer interface
  *	stop RMT timer 0
  */
-static void stop_rmt_timer0(smc)
-struct s_smc *smc ;
+static void stop_rmt_timer0(struct s_smc *smc)
 {
 	if (smc->r.rmt_timer0.tm_active)
 		smt_timer_stop(smc,&smc->r.rmt_timer0) ;
@@ -655,8 +636,7 @@
  * SMT timer interface
  *	stop RMT timer 1
  */
-static void stop_rmt_timer1(smc)
-struct s_smc *smc ;
+static void stop_rmt_timer1(struct s_smc *smc)
 {
 	if (smc->r.rmt_timer1.tm_active)
 		smt_timer_stop(smc,&smc->r.rmt_timer1) ;
@@ -666,9 +646,9 @@
  * SMT timer interface
  *	stop RMT timer 2
  */
-static void stop_rmt_timer2(smc)
-struct s_smc *smc ;
+static void stop_rmt_timer2(struct s_smc *smc)
 {
 	if (smc->r.rmt_timer2.tm_active)
 		smt_timer_stop(smc,&smc->r.rmt_timer2) ;
 }
+
diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
--- a/drivers/net/skfp/skfddi.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/skfp/skfddi.c	2004-06-23 19:04:25 -07:00
@@ -131,20 +131,10 @@
 		       int frag_count);
 int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
 		    int la_len);
-void smt_timer_poll(struct s_smc *smc);
-void ring_status_indication(struct s_smc *smc, u_long status);
-unsigned long smt_get_time(void);
-void smt_stat_counter(struct s_smc *smc, int stat);
-void cfm_state_change(struct s_smc *smc, int c_state);
-void ecm_state_change(struct s_smc *smc, int e_state);
-void pcm_state_change(struct s_smc *smc, int plc, int p_state);
-void rmt_state_change(struct s_smc *smc, int r_state);
-void drv_reset_indication(struct s_smc *smc);
 void dump_data(unsigned char *Data, int length);
 
-
 // External functions from the hardware module
-extern u_int mac_drv_check_space();
+extern u_int mac_drv_check_space(void);
 extern void read_address(struct s_smc *smc, u_char * mac_addr);
 extern void card_stop(struct s_smc *smc);
 extern int mac_drv_init(struct s_smc *smc);
@@ -157,9 +147,7 @@
 extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys,
 			int len, int frame_status);
 extern void mac_drv_rx_mode(struct s_smc *smc, int mode);
-extern void mac_drv_clear_tx_queue(struct s_smc *smc);
 extern void mac_drv_clear_rx_queue(struct s_smc *smc);
-extern void mac_clear_multicast(struct s_smc *smc);
 extern void enable_tx_irq(struct s_smc *smc, u_short queue);
 extern void mac_drv_clear_txd(struct s_smc *smc);
 
@@ -921,8 +909,7 @@
 				dmi = dev->mc_list;
 
 				for (i = 0; i < dev->mc_count; i++) {
-					mac_add_multicast(smc,
-							  dmi->dmi_addr, 1);
+					mac_add_multicast(smc, dmi->dmi_addr, 1);
 					PRINTK(KERN_INFO "ENABLE MC ADDRESS:");
 					PRINTK(" %02x %02x %02x ",
 					       dmi->dmi_addr[0],
diff -Nru a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
--- a/drivers/net/skfp/smt.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/skfp/smt.c	2004-06-23 19:04:28 -07:00
@@ -62,68 +62,63 @@
 /*
  * external functions
  */
-int pcm_status_twisted() ;
-void pcm_status_state() ;
-int pcm_status_type() ;
+int pcm_status_twisted(struct s_smc *smc);
 
-extern SMbuf *smt_get_mbuf() ;
-
-#define EXPORT_PMF
 /*
  * function prototypes
  */
-u_long smt_get_tid() ;
-EXPORT_PMF SMbuf *smt_build_frame() ;
-EXPORT_PMF void *sm_to_para() ;
 #ifdef	LITTLE_ENDIAN
-static int smt_swap_short() ;
+static int smt_swap_short(u_short s);
 #endif
-static int mac_index() ;
-static int phy_index() ;
-static int mac_con_resource_index() ;
-static int phy_con_resource_index() ;
-EXPORT_PMF void smt_send_frame() ;
-EXPORT_PMF void smt_set_timestamp() ;
-static void smt_send_rdf() ;
-static void smt_send_nif() ;
-static void smt_send_ecf() ;
-static void smt_echo_test() ;
-static void smt_send_sif_config() ;
-static void smt_send_sif_operation() ;
-EXPORT_PMF void smt_swap_para() ;
+static int mac_index(struct s_smc *smc, int mac);
+static int phy_index(struct s_smc *smc, int phy);
+static int mac_con_resource_index(struct s_smc *smc, int mac);
+static int phy_con_resource_index(struct s_smc *smc, int phy);
+static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
+			 int local);
+static void smt_send_nif(struct s_smc *smc, struct fddi_addr *dest, int fc,
+			 u_long tid, int type, int local);
+static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,
+                         u_long tid, int type, int len);
+static void smt_echo_test(struct s_smc *smc, int dna);
+static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,
+				u_long tid, int local);
+static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,
+				   u_long tid, int local);
 #ifdef LITTLE_ENDIAN
-static void smt_string_swap() ;
+static void smt_string_swap(void);
 #endif
-static void smt_add_frame_len() ;
-static void smt_fill_una() ;
-static void smt_fill_sde() ;
-static void smt_fill_state() ;
-static void smt_fill_timestamp() ;
-static void smt_fill_policy() ;
-static void smt_fill_latency() ;
-static void smt_fill_neighbor() ;
-static int  smt_fill_path() ;
-static void smt_fill_mac_status() ;
-static void smt_fill_lem() ;
-static void smt_fill_version() ;
-static void smt_fill_fsc() ;
-static void smt_fill_mac_counter() ;
-static void smt_fill_mac_fnc() ;
-static void smt_fill_manufacturer() ;
-static void smt_fill_user() ;
-static void smt_fill_setcount() ;
-static void smt_fill_echo() ;
-int smt_check_para() ;
+static void smt_add_frame_len(SMbuf *mb, int len);
+static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una);
+static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde);
+static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state);
+static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts);
+static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy);
+static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency);
+static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor);
+static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path);
+static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st);
+static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy);
+static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers);
+static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc);
+static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc);
+static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc);
+static void smt_fill_manufacturer(struct s_smc *smc, 
+				  struct smp_p_manufacturer *man);
+static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user);
+static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount);
+static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,
+			  int len);
 
-void smt_clear_una_dna() ;
-static void smt_clear_old_una_dna() ;
+void smt_clear_una_dna(struct s_smc *smc);
+static void smt_clear_old_una_dna(struct s_smc *smc);
 #ifdef	CONCENTRATOR
-static int entity_to_index() ;
+static int entity_to_index(void);
 #endif
-static void update_dac() ;
-static int div_ratio() ;
+static void update_dac(struct s_smc *smc, int report);
+static int div_ratio(u_long upper, u_long lower);
 #ifdef  USE_CAN_ADDR
-void	hwm_conv_can() ;
+void	hwm_conv_can(struct s_smc *smc, char *data, int len);
 #else
 #define		hwm_conv_can(smc,data,len)
 #endif
@@ -136,8 +131,7 @@
 /*
  * init SMT agent
  */
-void smt_agent_init(smc)
-struct s_smc *smc ;
+void smt_agent_init(struct s_smc *smc)
 {
 	int		i ;
 
@@ -183,17 +177,16 @@
  *	check tvu & tvd
  * end
  */
-void smt_agent_task(smc)
-struct s_smc *smc ;
+void smt_agent_task(struct s_smc *smc)
 {
 	smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
 		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
 	DB_SMT("SMT agent task\n",0,0) ;
 }
 
-void smt_please_reconnect(smc,reconn_time)
-struct s_smc	*smc ;		/* Pointer to SMT context */
-int		reconn_time ;	/* Wait for reconnect time in seconds */
+void smt_please_reconnect(struct s_smc *smc, int reconn_time)
+/* struct s_smc	*smc;  Pointer to SMT context */
+/* int reconn_time;    Wait for reconnect time in seconds */
 {
 	/*
 	 * The please reconnect variable is used as a timer.
@@ -210,9 +203,7 @@
 }
 
 #ifndef SMT_REAL_TOKEN_CT
-void smt_emulate_token_ct(smc, mac_index)
-struct s_smc	*smc;
-int		mac_index;
+void smt_emulate_token_ct(struct s_smc *smc, int mac_index)
 {
 	u_long	count;
 	u_long	time;
@@ -239,9 +230,7 @@
 #endif
 
 /*ARGSUSED1*/
-void smt_event(smc,event)
-struct s_smc *smc ;
-int event ;
+void smt_event(struct s_smc *smc, int event)
 {
 	u_long		time ;
 #ifndef SMT_REAL_TOKEN_CT
@@ -457,9 +446,7 @@
 		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
 }
 
-static int div_ratio(upper,lower)
-u_long upper ;
-u_long lower ;
+static int div_ratio(u_long upper, u_long lower)
 {
 	if ((upper<<16L) < upper)
 		upper = 0xffff0000L ;
@@ -475,10 +462,8 @@
 /*
  * receive packet handler
  */
-void smt_received_pack(smc,mb,fs)
-struct s_smc *smc ;
-SMbuf *mb ;
-int fs ;			/* frame status */
+void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs)
+/* int fs;  frame status */
 {
 	struct smt_header	*sm ;
 	int			local ;
@@ -823,9 +808,7 @@
 	smt_free_mbuf(smc,mb) ;
 }
 
-static void update_dac(smc,report)
-struct s_smc *smc ;
-int report ;
+static void update_dac(struct s_smc *smc, int report)
 {
 	int	cond ;
 
@@ -843,11 +826,9 @@
  *	set station ID
  *	send frame
  */
-EXPORT_PMF void smt_send_frame(smc,mb,fc,local)
-struct s_smc *smc ;
-SMbuf *mb ;			/* buffer to send */
-int fc ;			/* FC value */
-int local ;
+void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local)
+/* SMbuf *mb;	buffer to send */
+/* int fc;	FC value */
 {
 	struct smt_header	*sm ;
 
@@ -868,12 +849,11 @@
 /*
  * generate and send RDF
  */
-static void smt_send_rdf(smc,rej,fc,reason,local)
-struct s_smc *smc ;
-SMbuf	*rej ;			/* mbuf of offending frame */
-int	fc ;			/* FC of denied frame */
-int reason ;			/* reason code */
-int local ;
+static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
+			 int local)
+/* SMbuf *rej;	mbuf of offending frame */
+/* int fc;	FC of denied frame */
+/* int reason;	reason code */
 {
 	SMbuf	*mb ;
 	struct smt_header	*sm ;	/* header of offending frame */
@@ -946,13 +926,12 @@
 /*
  * generate and send NIF
  */
-static void smt_send_nif(smc,dest,fc,tid,type,local)
-struct s_smc *smc ;
-struct fddi_addr *dest ;		/* dest address */
-int fc ;				/* frame control */
-u_long tid ;				/* transaction id */
-int type ;				/* frame type */
-int local ;
+static void smt_send_nif(struct s_smc *smc, struct fddi_addr *dest, int fc,
+			 u_long tid, int type, int local)
+/* struct fddi_addr *dest;	dest address */
+/* int fc;			frame control */
+/* u_long tid;			transaction id */
+/* int type;			frame type */
 {
 	struct smt_nif	*nif ;
 	SMbuf		*mb ;
@@ -976,9 +955,7 @@
 /*
  * send NIF request (test purpose)
  */
-static void smt_send_nif_request(smc,dest)
-struct s_smc *smc ;
-struct fddi_addr *dest ;
+static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest)
 {
 	smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ;
 	smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST],
@@ -988,10 +965,8 @@
 /*
  * send ECF request (test purpose)
  */
-static void smt_send_ecf_request(smc,dest,len)
-struct s_smc *smc ;
-struct fddi_addr *dest ;
-int len ;
+static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest,
+				 int len)
 {
 	smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ;
 	smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF],
@@ -1002,9 +977,7 @@
 /*
  * echo test
  */
-static void smt_echo_test(smc,dna)
-struct s_smc *smc ;
-int dna ;
+static void smt_echo_test(struct s_smc *smc, int dna)
 {
 	u_long	tid ;
 
@@ -1019,13 +992,13 @@
 /*
  * generate and send ECF
  */
-static void smt_send_ecf(smc,dest,fc,tid,type,len)
-struct s_smc *smc ;
-struct fddi_addr *dest ;		/* dest address */
-int fc ;				/* frame control */
-u_long tid ;				/* transaction id */
-int type ;				/* frame type */
-int len ;				/* frame length */
+static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,
+			 u_long tid, int type, int len)
+/* struct fddi_addr *dest;	dest address */
+/* int fc;			frame control */
+/* u_long tid;			transaction id */
+/* int type;			frame type */
+/* int len;			frame length */
 {
 	struct smt_ecf	*ecf ;
 	SMbuf		*mb ;
@@ -1045,11 +1018,10 @@
  * generate and send SIF config response
  */
 
-static void smt_send_sif_config(smc,dest,tid,local)
-struct s_smc *smc ;
-struct fddi_addr *dest ;		/* dest address */
-u_long tid ;				/* transaction id */
-int local ;
+static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,
+				u_long tid, int local)
+/* struct fddi_addr *dest;	dest address */
+/* u_long tid;			transaction id */
 {
 	struct smt_sif_config	*sif ;
 	SMbuf			*mb ;
@@ -1079,11 +1051,10 @@
  * generate and send SIF operation response
  */
 
-static void smt_send_sif_operation(smc,dest,tid,local)
-struct s_smc *smc ;
-struct fddi_addr *dest ;		/* dest address */
-u_long tid ;				/* transaction id */
-int local ;
+static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,
+				   u_long tid, int local)
+/* struct fddi_addr *dest;	dest address */
+/* u_long tid;			transaction id */
 {
 	struct smt_sif_operation *sif ;
 	SMbuf			*mb ;
@@ -1128,11 +1099,8 @@
 /*
  * get and initialize SMT frame
  */
-EXPORT_PMF SMbuf *smt_build_frame(smc,class,type,length)
-struct s_smc *smc ;
-int class ;
-int type ;
-int length ;
+SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
+				  int length)
 {
 	SMbuf			*mb ;
 	struct smt_header	*smt ;
@@ -1167,9 +1135,7 @@
 	return(mb) ;
 }
 
-static void smt_add_frame_len(mb,len)
-SMbuf *mb ;
-int len ;
+static void smt_add_frame_len(SMbuf *mb, int len)
 {
 	struct smt_header	*smt ;
 
@@ -1183,9 +1149,7 @@
 /*
  * fill values in UNA parameter
  */
-static void smt_fill_una(smc,una)
-struct s_smc *smc ;
-struct smt_p_una *una ;
+static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una)
 {
 	SMTSETPARA(una,SMT_P_UNA) ;
 	una->una_pad = 0 ;
@@ -1195,9 +1159,7 @@
 /*
  * fill values in SDE parameter
  */
-static void smt_fill_sde(smc,sde)
-struct s_smc *smc ;
-struct smt_p_sde *sde ;
+static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde)
 {
 	SMTSETPARA(sde,SMT_P_SDE) ;
 	sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ;
@@ -1213,9 +1175,7 @@
 /*
  * fill in values in station state parameter
  */
-static void smt_fill_state(smc,state)
-struct s_smc *smc ;
-struct smt_p_state *state ;
+static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state)
 {
 	int	top ;
 	int	twist ;
@@ -1255,18 +1215,14 @@
 /*
  * fill values in timestamp parameter
  */
-static void smt_fill_timestamp(smc,ts)
-struct s_smc *smc ;
-struct smt_p_timestamp *ts ;
+static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts)
 {
 
 	SMTSETPARA(ts,SMT_P_TIMESTAMP) ;
 	smt_set_timestamp(smc,ts->ts_time) ;
 }
 
-EXPORT_PMF void smt_set_timestamp(smc,p)
-struct s_smc *smc ;
-u_char *p ;
+void smt_set_timestamp(struct s_smc *smc, u_char *p)
 {
 	u_long	time ;
 	u_long	utime ;
@@ -1300,9 +1256,7 @@
 /*
  * fill values in station policy parameter
  */
-static void smt_fill_policy(smc,policy)
-struct s_smc *smc ;
-struct smt_p_policy *policy ;
+static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy)
 {
 	int	i ;
 	u_char	*map ;
@@ -1333,9 +1287,7 @@
 /*
  * fill values in latency equivalent parameter
  */
-static void smt_fill_latency(smc,latency)
-struct s_smc *smc ;
-struct smt_p_latency *latency ;
+static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency)
 {
 	SMTSETPARA(latency,SMT_P_LATENCY) ;
 
@@ -1358,9 +1310,7 @@
 /*
  * fill values in MAC neighbors parameter
  */
-static void smt_fill_neighbor(smc,neighbor)
-struct s_smc *smc ;
-struct smt_p_neighbor *neighbor ;
+static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor)
 {
 	SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ;
 
@@ -1379,9 +1329,7 @@
 #define ALLPHYS	((smc->s.sas == SMT_SAS) ? 1 : 2)
 #endif
 
-static int smt_fill_path(smc,path)
-struct s_smc *smc ;
-struct smt_p_path *path ;
+static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path)
 {
 	SK_LOC_DECL(int,type) ;
 	SK_LOC_DECL(int,state) ;
@@ -1429,9 +1377,7 @@
 /*
  * fill values in mac status
  */
-static void smt_fill_mac_status(smc,st)
-struct s_smc *smc ;
-struct smt_p_mac_status *st ;
+static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st)
 {
 	SMTSETPARA(st,SMT_P_MAC_STATUS) ;
 
@@ -1458,11 +1404,7 @@
 /*
  * fill values in LEM status
  */
-
-static void smt_fill_lem(smc,lem,phy)
-struct s_smc *smc ;
-struct smt_p_lem *lem ;
-int phy ;
+static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy)
 {
 	struct fddi_mib_p	*mib ;
 
@@ -1484,9 +1426,7 @@
 /*
  * fill version parameter
  */
-static void smt_fill_version(smc,vers)
-struct s_smc *smc ;
-struct smt_p_version *vers ;
+static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers)
 {
 	SK_UNUSED(smc) ;
 	SMTSETPARA(vers,SMT_P_VERSION) ;
@@ -1505,9 +1445,7 @@
  * note: this para 200B is NOT in swap table, because it's also set in
  * PMF add_para
  */
-static void smt_fill_fsc(smc,fsc)
-struct s_smc *smc ;
-struct smt_p_fsc *fsc ;
+static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc)
 {
 	SK_UNUSED(smc) ;
 	SMTSETPARA(fsc,SMT_P_FSC) ;
@@ -1527,9 +1465,7 @@
 /*
  * fill mac counter field
  */
-static void smt_fill_mac_counter(smc,mc)
-struct s_smc *smc ;
-struct smt_p_mac_counter *mc ;
+static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc)
 {
 	SMTSETPARA(mc,SMT_P_MAC_COUNTER) ;
 	mc->mc_mib_index = INDEX_MAC ;
@@ -1541,9 +1477,7 @@
 /*
  * fill mac frame not copied counter
  */
-static void smt_fill_mac_fnc(smc,fnc)
-struct s_smc *smc ;
-struct smt_p_mac_fnc *fnc ;
+static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc)
 {
 	SMTSETPARA(fnc,SMT_P_MAC_FNC) ;
 	fnc->nc_mib_index = INDEX_MAC ;
@@ -1555,9 +1489,8 @@
 /*
  * fill manufacturer field
  */
-static void smt_fill_manufacturer(smc,man)
-struct s_smc *smc ;
-struct smp_p_manufacturer *man ;
+static void smt_fill_manufacturer(struct s_smc *smc, 
+				  struct smp_p_manufacturer *man)
 {
 	SMTSETPARA(man,SMT_P_MANUFACTURER) ;
 	memcpy((char *) man->mf_data,
@@ -1568,9 +1501,7 @@
 /*
  * fill user field
  */
-static void smt_fill_user(smc,user)
-struct s_smc *smc ;
-struct smp_p_user *user ;
+static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user)
 {
 	SMTSETPARA(user,SMT_P_USER) ;
 	memcpy((char *) user->us_data,
@@ -1578,14 +1509,10 @@
 		sizeof(user->us_data)) ;
 }
 
-
-
 /*
  * fill set count
  */
-static void smt_fill_setcount(smc,setcount)
-struct s_smc *smc ;
-struct smt_p_setcount *setcount ;
+static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount)
 {
 	SK_UNUSED(smc) ;
 	SMTSETPARA(setcount,SMT_P_SETCOUNT) ;
@@ -1597,13 +1524,9 @@
 /*
  * fill echo data
  */
-static void smt_fill_echo(smc,echo,seed,len)
-struct s_smc *smc ;
-struct smt_p_echo *echo ;
-u_long seed ;
-int len ;
+static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,
+			  int len)
 {
-
 	u_char	*p ;
 
 	SK_UNUSED(smc) ;
@@ -1619,22 +1542,19 @@
  * clear DNA and UNA
  * called from CFM if configuration changes
  */
-void smt_clear_una_dna(smc)
-struct s_smc *smc ;
+void smt_clear_una_dna(struct s_smc *smc)
 {
 	smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
 	smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
 }
 
-static void smt_clear_old_una_dna(smc)
-struct s_smc *smc ;
+static void smt_clear_old_una_dna(struct s_smc *smc)
 {
 	smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ;
 	smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ;
 }
 
-u_long smt_get_tid(smc)
-struct s_smc *smc ;
+u_long smt_get_tid(struct s_smc *smc)
 {
 	u_long	tid ;
 	while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0)
@@ -1723,10 +1643,8 @@
 
 #define N_SMT_PLEN	(sizeof(smt_pdef)/sizeof(smt_pdef[0]))
 
-int smt_check_para(smc,sm,list)
-struct s_smc *smc ;
-struct smt_header	*sm ;
-const u_short		list[] ;
+int smt_check_para(struct s_smc *smc, struct smt_header	*sm,
+		   const u_short list[])
 {
 	const u_short		*p = list ;
 	while (*p) {
@@ -1739,10 +1657,7 @@
 	return(0) ;
 }
 
-EXPORT_PMF void *sm_to_para(smc,sm,para)
-struct s_smc *smc ;
-struct smt_header	*sm ;
-int para ;
+void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para)
 {
 	char	*p ;
 	int	len ;
@@ -1773,9 +1688,7 @@
 	return(0) ;
 }
 
-int is_my_addr(smc,addr)
-struct s_smc *smc ;
-struct fddi_addr *addr ;
+int is_my_addr(struct s_smc *smc, struct fddi_addr *addr)
 {
 	return(*(short *)(&addr->a[0]) ==
 		*(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0])
@@ -1785,31 +1698,26 @@
 		*(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ;
 }
 
-int is_zero(addr)
-struct fddi_addr *addr ;
+int is_zero(struct fddi_addr *addr)
 {
 	return(*(short *)(&addr->a[0]) == 0 &&
 	       *(short *)(&addr->a[2]) == 0 &&
 	       *(short *)(&addr->a[4]) == 0 ) ;
 }
 
-int is_broadcast(addr)
-struct fddi_addr *addr ;
+int is_broadcast(struct fddi_addr *addr)
 {
 	return(*(u_short *)(&addr->a[0]) == 0xffff &&
 	       *(u_short *)(&addr->a[2]) == 0xffff &&
 	       *(u_short *)(&addr->a[4]) == 0xffff ) ;
 }
 
-int is_individual(addr)
-struct fddi_addr *addr ;
+int is_individual(struct fddi_addr *addr)
 {
 	return(!(addr->a[0] & GROUP_ADDR)) ;
 }
 
-int is_equal(addr1,addr2)
-struct fddi_addr *addr1 ;
-struct fddi_addr *addr2 ;
+int is_equal(struct fddi_addr *addr1, struct fddi_addr *addr2)
 {
 	return(*(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
 	       *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&
@@ -1821,9 +1729,7 @@
 /*
  * send ANTC data test frame
  */
-void fddi_send_antc(smc,dest)
-struct s_smc *smc ;
-struct fddi_addr *dest ;
+void fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest)
 {
 	SK_UNUSED(smc) ;
 	SK_UNUSED(dest) ;
@@ -1850,8 +1756,7 @@
 #ifdef	DEBUG
 #define hextoasc(x)	"0123456789abcdef"[x]
 
-char *addr_to_string(addr)
-struct fddi_addr *addr ;
+char *addr_to_string(struct fddi_addr *addr)
 {
 	int	i ;
 	static char	string[6*3] = "****" ;
@@ -1867,9 +1772,7 @@
 #endif
 
 #ifdef	AM29K
-smt_ifconfig(argc,argv)
-int argc ;
-char *argv[] ;
+smt_ifconfig(int argc, char *argv[])
 {
 	if (argc >= 2 && !strcmp(argv[0],"opt_bypass") &&
 	    !strcmp(argv[1],"yes")) {
@@ -1883,9 +1786,7 @@
 /*
  * return static mac index
  */
-static int mac_index(smc,mac)
-struct s_smc *smc ;
-int mac ;
+static int mac_index(struct s_smc *smc, int mac)
 {
 	SK_UNUSED(mac) ;
 #ifdef	CONCENTRATOR
@@ -1899,9 +1800,7 @@
 /*
  * return static phy index
  */
-static int phy_index(smc,phy)
-struct s_smc *smc ;
-int phy ;
+static int phy_index(struct s_smc *smc, int phy)
 {
 	SK_UNUSED(smc) ;
 	return(phy+1);
@@ -1910,9 +1809,7 @@
 /*
  * return dynamic mac connection resource index
  */
-static int mac_con_resource_index(smc,mac)
-struct s_smc *smc ;
-int mac ;
+static int mac_con_resource_index(struct s_smc *smc, int mac)
 {
 #ifdef	CONCENTRATOR
 	SK_UNUSED(smc) ;
@@ -1936,9 +1833,7 @@
 /*
  * return dynamic phy connection resource index
  */
-static int phy_con_resource_index(smc,phy)
-struct s_smc *smc ;
-int phy ;
+static int phy_con_resource_index(struct s_smc *smc, int phy)
 {
 #ifdef	CONCENTRATOR
 	return(entity_to_index(smc,cem_get_downstream(smc,ENTITY_PHY(phy)))) ;
@@ -1960,9 +1855,7 @@
 }
 
 #ifdef	CONCENTRATOR
-static int entity_to_index(smc,e)
-struct s_smc *smc ;
-int e ;
+static int entity_to_index(struct s_smc *smc, int e)
 {
 	if (e == ENTITY_MAC)
 		return(mac_index(smc,1)) ;
@@ -1972,16 +1865,13 @@
 #endif
 
 #ifdef	LITTLE_ENDIAN
-static int smt_swap_short(s)
-u_short s ;
+static int smt_swap_short(u_short s)
 {
 	return(((s>>8)&0xff)|((s&0xff)<<8)) ;
 }
 
-void smt_swap_para(sm,len,direction)
-struct smt_header *sm ;
-int len ;
-int direction ;			/* 0 encode 1 decode */
+void smt_swap_para(struct smt_header *sm, int len, int direction)
+/* int direction;	0 encode 1 decode */
 {
 	struct smt_para	*pa ;
 	const  struct smt_pdef	*pd ;
@@ -2027,10 +1917,7 @@
 	}
 }
 
-static void smt_string_swap(data,format,len)
-char *data ;
-const char *format ;
-int len ;
+static void smt_string_swap(char *data, const char *format, int len)
 {
 	const char	*open_paren = 0 ;
 	int	x ;
@@ -2081,10 +1968,8 @@
 	}
 }
 #else
-void smt_swap_para(sm,len,direction)
-struct smt_header *sm ;
-int len ;
-int direction ;			/* 0 encode 1 decode */
+void smt_swap_para(struct smt_header *sm, int len, int direction)
+/* int direction;	0 encode 1 decode */
 {
 	SK_UNUSED(sm) ;
 	SK_UNUSED(len) ;
@@ -2095,11 +1980,7 @@
 /*
  * PMF actions
  */
-int smt_action(smc,class,code,index)
-struct s_smc *smc ;
-int class ;
-int code ;
-int index ;
+int smt_action(struct s_smc *smc, int class, int code, int index)
 {
 	int	event ;
 	int	port ;
@@ -2190,9 +2071,7 @@
  *		set reconnect
  *	end
  */
-void smt_change_t_neg(smc,tneg)
-struct s_smc *smc ;
-u_long tneg ;
+void smt_change_t_neg(struct s_smc *smc, u_long tneg)
 {
 	smc->mib.a[PATH0].fddiPATHMaxT_Req = tneg ;
 
@@ -2207,10 +2086,7 @@
  * canonical conversion of <len> bytes beginning form *data
  */
 #ifdef  USE_CAN_ADDR
-void hwm_conv_can(smc,data,len)
-struct s_smc *smc ;
-char *data ;
-int len ;
+void hwm_conv_can(struct s_smc *smc, char *data, int len)
 {
 	int i ;
 
@@ -2223,3 +2099,4 @@
 #endif
 
 #endif	/* no SLIM_SMT */
+
diff -Nru a/drivers/net/skfp/smtdef.c b/drivers/net/skfp/smtdef.c
--- a/drivers/net/skfp/smtdef.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/skfp/smtdef.c	2004-06-23 19:04:25 -07:00
@@ -72,13 +72,11 @@
 #define DEFAULT_LCT_EXTEND	50
 
 /* Forward declarations */
-extern  void	smt_reset_defaults ();
-static	void	smt_init_mib ();
+void smt_reset_defaults(struct s_smc *smc, int level);
+static void smt_init_mib(struct s_smc *smc, int level);
+static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper);
 
-static int set_min_max() ;
-
-void smt_set_defaults(smc)
-struct s_smc *smc ;
+void smt_set_defaults(struct s_smc *smc)
 {
 	smt_reset_defaults(smc,0) ;
 }
@@ -86,9 +84,7 @@
 #define MS2BCLK(x)	((x)*12500L)
 #define US2BCLK(x)	((x)*1250L)
 
-void smt_reset_defaults(smc,level)
-struct s_smc *smc ;
-int level ;
+void smt_reset_defaults(struct s_smc *smc, int level)
 {
 	struct smt_config	*smt ;
 	int			i ;
@@ -170,9 +166,7 @@
 /*	 01234567890123456789012345678901	*/
 	"xxxSK-NET FDDI SMT 7.3 - V2.8.8" ;
 
-static void smt_init_mib(smc,level)
-struct s_smc *smc ;
-int level ;
+static void smt_init_mib(struct s_smc *smc, int level)
 {
 	struct fddi_mib		*mib ;
 	struct fddi_mib_p	*pm ;
@@ -292,8 +286,7 @@
 	(void) smt_set_mac_opvalues(smc) ;
 }
 
-int smt_set_mac_opvalues(smc)
-struct s_smc *smc ;
+int smt_set_mac_opvalues(struct s_smc *smc)
 {
 	int	st ;
 	int	st2 ;
@@ -318,8 +311,7 @@
 	return(st) ;
 }
 
-void smt_fixup_mib(smc)
-struct s_smc *smc ;
+void smt_fixup_mib(struct s_smc *smc)
 {
 #ifdef	CONCENTRATOR
 	switch (smc->s.sas) {
@@ -355,11 +347,7 @@
  *	use mib
  * NOTE : numbers are negative, negate comparison !
  */
-static int set_min_max(maxflag,mib,limit,oper)
-int maxflag ;
-u_long mib ;
-u_long limit ;
-u_long *oper ;
+static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper)
 {
 	u_long	old ;
 	old = *oper ;
@@ -369,3 +357,4 @@
 		*oper = mib ;
 	return(old != *oper) ;
 }
+
diff -Nru a/drivers/net/skfp/smtinit.c b/drivers/net/skfp/smtinit.c
--- a/drivers/net/skfp/smtinit.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/skfp/smtinit.c	2004-06-23 19:04:28 -07:00
@@ -27,7 +27,7 @@
 static const char ID_sccs[] = "@(#)smtinit.c	1.15 97/05/06 (C) SK " ;
 #endif
 
-extern void init_fddi_driver() ;
+void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);
 
 /* define global debug variable */
 #if defined(DEBUG) && !defined(DEBUG_BRD)
@@ -48,8 +48,7 @@
  * Can not be called in smt_reset_defaults, because it is not sure that
  * the OEM ID is already defined.
  */
-static void set_oem_spec_val(smc)
-struct s_smc *smc ;
+static void set_oem_spec_val(struct s_smc *smc)
 {
 	struct fddi_mib *mib ;
 
@@ -66,9 +65,8 @@
 /*
  * Init SMT
  */
-int init_smt(smc,mac_addr)
-struct s_smc *smc ;
-u_char *mac_addr ;		/* canonical address or NULL */
+int init_smt(struct s_smc *smc, u_char *mac_addr)
+/* u_char *mac_addr;	canonical address or NULL */
 {
 	int	p ;
 
@@ -124,3 +122,4 @@
 
 	return(0) ;
 }
+
diff -Nru a/drivers/net/skfp/smtparse.c b/drivers/net/skfp/smtparse.c
--- a/drivers/net/skfp/smtparse.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/skfp/smtparse.c	2004-06-23 19:04:27 -07:00
@@ -82,8 +82,9 @@
 /*
  * local function declarations
  */
-static u_long parse_num() ;
-static int parse_word() ;
+static u_long parse_num(int type, char _far *value, char *v, u_long mn,
+			u_long mx, int scale);
+static int parse_word(char *buf, char _far *text);
 
 #ifdef SIM
 #define DB_MAIN(a,b,c)	printf(a,b,c)
@@ -117,11 +118,8 @@
  *
  * END_MANUAL_ENTRY()
  */
-int smt_parse_arg(smc,keyword,type,value)
-struct s_smc *smc ;
-char _far *keyword ;
-int type ;
-char _far *value ;
+int smt_parse_arg(struct s_smc *smc, char _far *keyword, int type,
+		  char _far *value)
 {
 	char		keybuf[MAX_VAL+1];
 	char		valbuf[MAX_VAL+1];
@@ -287,9 +285,7 @@
 	return(0) ;
 }
 
-static int parse_word(buf,text)
-char *buf ;
-char _far *text ;
+static int parse_word(char *buf, char _far *text)
 {
 	char		c ;
 	char 		*p ;
@@ -364,13 +360,8 @@
 	return(0) ;
 }
 
-static u_long parse_num(type,value,v,mn,mx,scale)
-int type ;
-char _far *value ;
-char *v ;
-u_long mn ;
-u_long mx ;
-int scale ;
+static u_long parse_num(int type, char _far *value, char *v, u_long mn,
+			u_long mx, int scale)
 {
 	u_long	x = 0 ;
 	char	c ;
@@ -473,3 +464,4 @@
 	exit(0) ;
 }
 #endif
+
diff -Nru a/drivers/net/skfp/smttimer.c b/drivers/net/skfp/smttimer.c
--- a/drivers/net/skfp/smttimer.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/skfp/smttimer.c	2004-06-23 19:04:26 -07:00
@@ -26,18 +26,9 @@
 static const char ID_sccs[] = "@(#)smttimer.c	2.4 97/08/04 (C) SK " ;
 #endif
 
-/*
- * external function declarations
- */
-extern u_long hwt_read() ;
-extern void hwt_stop() ;
-extern void hwt_start() ;
+static void timer_done(struct s_smc *smc, int restart);
 
-static void timer_done() ;
-
-
-void smt_timer_init(smc)
-struct s_smc *smc ;
+void smt_timer_init(struct s_smc *smc)
 {
 	smc->t.st_queue = 0 ;
 	smc->t.st_fast.tm_active = FALSE ;
@@ -45,9 +36,7 @@
 	hwt_init(smc) ;
 }
 
-void smt_timer_stop(smc,timer)
-struct s_smc *smc ;
-struct smt_timer *timer ;
+void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
 {
 	struct smt_timer	**prev ;
 	struct smt_timer	*tm ;
@@ -70,11 +59,8 @@
 	}
 }
 
-void smt_timer_start(smc,timer,time,token)
-struct s_smc *smc ;
-struct smt_timer *timer ;
-u_long		time ;
-u_long		token ;
+void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
+		     u_long token)
 {
 	struct smt_timer	**prev ;
 	struct smt_timer	*tm ;
@@ -121,21 +107,17 @@
 	hwt_start(smc,smc->t.st_queue->tm_delta) ;
 }
 
-void smt_force_irq(smc)
-struct s_smc *smc ;
+void smt_force_irq(struct s_smc *smc)
 {
 	smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST)); 
 }
 
-void smt_timer_done(smc)
-struct s_smc *smc ;
+void smt_timer_done(struct s_smc *smc)
 {
 	timer_done(smc,1) ;
 }
 
-static void timer_done(smc,restart)
-struct s_smc *smc ;
-int restart ;
+static void timer_done(struct s_smc *smc, int restart)
 {
 	u_long			delta ;
 	struct smt_timer	*tm ;
@@ -171,3 +153,4 @@
 	if (restart && smc->t.st_queue)
 		hwt_start(smc,smc->t.st_queue->tm_delta) ;
 }
+
diff -Nru a/drivers/net/skfp/srf.c b/drivers/net/skfp/srf.c
--- a/drivers/net/skfp/srf.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/skfp/srf.c	2004-06-23 19:04:27 -07:00
@@ -38,10 +38,10 @@
 /*
  * function declarations
  */
-static void clear_all_rep() ;
-static void clear_reported() ;
-static void smt_send_srf() ;
-static struct s_srf_evc *smt_get_evc() ;
+static void clear_all_rep(struct s_smc *smc);
+static void clear_reported(struct s_smc *smc);
+static void smt_send_srf(struct s_smc *smc);
+static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index);
 
 #define MAX_EVCS	(sizeof(smc->evcs)/sizeof(smc->evcs[0]))
 
@@ -69,8 +69,7 @@
 
 #define MAX_INIT_EVC	(sizeof(evc_inits)/sizeof(evc_inits[0]))
 
-void smt_init_evc(smc)
-struct s_smc *smc ;
+void smt_init_evc(struct s_smc *smc)
 {
 	struct s_srf_evc	*evc ;
 	const struct evc_init 	*init ;
@@ -159,10 +158,7 @@
 	smc->srf.sr_state = SR0_WAIT ;
 }
 
-static struct s_srf_evc *smt_get_evc(smc,code,index)
-struct s_smc *smc ;
-int code ;
-int index ;
+static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
 {
 	int			i ;
 	struct s_srf_evc	*evc ;
@@ -188,11 +184,7 @@
 } ;
 #endif
 
-void smt_srf_event(smc,code,index,cond)
-struct s_smc *smc ;
-int code ;
-int index ;
-int cond ;
+void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
 {
 	struct s_srf_evc	*evc ;
 	int			cond_asserted = 0 ;
@@ -340,8 +332,7 @@
 	}
 }
 
-static void clear_all_rep(smc)
-struct s_smc *smc ;
+static void clear_all_rep(struct s_smc *smc)
 {
 	struct s_srf_evc	*evc ;
 	int			i ;
@@ -354,8 +345,7 @@
 	smc->srf.any_report = FALSE ;
 }
 
-static void clear_reported(smc)
-struct s_smc *smc ;
+static void clear_reported(struct s_smc *smc)
 {
 	struct s_srf_evc	*evc ;
 	int			i ;
@@ -375,13 +365,10 @@
 	}
 }
 
-extern SMbuf *smt_build_frame() ;
-
 /*
  * build and send SMT SRF frame
  */
-static void smt_send_srf(smc)
-struct s_smc *smc ;
+static void smt_send_srf(struct s_smc *smc)
 {
 
 	struct smt_header	*smt ;
@@ -439,3 +426,4 @@
 
 #endif	/* no BOOT */
 #endif	/* no SLIM_SMT */
+
diff -Nru a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
--- a/drivers/net/smc-mca.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/smc-mca.c	2004-06-23 19:04:25 -07:00
@@ -51,6 +51,8 @@
 #include "8390.h"
 #include "smc-mca.h"
 
+#define DRV_NAME "smc-mca"
+
 static int ultramca_open(struct net_device *dev);
 static void ultramca_reset_8390(struct net_device *dev);
 static void ultramca_get_8390_hdr(struct net_device *dev,
@@ -265,7 +267,7 @@
 		goto err_unclaim;
 	}
 
-	if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name)) {
+	if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) {
 		rc = -ENODEV;
 		goto err_unclaim;
 	}
diff -Nru a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
--- a/drivers/net/smc-ultra.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/smc-ultra.c	2004-06-23 19:04:25 -07:00
@@ -72,6 +72,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "smc-ultra"
+
 /* A zero-terminated list of I/O addresses to be probed. */
 static unsigned int ultra_portlist[] __initdata =
 {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
@@ -178,6 +180,7 @@
 	release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init ultra_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -202,6 +205,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init ultra_probe1(struct net_device *dev, int ioaddr)
 {
@@ -215,7 +219,7 @@
 	unsigned char idreg = inb(ioaddr + 7);
 	unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
 
-	if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	/* Check the ID nibble. */
diff -Nru a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
--- a/drivers/net/smc-ultra32.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/smc-ultra32.c	2004-06-23 19:04:28 -07:00
@@ -61,6 +61,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "smc-ultra32"
+
 static int ultra32_probe1(struct net_device *dev, int ioaddr);
 static int ultra32_open(struct net_device *dev);
 static void ultra32_reset_8390(struct net_device *dev);
@@ -163,7 +165,7 @@
 	unsigned char reg4;
 	const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"};
 
-	if (!request_region(ioaddr, ULTRA32_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, ULTRA32_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	if (inb(ioaddr + ULTRA32_IDPORT) == 0xff ||
diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c
--- a/drivers/net/smc9194.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/smc9194.c	2004-06-23 19:04:28 -07:00
@@ -78,6 +78,8 @@
 
 #include "smc9194.h"
 
+#define DRV_NAME "smc9194"
+
 /*------------------------------------------------------------------------
  .
  . Configuration options, for the experienced user to change.
@@ -94,16 +96,51 @@
 #define USE_32_BIT 1
 #endif
 
+#if defined(__H8300H__) || defined(__H8300S__)
+#define NO_AUTOPROBE
+#undef insl
+#undef outsl
+#define insl(a,b,l)  io_insl_noswap(a,b,l)
+#define outsl(a,b,l) io_outsl_noswap(a,b,l)
+#endif
+
 /*
  .the SMC9194 can be at any of the following port addresses.  To change,
  .for a slightly different card, you can add it to the array.  Keep in
  .mind that the array must end in zero.
 */
-static unsigned int smc_portlist[] __initdata = { 
-	0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
-	0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
+
+struct devlist {
+	unsigned int port;
+	unsigned int irq;
 };
 
+#if defined(CONFIG_H8S_EDOSK2674)
+static struct devlist smc_devlist[] __initdata = {
+	{.port = 0xf80000, .irq = 16},
+	{.port = 0,        .irq = 0 },
+};
+#else
+static struct devlist smc_devlist[] __initdata = {
+	{.port = 0x200, .irq = 0},
+	{.port = 0x220, .irq = 0},
+	{.port = 0x240, .irq = 0},
+	{.port = 0x260, .irq = 0},
+	{.port = 0x280, .irq = 0},
+	{.port = 0x2A0, .irq = 0},
+	{.port = 0x2C0, .irq = 0},
+	{.port = 0x2E0, .irq = 0},
+	{.port = 0x300, .irq = 0},
+	{.port = 0x320, .irq = 0},
+	{.port = 0x340, .irq = 0},
+	{.port = 0x360, .irq = 0},
+	{.port = 0x380, .irq = 0},
+	{.port = 0x3A0, .irq = 0},
+	{.port = 0x3C0, .irq = 0},
+	{.port = 0x3E0, .irq = 0},
+	{.port = 0,     .irq = 0},
+};
+#endif
 /*
  . Wait time for memory to be free.  This probably shouldn't be
  . tuned that much, as waiting for this means nothing else happens
@@ -466,7 +503,7 @@
 static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
 {
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned short ioaddr 	= dev->base_addr;
+	unsigned int ioaddr 	= dev->base_addr;
 	word 			length;
 	unsigned short 		numPages;
 	word			time_out;
@@ -580,7 +617,7 @@
 	byte	 		packet_no;
 	struct sk_buff * 	skb = lp->saved_skb;
 	word			length;
-	unsigned short		ioaddr;
+	unsigned int		ioaddr;
 	byte			* buf;
 
 	ioaddr = dev->base_addr;
@@ -635,7 +672,11 @@
 #ifdef USE_32_BIT
 	if ( length & 0x2  ) {
 		outsl(ioaddr + DATA_1, buf,  length >> 2 );
+#if !defined(__H8300H__) && !defined(__H8300S__)
 		outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
+#else
+		ctrl_outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
+#endif
 	}
 	else
 		outsl(ioaddr + DATA_1, buf,  length >> 2 );
@@ -691,9 +732,12 @@
 struct net_device * __init smc_init(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct smc_local));
-	unsigned *port;
+	static struct devlist *smcdev = smc_devlist;
 	int err = 0;
 
+#ifndef NO_AUTOPROBE
+	smcdev = smc_devlist;
+#endif
 	if (!dev)
 		return ERR_PTR(-ENODEV);
 
@@ -711,11 +755,11 @@
 	} else if (io != 0) {	/* Don't probe at all. */
 		err = -ENXIO;
 	} else {
-		for (port = smc_portlist; *port; port++) {
-			if (smc_probe(dev, *port) == 0)
+		for (;smcdev->port; smcdev++) {
+			if (smc_probe(dev, smcdev->port) == 0)
 				break;
 		}
-		if (!*port)
+		if (!smcdev->port)
 			err = -ENODEV;
 	}
 	if (err)
@@ -741,6 +785,7 @@
 */
 int __init smc_findirq( int ioaddr )
 {
+#ifndef NO_AUTOPROBE
 	int	timeout = 20;
 	unsigned long cookie;
 
@@ -795,6 +840,14 @@
 
 	/* and return what I found */
 	return probe_irq_off(cookie);
+#else /* NO_AUTOPROBE */
+	struct devlist *smcdev;
+	for (smcdev = smc_devlist; smcdev->port; smcdev++) {
+		if (smcdev->port == ioaddr)
+			return smcdev->irq;
+	}
+	return 0;
+#endif
 }
 
 /*----------------------------------------------------------------------
@@ -843,7 +896,7 @@
 	word memory_cfg_register;
 
 	/* Grab the region so that no one else tries to probe our ioports. */
-	if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
+	if (!request_region(ioaddr, SMC_IO_EXTENT, DRV_NAME))
 		return -EBUSY;
 
 	dev->irq = irq;
@@ -863,6 +916,7 @@
 		retval = -ENODEV;
 		goto err_out;
 	}
+#if !defined(CONFIG_H8S_EDOSK2674)
 	/* well, we've already written once, so hopefully another time won't
  	   hurt.  This time, I need to switch the bank register to bank 1,
 	   so I can access the base address register */
@@ -877,6 +931,10 @@
 		retval = -ENODEV;
 		goto err_out;
 	}
+#else
+	(void)base_address_register; /* Warning suppression */
+#endif
+
 
 	/*  check if the revision register is something that I recognize.
 	    These might need to be added to later, as future revisions
@@ -1001,9 +1059,9 @@
 	memset(dev->priv, 0, sizeof(struct smc_local));
 
 	/* Grab the IRQ */
-      	retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
+      	retval = request_irq(dev->irq, &smc_interrupt, 0, DRV_NAME, dev);
       	if (retval) {
-		printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
+		printk("%s: unable to get IRQ %d (irqval=%d).\n", DRV_NAME,
 			dev->irq, retval);
   	  	goto err_out;
       	}
diff -Nru a/drivers/net/starfire.c b/drivers/net/starfire.c
--- a/drivers/net/starfire.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/net/starfire.c	2004-06-23 19:04:29 -07:00
@@ -880,7 +880,7 @@
 
 	irq = pdev->irq;
 
-	if (pci_request_regions (pdev, dev->name)) {
+	if (pci_request_regions (pdev, DRV_NAME)) {
 		printk(KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", card_idx);
 		goto err_out_free_netdev;
 	}
diff -Nru a/drivers/net/stnic.c b/drivers/net/stnic.c
--- a/drivers/net/stnic.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/stnic.c	2004-06-23 19:04:27 -07:00
@@ -28,6 +28,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "stnic"
+
 #define byte	unsigned char
 #define half	unsigned short
 #define word	unsigned int
@@ -130,7 +132,7 @@
 
   /* Snarf the interrupt now.  There's no point in waiting since we cannot
      share and the board will usually be enabled. */
-  err = request_irq (dev->irq, ei_interrupt, 0, dev->name, dev);
+  err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev);
   if (err)  {
       printk (KERN_EMERG " unable to get IRQ %d.\n", dev->irq);
       free_netdev(dev);
diff -Nru a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
--- a/drivers/net/sun3_82586.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/sun3_82586.c	2004-06-23 19:04:27 -07:00
@@ -53,6 +53,8 @@
 
 #include "sun3_82586.h"
 
+#define DRV_NAME "sun3_82586"
+
 #define DEBUG       /* debug on */
 #define SYSBUSVAL 0 /* 16 Bit */
 #define SUN3_82586_TOTAL_SIZE	PAGE_SIZE
@@ -336,7 +338,7 @@
 {
 	int i, size, retval;
 
-	if (!request_region(ioaddr, SUN3_82586_TOTAL_SIZE, dev->name))
+	if (!request_region(ioaddr, SUN3_82586_TOTAL_SIZE, DRV_NAME))
 		return -EBUSY;
 
 	/* copy in the ethernet address from the prom */
diff -Nru a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
--- a/drivers/net/sun3lance.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/sun3lance.c	2004-06-23 19:04:28 -07:00
@@ -42,7 +42,6 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/pgalloc.h>
 #include <asm/dvma.h>
 #include <asm/idprom.h>
 #include <asm/machines.h>
diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c
--- a/drivers/net/sungem.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/sungem.c	2004-06-23 19:04:28 -07:00
@@ -33,6 +33,7 @@
 #include <linux/crc32.h>
 #include <linux/random.h>
 #include <linux/workqueue.h>
+#include <linux/if_vlan.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -742,7 +743,7 @@
 				       PCI_DMA_FROMDEVICE);
 			gp->rx_skbs[entry] = new_skb;
 			new_skb->dev = gp->dev;
-			skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET));
+			skb_put(new_skb, (gp->rx_buf_sz + RX_OFFSET));
 			rxd->buffer = cpu_to_le64(pci_map_page(gp->pdev,
 							       virt_to_page(new_skb->data),
 							       offset_in_page(new_skb->data),
@@ -1482,6 +1483,9 @@
 
 	gem_clean_rings(gp);
 
+	gp->rx_buf_sz = max(dev->mtu + ETH_HLEN + VLAN_HLEN,
+			    (unsigned)VLAN_ETH_FRAME_LEN);
+
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb;
 		struct gem_rxd *rxd = &gb->rxd[i];
@@ -1495,7 +1499,7 @@
 
 		gp->rx_skbs[i] = skb;
 		skb->dev = dev;
-		skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET));
+		skb_put(skb, (gp->rx_buf_sz + RX_OFFSET));
 		dma_addr = pci_map_page(gp->pdev,
 					virt_to_page(skb->data),
 					offset_in_page(skb->data),
@@ -1750,7 +1754,7 @@
 	writel(0x40, gp->regs + MAC_MINFSZ);
 
 	/* Ethernet payload + header + FCS + optional VLAN tag. */
-	writel(0x20000000 | (gp->dev->mtu + ETH_HLEN + 4 + 4), gp->regs + MAC_MAXFSZ);
+	writel(0x20000000 | (gp->rx_buf_sz + 4), gp->regs + MAC_MAXFSZ);
 
 	writel(0x07, gp->regs + MAC_PASIZE);
 	writel(0x04, gp->regs + MAC_JAMSIZE);
@@ -1827,7 +1831,7 @@
 	if (gp->rx_fifo_sz <= (2 * 1024)) {
 		gp->rx_pause_off = gp->rx_pause_on = gp->rx_fifo_sz;
 	} else {
-		int max_frame = (gp->dev->mtu + ETH_HLEN + 4 + 4 + 64) & ~63;
+		int max_frame = (gp->rx_buf_sz + 4 + 64) & ~63;
 		int off = (gp->rx_fifo_sz - (max_frame * 2));
 		int on = off - max_frame;
 
@@ -2717,7 +2721,7 @@
 
 	gp = dev->priv;
 
-	err = pci_request_regions(pdev, dev->name);
+	err = pci_request_regions(pdev, DRV_NAME);
 	if (err) {
 		printk(KERN_ERR PFX "Cannot obtain PCI resources, "
 		       "aborting.\n");
diff -Nru a/drivers/net/sungem.h b/drivers/net/sungem.h
--- a/drivers/net/sungem.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/sungem.h	2004-06-23 19:04:27 -07:00
@@ -911,7 +911,7 @@
 	  (GP)->tx_old - (GP)->tx_new - 1)
 
 #define RX_OFFSET          2
-#define RX_BUF_ALLOC_SIZE(gp)	((gp)->dev->mtu + 46 + RX_OFFSET + 64)
+#define RX_BUF_ALLOC_SIZE(gp)	((gp)->rx_buf_sz + 28 + RX_OFFSET + 64)
 
 #define RX_COPY_THRESHOLD  256
 
@@ -979,6 +979,7 @@
 	int			rx_fifo_sz;
 	int			rx_pause_off;
 	int			rx_pause_on;
+	int			rx_buf_sz;
 	int			mii_phy_addr;
 
 	u32			mac_rx_cfg;
diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c
--- a/drivers/net/sunhme.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/sunhme.c	2004-06-23 19:04:26 -07:00
@@ -68,6 +68,8 @@
 #include "sunhme.h"
 
 
+#define DRV_NAME "sunhme"
+
 static int macaddr[6];
 
 /* accept MAC address of the form macaddr=0x08,0x00,0x20,0x30,0x40,0x50 */
@@ -2920,7 +2922,8 @@
 	struct list_head *tmp;
 	int n_hmes;
 
-	if (busdev->vendor != PCI_VENDOR_ID_DEC ||
+	if (busdev == NULL ||
+	    busdev->vendor != PCI_VENDOR_ID_DEC ||
 	    busdev->device != PCI_DEVICE_ID_DEC_21153)
 		return 0;
 
@@ -3085,7 +3088,7 @@
 		printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n");
 		goto err_out_clear_quattro;
 	}
-	if (pci_request_regions(pdev, dev->name)) {
+	if (pci_request_regions(pdev, DRV_NAME)) {
 		printk(KERN_ERR "happymeal(PCI): Cannot obtain PCI resources, "
 		       "aborting.\n");
 		goto err_out_clear_quattro;
diff -Nru a/drivers/net/tc35815.c b/drivers/net/tc35815.c
--- a/drivers/net/tc35815.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/tc35815.c	2004-06-23 19:04:25 -07:00
@@ -1717,7 +1717,7 @@
 }
 
 static struct pci_driver tc35815_driver = {
-	.name =TC35815_MODULE_NAME,
+	.name = TC35815_MODULE_NAME,
 	.probe = tc35815_probe,
 	.remove = NULL,
 	.id_table = tc35815_pci_tbl,
diff -Nru a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
--- a/drivers/net/tokenring/ibmtr.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/tokenring/ibmtr.c	2004-06-23 19:04:27 -07:00
@@ -127,6 +127,7 @@
 
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
+#include <linux/ip.h>
 #include <linux/trdevice.h>
 #include <linux/ibmtr.h>
 
diff -Nru a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
--- a/drivers/net/tulip/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/tulip/Kconfig	2004-06-23 19:04:28 -07:00
@@ -71,10 +71,17 @@
 config TULIP_NAPI
 	bool "Use NAPI RX polling "
 	depends on TULIP
-	---help---
-	  This is of useful for servers and routers dealing with high network loads.
- 
-	  See <file:Documentation/networking/NAPI_HOWTO.txt>.
+	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.
 
diff -Nru a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
--- a/drivers/net/tulip/winbond-840.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/tulip/winbond-840.c	2004-06-23 19:04:25 -07:00
@@ -1292,14 +1292,8 @@
 				pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry],
 							    np->rx_skbuff[entry]->len,
 							    PCI_DMA_FROMDEVICE);
-				/* Call copy + cksum if available. */
-#if HAS_IP_COPYSUM
 				eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
-#else
-				memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail,
-					   pkt_len);
-#endif
 				pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry],
 							       np->rx_skbuff[entry]->len,
 							       PCI_DMA_FROMDEVICE);
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/via-rhine.c	2004-06-23 19:04:28 -07:00
@@ -354,59 +354,46 @@
    second only the 1234 card.
 */
 
-enum pci_flags_bit {
-	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+enum rhine_revs {
+	VT86C100A	= 0x00,
+	VT6102		= 0x40,
+	VT8231		= 0x50,	/* Integrated MAC */
+	VT8233		= 0x60,	/* Integrated MAC */
+	VT8235		= 0x74,	/* Integrated MAC */
+	VT8237		= 0x78,	/* Integrated MAC */
+	VTunknown0	= 0x7C,
+	VT6105		= 0x80,
+	VT6105_B0	= 0x83,
+	VT6105L		= 0x8A,
+	VT6107		= 0x8C,
+	VTunknown1	= 0x8E,
+	VT6105M		= 0x90,
 };
 
-enum rhine_chips {
-	VT86C100A = 0,
-	VT6102,
-	VT6105,
-	VT6105M
-};
-
-struct rhine_chip_info {
-	const char *name;
-	u16 pci_flags;
-	int io_size;
-	int drv_flags;
-};
-
-
-enum chip_capability_flags {
-	CanHaveMII=1, HasESIPhy=2, HasDavicomPhy=4,
-	ReqTxAlign=0x10, HasWOL=0x20,
+enum rhine_quirks {
+	rqWOL		= 0x0001,	/* Wake-On-LAN support */
+	rqForceReset	= 0x0002,
+	rqDavicomPhy	= 0x0020,
+	rq6patterns	= 0x0040,	/* 6 instead of 4 patterns for WOL */
+	rqStatusWBRace	= 0x0080,	/* Tx Status Writeback Error possible */
+	rqRhineI	= 0x0100,	/* See comment below */
 };
+/*
+ * rqRhineI: VT86C100A (aka Rhine-I) uses different bits to enable
+ * MMIO as well as for the collision counter and the Tx FIFO underflow
+ * indicator. In addition, Tx and Rx buffers need to 4 byte aligned.
+ */
 
-#ifdef USE_MMIO
-#define RHINE_IOTYPE (PCI_USES_MEM | PCI_USES_MASTER | PCI_ADDR1)
-#else
-#define RHINE_IOTYPE (PCI_USES_IO  | PCI_USES_MASTER | PCI_ADDR0)
-#endif
 /* Beware of PCI posted writes */
 #define IOSYNC	do { readb(dev->base_addr + StationAddr); } while (0)
 
-/* directly indexed by enum rhine_chips, above */
-static struct rhine_chip_info rhine_chip_info[] __devinitdata =
-{
-	{ "VIA VT86C100A Rhine", RHINE_IOTYPE, 128,
-	  CanHaveMII | ReqTxAlign | HasDavicomPhy },
-	{ "VIA VT6102 Rhine-II", RHINE_IOTYPE, 256,
-	  CanHaveMII | HasWOL },
-	{ "VIA VT6105 Rhine-III", RHINE_IOTYPE, 256,
-	  CanHaveMII | HasWOL },
-	{ "VIA VT6105M Rhine-III", RHINE_IOTYPE, 256,
-	  CanHaveMII | HasWOL },
-};
-
 static struct pci_device_id rhine_pci_tbl[] =
 {
-	{0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT86C100A},
-	{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6102},
-	{0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105}, /* 6105{,L,LOM} */
-	{0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105M},
-	{0,}	/* terminate list */
+	{0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT86C100A */
+	{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6102 */
+	{0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* 6105{,L,LOM} */
+	{0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6105M */
+	{ }	/* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);
 
@@ -421,8 +408,10 @@
 	MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74,
 	ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B,
 	RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81,
-	StickyHW=0x83, IntrStatus2=0x84, WOLcrClr=0xA4, WOLcgClr=0xA7,
-	PwrcsrClr=0xAC,
+	StickyHW=0x83, IntrStatus2=0x84,
+	WOLcrSet=0xA0, WOLcrClr=0xA4, WOLcrClr1=0xA6,
+	WOLcgClr=0xA7,
+	PwrcsrSet=0xA8, PwrcsrSet1=0xA9, PwrcsrClr=0xAC, PwrcsrClr1=0xAD,
 };
 
 /* Bits in ConfigD */
@@ -514,7 +503,7 @@
 	spinlock_t lock;
 
 	/* Frequently used values: keep some adjacent for cache effect. */
-	int chip_id, drv_flags;
+	u32 quirks;
 	struct rx_desc *rx_head_desc;
 	unsigned int cur_rx, dirty_rx;	/* Producer/consumer ring indices */
 	unsigned int cur_tx, dirty_tx;
@@ -522,7 +511,6 @@
 	u16 chip_cmd;			/* Current setting for ChipCmd */
 
 	/* These values are keep track of the transceiver/media in use. */
-	unsigned int default_port:4;	/* Last dev->if_port value. */
 	u8 tx_thresh, rx_thresh;
 
 	/* MII transceiver section. */
@@ -557,12 +545,41 @@
 
 	intr_status = readw(ioaddr + IntrStatus);
 	/* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */
-	if (rp->chip_id == VT6102)
+	if (rp->quirks & rqStatusWBRace)
 		intr_status |= readb(ioaddr + IntrStatus2) << 16;
 	return intr_status;
 }
 
-static void wait_for_reset(struct net_device *dev, int chip_id, char *name)
+/*
+ * Get power related registers into sane state.
+ * Returns content of power-event (WOL) registers.
+ */
+static void rhine_power_init(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct rhine_private *rp = netdev_priv(dev);
+
+	if (rp->quirks & rqWOL) {
+		/* Make sure chip is in power state D0 */
+		writeb(readb(ioaddr + StickyHW) & 0xFC, ioaddr + StickyHW);
+
+		/* Disable "force PME-enable" */
+		writeb(0x80, ioaddr + WOLcgClr);
+
+		/* Clear power-event config bits (WOL) */
+		writeb(0xFF, ioaddr + WOLcrClr);
+		/* More recent cards can manage two additional patterns */
+		if (rp->quirks & rq6patterns)
+			writeb(0x03, ioaddr + WOLcrClr1);
+
+		/* Clear power-event status bits */
+		writeb(0xFF, ioaddr + PwrcsrClr);
+		if (rp->quirks & rq6patterns)
+			writeb(0x03, ioaddr + PwrcsrClr1);
+	}
+}
+
+static void wait_for_reset(struct net_device *dev, u32 quirks, char *name)
 {
 	long ioaddr = dev->base_addr;
 	int boguscnt = 20;
@@ -574,7 +591,7 @@
 			"Trying harder.\n", name);
 
 		/* Rhine-II needs to be forced sometimes */
-		if (chip_id == VT6102)
+		if (quirks & rqForceReset)
 			writeb(0x40, ioaddr + MiscCmd);
 
 		/* VT86C100A may need long delay after reset (dlink) */
@@ -590,10 +607,10 @@
 }
 
 #ifdef USE_MMIO
-static void __devinit enable_mmio(long ioaddr, int chip_id)
+static void __devinit enable_mmio(long ioaddr, u32 quirks)
 {
 	int n;
-	if (chip_id == VT86C100A) {
+	if (quirks & rqRhineI) {
 		/* More recent docs say that this bit is reserved ... */
 		n = inb(ioaddr + ConfigA) | 0x20;
 		outb(n, ioaddr + ConfigA);
@@ -628,16 +645,18 @@
 {
 	struct net_device *dev;
 	struct rhine_private *rp;
-	int i, option;
-	int chip_id = (int) ent->driver_data;
+	int i, option, rc;
+	u8 pci_rev;
+	u32 quirks;
 	static int card_idx = -1;
 	long ioaddr;
 	long memaddr;
 	int io_size;
-	int pci_flags;
+	int phy, phy_idx = 0;
 #ifdef USE_MMIO
 	long ioaddr0;
 #endif
+	const char *name;
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -648,14 +667,34 @@
 
 	card_idx++;
 	option = card_idx < MAX_UNITS ? options[card_idx] : 0;
-	io_size = rhine_chip_info[chip_id].io_size;
-	pci_flags = rhine_chip_info[chip_id].pci_flags;
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
+
+	io_size = 256;
+	if (pci_rev < VT6102) {
+		quirks = rqRhineI | rqDavicomPhy;
+		io_size = 128;
+		name = "VT86C100A Rhine";
+	}
+	else {
+		quirks = rqWOL | rqForceReset;
+		if (pci_rev < VT6105) {
+			name = "Rhine II";
+			quirks |= rqStatusWBRace;	/* Rhine-II exclusive */
+		}
+		else {
+			name = "Rhine III";
+			if (pci_rev >= VT6105_B0)
+				quirks |= rq6patterns;
+		}
+	}
 
-	if (pci_enable_device(pdev))
+	rc = pci_enable_device(pdev);
+	if (rc)
 		goto err_out;
 
 	/* this should always be supported */
-	if (pci_set_dma_mask(pdev, 0xffffffff)) {
+	rc = pci_set_dma_mask(pdev, 0xffffffff);
+	if (rc) {
 		printk(KERN_ERR "32-bit PCI DMA addresses not supported by "
 		       "the card!?\n");
 		goto err_out;
@@ -664,6 +703,7 @@
 	/* sanity check */
 	if ((pci_resource_len(pdev, 0) < io_size) ||
 	    (pci_resource_len(pdev, 1) < io_size)) {
+		rc = -EIO;
 		printk(KERN_ERR "Insufficient PCI resources, aborting\n");
 		goto err_out;
 	}
@@ -671,11 +711,11 @@
 	ioaddr = pci_resource_start(pdev, 0);
 	memaddr = pci_resource_start(pdev, 1);
 
-	if (pci_flags & PCI_USES_MASTER)
-		pci_set_master(pdev);
+	pci_set_master(pdev);
 
 	dev = alloc_etherdev(sizeof(*rp));
 	if (dev == NULL) {
+		rc = -ENOMEM;
 		printk(KERN_ERR "init_ethernet failed for card #%d\n",
 		       card_idx);
 		goto err_out;
@@ -683,15 +723,17 @@
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	if (pci_request_regions(pdev, shortname))
+	rc = pci_request_regions(pdev, shortname);
+	if (rc)
 		goto err_out_free_netdev;
 
 #ifdef USE_MMIO
 	ioaddr0 = ioaddr;
-	enable_mmio(ioaddr0, chip_id);
+	enable_mmio(ioaddr0, quirks);
 
 	ioaddr = (long) ioremap(memaddr, io_size);
 	if (!ioaddr) {
+		rc = -EIO;
 		printk(KERN_ERR "ioremap failed for device %s, region 0x%X "
 		       "@ 0x%lX\n", pci_name(pdev), io_size, memaddr);
 		goto err_out_free_res;
@@ -704,36 +746,21 @@
 		unsigned char a = inb(ioaddr0+reg);
 		unsigned char b = readb(ioaddr+reg);
 		if (a != b) {
+			rc = -EIO;
 			printk(KERN_ERR "MMIO do not match PIO [%02x] "
 			       "(%02x != %02x)\n", reg, a, b);
 			goto err_out_unmap;
 		}
 	}
 #endif /* USE_MMIO */
+	dev->base_addr = ioaddr;
 
-	/* D-Link provided reset code (with comment additions) */
-	if (rhine_chip_info[chip_id].drv_flags & HasWOL) {
-		unsigned char byOrgValue;
-
-		/* clear sticky bit before reset & read ethernet address */
-		byOrgValue = readb(ioaddr + StickyHW);
-		byOrgValue = byOrgValue & 0xFC;
-		writeb(byOrgValue, ioaddr + StickyHW);
-
-		/* (bits written are cleared?) */
-		/* disable force PME-enable */
-		writeb(0x80, ioaddr + WOLcgClr);
-		/* disable power-event config bit */
-		writeb(0xFF, ioaddr + WOLcrClr);
-		/* clear power status (undocumented in vt6102 docs?) */
-		writeb(0xFF, ioaddr + PwrcsrClr);
-	}
+	rhine_power_init(dev);
 
 	/* Reset the chip to erase previous misconfiguration. */
 	writew(CmdReset, ioaddr + ChipCmd);
 
-	dev->base_addr = ioaddr;
-	wait_for_reset(dev, chip_id, shortname);
+	wait_for_reset(dev, quirks, shortname);
 
 	/* Reload the station address from the EEPROM. */
 #ifdef USE_MMIO
@@ -741,7 +768,7 @@
 	/* Reloading from eeprom overwrites cfgA-D, so we must re-enable MMIO.
 	   If reload_eeprom() was done first this could be avoided, but it is
 	   not known if that still works with the "win98-reboot" problem. */
-	enable_mmio(ioaddr0, chip_id);
+	enable_mmio(ioaddr0, quirks);
 #else
 	reload_eeprom(ioaddr);
 #endif
@@ -750,11 +777,12 @@
 		dev->dev_addr[i] = readb(ioaddr + StationAddr + i);
 
 	if (!is_valid_ether_addr(dev->dev_addr)) {
+		rc = -EIO;
 		printk(KERN_ERR "Invalid MAC address for card #%d\n", card_idx);
 		goto err_out_unmap;
 	}
 
-	if (chip_id == VT6102) {
+	if (quirks & rqWOL) {
 		/*
 		 * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA
 		 * turned on. it makes MAC receive magic packet
@@ -772,9 +800,8 @@
 
 	rp = netdev_priv(dev);
 	spin_lock_init(&rp->lock);
-	rp->chip_id = chip_id;
-	rp->drv_flags = rhine_chip_info[chip_id].drv_flags;
 	rp->pdev = pdev;
+	rp->quirks = quirks;
 	rp->mii_if.dev = dev;
 	rp->mii_if.mdio_read = mdio_read;
 	rp->mii_if.mdio_write = mdio_write;
@@ -797,19 +824,18 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	dev->poll_controller = rhine_poll;
 #endif
-	if (rp->drv_flags & ReqTxAlign)
+	if (rp->quirks & rqRhineI)
 		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
 	/* dev->name not defined before register_netdev()! */
-	i = register_netdev(dev);
-	if (i)
+	rc = register_netdev(dev);
+	if (rc)
 		goto err_out_unmap;
 
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x220)
 			rp->mii_if.full_duplex = 1;
-		rp->default_port = option & 15;
 	}
 	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
 		rp->mii_if.full_duplex = 1;
@@ -820,9 +846,14 @@
 		rp->mii_if.force_media = 1;
 	}
 
-	printk(KERN_INFO "%s: %s at 0x%lx, ",
-	       dev->name, rhine_chip_info[chip_id].name,
-	       (pci_flags & PCI_USES_IO) ? ioaddr : memaddr);
+	printk(KERN_INFO "%s: VIA %s at 0x%lx, ",
+	       dev->name, name,
+#ifdef USE_MMIO
+		memaddr
+#else
+		ioaddr
+#endif
+		 );
 
 	for (i = 0; i < 5; i++)
 		printk("%2.2x:", dev->dev_addr[i]);
@@ -830,41 +861,35 @@
 
 	pci_set_drvdata(pdev, dev);
 
-	if (rp->drv_flags & CanHaveMII) {
-		int phy, phy_idx = 0;
-		rp->phys[0] = 1;		/* Standard for this chip. */
-		for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) {
-			int mii_status = mdio_read(dev, phy, 1);
-			if (mii_status != 0xffff && mii_status != 0x0000) {
-				rp->phys[phy_idx++] = phy;
-				rp->mii_if.advertising = mdio_read(dev, phy, 4);
-				printk(KERN_INFO "%s: MII PHY found at address "
-				       "%d, status 0x%4.4x advertising %4.4x "
-				       "Link %4.4x.\n", dev->name, phy,
-				       mii_status, rp->mii_if.advertising,
-				       mdio_read(dev, phy, 5));
-
-				/* set IFF_RUNNING */
-				if (mii_status & BMSR_LSTATUS)
-					netif_carrier_on(dev);
-				else
-					netif_carrier_off(dev);
+	rp->phys[0] = 1;		/* Standard for this chip. */
+	for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) {
+		int mii_status = mdio_read(dev, phy, 1);
+		if (mii_status != 0xffff && mii_status != 0x0000) {
+			rp->phys[phy_idx++] = phy;
+			rp->mii_if.advertising = mdio_read(dev, phy, 4);
+			printk(KERN_INFO "%s: MII PHY found at address "
+			       "%d, status 0x%4.4x advertising %4.4x "
+			       "Link %4.4x.\n", dev->name, phy,
+			       mii_status, rp->mii_if.advertising,
+			       mdio_read(dev, phy, 5));
+
+			/* set IFF_RUNNING */
+			if (mii_status & BMSR_LSTATUS)
+				netif_carrier_on(dev);
+			else
+				netif_carrier_off(dev);
 
-				break;
-			}
+			break;
 		}
-		rp->mii_cnt = phy_idx;
-		rp->mii_if.phy_id = rp->phys[0];
 	}
+	rp->mii_cnt = phy_idx;
+	rp->mii_if.phy_id = rp->phys[0];
 
 	/* Allow forcing the media type. */
 	if (option > 0) {
 		if (option & 0x220)
 			rp->mii_if.full_duplex = 1;
-		rp->default_port = option & 0x3ff;
 		if (option & 0x330) {
-			/* FIXME: shouldn't someone check this variable? */
-			/* rp->medialock = 1; */
 			printk(KERN_INFO " Forcing %dMbs %s-duplex "
 				"operation.\n",
 			       (option & 0x300 ? 100 : 10),
@@ -887,7 +912,7 @@
 err_out_free_netdev:
 	free_netdev(dev);
 err_out:
-	return -ENODEV;
+	return rc;
 }
 
 static int alloc_ring(struct net_device* dev)
@@ -904,7 +929,7 @@
 		printk(KERN_ERR "Could not allocate DMA memory.\n");
 		return -ENOMEM;
 	}
-	if (rp->drv_flags & ReqTxAlign) {
+	if (rp->quirks & rqRhineI) {
 		rp->tx_bufs = pci_alloc_consistent(rp->pdev,
 						   PKT_BUF_SZ * TX_RING_SIZE,
 						   &rp->tx_bufs_dma);
@@ -1063,9 +1088,6 @@
 	rp->rx_thresh = 0x60;		/* Written in rhine_set_rx_mode(). */
 	rp->mii_if.full_duplex = 0;
 
-	if (dev->if_port == 0)
-		dev->if_port = rp->default_port;
-
 	writel(rp->rx_ring_dma, ioaddr + RxRingPtr);
 	writel(rp->tx_ring_dma, ioaddr + TxRingPtr);
 
@@ -1087,9 +1109,8 @@
 
 	/* The LED outputs of various MII xcvrs should be configured. */
 	/* For NS or Mison phys, turn on bit 1 in register 0x17 */
-	/* For ESI phys, turn on bit 7 in register 0x17. */
 	mdio_write(dev, rp->phys[0], 0x17, mdio_read(dev, rp->phys[0], 0x17) |
-		   (rp->drv_flags & HasESIPhy) ? 0x0080 : 0x0001);
+		   0x0001);
 }
 
 /* Read and write over the MII Management Data I/O (MDIO) interface. */
@@ -1166,7 +1187,7 @@
 		return i;
 	alloc_rbufs(dev);
 	alloc_tbufs(dev);
-	wait_for_reset(dev, rp->chip_id, dev->name);
+	wait_for_reset(dev, rp->quirks, dev->name);
 	init_registers(dev);
 	if (debug > 2)
 		printk(KERN_DEBUG "%s: Done rhine_open(), status %4.4x "
@@ -1257,8 +1278,6 @@
 	       dev->name, readw(ioaddr + IntrStatus),
 	       mdio_read(dev, rp->phys[0], MII_BMSR));
 
-	dev->if_port = 0;
-
 	/* protect against concurrent rx interrupts */
 	disable_irq(rp->pdev->irq);
 
@@ -1274,7 +1293,7 @@
 	alloc_rbufs(dev);
 
 	/* Reinitialize the hardware. */
-	wait_for_reset(dev, rp->chip_id, dev->name);
+	wait_for_reset(dev, rp->quirks, dev->name);
 	init_registers(dev);
 
 	spin_unlock(&rp->lock);
@@ -1305,7 +1324,7 @@
 
 	rp->tx_skbuff[entry] = skb;
 
-	if ((rp->drv_flags & ReqTxAlign) &&
+	if ((rp->quirks & rqRhineI) &&
 	    (((long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW)) {
 		/* Must use alignment buffer. */
 		if (skb->len > PKT_BUF_SZ) {
@@ -1454,7 +1473,7 @@
 			if (txstatus & 0x0200) rp->stats.tx_window_errors++;
 			if (txstatus & 0x0100) rp->stats.tx_aborted_errors++;
 			if (txstatus & 0x0080) rp->stats.tx_heartbeat_errors++;
-			if (((rp->chip_id == VT86C100A) && txstatus & 0x0002) ||
+			if (((rp->quirks & rqRhineI) && txstatus & 0x0002) ||
 			    (txstatus & 0x0800) || (txstatus & 0x1000)) {
 				rp->stats.tx_fifo_errors++;
 				rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
@@ -1462,7 +1481,7 @@
 			}
 			/* Transmitter restarted in 'abnormal' handler. */
 		} else {
-			if (rp->chip_id == VT86C100A)
+			if (rp->quirks & rqRhineI)
 				rp->stats.collisions += (txstatus >> 3) & 0x0F;
 			else
 				rp->stats.collisions += txstatus & 0x0F;
@@ -1563,15 +1582,10 @@
 				   eth_copy_and_sum is memcpy for all archs so
 				   this is kind of pointless right now
 				   ... or? */
-#if HAS_IP_COPYSUM		/* Call copy + cksum if available. */
 				eth_copy_and_sum(skb,
 						 rp->rx_skbuff[entry]->tail,
 						 pkt_len, 0);
 				skb_put(skb, pkt_len);
-#else
-				memcpy(skb_put(skb, pkt_len),
-				       rp->rx_skbuff[entry]->tail, pkt_len);
-#endif
 				pci_dma_sync_single_for_device(rp->pdev,
 							       rp->rx_skbuff_dma[entry],
 							       rp->rx_buf_sz,
@@ -1679,7 +1693,7 @@
 	if (intr_status & (IntrLinkChange)) {
 		if (readb(ioaddr + MIIStatus) & 0x02) {
 			/* Link failed, restart autonegotiation. */
-			if (rp->drv_flags & HasDavicomPhy)
+			if (rp->quirks & rqRhineI)
 				mdio_write(dev, rp->phys[0], MII_BMCR, 0x3300);
 		} else
 			rhine_check_duplex(dev);
@@ -1805,9 +1819,6 @@
 	struct rhine_private *rp = netdev_priv(dev);
 	int rc;
 
-	if (!(rp->drv_flags & CanHaveMII))
-		return -EINVAL;
-
 	spin_lock_irq(&rp->lock);
 	rc = mii_ethtool_gset(&rp->mii_if, cmd);
 	spin_unlock_irq(&rp->lock);
@@ -1820,9 +1831,6 @@
 	struct rhine_private *rp = netdev_priv(dev);
 	int rc;
 
-	if (!(rp->drv_flags & CanHaveMII))
-		return -EINVAL;
-
 	spin_lock_irq(&rp->lock);
 	rc = mii_ethtool_sset(&rp->mii_if, cmd);
 	spin_unlock_irq(&rp->lock);
@@ -1834,18 +1842,12 @@
 {
 	struct rhine_private *rp = netdev_priv(dev);
 
-	if (!(rp->drv_flags & CanHaveMII))
-		return -EINVAL;
-
 	return mii_nway_restart(&rp->mii_if);
 }
 
 static u32 netdev_get_link(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
-
-	if (!(rp->drv_flags & CanHaveMII))
-		return 0;	/* -EINVAL */
 
 	return mii_link_ok(&rp->mii_if);
 }
diff -Nru a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/via-velocity.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,3277 @@
+/*
+ * This code is derived from the VIA reference driver (copyright message
+ * below) provided to Red Hat by VIA Networking Technologies, Inc. for
+ * addition to the Linux kernel.
+ *
+ * The code has been merged into one source file, cleaned up to follow
+ * Linux coding style,  ported to the Linux 2.6 kernel tree and cleaned
+ * for 64bit hardware platforms.
+ *
+ * TODO
+ *	Big-endian support
+ *	rx_copybreak/alignment
+ *	Scatter gather
+ *	More testing
+ *
+ * The changes are (c) Copyright 2004, Red Hat Inc. <alan@redhat.com>
+ * Additional fixes and clean up: Francois Romieu
+ *
+ * This source has not been verified for use in safety critical systems.
+ *
+ * Please direct queries about the revamped driver to the linux-kernel
+ * list not VIA.
+ *
+ * Original code:
+ *
+ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
+ * All rights reserved.
+ *
+ * This software may be redistributed and/or modified under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * Author: Chuang Liang-Shing, AJ Jiang
+ *
+ * Date: Jan 24, 2003
+ *
+ * MODULE_LICENSE("GPL");
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <asm/io.h>
+#include <linux/if.h>
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/inetdevice.h>
+#include <linux/reboot.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/in.h>
+#include <linux/if_arp.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+
+#include "via-velocity.h"
+
+
+static int velocity_nics = 0;
+static int msglevel = MSG_LEVEL_INFO;
+
+
+static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static struct ethtool_ops velocity_ethtool_ops;
+
+/*
+    Define module options
+*/
+
+MODULE_AUTHOR("VIA Networking Technologies, Inc.");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("VIA Networking Velocity Family Gigabit Ethernet Adapter Driver");
+
+#define VELOCITY_PARAM(N,D) \
+        static const int N[MAX_UNITS]=OPTION_DEFAULT;\
+        MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UNITS) "i");\
+        MODULE_PARM_DESC(N, D);
+
+#define RX_DESC_MIN     64
+#define RX_DESC_MAX     255
+#define RX_DESC_DEF     64
+VELOCITY_PARAM(RxDescriptors, "Number of receive descriptors");
+
+#define TX_DESC_MIN     16
+#define TX_DESC_MAX     256
+#define TX_DESC_DEF     64
+VELOCITY_PARAM(TxDescriptors, "Number of transmit descriptors");
+
+#define VLAN_ID_MIN     0
+#define VLAN_ID_MAX     4095
+#define VLAN_ID_DEF     0
+/* VID_setting[] is used for setting the VID of NIC.
+   0: default VID.
+   1-4094: other VIDs.
+*/
+VELOCITY_PARAM(VID_setting, "802.1Q VLAN ID");
+
+#define RX_THRESH_MIN   0
+#define RX_THRESH_MAX   3
+#define RX_THRESH_DEF   0
+/* rx_thresh[] is used for controlling the receive fifo threshold.
+   0: indicate the rxfifo threshold is 128 bytes.
+   1: indicate the rxfifo threshold is 512 bytes.
+   2: indicate the rxfifo threshold is 1024 bytes.
+   3: indicate the rxfifo threshold is store & forward.
+*/
+VELOCITY_PARAM(rx_thresh, "Receive fifo threshold");
+
+#define DMA_LENGTH_MIN  0
+#define DMA_LENGTH_MAX  7
+#define DMA_LENGTH_DEF  0
+
+/* DMA_length[] is used for controlling the DMA length
+   0: 8 DWORDs
+   1: 16 DWORDs
+   2: 32 DWORDs
+   3: 64 DWORDs
+   4: 128 DWORDs
+   5: 256 DWORDs
+   6: SF(flush till emply)
+   7: SF(flush till emply)
+*/
+VELOCITY_PARAM(DMA_length, "DMA length");
+
+#define TAGGING_DEF     0
+/* enable_tagging[] is used for enabling 802.1Q VID tagging.
+   0: disable VID seeting(default).
+   1: enable VID setting.
+*/
+VELOCITY_PARAM(enable_tagging, "Enable 802.1Q tagging");
+
+#define IP_ALIG_DEF     0
+/* IP_byte_align[] is used for IP header DWORD byte aligned
+   0: indicate the IP header won't be DWORD byte aligned.(Default) .
+   1: indicate the IP header will be DWORD byte aligned.
+      In some enviroment, the IP header should be DWORD byte aligned,
+      or the packet will be droped when we receive it. (eg: IPVS)
+*/
+VELOCITY_PARAM(IP_byte_align, "Enable IP header dword aligned");
+
+#define TX_CSUM_DEF     1
+/* txcsum_offload[] is used for setting the checksum offload ability of NIC.
+   (We only support RX checksum offload now)
+   0: disable csum_offload[checksum offload
+   1: enable checksum offload. (Default)
+*/
+VELOCITY_PARAM(txcsum_offload, "Enable transmit packet checksum offload");
+
+#define FLOW_CNTL_DEF   1
+#define FLOW_CNTL_MIN   1
+#define FLOW_CNTL_MAX   5
+
+/* flow_control[] is used for setting the flow control ability of NIC.
+   1: hardware deafult - AUTO (default). Use Hardware default value in ANAR.
+   2: enable TX flow control.
+   3: enable RX flow control.
+   4: enable RX/TX flow control.
+   5: disable
+*/
+VELOCITY_PARAM(flow_control, "Enable flow control ability");
+
+#define MED_LNK_DEF 0
+#define MED_LNK_MIN 0
+#define MED_LNK_MAX 4
+/* speed_duplex[] is used for setting the speed and duplex mode of NIC.
+   0: indicate autonegotiation for both speed and duplex mode
+   1: indicate 100Mbps half duplex mode
+   2: indicate 100Mbps full duplex mode
+   3: indicate 10Mbps half duplex mode
+   4: indicate 10Mbps full duplex mode
+
+   Note:
+        if EEPROM have been set to the force mode, this option is ignored
+            by driver.
+*/
+VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode");
+
+#define VAL_PKT_LEN_DEF     0
+/* ValPktLen[] is used for setting the checksum offload ability of NIC.
+   0: Receive frame with invalid layer 2 length (Default)
+   1: Drop frame with invalid layer 2 length
+*/
+VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame");
+
+#define WOL_OPT_DEF     0
+#define WOL_OPT_MIN     0
+#define WOL_OPT_MAX     7
+/* wol_opts[] is used for controlling wake on lan behavior.
+   0: Wake up if recevied a magic packet. (Default)
+   1: Wake up if link status is on/off.
+   2: Wake up if recevied an arp packet.
+   4: Wake up if recevied any unicast packet.
+   Those value can be sumed up to support more than one option.
+*/
+VELOCITY_PARAM(wol_opts, "Wake On Lan options");
+
+#define INT_WORKS_DEF   20
+#define INT_WORKS_MIN   10
+#define INT_WORKS_MAX   64
+
+VELOCITY_PARAM(int_works, "Number of packets per interrupt services");
+
+static int velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info);
+static int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev);
+static void velocity_print_info(struct velocity_info *vptr);
+static int velocity_open(struct net_device *dev);
+static int velocity_change_mtu(struct net_device *dev, int mtu);
+static int velocity_xmit(struct sk_buff *skb, struct net_device *dev);
+static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs);
+static void velocity_set_multi(struct net_device *dev);
+static struct net_device_stats *velocity_get_stats(struct net_device *dev);
+static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int velocity_close(struct net_device *dev);
+static int velocity_rx_srv(struct velocity_info *vptr, int status);
+static int velocity_receive_frame(struct velocity_info *, int idx);
+static int velocity_alloc_rx_buf(struct velocity_info *, int idx);
+static void velocity_init_registers(struct velocity_info *vptr, enum velocity_init_type type);
+static void velocity_free_rd_ring(struct velocity_info *vptr);
+static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *);
+static int velocity_soft_reset(struct velocity_info *vptr);
+static void mii_init(struct velocity_info *vptr, u32 mii_status);
+static u32 velocity_get_opt_media_mode(struct velocity_info *vptr);
+static void velocity_print_link_status(struct velocity_info *vptr);
+static void safe_disable_mii_autopoll(struct mac_regs * regs);
+static void velocity_shutdown(struct velocity_info *vptr);
+static void enable_flow_control_ability(struct velocity_info *vptr);
+static void enable_mii_autopoll(struct mac_regs * regs);
+static int velocity_mii_read(struct mac_regs *, u8 byIdx, u16 * pdata);
+static int velocity_mii_write(struct mac_regs *, u8 byMiiAddr, u16 data);
+static int velocity_set_wol(struct velocity_info *vptr);
+static void velocity_save_context(struct velocity_info *vptr, struct velocity_context *context);
+static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context);
+static u32 mii_check_media_mode(struct mac_regs * regs);
+static u32 check_connection_type(struct mac_regs * regs);
+static void velocity_init_cam_filter(struct velocity_info *vptr);
+static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status);
+
+#ifdef CONFIG_PM
+static int velocity_suspend(struct pci_dev *pdev, u32 state);
+static int velocity_resume(struct pci_dev *pdev);
+
+static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr);
+
+static struct notifier_block velocity_inetaddr_notifier = {
+      notifier_call:velocity_netdev_event,
+};
+
+#endif				/* CONFIG_PM */
+
+/*
+ *	Internal board variants. At the moment we have only one
+ */
+
+static struct velocity_info_tbl chip_info_table[] = {
+	{CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 1, 0x00FFFFFFUL},
+	{0, NULL}
+};
+
+/*
+ *	Describe the PCI device identifiers that we support in this
+ *	device driver. Used for hotplug autoloading.
+ */
+
+static struct pci_device_id velocity_id_table[] __devinitdata = {
+	{0x1106, 0x3119, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &chip_info_table[0]},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, velocity_id_table);
+
+/**
+ *	get_chip_name	- 	identifier to name
+ *	@id: chip identifier
+ *
+ *	Given a chip identifier return a suitable description. Returns
+ *	a pointer a static string valid while the driver is loaded.
+ */
+
+static char __devinit *get_chip_name(enum chip_type chip_id)
+{
+	int i;
+	for (i = 0; chip_info_table[i].name != NULL; i++)
+		if (chip_info_table[i].chip_id == chip_id)
+			break;
+	return chip_info_table[i].name;
+}
+
+/**
+ *	velocity_remove1	-	device unplug
+ *	@pdev: PCI device being removed
+ *
+ *	Device unload callback. Called on an unplug or on module
+ *	unload for each active device that is present. Disconnects
+ *	the device from the network layer and frees all the resources
+ */
+
+static void __devexit velocity_remove1(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct velocity_info *vptr = dev->priv;
+
+	unregister_netdev(dev);
+	iounmap(vptr->mac_regs);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(dev);
+}
+
+/**
+ *	velocity_set_int_opt	-	parser for integer options
+ *	@opt: pointer to option value
+ *	@val: value the user requested (or -1 for default)
+ *	@min: lowest value allowed
+ *	@max: highest value allowed
+ *	@def: default value
+ *	@name: property name
+ *	@dev: device name
+ *
+ *	Set an integer property in the module options. This function does
+ *	all the verification and checking as well as reporting so that
+ *	we don't duplicate code for each option.
+ */
+
+static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, char *devname)
+{
+	if (val == -1)
+		*opt = def;
+	else if (val < min || val > max) {
+		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n",
+					devname, name, min, max);
+		*opt = def;
+	} else {
+		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n",
+					devname, name, val);
+		*opt = val;
+	}
+}
+
+/**
+ *	velocity_set_bool_opt	-	parser for boolean options
+ *	@opt: pointer to option value
+ *	@val: value the user requested (or -1 for default)
+ *	@def: default value (yes/no)
+ *	@flag: numeric value to set for true.
+ *	@name: property name
+ *	@dev: device name
+ *
+ *	Set a boolean property in the module options. This function does
+ *	all the verification and checking as well as reporting so that
+ *	we don't duplicate code for each option.
+ */
+
+static void __devinit velocity_set_bool_opt(u32 * opt, int val, int def, u32 flag, char *name, char *devname)
+{
+	(*opt) &= (~flag);
+	if (val == -1)
+		*opt |= (def ? flag : 0);
+	else if (val < 0 || val > 1) {
+		printk(KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (0-1)\n", 
+			devname, name);
+		*opt |= (def ? flag : 0);
+	} else {
+		printk(KERN_INFO "%s: set parameter %s to %s\n", 
+			devname, name, val ? "TRUE" : "FALSE");
+		*opt |= (val ? flag : 0);
+	}
+}
+
+/**
+ *	velocity_get_options	-	set options on device
+ *	@opts: option structure for the device
+ *	@index: index of option to use in module options array
+ *	@devname: device name
+ *
+ *	Turn the module and command options into a single structure
+ *	for the current device
+ */
+
+static void __devinit velocity_get_options(struct velocity_opt *opts, int index, char *devname)
+{
+
+	velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname);
+	velocity_set_int_opt(&opts->DMA_length, DMA_length[index], DMA_LENGTH_MIN, DMA_LENGTH_MAX, DMA_LENGTH_DEF, "DMA_length", devname);
+	velocity_set_int_opt(&opts->numrx, RxDescriptors[index], RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF, "RxDescriptors", devname);
+	velocity_set_int_opt(&opts->numtx, TxDescriptors[index], TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF, "TxDescriptors", devname);
+	velocity_set_int_opt(&opts->vid, VID_setting[index], VLAN_ID_MIN, VLAN_ID_MAX, VLAN_ID_DEF, "VID_setting", devname);
+	velocity_set_bool_opt(&opts->flags, enable_tagging[index], TAGGING_DEF, VELOCITY_FLAGS_TAGGING, "enable_tagging", devname);
+	velocity_set_bool_opt(&opts->flags, txcsum_offload[index], TX_CSUM_DEF, VELOCITY_FLAGS_TX_CSUM, "txcsum_offload", devname);
+	velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname);
+	velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname);
+	velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname);
+	velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname);
+	velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);
+	velocity_set_int_opt((int *) &opts->int_works, int_works[index], INT_WORKS_MIN, INT_WORKS_MAX, INT_WORKS_DEF, "Interrupt service works", devname);
+	opts->numrx = (opts->numrx & ~3);
+}
+
+/**
+ *	velocity_init_cam_filter	-	initialise CAM
+ *	@vptr: velocity to program
+ *
+ *	Initialize the content addressable memory used for filters. Load
+ *	appropriately according to the presence of VLAN
+ */
+
+static void velocity_init_cam_filter(struct velocity_info *vptr)
+{
+	struct mac_regs * regs = vptr->mac_regs;
+
+	/* T urn on MCFG_PQEN, turn off MCFG_RTGOPT */
+	WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
+	WORD_REG_BITS_ON(MCFG_VIDFR, &regs->MCFG);
+
+	/* Disable all CAMs */
+	memset(vptr->vCAMmask, 0, sizeof(u8) * 8);
+	memset(vptr->mCAMmask, 0, sizeof(u8) * 8);
+	mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM);
+	mac_set_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM);
+
+	/* Enable first VCAM */
+	if (vptr->flags & VELOCITY_FLAGS_TAGGING) {
+		/* If Tagging option is enabled and VLAN ID is not zero, then
+		   turn on MCFG_RTGOPT also */
+		if (vptr->options.vid != 0)
+			WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
+
+		mac_set_cam(regs, 0, (u8 *) & (vptr->options.vid), VELOCITY_VLAN_ID_CAM);
+		vptr->vCAMmask[0] |= 1;
+		mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM);
+	} else {
+		u16 temp = 0;
+		mac_set_cam(regs, 0, (u8 *) &temp, VELOCITY_VLAN_ID_CAM);
+		temp = 1;
+		mac_set_cam_mask(regs, (u8 *) &temp, VELOCITY_VLAN_ID_CAM);
+	}
+}
+
+/**
+ *	velocity_rx_reset	-	handle a receive reset
+ *	@vptr: velocity we are resetting
+ *
+ *	Reset the ownership and status for the receive ring side.
+ *	Hand all the receive queue to the NIC.
+ */
+
+static void velocity_rx_reset(struct velocity_info *vptr)
+{
+
+	struct mac_regs * regs = vptr->mac_regs;
+	int i;
+
+	vptr->rd_used = vptr->rd_curr = 0;
+
+	/*
+	 *	Init state, all RD entries belong to the NIC
+	 */
+	for (i = 0; i < vptr->options.numrx; ++i)
+		vptr->rd_ring[i].rdesc0.owner = cpu_to_le32(OWNED_BY_NIC);
+
+	writew(vptr->options.numrx, &regs->RBRDU);
+	writel(vptr->rd_pool_dma, &regs->RDBaseLo);
+	writew(0, &regs->RDIdx);
+	writew(vptr->options.numrx - 1, &regs->RDCSize);
+}
+
+/**
+ *	velocity_init_registers	-	initialise MAC registers
+ *	@vptr: velocity to init
+ *	@type: type of initialisation (hot or cold)
+ *
+ *	Initialise the MAC on a reset or on first set up on the
+ *	hardware.
+ */
+
+static void velocity_init_registers(struct velocity_info *vptr, 
+				    enum velocity_init_type type)
+{
+	struct mac_regs * regs = vptr->mac_regs;
+	int i, mii_status;
+
+	mac_wol_reset(regs);
+
+	switch (type) {
+	case VELOCITY_INIT_RESET:
+	case VELOCITY_INIT_WOL:
+
+		netif_stop_queue(vptr->dev);
+
+		/*
+		 *	Reset RX to prevent RX pointer not on the 4X location
+		 */
+		velocity_rx_reset(vptr);
+		mac_rx_queue_run(regs);
+		mac_rx_queue_wake(regs);
+
+		mii_status = velocity_get_opt_media_mode(vptr);
+		if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
+			velocity_print_link_status(vptr);
+			if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
+				netif_wake_queue(vptr->dev);
+		}
+
+		enable_flow_control_ability(vptr);
+
+		mac_clear_isr(regs);
+		writel(CR0_STOP, &regs->CR0Clr);
+		writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), 
+							&regs->CR0Set);
+
+		break;
+
+	case VELOCITY_INIT_COLD:
+	default:
+		/*
+		 *	Do reset
+		 */
+		velocity_soft_reset(vptr);
+		mdelay(5);
+
+		mac_eeprom_reload(regs);
+		for (i = 0; i < 6; i++) {
+			writeb(vptr->dev->dev_addr[i], &(regs->PAR[i]));
+		}
+		/*
+		 *	clear Pre_ACPI bit.
+		 */
+		BYTE_REG_BITS_OFF(CFGA_PACPI, &(regs->CFGA));
+		mac_set_rx_thresh(regs, vptr->options.rx_thresh);
+		mac_set_dma_length(regs, vptr->options.DMA_length);
+
+		writeb(WOLCFG_SAM | WOLCFG_SAB, &regs->WOLCFGSet);
+		/*
+		 *	Bback off algorithm use original IEEE standard
+		 */
+		BYTE_REG_BITS_SET(CFGB_OFSET, (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), &regs->CFGB);
+
+		/*
+		 *	Set packet filter: Receive directed and broadcast address
+		 */
+		velocity_set_multi(vptr->dev);
+
+		/*
+		 *	Enable MII auto-polling
+		 */
+		enable_mii_autopoll(regs);
+
+		vptr->int_mask = INT_MASK_DEF;
+
+		writel(cpu_to_le32(vptr->rd_pool_dma), &regs->RDBaseLo);
+		writew(vptr->options.numrx - 1, &regs->RDCSize);
+		mac_rx_queue_run(regs);
+		mac_rx_queue_wake(regs);
+
+		writew(vptr->options.numtx - 1, &regs->TDCSize);
+
+		for (i = 0; i < vptr->num_txq; i++) {
+			writel(cpu_to_le32(vptr->td_pool_dma[i]), &(regs->TDBaseLo[i]));
+			mac_tx_queue_run(regs, i);
+		}
+
+		velocity_init_cam_filter(vptr);
+
+		init_flow_control_register(vptr);
+
+		writel(CR0_STOP, &regs->CR0Clr);
+		writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), &regs->CR0Set);
+
+		mii_status = velocity_get_opt_media_mode(vptr);
+		netif_stop_queue(vptr->dev);
+		mac_clear_isr(regs);
+
+		mii_init(vptr, mii_status);
+
+		if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
+			velocity_print_link_status(vptr);
+			if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
+				netif_wake_queue(vptr->dev);
+		}
+
+		enable_flow_control_ability(vptr);
+		mac_hw_mibs_init(regs);
+		mac_write_int_mask(vptr->int_mask, regs);
+		mac_clear_isr(regs);
+
+	}
+}
+
+/**
+ *	velocity_soft_reset	-	soft reset
+ *	@vptr: velocity to reset
+ *
+ *	Kick off a soft reset of the velocity adapter and then poll
+ *	until the reset sequence has completed before returning.
+ */
+
+static int velocity_soft_reset(struct velocity_info *vptr)
+{
+	struct mac_regs * regs = vptr->mac_regs;
+	int i = 0;
+
+	writel(CR0_SFRST, &regs->CR0Set);
+
+	for (i = 0; i < W_MAX_TIMEOUT; i++) {
+		udelay(5);
+		if (!DWORD_REG_BITS_IS_ON(CR0_SFRST, &regs->CR0Set))
+			break;
+	}
+
+	if (i == W_MAX_TIMEOUT) {
+		writel(CR0_FORSRST, &regs->CR0Set);
+		/* FIXME: PCI POSTING */
+		/* delay 2ms */
+		mdelay(2);
+	}
+	return 0;
+}
+
+/**
+ *	velocity_found1		-	set up discovered velocity card
+ *	@pdev: PCI device
+ *	@ent: PCI device table entry that matched
+ *
+ *	Configure a discovered adapter from scratch. Return a negative
+ *	errno error code on failure paths.
+ */
+
+static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int first = 1;
+	struct net_device *dev;
+	int i;
+	struct velocity_info_tbl *info = (struct velocity_info_tbl *) ent->driver_data;
+	struct velocity_info *vptr;
+	struct mac_regs * regs;
+	int ret = -ENOMEM;
+
+	if (velocity_nics++ >= MAX_UNITS) {
+		printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs.\n", 
+				velocity_nics);
+		return -ENODEV;
+	}
+
+	dev = alloc_etherdev(sizeof(struct velocity_info));
+
+	if (dev == NULL) {
+		printk(KERN_ERR VELOCITY_NAME ": allocate net device failed.\n");
+		goto out;
+	}
+	
+	/* Chain it all together */
+	
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	vptr = dev->priv;
+
+
+	if (first) {
+		printk(KERN_INFO "%s Ver. %s\n", 
+			VELOCITY_FULL_DRV_NAM, VELOCITY_VERSION);
+		printk(KERN_INFO "Copyright (c) 2002, 2003 VIA Networking Technologies, Inc.\n");
+		printk(KERN_INFO "Copyright (c) 2004 Red Hat Inc.\n");
+		first = 0;
+	}
+
+	velocity_init_info(pdev, vptr, info);
+
+	vptr->dev = dev;
+
+	dev->priv = vptr;
+	dev->irq = pdev->irq;
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0) 
+		goto err_free_dev;
+
+	ret = velocity_get_pci_info(vptr, pdev);
+	if (ret < 0) {
+		printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device.\n");
+		goto err_disable;
+	}
+
+	ret = pci_request_regions(pdev, VELOCITY_NAME);
+	if (ret < 0) {
+		printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device.\n");
+		goto err_disable;
+	}
+
+	regs = ioremap(vptr->memaddr, vptr->io_size);
+	if (regs == NULL) {
+		ret = -EIO;
+		goto err_release_res;
+	}
+
+	vptr->mac_regs = regs;
+
+	mac_wol_reset(regs);
+
+	dev->base_addr = vptr->ioaddr;
+
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = readb(&regs->PAR[i]);
+
+
+	velocity_get_options(&vptr->options, velocity_nics - 1, dev->name);
+
+	/* 
+	 *	Mask out the options cannot be set to the chip
+	 */
+	 
+	vptr->options.flags &= info->flags;
+
+	/*
+	 *	Enable the chip specified capbilities
+	 */
+	 
+	vptr->flags = vptr->options.flags | (info->flags & 0xFF000000UL);
+
+	vptr->wol_opts = vptr->options.wol_opts;
+	vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
+
+	vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
+
+	dev->irq = pdev->irq;
+	dev->open = velocity_open;
+	dev->hard_start_xmit = velocity_xmit;
+	dev->stop = velocity_close;
+	dev->get_stats = velocity_get_stats;
+	dev->set_multicast_list = velocity_set_multi;
+	dev->do_ioctl = velocity_ioctl;
+	dev->ethtool_ops = &velocity_ethtool_ops;
+	dev->change_mtu = velocity_change_mtu;
+#ifdef  VELOCITY_ZERO_COPY_SUPPORT
+	dev->features |= NETIF_F_SG;
+#endif
+
+	if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) {
+		dev->features |= NETIF_F_HW_CSUM;
+	}
+
+	ret = register_netdev(dev);
+	if (ret < 0)
+		goto err_iounmap;
+
+	velocity_print_info(vptr);
+	pci_set_drvdata(pdev, dev);
+	
+	/* and leave the chip powered down */
+	
+	pci_set_power_state(pdev, 3);
+out:
+	return ret;
+
+err_iounmap:
+	iounmap(regs);
+err_release_res:
+	pci_release_regions(pdev);
+err_disable:
+	pci_disable_device(pdev);
+err_free_dev:
+	free_netdev(dev);
+	goto out;
+}
+
+/**
+ *	velocity_print_info	-	per driver data
+ *	@vptr: velocity
+ *
+ *	Print per driver data as the kernel driver finds Velocity
+ *	hardware
+ */
+
+static void __devinit velocity_print_info(struct velocity_info *vptr)
+{
+	struct net_device *dev = vptr->dev;
+
+	printk(KERN_INFO "%s: %s\n", dev->name, get_chip_name(vptr->chip_id));
+	printk(KERN_INFO "%s: Ethernet Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", 
+		dev->name, 
+		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], 
+		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+}
+
+/**
+ *	velocity_init_info	-	init private data
+ *	@pdev: PCI device
+ *	@vptr: Velocity info
+ *	@info: Board type
+ *
+ *	Set up the initial velocity_info struct for the device that has been
+ *	discovered.
+ */
+
+static void __devinit velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info)
+{
+	memset(vptr, 0, sizeof(struct velocity_info));
+
+	vptr->pdev = pdev;
+	vptr->chip_id = info->chip_id;
+	vptr->io_size = info->io_size;
+	vptr->num_txq = info->txqueue;
+	vptr->multicast_limit = MCAM_SIZE;
+
+	spin_lock_init(&vptr->lock);
+	spin_lock_init(&vptr->xmit_lock);
+}
+
+/**
+ *	velocity_get_pci_info	-	retrieve PCI info for device
+ *	@vptr: velocity device
+ *	@pdev: PCI device it matches
+ *
+ *	Retrieve the PCI configuration space data that interests us from
+ *	the kernel PCI layer
+ */
+
+static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
+{
+
+	if(pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0)
+		return -EIO;
+		
+	pci_set_master(pdev);
+
+	vptr->ioaddr = pci_resource_start(pdev, 0);
+	vptr->memaddr = pci_resource_start(pdev, 1);
+	
+	if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO))
+	{
+		printk(KERN_ERR "%s: region #0 is not an I/O resource, aborting.\n",
+				pci_name(pdev));
+		return -EINVAL;
+	}
+
+	if((pci_resource_flags(pdev, 1) & IORESOURCE_IO))
+	{
+		printk(KERN_ERR "%s: region #1 is an I/O resource, aborting.\n",
+				pci_name(pdev));
+		return -EINVAL;
+	}
+
+	if(pci_resource_len(pdev, 1) < 256)
+	{
+		printk(KERN_ERR "%s: region #1 is too small.\n", 
+				pci_name(pdev));
+		return -EINVAL;
+	}
+	vptr->pdev = pdev;
+
+	return 0;
+}
+
+/**
+ *	velocity_init_rings	-	set up DMA rings
+ *	@vptr: Velocity to set up
+ *
+ *	Allocate PCI mapped DMA rings for the receive and transmit layer
+ *	to use.
+ */
+
+static int velocity_init_rings(struct velocity_info *vptr)
+{
+	int i;
+	unsigned int psize;
+	unsigned int tsize;
+	dma_addr_t pool_dma;
+	u8 *pool;
+
+	/*
+	 *	Allocate all RD/TD rings a single pool 
+	 */
+	 
+	psize = vptr->options.numrx * sizeof(struct rx_desc) + 
+		vptr->options.numtx * sizeof(struct tx_desc) * vptr->num_txq;
+
+	/*
+	 * pci_alloc_consistent() fulfills the requirement for 64 bytes
+	 * alignment
+	 */
+	pool = pci_alloc_consistent(vptr->pdev, psize, &pool_dma);
+
+	if (pool == NULL) {
+		printk(KERN_ERR "%s : DMA memory allocation failed.\n", 
+					vptr->dev->name);
+		return -ENOMEM;
+	}
+
+	memset(pool, 0, psize);
+
+	vptr->rd_ring = (struct rx_desc *) pool;
+
+	vptr->rd_pool_dma = pool_dma;
+
+	tsize = vptr->options.numtx * PKT_BUF_SZ * vptr->num_txq;
+	vptr->tx_bufs = pci_alloc_consistent(vptr->pdev, tsize, 
+						&vptr->tx_bufs_dma);
+
+	if (vptr->tx_bufs == NULL) {
+		printk(KERN_ERR "%s: DMA memory allocation failed.\n", 
+					vptr->dev->name);
+		pci_free_consistent(vptr->pdev, psize, pool, pool_dma);
+		return -ENOMEM;
+	}
+
+	memset(vptr->tx_bufs, 0, vptr->options.numtx * PKT_BUF_SZ * vptr->num_txq);
+
+	i = vptr->options.numrx * sizeof(struct rx_desc);
+	pool += i;
+	pool_dma += i;
+	for (i = 0; i < vptr->num_txq; i++) {
+		int offset = vptr->options.numtx * sizeof(struct tx_desc);
+
+		vptr->td_pool_dma[i] = pool_dma;
+		vptr->td_rings[i] = (struct tx_desc *) pool;
+		pool += offset;
+		pool_dma += offset;
+	}
+	return 0;
+}
+
+/**
+ *	velocity_free_rings	-	free PCI ring pointers
+ *	@vptr: Velocity to free from
+ *
+ *	Clean up the PCI ring buffers allocated to this velocity.
+ */
+
+static void velocity_free_rings(struct velocity_info *vptr)
+{
+	int size;
+
+	size = vptr->options.numrx * sizeof(struct rx_desc) + 
+	       vptr->options.numtx * sizeof(struct tx_desc) * vptr->num_txq;
+
+	pci_free_consistent(vptr->pdev, size, vptr->rd_ring, vptr->rd_pool_dma);
+
+	size = vptr->options.numtx * PKT_BUF_SZ * vptr->num_txq;
+
+	pci_free_consistent(vptr->pdev, size, vptr->tx_bufs, vptr->tx_bufs_dma);
+}
+
+/**
+ *	velocity_init_rd_ring	-	set up receive ring
+ *	@vptr: velocity to configure
+ *
+ *	Allocate and set up the receive buffers for each ring slot and
+ *	assign them to the network adapter.
+ */
+
+static int velocity_init_rd_ring(struct velocity_info *vptr)
+{
+	int i, ret = -ENOMEM;
+	struct rx_desc *rd;
+	struct velocity_rd_info *rd_info;
+	unsigned int rsize = sizeof(struct velocity_rd_info) * 
+					vptr->options.numrx;
+
+	vptr->rd_info = kmalloc(rsize, GFP_KERNEL);
+	if(vptr->rd_info == NULL)
+		goto out;
+	memset(vptr->rd_info, 0, rsize);
+
+	/* Init the RD ring entries */
+	for (i = 0; i < vptr->options.numrx; i++) {
+		rd = &(vptr->rd_ring[i]);
+		rd_info = &(vptr->rd_info[i]);
+
+		ret = velocity_alloc_rx_buf(vptr, i);
+		if (ret < 0) {
+			VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
+				"%s: failed to allocate RX buffer.\n", 
+				vptr->dev->name);
+			velocity_free_rd_ring(vptr);
+			goto out;
+		}
+		rd->rdesc0.owner = OWNED_BY_NIC;
+	}
+	vptr->rd_used = vptr->rd_curr = 0;
+out:
+	return ret;
+}
+
+/**
+ *	velocity_free_rd_ring	-	set up receive ring
+ *	@vptr: velocity to clean up
+ *
+ *	Free the receive buffers for each ring slot and any
+ *	attached socket buffers that need to go away.
+ */
+
+static void velocity_free_rd_ring(struct velocity_info *vptr)
+{
+	int i;
+
+	if (vptr->rd_info == NULL)
+		return;
+
+	for (i = 0; i < vptr->options.numrx; i++) {
+		struct velocity_rd_info *rd_info = &(vptr->rd_info[i]);
+
+		if (!rd_info->skb_dma)
+			continue;
+		pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz,
+				 PCI_DMA_FROMDEVICE);
+		rd_info->skb_dma = (dma_addr_t) NULL;
+
+		dev_kfree_skb(rd_info->skb);
+		rd_info->skb = NULL;
+	}
+
+	kfree(vptr->rd_info);
+	vptr->rd_info = NULL;
+}
+
+/**
+ *	velocity_init_td_ring	-	set up transmit ring
+ *	@vptr:	velocity
+ *
+ *	Set up the transmit ring and chain the ring pointers together.
+ *	Returns zero on success or a negative posix errno code for
+ *	failure.
+ */
+ 
+static int velocity_init_td_ring(struct velocity_info *vptr)
+{
+	int i, j;
+	dma_addr_t curr;
+	struct tx_desc *td;
+	struct velocity_td_info *td_info;
+	unsigned int tsize = sizeof(struct velocity_td_info) * 
+					vptr->options.numtx;
+
+	/* Init the TD ring entries */
+	for (j = 0; j < vptr->num_txq; j++) {
+		curr = vptr->td_pool_dma[j];
+
+		vptr->td_infos[j] = kmalloc(tsize, GFP_KERNEL);
+		if(vptr->td_infos[j] == NULL)
+		{
+			while(--j >= 0)
+				kfree(vptr->td_infos[j]);
+			return -ENOMEM;
+		}
+		memset(vptr->td_infos[j], 0, tsize);
+
+		for (i = 0; i < vptr->options.numtx; i++, curr += sizeof(struct tx_desc)) {
+			td = &(vptr->td_rings[j][i]);
+			td_info = &(vptr->td_infos[j][i]);
+			td_info->buf = vptr->tx_bufs + (i + j) * PKT_BUF_SZ;
+			td_info->buf_dma = vptr->tx_bufs_dma + (i + j) * PKT_BUF_SZ;
+		}
+		vptr->td_tail[j] = vptr->td_curr[j] = vptr->td_used[j] = 0;
+	}
+	return 0;
+}
+
+/*
+ *	FIXME: could we merge this with velocity_free_tx_buf ?
+ */
+
+static void velocity_free_td_ring_entry(struct velocity_info *vptr,
+							 int q, int n)
+{
+	struct velocity_td_info * td_info = &(vptr->td_infos[q][n]);
+	int i;
+	
+	if (td_info == NULL)
+		return;
+		
+	if (td_info->skb) {
+		for (i = 0; i < td_info->nskb_dma; i++)
+		{
+			if (td_info->skb_dma[i]) {
+				pci_unmap_single(vptr->pdev, td_info->skb_dma[i], 
+					td_info->skb->len, PCI_DMA_TODEVICE);
+				td_info->skb_dma[i] = (dma_addr_t) NULL;
+			}
+		}
+		dev_kfree_skb(td_info->skb);
+		td_info->skb = NULL;
+	}
+}
+
+/**
+ *	velocity_free_td_ring	-	free td ring
+ *	@vptr: velocity
+ *
+ *	Free up the transmit ring for this particular velocity adapter.
+ *	We free the ring contents but not the ring itself.
+ */
+ 
+static void velocity_free_td_ring(struct velocity_info *vptr)
+{
+	int i, j;
+
+	for (j = 0; j < vptr->num_txq; j++) {
+		if (vptr->td_infos[j] == NULL)
+			continue;
+		for (i = 0; i < vptr->options.numtx; i++) {
+			velocity_free_td_ring_entry(vptr, j, i);
+
+		}
+		if (vptr->td_infos[j]) {
+			kfree(vptr->td_infos[j]);
+			vptr->td_infos[j] = NULL;
+		}
+	}
+}
+
+/**
+ *	velocity_rx_srv		-	service RX interrupt
+ *	@vptr: velocity
+ *	@status: adapter status (unused)
+ *
+ *	Walk the receive ring of the velocity adapter and remove
+ *	any received packets from the receive queue. Hand the ring
+ *	slots back to the adapter for reuse.
+ */
+ 
+static int velocity_rx_srv(struct velocity_info *vptr, int status)
+{
+	struct rx_desc *rd;
+	struct net_device_stats *stats = &vptr->stats;
+	struct mac_regs * regs = vptr->mac_regs;
+	int rd_curr = vptr->rd_curr;
+	int works = 0;
+
+	while (1) {
+
+		rd = &(vptr->rd_ring[rd_curr]);
+
+		if ((vptr->rd_info[rd_curr]).skb == NULL) {
+			if (velocity_alloc_rx_buf(vptr, rd_curr) < 0)
+				break;
+		}
+
+		if (works++ > 15)
+			break;
+
+		if (rd->rdesc0.owner == OWNED_BY_NIC)
+			break;
+
+		/*
+		 *	Don't drop CE or RL error frame although RXOK is off
+		 *	FIXME: need to handle copybreak
+		 */
+		if ((rd->rdesc0.RSR & RSR_RXOK) || (!(rd->rdesc0.RSR & RSR_RXOK) && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) {
+			if (velocity_receive_frame(vptr, rd_curr) == 0) {
+				if (velocity_alloc_rx_buf(vptr, rd_curr) < 0) {
+					VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not allocate rx buf\n", vptr->dev->name);
+					break;
+				}
+			} else {
+				stats->rx_dropped++;
+			}
+		} else {
+			if (rd->rdesc0.RSR & RSR_CRC)
+				stats->rx_crc_errors++;
+			if (rd->rdesc0.RSR & RSR_FAE)
+				stats->rx_frame_errors++;
+
+			stats->rx_dropped++;
+		}
+
+		rd->inten = 1;
+
+		if (++vptr->rd_used >= 4) {
+			int i, rd_prev = rd_curr;
+			for (i = 0; i < 4; i++) {
+				if (--rd_prev < 0)
+					rd_prev = vptr->options.numrx - 1;
+
+				rd = &(vptr->rd_ring[rd_prev]);
+				rd->rdesc0.owner = OWNED_BY_NIC;
+			}
+			writew(4, &(regs->RBRDU));
+			vptr->rd_used -= 4;
+		}
+
+		vptr->dev->last_rx = jiffies;
+
+		rd_curr++;
+		if (rd_curr >= vptr->options.numrx)
+			rd_curr = 0;
+	}
+	vptr->rd_curr = rd_curr;
+	VAR_USED(stats);
+	return works;
+}
+
+/**
+ *	velocity_rx_csum	-	checksum process
+ *	@rd: receive packet descriptor
+ *	@skb: network layer packet buffer
+ *
+ *	Process the status bits for the received packet and determine
+ *	if the checksum was computed and verified by the hardware
+ */
+ 
+static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
+{
+	skb->ip_summed = CHECKSUM_NONE;
+
+	if (rd->rdesc1.CSM & CSM_IPKT) {
+		if (rd->rdesc1.CSM & CSM_IPOK) {
+			if ((rd->rdesc1.CSM & CSM_TCPKT) || 
+					(rd->rdesc1.CSM & CSM_UDPKT)) {
+				if (!(rd->rdesc1.CSM & CSM_TUPOK)) {
+					return;
+				}
+			}
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		}
+	}
+}
+
+/**
+ *	velocity_receive_frame	-	received packet processor
+ *	@vptr: velocity we are handling
+ *	@idx: ring index
+ *	
+ *	A packet has arrived. We process the packet and if appropriate
+ *	pass the frame up the network stack
+ */
+ 
+static int velocity_receive_frame(struct velocity_info *vptr, int idx)
+{
+	struct net_device_stats *stats = &vptr->stats;
+	struct velocity_rd_info *rd_info = &(vptr->rd_info[idx]);
+	struct rx_desc *rd = &(vptr->rd_ring[idx]);
+	struct sk_buff *skb;
+
+	if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
+		VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->dev->name);
+		stats->rx_length_errors++;
+		return -EINVAL;
+	}
+
+	if (rd->rdesc0.RSR & RSR_MAR)
+		vptr->stats.multicast++;
+
+	skb = rd_info->skb;
+	skb->dev = vptr->dev;
+
+	pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz, 
+							PCI_DMA_FROMDEVICE);
+	rd_info->skb_dma = (dma_addr_t) NULL;
+	rd_info->skb = NULL;
+
+	/* FIXME - memmove ? */
+	if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) {
+		int i;
+		for (i = rd->rdesc0.len + 4; i >= 0; i--)
+			*(skb->data + i + 2) = *(skb->data + i);
+		skb->data += 2;
+		skb->tail += 2;
+	}
+
+	skb_put(skb, (rd->rdesc0.len - 4));
+	skb->protocol = eth_type_trans(skb, skb->dev);
+
+	/*
+	 *	Drop frame not meeting IEEE 802.3
+	 */
+	 
+	if (vptr->flags & VELOCITY_FLAGS_VAL_PKT_LEN) {
+		if (rd->rdesc0.RSR & RSR_RL) {
+			stats->rx_length_errors++;
+			return -EINVAL;
+		}
+	}
+
+	velocity_rx_csum(rd, skb);
+	
+	/*
+	 *	FIXME: need rx_copybreak handling
+	 */
+
+	stats->rx_bytes += skb->len;
+	netif_rx(skb);
+
+	return 0;
+}
+
+/**
+ *	velocity_alloc_rx_buf	-	allocate aligned receive buffer
+ *	@vptr: velocity
+ *	@idx: ring index
+ *
+ *	Allocate a new full sized buffer for the reception of a frame and
+ *	map it into PCI space for the hardware to use. The hardware
+ *	requires *64* byte alignment of the buffer which makes life
+ *	less fun than would be ideal.
+ */
+ 
+static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
+{
+	struct rx_desc *rd = &(vptr->rd_ring[idx]);
+	struct velocity_rd_info *rd_info = &(vptr->rd_info[idx]);
+
+	rd_info->skb = dev_alloc_skb(vptr->rx_buf_sz + 64);
+	if (rd_info->skb == NULL)
+		return -ENOMEM;
+
+	/*
+	 *	Do the gymnastics to get the buffer head for data at
+	 *	64byte alignment.
+	 */
+	skb_reserve(rd_info->skb, (unsigned long) rd_info->skb->tail & 63);
+	rd_info->skb->dev = vptr->dev;
+	rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->tail, vptr->rx_buf_sz, PCI_DMA_FROMDEVICE);
+	
+	/*
+	 *	Fill in the descriptor to match
+ 	 */	
+ 	 
+	*((u32 *) & (rd->rdesc0)) = 0;
+	rd->len = cpu_to_le32(vptr->rx_buf_sz);
+	rd->inten = 1;
+	rd->pa_low = cpu_to_le32(rd_info->skb_dma);
+	rd->pa_high = 0;
+	return 0;
+}
+
+/**
+ *	tx_srv		-	transmit interrupt service
+ *	@vptr; Velocity
+ *	@status:
+ *
+ *	Scan the queues looking for transmitted packets that
+ *	we can complete and clean up. Update any statistics as
+ *	neccessary/
+ */
+ 
+static int velocity_tx_srv(struct velocity_info *vptr, u32 status)
+{
+	struct tx_desc *td;
+	int qnum;
+	int full = 0;
+	int idx;
+	int works = 0;
+	struct velocity_td_info *tdinfo;
+	struct net_device_stats *stats = &vptr->stats;
+
+	for (qnum = 0; qnum < vptr->num_txq; qnum++) {
+		for (idx = vptr->td_tail[qnum]; vptr->td_used[qnum] > 0; 
+			idx = (idx + 1) % vptr->options.numtx) {
+
+			/*
+			 *	Get Tx Descriptor
+			 */
+			td = &(vptr->td_rings[qnum][idx]);
+			tdinfo = &(vptr->td_infos[qnum][idx]);
+
+			if (td->tdesc0.owner == OWNED_BY_NIC)
+				break;
+
+			if ((works++ > 15))
+				break;
+
+			if (td->tdesc0.TSR & TSR0_TERR) {
+				stats->tx_errors++;
+				stats->tx_dropped++;
+				if (td->tdesc0.TSR & TSR0_CDH)
+					stats->tx_heartbeat_errors++;
+				if (td->tdesc0.TSR & TSR0_CRS)
+					stats->tx_carrier_errors++;
+				if (td->tdesc0.TSR & TSR0_ABT)
+					stats->tx_aborted_errors++;
+				if (td->tdesc0.TSR & TSR0_OWC)
+					stats->tx_window_errors++;
+			} else {
+				stats->tx_packets++;
+				stats->tx_bytes += tdinfo->skb->len;
+			}
+			velocity_free_tx_buf(vptr, tdinfo);
+			vptr->td_used[qnum]--;
+		}
+		vptr->td_tail[qnum] = idx;
+
+		if (AVAIL_TD(vptr, qnum) < 1) {
+			full = 1;
+		}
+	}
+	/*
+	 *	Look to see if we should kick the transmit network
+	 *	layer for more work.
+	 */
+	if (netif_queue_stopped(vptr->dev) && (full == 0)
+	    && (!(vptr->mii_status & VELOCITY_LINK_FAIL))) {
+		netif_wake_queue(vptr->dev);
+	}
+	return works;
+}
+
+/**
+ *	velocity_print_link_status	-	link status reporting
+ *	@vptr: velocity to report on
+ *
+ *	Turn the link status of the velocity card into a kernel log
+ *	description of the new link state, detailing speed and duplex
+ *	status
+ */
+
+static void velocity_print_link_status(struct velocity_info *vptr)
+{
+
+	if (vptr->mii_status & VELOCITY_LINK_FAIL) {
+		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);
+	} else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
+		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link autonegation", vptr->dev->name);
+
+		if (vptr->mii_status & VELOCITY_SPEED_1000)
+			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");
+		else if (vptr->mii_status & VELOCITY_SPEED_100)
+			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps");
+		else
+			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps");
+
+		if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+			VELOCITY_PRT(MSG_LEVEL_INFO, " full duplex\n");
+		else
+			VELOCITY_PRT(MSG_LEVEL_INFO, " half duplex\n");
+	} else {
+		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);
+		switch (vptr->options.spd_dpx) {
+		case SPD_DPX_100_HALF:
+			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n");
+			break;
+		case SPD_DPX_100_FULL:
+			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps full duplex\n");
+			break;
+		case SPD_DPX_10_HALF:
+			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps half duplex\n");
+			break;
+		case SPD_DPX_10_FULL:
+			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps full duplex\n");
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+/**
+ *	velocity_error	-	handle error from controller
+ *	@vptr: velocity
+ *	@status: card status
+ *
+ *	Process an error report from the hardware and attempt to recover
+ *	the card itself. At the moment we cannot recover from some 
+ *	theoretically impossible errors but this could be fixed using
+ *	the pci_device_failed logic to bounce the hardware
+ *
+ */
+ 
+static void velocity_error(struct velocity_info *vptr, int status)
+{
+
+	if (status & ISR_TXSTLI) {
+		struct mac_regs * regs = vptr->mac_regs;
+
+		printk(KERN_ERR "TD structure errror TDindex=%hx\n", readw(&regs->TDIdx[0]));
+		BYTE_REG_BITS_ON(TXESR_TDSTR, &regs->TXESR);
+		writew(TRDCSR_RUN, &regs->TDCSRClr);
+		netif_stop_queue(vptr->dev);
+		
+		/* FIXME: port over the pci_device_failed code and use it
+		   here */
+	}
+
+	if (status & ISR_SRCI) {
+		struct mac_regs * regs = vptr->mac_regs;
+		int linked;
+
+		if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
+			vptr->mii_status = check_connection_type(regs);
+
+			/*
+			 *	If it is a 3119, disable frame bursting in 
+			 *	halfduplex mode and enable it in fullduplex
+			 *	 mode
+			 */
+			if (vptr->rev_id < REV_ID_VT3216_A0) {
+				if (vptr->mii_status | VELOCITY_DUPLEX_FULL)
+					BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
+				else
+					BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
+			}
+			/*
+			 *	Only enable CD heart beat counter in 10HD mode
+			 */
+			if (!(vptr->mii_status & VELOCITY_DUPLEX_FULL) && (vptr->mii_status & VELOCITY_SPEED_10)) {
+				BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
+			} else {
+				BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
+			}
+		}
+		/*
+		 *	Get link status from PHYSR0
+		 */
+		linked = readb(&regs->PHYSR0) & PHYSR0_LINKGD;
+
+		if (linked) {
+			vptr->mii_status &= ~VELOCITY_LINK_FAIL;
+		} else {
+			vptr->mii_status |= VELOCITY_LINK_FAIL;
+		}
+
+		velocity_print_link_status(vptr);
+		enable_flow_control_ability(vptr);
+
+		/*
+		 *	Re-enable auto-polling because SRCI will disable 
+		 *	auto-polling
+		 */
+		 
+		enable_mii_autopoll(regs);
+
+		if (vptr->mii_status & VELOCITY_LINK_FAIL)
+			netif_stop_queue(vptr->dev);
+		else
+			netif_wake_queue(vptr->dev);
+
+	};
+	if (status & ISR_MIBFI)
+		velocity_update_hw_mibs(vptr);
+	if (status & ISR_LSTEI)
+		mac_rx_queue_wake(vptr->mac_regs);
+}
+
+/**
+ *	velocity_free_tx_buf	-	free transmit buffer
+ *	@vptr: velocity
+ *	@tdinfo: buffer
+ *
+ *	Release an transmit buffer. If the buffer was preallocated then
+ *	recycle it, if not then unmap the buffer.
+ */
+ 
+static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *tdinfo)
+{
+	struct sk_buff *skb = tdinfo->skb;
+	int i;
+
+	/*
+	 *	Don't unmap the pre-allocated tx_bufs
+	 */
+	if (tdinfo->skb_dma && (tdinfo->skb_dma[0] != tdinfo->buf_dma)) {
+
+		for (i = 0; i < tdinfo->nskb_dma; i++) {
+#ifdef VELOCITY_ZERO_COPY_SUPPORT
+			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], td->tdesc1.len, PCI_DMA_TODEVICE);
+#else
+			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], skb->len, PCI_DMA_TODEVICE);
+#endif
+			tdinfo->skb_dma[i] = 0;
+		}
+	}
+	dev_kfree_skb_irq(skb);
+	tdinfo->skb = NULL;
+}
+
+/**
+ *	velocity_open		-	interface activation callback
+ *	@dev: network layer device to open
+ *
+ *	Called when the network layer brings the interface up. Returns
+ *	a negative posix error code on failure, or zero on success.
+ *
+ *	All the ring allocation and set up is done on open for this
+ *	adapter to minimise memory usage when inactive
+ */
+ 
+static int velocity_open(struct net_device *dev)
+{
+	struct velocity_info *vptr = dev->priv;
+	int ret;
+
+	vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32);
+
+	ret = velocity_init_rings(vptr);
+	if (ret < 0)
+		goto out;
+
+	ret = velocity_init_rd_ring(vptr);
+	if (ret < 0)
+		goto err_free_desc_rings;
+
+	ret = velocity_init_td_ring(vptr);
+	if (ret < 0)
+		goto err_free_rd_ring;
+	
+	/* Ensure chip is running */	
+	pci_set_power_state(vptr->pdev, 0);
+	
+	velocity_init_registers(vptr, VELOCITY_INIT_COLD);
+
+	ret = request_irq(vptr->pdev->irq, &velocity_intr, SA_SHIRQ,
+			  dev->name, dev);
+	if (ret < 0) {
+		/* Power down the chip */
+		pci_set_power_state(vptr->pdev, 3);
+		goto err_free_td_ring;
+	}
+
+	mac_enable_int(vptr->mac_regs);
+	netif_start_queue(dev);
+	vptr->flags |= VELOCITY_FLAGS_OPENED;
+out:
+	return ret;
+
+err_free_td_ring:
+	velocity_free_td_ring(vptr);
+err_free_rd_ring:
+	velocity_free_rd_ring(vptr);
+err_free_desc_rings:
+	velocity_free_rings(vptr);
+	goto out;
+}
+
+/** 
+ *	velocity_change_mtu	-	MTU change callback
+ *	@dev: network device
+ *	@new_mtu: desired MTU
+ *
+ *	Handle requests from the networking layer for MTU change on
+ *	this interface. It gets called on a change by the network layer.
+ *	Return zero for success or negative posix error code.
+ */
+ 
+static int velocity_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct velocity_info *vptr = dev->priv;
+	unsigned long flags;
+	int oldmtu = dev->mtu;
+	int ret = 0;
+
+	if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) {
+		VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n", 
+				vptr->dev->name);
+		return -EINVAL;
+	}
+
+	if (new_mtu != oldmtu) {
+		spin_lock_irqsave(&vptr->lock, flags);
+
+		netif_stop_queue(dev);
+		velocity_shutdown(vptr);
+
+		velocity_free_td_ring(vptr);
+		velocity_free_rd_ring(vptr);
+
+		dev->mtu = new_mtu;
+		if (new_mtu > 8192)
+			vptr->rx_buf_sz = 9 * 1024;
+		else if (new_mtu > 4096)
+			vptr->rx_buf_sz = 8192;
+		else
+			vptr->rx_buf_sz = 4 * 1024;
+
+		ret = velocity_init_rd_ring(vptr);
+		if (ret < 0)
+			goto out_unlock;
+
+		ret = velocity_init_td_ring(vptr);
+		if (ret < 0)
+			goto out_unlock;
+
+		velocity_init_registers(vptr, VELOCITY_INIT_COLD);
+
+		mac_enable_int(vptr->mac_regs);
+		netif_start_queue(dev);
+out_unlock:
+		spin_unlock_irqrestore(&vptr->lock, flags);
+	}
+
+	return ret;
+}
+
+/**
+ *	velocity_shutdown	-	shut down the chip
+ *	@vptr: velocity to deactivate
+ *
+ *	Shuts down the internal operations of the velocity and
+ *	disables interrupts, autopolling, transmit and receive
+ */
+ 
+static void velocity_shutdown(struct velocity_info *vptr)
+{
+	struct mac_regs * regs = vptr->mac_regs;
+	mac_disable_int(regs);
+	writel(CR0_STOP, &regs->CR0Set);
+	writew(0xFFFF, &regs->TDCSRClr);
+	writeb(0xFF, &regs->RDCSRClr);
+	safe_disable_mii_autopoll(regs);
+	mac_clear_isr(regs);
+}
+
+/**
+ *	velocity_close		-	close adapter callback
+ *	@dev: network device
+ *
+ *	Callback from the network layer when the velocity is being
+ *	deactivated by the network layer
+ */
+
+static int velocity_close(struct net_device *dev)
+{
+	struct velocity_info *vptr = dev->priv;
+
+	netif_stop_queue(dev);
+	velocity_shutdown(vptr);
+
+	if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED)
+		velocity_get_ip(vptr);
+	if (dev->irq != 0)
+		free_irq(dev->irq, dev);
+		
+	/* Power down the chip */
+	pci_set_power_state(vptr->pdev, 3);
+	
+	/* Free the resources */
+	velocity_free_td_ring(vptr);
+	velocity_free_rd_ring(vptr);
+	velocity_free_rings(vptr);
+
+	vptr->flags &= (~VELOCITY_FLAGS_OPENED);
+	return 0;
+}
+
+/**
+ *	velocity_xmit		-	transmit packet callback
+ *	@skb: buffer to transmit
+ *	@dev: network device
+ *
+ *	Called by the networ layer to request a packet is queued to
+ *	the velocity. Returns zero on success.
+ */
+ 
+static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct velocity_info *vptr = dev->priv;
+	int qnum = 0;
+	struct tx_desc *td_ptr;
+	struct velocity_td_info *tdinfo;
+	unsigned long flags;
+	int index;
+
+	int pktlen = skb->len;
+
+	spin_lock_irqsave(&vptr->lock, flags);
+
+	index = vptr->td_curr[qnum];
+	td_ptr = &(vptr->td_rings[qnum][index]);
+	tdinfo = &(vptr->td_infos[qnum][index]);
+
+	td_ptr->tdesc1.TCPLS = TCPLS_NORMAL;
+	td_ptr->tdesc1.TCR = TCR0_TIC;
+	td_ptr->td_buf[0].queue = 0;
+
+	/*
+	 *	Pad short frames. 
+	 */
+	if (pktlen < ETH_ZLEN) {
+		/* Cannot occur until ZC support */
+		if(skb_linearize(skb, GFP_ATOMIC))
+			return 0; 
+		pktlen = ETH_ZLEN;
+		memcpy(tdinfo->buf, skb->data, skb->len);
+		memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);
+		tdinfo->skb = skb;
+		tdinfo->skb_dma[0] = tdinfo->buf_dma;
+		td_ptr->tdesc0.pktsize = pktlen;
+		td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
+		td_ptr->td_buf[0].pa_high = 0;
+		td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;
+		tdinfo->nskb_dma = 1;
+		td_ptr->tdesc1.CMDZ = 2;
+	} else
+#ifdef VELOCITY_ZERO_COPY_SUPPORT
+	if (skb_shinfo(skb)->nr_frags > 0) {
+		int nfrags = skb_shinfo(skb)->nr_frags;
+		tdinfo->skb = skb;
+		if (nfrags > 6) {
+			skb_linearize(skb, GFP_ATOMIC);
+			memcpy(tdinfo->buf, skb->data, skb->len);
+			tdinfo->skb_dma[0] = tdinfo->buf_dma;
+			td_ptr->tdesc0.pktsize = 
+			td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
+			td_ptr->td_buf[0].pa_high = 0;
+			td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;
+			tdinfo->nskb_dma = 1;
+			td_ptr->tdesc1.CMDZ = 2;
+		} else {
+			int i = 0;
+			tdinfo->nskb_dma = 0;
+			tdinfo->skb_dma[i] = pci_map_single(vptr->pdev, skb->data, skb->len - skb->data_len, PCI_DMA_TODEVICE);
+
+			td_ptr->tdesc0.pktsize = pktlen;
+
+			/* FIXME: support 48bit DMA later */
+			td_ptr->td_buf[i].pa_low = cpu_to_le32(tdinfo->skb_dma);
+			td_ptr->td_buf[i].pa_high = 0;
+			td_ptr->td_buf[i].bufsize = skb->len->skb->data_len;
+
+			for (i = 0; i < nfrags; i++) {
+				skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+				void *addr = ((void *) page_address(frag->page + frag->page_offset));
+
+				tdinfo->skb_dma[i + 1] = pci_map_single(vptr->pdev, addr, frag->size, PCI_DMA_TODEVICE);
+
+				td_ptr->td_buf[i + 1].pa_low = cpu_to_le32(tdinfo->skb_dma[i + 1]);
+				td_ptr->td_buf[i + 1].pa_high = 0;
+				td_ptr->td_buf[i + 1].bufsize = frag->size;
+			}
+			tdinfo->nskb_dma = i - 1;
+			td_ptr->tdesc1.CMDZ = i;
+		}
+
+	} else
+#endif
+	{
+		/*
+		 *	Map the linear network buffer into PCI space and
+		 *	add it to the transmit ring.
+		 */
+		tdinfo->skb = skb;
+		tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE);
+		td_ptr->tdesc0.pktsize = pktlen;
+		td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
+		td_ptr->td_buf[0].pa_high = 0;
+		td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;
+		tdinfo->nskb_dma = 1;
+		td_ptr->tdesc1.CMDZ = 2;
+	}
+
+	if (vptr->flags & VELOCITY_FLAGS_TAGGING) {
+		td_ptr->tdesc1.pqinf.VID = (vptr->options.vid & 0xfff);
+		td_ptr->tdesc1.pqinf.priority = 0;
+		td_ptr->tdesc1.pqinf.CFI = 0;
+		td_ptr->tdesc1.TCR |= TCR0_VETAG;
+	}
+
+	/*
+	 *	Handle hardware checksum
+	 */
+	if ((vptr->flags & VELOCITY_FLAGS_TX_CSUM)
+				 && (skb->ip_summed == CHECKSUM_HW)) {
+		struct iphdr *ip = skb->nh.iph;
+		if (ip->protocol == IPPROTO_TCP)
+			td_ptr->tdesc1.TCR |= TCR0_TCPCK;
+		else if (ip->protocol == IPPROTO_UDP)
+			td_ptr->tdesc1.TCR |= (TCR0_UDPCK);
+		td_ptr->tdesc1.TCR |= TCR0_IPCK;
+	}
+	{
+
+		int prev = index - 1;
+
+		if (prev < 0)
+			prev = vptr->options.numtx - 1;
+		td_ptr->tdesc0.owner = OWNED_BY_NIC;
+		vptr->td_used[qnum]++;
+		vptr->td_curr[qnum] = (index + 1) % vptr->options.numtx;
+
+		if (AVAIL_TD(vptr, qnum) < 1)
+			netif_stop_queue(dev);
+
+		td_ptr = &(vptr->td_rings[qnum][prev]);
+		td_ptr->td_buf[0].queue = 1;
+		mac_tx_queue_wake(vptr->mac_regs, qnum);
+	}
+	dev->trans_start = jiffies;
+	spin_unlock_irqrestore(&vptr->lock, flags);
+	return 0;
+}
+
+/**
+ *	velocity_intr		-	interrupt callback
+ *	@irq: interrupt number
+ *	@dev_instance: interrupting device
+ *	@pt_regs: CPU register state at interrupt
+ *
+ *	Called whenever an interrupt is generated by the velocity
+ *	adapter IRQ line. We may not be the source of the interrupt
+ *	and need to identify initially if we are, and if not exit as
+ *	efficiently as possible.
+ */
+ 
+static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_instance;
+	struct velocity_info *vptr = dev->priv;
+	u32 isr_status;
+	int max_count = 0;
+
+
+	spin_lock(&vptr->lock);
+	isr_status = mac_read_isr(vptr->mac_regs);
+
+	/* Not us ? */
+	if (isr_status == 0) {
+		spin_unlock(&vptr->lock);
+		return IRQ_NONE;
+	}
+
+	mac_disable_int(vptr->mac_regs);
+
+	/*
+	 *	Keep processing the ISR until we have completed
+	 *	processing and the isr_status becomes zero
+	 */
+	 
+	while (isr_status != 0) {
+		mac_write_isr(vptr->mac_regs, isr_status);
+		if (isr_status & (~(ISR_PRXI | ISR_PPRXI | ISR_PTXI | ISR_PPTXI)))
+			velocity_error(vptr, isr_status);
+		if (isr_status & (ISR_PRXI | ISR_PPRXI))
+			max_count += velocity_rx_srv(vptr, isr_status);
+		if (isr_status & (ISR_PTXI | ISR_PPTXI))
+			max_count += velocity_tx_srv(vptr, isr_status);
+		isr_status = mac_read_isr(vptr->mac_regs);
+		if (max_count > vptr->options.int_works)
+		{
+			printk(KERN_WARNING "%s: excessive work at interrupt.\n", 
+				dev->name);
+			max_count = 0;
+		}
+	}
+	spin_unlock(&vptr->lock);
+	mac_enable_int(vptr->mac_regs);
+	return IRQ_HANDLED;
+
+}
+
+
+/**
+ *	ether_crc	-	ethernet CRC function
+ *
+ *	Compute an ethernet CRC hash of the data block provided. This
+ *	is not performance optimised but is not needed in performance
+ *	critical code paths.
+ *
+ *	FIXME: could we use shared code here ?
+ */
+ 
+static inline u32 ether_crc(int length, unsigned char *data)
+{
+	static unsigned const ethernet_polynomial = 0x04c11db7U;
+	
+	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;
+}
+
+/**
+ *	velocity_set_multi	-	filter list change callback
+ *	@dev: network device
+ *
+ *	Called by the network layer when the filter lists need to change
+ *	for a velocity adapter. Reload the CAMs with the new address
+ *	filter ruleset.
+ */
+ 
+static void velocity_set_multi(struct net_device *dev)
+{
+	struct velocity_info *vptr = dev->priv;
+	struct mac_regs * regs = vptr->mac_regs;
+	u8 rx_mode;
+	int i;
+	struct dev_mc_list *mclist;
+
+	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */
+		/* Unconditionally log net taps. */
+		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
+		writel(0xffffffff, &regs->MARCAM[0]);
+		writel(0xffffffff, &regs->MARCAM[4]);
+		rx_mode = (RCR_AM | RCR_AB | RCR_PROM);
+	} else if ((dev->mc_count > vptr->multicast_limit)
+		   || (dev->flags & IFF_ALLMULTI)) {
+		writel(0xffffffff, &regs->MARCAM[0]);
+		writel(0xffffffff, &regs->MARCAM[4]);
+		rx_mode = (RCR_AM | RCR_AB);
+	} else {
+		int offset = MCAM_SIZE - vptr->multicast_limit;
+		mac_get_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM);
+
+		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) {
+			mac_set_cam(regs, i + offset, mclist->dmi_addr, VELOCITY_MULTICAST_CAM);
+			vptr->mCAMmask[(offset + i) / 8] |= 1 << ((offset + i) & 7);
+		}
+
+		mac_set_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM);
+		rx_mode = (RCR_AM | RCR_AB);
+	}
+	if (dev->mtu > 1500)
+		rx_mode |= RCR_AL;
+
+	BYTE_REG_BITS_ON(rx_mode, &regs->RCR);
+
+}
+
+/**
+ *	velocity_get_status	-	statistics callback
+ *	@dev: network device
+ *
+ *	Callback from the network layer to allow driver statistics
+ *	to be resynchronized with hardware collected state. In the
+ *	case of the velocity we need to pull the MIB counters from
+ *	the hardware into the counters before letting the network
+ *	layer display them.
+ */
+ 
+static struct net_device_stats *velocity_get_stats(struct net_device *dev)
+{
+	struct velocity_info *vptr = dev->priv;
+	
+	/* If the hardware is down, don't touch MII */
+	if(!netif_running(dev))
+		return &vptr->stats;
+
+	spin_lock_irq(&vptr->lock);
+	velocity_update_hw_mibs(vptr);
+	spin_unlock_irq(&vptr->lock);
+
+	vptr->stats.rx_packets = vptr->mib_counter[HW_MIB_ifRxAllPkts];
+	vptr->stats.rx_errors = vptr->mib_counter[HW_MIB_ifRxErrorPkts];
+	vptr->stats.rx_length_errors = vptr->mib_counter[HW_MIB_ifInRangeLengthErrors];
+
+//  unsigned long   rx_dropped;     /* no space in linux buffers    */
+	vptr->stats.collisions = vptr->mib_counter[HW_MIB_ifTxEtherCollisions];
+	/* detailed rx_errors: */
+//  unsigned long   rx_length_errors;
+//  unsigned long   rx_over_errors;     /* receiver ring buff overflow  */
+	vptr->stats.rx_crc_errors = vptr->mib_counter[HW_MIB_ifRxPktCRCE];
+//  unsigned long   rx_frame_errors;    /* recv'd frame alignment error */
+//  unsigned long   rx_fifo_errors;     /* recv'r fifo overrun      */
+//  unsigned long   rx_missed_errors;   /* receiver missed packet   */
+
+	/* detailed tx_errors */
+//  unsigned long   tx_fifo_errors;
+
+	return &vptr->stats;
+}
+
+
+/**
+ *	velocity_ioctl		-	ioctl entry point
+ *	@dev: network device
+ *	@rq: interface request ioctl
+ *	@cmd: command code
+ *
+ *	Called when the user issues an ioctl request to the network
+ *	device in question. The velocity interface supports MII.
+ */
+ 
+static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct velocity_info *vptr = dev->priv;
+	int ret;
+
+	/* If we are asked for information and the device is power
+	   saving then we need to bring the device back up to talk to it */
+	   	
+	if(!netif_running(dev))
+		pci_set_power_state(vptr->pdev, 0);
+		
+	switch (cmd) {
+	case SIOCGMIIPHY:	/* Get address of MII PHY in use. */
+	case SIOCGMIIREG:	/* Read MII PHY register. */
+	case SIOCSMIIREG:	/* Write to MII PHY register. */
+		ret = velocity_mii_ioctl(dev, rq, cmd);
+		break;
+
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	if(!netif_running(dev))
+		pci_set_power_state(vptr->pdev, 3);
+		
+		
+	return ret;
+}
+
+/*
+ *	Definition for our device driver. The PCI layer interface
+ *	uses this to handle all our card discover and plugging
+ */
+ 
+static struct pci_driver velocity_driver = {
+      name:VELOCITY_NAME,
+      id_table:velocity_id_table,
+      probe:velocity_found1,
+      remove:velocity_remove1,
+#ifdef CONFIG_PM
+      suspend:velocity_suspend,
+      resume:velocity_resume,
+#endif
+};
+
+/**
+ *	velocity_init_module	-	load time function
+ *
+ *	Called when the velocity module is loaded. The PCI driver
+ *	is registered with the PCI layer, and in turn will call
+ *	the probe functions for each velocity adapter installed
+ *	in the system.
+ */
+ 
+static int __init velocity_init_module(void)
+{
+	int ret;
+	ret = pci_module_init(&velocity_driver);
+
+#ifdef CONFIG_PM
+	register_inetaddr_notifier(&velocity_inetaddr_notifier);
+#endif
+	return ret;
+}
+
+/**
+ *	velocity_cleanup	-	module unload
+ *
+ *	When the velocity hardware is unloaded this function is called.
+ *	It will clean up the notifiers and the unregister the PCI 
+ *	driver interface for this hardware. This in turn cleans up
+ *	all discovered interfaces before returning from the function
+ */
+ 
+static void __exit velocity_cleanup_module(void)
+{
+#ifdef CONFIG_PM
+	unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
+#endif
+	pci_unregister_driver(&velocity_driver);
+}
+
+module_init(velocity_init_module);
+module_exit(velocity_cleanup_module);
+
+
+/*
+ * MII access , media link mode setting functions
+ */
+ 
+ 
+/**
+ *	mii_init	-	set up MII
+ *	@vptr: velocity adapter
+ *	@mii_status:  links tatus
+ *
+ *	Set up the PHY for the current link state.
+ */
+ 
+static void mii_init(struct velocity_info *vptr, u32 mii_status)
+{
+	u16 BMCR;
+
+	switch (PHYID_GET_PHY_ID(vptr->phy_id)) {
+	case PHYID_CICADA_CS8201:
+		/*
+		 *	Reset to hardware default
+		 */
+		MII_REG_BITS_OFF((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs);
+		/*
+		 *	Turn on ECHODIS bit in NWay-forced full mode and turn it
+		 *	off it in NWay-forced half mode for NWay-forced v.s. 
+		 *	legacy-forced issue.
+		 */
+		if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+			MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
+		else
+			MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
+		/*
+		 *	Turn on Link/Activity LED enable bit for CIS8201
+		 */
+		MII_REG_BITS_ON(PLED_LALBE, MII_REG_PLED, vptr->mac_regs);
+		break;
+	case PHYID_VT3216_32BIT:
+	case PHYID_VT3216_64BIT:
+		/*
+		 *	Reset to hardware default
+		 */
+		MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs);
+		/*
+		 *	Turn on ECHODIS bit in NWay-forced full mode and turn it
+		 *	off it in NWay-forced half mode for NWay-forced v.s. 
+		 *	legacy-forced issue
+		 */
+		if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+			MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
+		else
+			MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
+		break;
+
+	case PHYID_MARVELL_1000:
+	case PHYID_MARVELL_1000S:
+		/*
+		 *	Assert CRS on Transmit 
+		 */
+		MII_REG_BITS_ON(PSCR_ACRSTX, MII_REG_PSCR, vptr->mac_regs);
+		/*
+		 *	Reset to hardware default 
+		 */
+		MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs);
+		break;
+	default:
+		;
+	}
+	velocity_mii_read(vptr->mac_regs, MII_REG_BMCR, &BMCR);
+	if (BMCR & BMCR_ISO) {
+		BMCR &= ~BMCR_ISO;
+		velocity_mii_write(vptr->mac_regs, MII_REG_BMCR, BMCR);
+	}
+}
+
+/**
+ *	safe_disable_mii_autopoll	-	autopoll off
+ *	@regs: velocity registers
+ *
+ *	Turn off the autopoll and wait for it to disable on the chip
+ */
+ 
+static void safe_disable_mii_autopoll(struct mac_regs * regs)
+{
+	u16 ww;
+
+	/*  turn off MAUTO */
+	writeb(0, &regs->MIICR);
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		udelay(1);
+		if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
+			break;
+	}
+}
+
+/**
+ *	enable_mii_autopoll	-	turn on autopolling
+ *	@regs: velocity registers
+ *
+ *	Enable the MII link status autopoll feature on the Velocity
+ *	hardware. Wait for it to enable.
+ */
+
+static void enable_mii_autopoll(struct mac_regs * regs)
+{
+	int ii;
+
+	writeb(0, &(regs->MIICR));
+	writeb(MIIADR_SWMPL, &regs->MIIADR);
+
+	for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
+		udelay(1);
+		if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
+			break;
+	}
+
+	writeb(MIICR_MAUTO, &regs->MIICR);
+
+	for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
+		udelay(1);
+		if (!BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
+			break;
+	}
+
+}
+
+/**
+ *	velocity_mii_read	-	read MII data
+ *	@regs: velocity registers
+ *	@index: MII register index
+ *	@data: buffer for received data
+ *
+ *	Perform a single read of an MII 16bit register. Returns zero
+ *	on success or -ETIMEDOUT if the PHY did not respond.
+ */
+ 
+static int velocity_mii_read(struct mac_regs * regs, u8 index, u16 *data)
+{
+	u16 ww;
+
+	/*
+	 *	Disable MIICR_MAUTO, so that mii addr can be set normally
+	 */
+	safe_disable_mii_autopoll(regs);
+
+	writeb(index, &regs->MIIADR);
+
+	BYTE_REG_BITS_ON(MIICR_RCMD, &regs->MIICR);
+
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		if (!(readb(&regs->MIICR) & MIICR_RCMD))
+			break;
+	}
+
+	*data = readw(&regs->MIIDATA);
+
+	enable_mii_autopoll(regs);
+	if (ww == W_MAX_TIMEOUT)
+		return -ETIMEDOUT;
+	return 0;
+}
+
+/**
+ *	velocity_mii_write	-	write MII data
+ *	@regs: velocity registers
+ *	@index: MII register index
+ *	@data: 16bit data for the MII register
+ *
+ *	Perform a single write to an MII 16bit register. Returns zero
+ *	on success or -ETIMEDOUT if the PHY did not respond.
+ */
+ 
+static int velocity_mii_write(struct mac_regs * regs, u8 mii_addr, u16 data)
+{
+	u16 ww;
+
+	/*
+	 *	Disable MIICR_MAUTO, so that mii addr can be set normally
+	 */
+	safe_disable_mii_autopoll(regs);
+
+	/* MII reg offset */
+	writeb(mii_addr, &regs->MIIADR);
+	/* set MII data */
+	writew(data, &regs->MIIDATA);
+
+	/* turn on MIICR_WCMD */
+	BYTE_REG_BITS_ON(MIICR_WCMD, &regs->MIICR);
+
+	/* W_MAX_TIMEOUT is the timeout period */
+	for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+		udelay(5);
+		if (!(readb(&regs->MIICR) & MIICR_WCMD))
+			break;
+	}
+	enable_mii_autopoll(regs);
+
+	if (ww == W_MAX_TIMEOUT)
+		return -ETIMEDOUT;
+	return 0;
+}
+
+/**
+ *	velocity_get_opt_media_mode	-	get media selection
+ *	@vptr: velocity adapter
+ *
+ *	Get the media mode stored in EEPROM or module options and load
+ *	mii_status accordingly. The requested link state information
+ *	is also returned.
+ */
+ 
+static u32 velocity_get_opt_media_mode(struct velocity_info *vptr)
+{
+	u32 status = 0;
+
+	switch (vptr->options.spd_dpx) {
+	case SPD_DPX_AUTO:
+		status = VELOCITY_AUTONEG_ENABLE;
+		break;
+	case SPD_DPX_100_FULL:
+		status = VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL;
+		break;
+	case SPD_DPX_10_FULL:
+		status = VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL;
+		break;
+	case SPD_DPX_100_HALF:
+		status = VELOCITY_SPEED_100;
+		break;
+	case SPD_DPX_10_HALF:
+		status = VELOCITY_SPEED_10;
+		break;
+	}
+	vptr->mii_status = status;
+	return status;
+}
+
+/**
+ *	mii_set_auto_on		-	autonegotiate on
+ *	@vptr: velocity
+ *
+ *	Enable autonegotation on this interface
+ */
+ 
+static void mii_set_auto_on(struct velocity_info *vptr)
+{
+	if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs))
+		MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs);
+	else
+		MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
+}
+
+
+/*
+static void mii_set_auto_off(struct velocity_info * vptr)
+{
+    MII_REG_BITS_OFF(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
+}
+*/
+
+/**
+ *	set_mii_flow_control	-	flow control setup
+ *	@vptr: velocity interface
+ *
+ *	Set up the flow control on this interface according to
+ *	the supplied user/eeprom options.
+ */
+ 
+static void set_mii_flow_control(struct velocity_info *vptr)
+{
+	/*Enable or Disable PAUSE in ANAR */
+	switch (vptr->options.flow_cntl) {
+	case FLOW_CNTL_TX:
+		MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+		MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+		break;
+
+	case FLOW_CNTL_RX:
+		MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+		MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+		break;
+
+	case FLOW_CNTL_TX_RX:
+		MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+		MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+		break;
+
+	case FLOW_CNTL_DISABLE:
+		MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+		MII_REG_BITS_OFF(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ *	velocity_set_media_mode		-	set media mode
+ *	@mii_status: old MII link state
+ *
+ *	Check the media link state and configure the flow control
+ *	PHY and also velocity hardware setup accordingly. In particular
+ *	we need to set up CD polling and frame bursting.
+ */
+ 
+static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
+{
+	u32 curr_status;
+	struct mac_regs * regs = vptr->mac_regs;
+
+	vptr->mii_status = mii_check_media_mode(vptr->mac_regs);
+	curr_status = vptr->mii_status & (~VELOCITY_LINK_FAIL);
+
+	/* Set mii link status */
+	set_mii_flow_control(vptr);
+
+	/*
+	   Check if new status is consisent with current status
+	   if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE)
+	   || (mii_status==curr_status)) {
+	   vptr->mii_status=mii_check_media_mode(vptr->mac_regs);
+	   vptr->mii_status=check_connection_type(vptr->mac_regs);
+	   VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity link no change\n");
+	   return 0;
+	   }
+	 */
+
+	if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201) {
+		MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, vptr->mac_regs);
+	}
+
+	/*
+	 *	If connection type is AUTO
+	 */
+	if (mii_status & VELOCITY_AUTONEG_ENABLE) {
+		VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity is AUTO mode\n");
+		/* clear force MAC mode bit */
+		BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, &regs->CHIPGCR);
+		/* set duplex mode of MAC according to duplex mode of MII */
+		MII_REG_BITS_ON(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10, MII_REG_ANAR, vptr->mac_regs);
+		MII_REG_BITS_ON(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs);
+		MII_REG_BITS_ON(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs);
+
+		/* enable AUTO-NEGO mode */
+		mii_set_auto_on(vptr);
+	} else {
+		u16 ANAR;
+		u8 CHIPGCR;
+
+		/*
+		 * 1. if it's 3119, disable frame bursting in halfduplex mode
+		 *    and enable it in fullduplex mode
+		 * 2. set correct MII/GMII and half/full duplex mode in CHIPGCR
+		 * 3. only enable CD heart beat counter in 10HD mode
+		 */
+
+		/* set force MAC mode bit */
+		BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
+
+		CHIPGCR = readb(&regs->CHIPGCR);
+		CHIPGCR &= ~CHIPGCR_FCGMII;
+
+		if (mii_status & VELOCITY_DUPLEX_FULL) {
+			CHIPGCR |= CHIPGCR_FCFDX;
+			writeb(CHIPGCR, &regs->CHIPGCR);
+			VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced full mode\n");
+			if (vptr->rev_id < REV_ID_VT3216_A0)
+				BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
+		} else {
+			CHIPGCR &= ~CHIPGCR_FCFDX;
+			VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced half mode\n");
+			writeb(CHIPGCR, &regs->CHIPGCR);
+			if (vptr->rev_id < REV_ID_VT3216_A0)
+				BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
+		}
+
+		MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs);
+
+		if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10)) {
+			BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
+		} else {
+			BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
+		}
+		/* MII_REG_BITS_OFF(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs); */
+		velocity_mii_read(vptr->mac_regs, MII_REG_ANAR, &ANAR);
+		ANAR &= (~(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10));
+		if (mii_status & VELOCITY_SPEED_100) {
+			if (mii_status & VELOCITY_DUPLEX_FULL)
+				ANAR |= ANAR_TXFD;
+			else
+				ANAR |= ANAR_TX;
+		} else {
+			if (mii_status & VELOCITY_DUPLEX_FULL)
+				ANAR |= ANAR_10FD;
+			else
+				ANAR |= ANAR_10;
+		}
+		velocity_mii_write(vptr->mac_regs, MII_REG_ANAR, ANAR);
+		/* enable AUTO-NEGO mode */
+		mii_set_auto_on(vptr);
+		/* MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); */
+	}
+	/* vptr->mii_status=mii_check_media_mode(vptr->mac_regs); */
+	/* vptr->mii_status=check_connection_type(vptr->mac_regs); */
+	return VELOCITY_LINK_CHANGE;
+}
+
+/**
+ *	mii_check_media_mode	-	check media state
+ *	@regs: velocity registers
+ *
+ *	Check the current MII status and determine the link status
+ *	accordingly
+ */
+ 
+static u32 mii_check_media_mode(struct mac_regs * regs)
+{
+	u32 status = 0;
+	u16 ANAR;
+
+	if (!MII_REG_BITS_IS_ON(BMSR_LNK, MII_REG_BMSR, regs))
+		status |= VELOCITY_LINK_FAIL;
+
+	if (MII_REG_BITS_IS_ON(G1000CR_1000FD, MII_REG_G1000CR, regs))
+		status |= VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
+	else if (MII_REG_BITS_IS_ON(G1000CR_1000, MII_REG_G1000CR, regs))
+		status |= (VELOCITY_SPEED_1000);
+	else {
+		velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
+		if (ANAR & ANAR_TXFD)
+			status |= (VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL);
+		else if (ANAR & ANAR_TX)
+			status |= VELOCITY_SPEED_100;
+		else if (ANAR & ANAR_10FD)
+			status |= (VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL);
+		else
+			status |= (VELOCITY_SPEED_10);
+	}
+
+	if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
+		velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
+		if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
+		    == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
+			if (MII_REG_BITS_IS_ON(G1000CR_1000 | G1000CR_1000FD, MII_REG_G1000CR, regs))
+				status |= VELOCITY_AUTONEG_ENABLE;
+		}
+	}
+
+	return status;
+}
+
+static u32 check_connection_type(struct mac_regs * regs)
+{
+	u32 status = 0;
+	u8 PHYSR0;
+	u16 ANAR;
+	PHYSR0 = readb(&regs->PHYSR0);
+
+	/*
+	   if (!(PHYSR0 & PHYSR0_LINKGD))
+	   status|=VELOCITY_LINK_FAIL;
+	 */
+
+	if (PHYSR0 & PHYSR0_FDPX)
+		status |= VELOCITY_DUPLEX_FULL;
+
+	if (PHYSR0 & PHYSR0_SPDG)
+		status |= VELOCITY_SPEED_1000;
+	if (PHYSR0 & PHYSR0_SPD10)
+		status |= VELOCITY_SPEED_10;
+	else
+		status |= VELOCITY_SPEED_100;
+
+	if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
+		velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
+		if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
+		    == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
+			if (MII_REG_BITS_IS_ON(G1000CR_1000 | G1000CR_1000FD, MII_REG_G1000CR, regs))
+				status |= VELOCITY_AUTONEG_ENABLE;
+		}
+	}
+
+	return status;
+}
+
+/**
+ *	enable_flow_control_ability	-	flow control
+ *	@vptr: veloity to configure
+ *
+ *	Set up flow control according to the flow control options
+ *	determined by the eeprom/configuration.
+ */
+
+static void enable_flow_control_ability(struct velocity_info *vptr)
+{
+
+	struct mac_regs * regs = vptr->mac_regs;
+
+	switch (vptr->options.flow_cntl) {
+
+	case FLOW_CNTL_DEFAULT:
+		if (BYTE_REG_BITS_IS_ON(PHYSR0_RXFLC, &regs->PHYSR0))
+			writel(CR0_FDXRFCEN, &regs->CR0Set);
+		else
+			writel(CR0_FDXRFCEN, &regs->CR0Clr);
+
+		if (BYTE_REG_BITS_IS_ON(PHYSR0_TXFLC, &regs->PHYSR0))
+			writel(CR0_FDXTFCEN, &regs->CR0Set);
+		else
+			writel(CR0_FDXTFCEN, &regs->CR0Clr);
+		break;
+
+	case FLOW_CNTL_TX:
+		writel(CR0_FDXTFCEN, &regs->CR0Set);
+		writel(CR0_FDXRFCEN, &regs->CR0Clr);
+		break;
+
+	case FLOW_CNTL_RX:
+		writel(CR0_FDXRFCEN, &regs->CR0Set);
+		writel(CR0_FDXTFCEN, &regs->CR0Clr);
+		break;
+
+	case FLOW_CNTL_TX_RX:
+		writel(CR0_FDXTFCEN, &regs->CR0Set);
+		writel(CR0_FDXRFCEN, &regs->CR0Set);
+		break;
+
+	case FLOW_CNTL_DISABLE:
+		writel(CR0_FDXRFCEN, &regs->CR0Clr);
+		writel(CR0_FDXTFCEN, &regs->CR0Clr);
+		break;
+
+	default:
+		break;
+	}
+
+}
+
+
+/**
+ *	velocity_ethtool_up	-	pre hook for ethtool
+ *	@dev: network device
+ *
+ *	Called before an ethtool operation. We need to make sure the
+ *	chip is out of D3 state before we poke at it.
+ */
+ 
+static int velocity_ethtool_up(struct net_device *dev)
+{
+	struct velocity_info *vptr = dev->priv;
+	if(!netif_running(dev))
+		pci_set_power_state(vptr->pdev, 0);
+	return 0;
+}	
+
+/**
+ *	velocity_ethtool_down	-	post hook for ethtool
+ *	@dev: network device
+ *
+ *	Called after an ethtool operation. Restore the chip back to D3
+ *	state if it isn't running.
+ */
+ 
+static void velocity_ethtool_down(struct net_device *dev)
+{
+	struct velocity_info *vptr = dev->priv;
+	if(!netif_running(dev))
+		pci_set_power_state(vptr->pdev, 3);
+}
+
+static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct velocity_info *vptr = dev->priv;
+	struct mac_regs * regs = vptr->mac_regs;
+	u32 status;
+	status = check_connection_type(vptr->mac_regs);
+
+	cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
+	if (status & VELOCITY_SPEED_100)
+		cmd->speed = SPEED_100;
+	else
+		cmd->speed = SPEED_10;
+	cmd->autoneg = (status & VELOCITY_AUTONEG_ENABLE) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+	cmd->port = PORT_TP;
+	cmd->transceiver = XCVR_INTERNAL;
+	cmd->phy_address = readb(&regs->MIIADR) & 0x1F;
+
+	if (status & VELOCITY_DUPLEX_FULL)
+		cmd->duplex = DUPLEX_FULL;
+	else
+		cmd->duplex = DUPLEX_HALF;
+		
+	return 0;
+}
+
+static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct velocity_info *vptr = dev->priv;
+	u32 curr_status;
+	u32 new_status = 0;
+	int ret = 0;
+	
+	curr_status = check_connection_type(vptr->mac_regs);
+	curr_status &= (~VELOCITY_LINK_FAIL);
+
+	new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0);
+	new_status |= ((cmd->speed == SPEED_100) ? VELOCITY_SPEED_100 : 0);
+	new_status |= ((cmd->speed == SPEED_10) ? VELOCITY_SPEED_10 : 0);
+	new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0);
+
+	if ((new_status & VELOCITY_AUTONEG_ENABLE) && (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE)))
+		ret = -EINVAL;
+	else
+		velocity_set_media_mode(vptr, new_status);
+
+	return ret;
+}
+
+static u32 velocity_get_link(struct net_device *dev)
+{
+	struct velocity_info *vptr = dev->priv;
+	struct mac_regs * regs = vptr->mac_regs;
+	return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0)  ? 0 : 1;
+}
+
+static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct velocity_info *vptr = dev->priv;
+	strcpy(info->driver, VELOCITY_NAME);
+	strcpy(info->version, VELOCITY_VERSION);
+	strcpy(info->bus_info, vptr->pdev->slot_name);
+}
+
+static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct velocity_info *vptr = dev->priv;
+	wol->supported = WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP;
+	wol->wolopts |= WAKE_MAGIC;
+	/*
+	   if (vptr->wol_opts & VELOCITY_WOL_PHY)
+		   wol.wolopts|=WAKE_PHY;
+			 */
+	if (vptr->wol_opts & VELOCITY_WOL_UCAST)
+		wol->wolopts |= WAKE_UCAST;
+	if (vptr->wol_opts & VELOCITY_WOL_ARP)
+		wol->wolopts |= WAKE_ARP;
+	memcpy(&wol->sopass, vptr->wol_passwd, 6);
+}
+
+static int velocity_ethtool_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct velocity_info *vptr = dev->priv;
+
+	if (!(wol->wolopts & (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP)))
+		return -EFAULT;
+	vptr->wol_opts = VELOCITY_WOL_MAGIC;
+
+	/*
+	   if (wol.wolopts & WAKE_PHY) {
+	   vptr->wol_opts|=VELOCITY_WOL_PHY;
+	   vptr->flags |=VELOCITY_FLAGS_WOL_ENABLED;
+	   }
+	 */
+
+	if (wol->wolopts & WAKE_MAGIC) {
+		vptr->wol_opts |= VELOCITY_WOL_MAGIC;
+		vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
+	}
+	if (wol->wolopts & WAKE_UCAST) {
+		vptr->wol_opts |= VELOCITY_WOL_UCAST;
+		vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
+	}
+	if (wol->wolopts & WAKE_ARP) {
+		vptr->wol_opts |= VELOCITY_WOL_ARP;
+		vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
+	}
+	memcpy(vptr->wol_passwd, wol->sopass, 6);
+	return 0;
+}
+
+static u32 velocity_get_msglevel(struct net_device *dev)
+{
+	return msglevel;
+}
+
+static void velocity_set_msglevel(struct net_device *dev, u32 value)
+{
+	 msglevel = value;
+}
+
+static struct ethtool_ops velocity_ethtool_ops = {
+	.get_settings	=	velocity_get_settings,
+	.set_settings	=	velocity_set_settings,
+	.get_drvinfo	=	velocity_get_drvinfo,
+	.get_wol	=	velocity_ethtool_get_wol,
+	.set_wol	=	velocity_ethtool_set_wol,
+	.get_msglevel	=	velocity_get_msglevel,
+	.set_msglevel	=	velocity_set_msglevel,
+	.get_link	=	velocity_get_link,
+	.begin		=	velocity_ethtool_up,
+	.complete	=	velocity_ethtool_down
+};
+
+/**
+ *	velocity_mii_ioctl		-	MII ioctl handler
+ *	@dev: network device
+ *	@ifr: the ifreq block for the ioctl
+ *	@cmd: the command
+ *
+ *	Process MII requests made via ioctl from the network layer. These
+ *	are used by tools like kudzu to interrogate the link state of the
+ *	hardware
+ */
+ 
+static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct velocity_info *vptr = dev->priv;
+	struct mac_regs * regs = vptr->mac_regs;
+	unsigned long flags;
+	struct mii_ioctl_data *miidata = (struct mii_ioctl_data *) &(ifr->ifr_data);
+	int err;
+	
+	switch (cmd) {
+	case SIOCGMIIPHY:
+		miidata->phy_id = readb(&regs->MIIADR) & 0x1f;
+		break;
+	case SIOCGMIIREG:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if(velocity_mii_read(vptr->mac_regs, miidata->reg_num & 0x1f, &(miidata->val_out)) < 0)
+			return -ETIMEDOUT;
+		break;
+	case SIOCSMIIREG:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		spin_lock_irqsave(&vptr->lock, flags);
+		err = velocity_mii_write(vptr->mac_regs, miidata->reg_num & 0x1f, miidata->val_in);
+		spin_unlock_irqrestore(&vptr->lock, flags);
+		check_connection_type(vptr->mac_regs);
+		if(err)
+			return err;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+/**
+ *	velocity_save_context	-	save registers
+ *	@vptr: velocity 
+ *	@context: buffer for stored context
+ *
+ *	Retrieve the current configuration from the velocity hardware
+ *	and stash it in the context structure, for use by the context
+ *	restore functions. This allows us to save things we need across
+ *	power down states
+ */
+ 
+static void velocity_save_context(struct velocity_info *vptr, struct velocity_context * context)
+{
+	struct mac_regs * regs = vptr->mac_regs;
+	u16 i;
+	u8 *ptr = (u8 *)regs;
+
+	for (i = MAC_REG_PAR; i < MAC_REG_CR0_CLR; i += 4)
+		*((u32 *) (context->mac_reg + i)) = readl(ptr + i);
+
+	for (i = MAC_REG_MAR; i < MAC_REG_TDCSR_CLR; i += 4)
+		*((u32 *) (context->mac_reg + i)) = readl(ptr + i);
+
+	for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4)
+		*((u32 *) (context->mac_reg + i)) = readl(ptr + i);
+
+}
+
+/**
+ *	velocity_restore_context	-	restore registers
+ *	@vptr: velocity 
+ *	@context: buffer for stored context
+ *
+ *	Reload the register configuration from the velocity context 
+ *	created by velocity_save_context.
+ */
+ 
+static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context)
+{
+	struct mac_regs * regs = vptr->mac_regs;
+	int i;
+	u8 *ptr = (u8 *)regs;
+
+	for (i = MAC_REG_PAR; i < MAC_REG_CR0_SET; i += 4) {
+		writel(*((u32 *) (context->mac_reg + i)), ptr + i);
+	}
+
+	/* Just skip cr0 */
+	for (i = MAC_REG_CR1_SET; i < MAC_REG_CR0_CLR; i++) {
+		/* Clear */
+		writeb(~(*((u8 *) (context->mac_reg + i))), ptr + i + 4);
+		/* Set */
+		writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
+	}
+
+	for (i = MAC_REG_MAR; i < MAC_REG_IMR; i += 4) {
+		writel(*((u32 *) (context->mac_reg + i)), ptr + i);
+	}
+
+	for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4) {
+		writel(*((u32 *) (context->mac_reg + i)), ptr + i);
+	}
+
+	for (i = MAC_REG_TDCSR_SET; i <= MAC_REG_RDCSR_SET; i++) {
+		writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
+	}
+
+}
+
+static int velocity_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct velocity_info *vptr = pci_get_drvdata(pdev);
+	unsigned long flags;
+	
+	if(!netif_running(vptr->dev))
+		return 0;
+		
+	netif_device_detach(vptr->dev);
+	
+	spin_lock_irqsave(&vptr->lock, flags);
+	pci_save_state(pdev, vptr->pci_state);
+#ifdef ETHTOOL_GWOL
+	if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
+		velocity_get_ip(vptr);
+		velocity_save_context(vptr, &vptr->context);
+		velocity_shutdown(vptr);
+		velocity_set_wol(vptr);
+		pci_enable_wake(pdev, 3, 1);
+		pci_set_power_state(pdev, 3);
+	} else {
+		velocity_save_context(vptr, &vptr->context);
+		velocity_shutdown(vptr);
+		pci_disable_device(pdev);
+		pci_set_power_state(pdev, state);
+	}
+#else
+	pci_set_power_state(pdev, state);
+#endif
+	spin_unlock_irqrestore(&vptr->lock, flags);
+	return 0;
+}
+
+static int velocity_resume(struct pci_dev *pdev)
+{
+	struct velocity_info *vptr = pci_get_drvdata(pdev);
+	unsigned long flags;
+	int i;
+	
+	if(!netif_running(vptr->dev))
+		return 0;
+		
+	pci_set_power_state(pdev, 0);
+	pci_enable_wake(pdev, 0, 0);
+	pci_restore_state(pdev, vptr->pci_state);
+
+	mac_wol_reset(vptr->mac_regs);
+
+	spin_lock_irqsave(&vptr->lock, flags);
+	velocity_restore_context(vptr, &vptr->context);
+	velocity_init_registers(vptr, VELOCITY_INIT_WOL);
+	mac_disable_int(vptr->mac_regs);
+
+	velocity_tx_srv(vptr, 0);
+
+	for (i = 0; i < vptr->num_txq; i++) {
+		if (vptr->td_used[i]) {
+			mac_tx_queue_wake(vptr->mac_regs, i);
+		}
+	}
+
+	mac_enable_int(vptr->mac_regs);
+	spin_unlock_irqrestore(&vptr->lock, flags);
+	netif_device_attach(vptr->dev);
+
+	return 0;
+}
+
+static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
+{
+	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
+	struct net_device *dev;
+	struct velocity_info *vptr;
+
+	if (ifa) {
+		dev = ifa->ifa_dev->dev;
+		vptr = dev->priv;
+		velocity_get_ip(vptr);
+	}
+	return NOTIFY_DONE;
+}
+#endif
+
+/*
+ * Purpose: Functions to set WOL.
+ */
+
+const static unsigned short crc16_tab[256] = {
+	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+
+static u32 mask_pattern[2][4] = {
+	{0x00203000, 0x000003C0, 0x00000000, 0x0000000},	/* ARP		*/
+	{0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff}		/* Magic Packet */ 
+};
+
+/**
+ *	ether_crc16	-	compute ethernet CRC
+ *	@len: buffer length
+ *	@cp: buffer
+ *	@crc16: initial CRC
+ *
+ *	Compute a CRC value for a block of data. 
+ *	FIXME: can we use generic functions ?
+ */
+ 
+static u16 ether_crc16(int len, u8 * cp, u16 crc16)
+{
+	while (len--)
+		crc16 = (crc16 >> 8) ^ crc16_tab[(crc16 ^ *cp++) & 0xff];
+	return (crc16);
+}
+
+/**
+ *	bit_reverse		-	16bit reverse
+ *	@data: 16bit data t reverse
+ *
+ *	Reverse the order of a 16bit value and return the reversed bits
+ */
+ 
+static u16 bit_reverse(u16 data)
+{
+	u32 new = 0x00000000;
+	int ii;
+
+
+	for (ii = 0; ii < 16; ii++) {
+		new |= ((u32) (data & 1) << (31 - ii));
+		data >>= 1;
+	}
+
+	return (u16) (new >> 16);
+}
+
+/**
+ *	wol_calc_crc		-	WOL CRC
+ *	@pattern: data pattern
+ *	@mask_pattern: mask
+ *
+ *	Compute the wake on lan crc hashes for the packet header
+ *	we are interested in.
+ */
+ 
+u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
+{
+	u16 crc = 0xFFFF;
+	u8 mask;
+	int i, j;
+
+	for (i = 0; i < size; i++) {
+		mask = mask_pattern[i];
+
+		/* Skip this loop if the mask equals to zero */
+		if (mask == 0x00)
+			continue;
+
+		for (j = 0; j < 8; j++) {
+			if ((mask & 0x01) == 0) {
+				mask >>= 1;
+				continue;
+			}
+			mask >>= 1;
+			crc = ether_crc16(1, &(pattern[i * 8 + j]), crc);
+		}
+	}
+	/*	Finally, invert the result once to get the correct data */
+	crc = ~crc;
+	return bit_reverse(crc);
+}
+
+/**
+ *	velocity_set_wol	-	set up for wake on lan
+ *	@vptr: velocity to set WOL status on
+ *
+ *	Set a card up for wake on lan either by unicast or by
+ *	ARP packet.
+ *
+ *	FIXME: check static buffer is safe here
+ */
+ 
+static int velocity_set_wol(struct velocity_info *vptr)
+{
+	struct mac_regs * regs = vptr->mac_regs;
+	static u8 buf[256];
+	int i;
+
+	writew(0xFFFF, &regs->WOLCRClr);
+	writeb(WOLCFG_SAB | WOLCFG_SAM, &regs->WOLCFGSet);
+	writew(WOLCR_MAGIC_EN, &regs->WOLCRSet);
+
+	/*
+	   if (vptr->wol_opts & VELOCITY_WOL_PHY)
+	   writew((WOLCR_LINKON_EN|WOLCR_LINKOFF_EN), &regs->WOLCRSet);
+	 */
+
+	if (vptr->wol_opts & VELOCITY_WOL_UCAST) {
+		writew(WOLCR_UNICAST_EN, &regs->WOLCRSet);
+	}
+
+	if (vptr->wol_opts & VELOCITY_WOL_ARP) {
+		struct arp_packet *arp = (struct arp_packet *) buf;
+		u16 crc;
+		memset(buf, 0, sizeof(struct arp_packet) + 7);
+
+		for (i = 0; i < 4; i++)
+			writel(mask_pattern[0][i], &regs->ByteMask[0][i]);
+
+		arp->type = htons(ETH_P_ARP);
+		arp->ar_op = htons(1);
+
+		memcpy(arp->ar_tip, vptr->ip_addr, 4);
+
+		crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf, (u8 *) & mask_pattern[0][0]);
+
+		writew(crc, &regs->PatternCRC[0]);
+		writew(WOLCR_ARP_EN, &regs->WOLCRSet);
+	}
+
+	BYTE_REG_BITS_ON(PWCFG_WOLTYPE, &regs->PWCFGSet);
+	BYTE_REG_BITS_ON(PWCFG_LEGACY_WOLEN, &regs->PWCFGSet);
+
+	writew(0x0FFF, &regs->WOLSRClr);
+
+	if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
+		if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
+			MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, vptr->mac_regs);
+
+		MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs);
+	}
+
+	if (vptr->mii_status & VELOCITY_SPEED_1000)
+		MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs);
+
+	BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
+
+	{
+		u8 GCR;
+		GCR = readb(&regs->CHIPGCR);
+		GCR = (GCR & ~CHIPGCR_FCGMII) | CHIPGCR_FCFDX;
+		writeb(GCR, &regs->CHIPGCR);
+	}
+
+	BYTE_REG_BITS_OFF(ISR_PWEI, &regs->ISR);
+	/* Turn on SWPTAG just before entering power mode */
+	BYTE_REG_BITS_ON(STICKHW_SWPTAG, &regs->STICKHW);
+	/* Go to bed ..... */
+	BYTE_REG_BITS_ON((STICKHW_DS1 | STICKHW_DS0), &regs->STICKHW);
+
+	return 0;
+}
+
diff -Nru a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/via-velocity.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,1885 @@
+/*
+ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
+ * All rights reserved.
+ *
+ * This software may be redistributed and/or modified under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * File: via-velocity.h
+ *
+ * Purpose: Header file to define driver's private structures.
+ *
+ * Author: Chuang Liang-Shing, AJ Jiang
+ *
+ * Date: Jan 24, 2003
+ */
+
+
+#ifndef VELOCITY_H
+#define VELOCITY_H
+
+#define VELOCITY_TX_CSUM_SUPPORT
+
+#define VELOCITY_NAME          "via-velocity"
+#define VELOCITY_FULL_DRV_NAM  "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver"
+#define VELOCITY_VERSION       "1.13"
+
+#define PKT_BUF_SZ          1540
+
+#define MAX_UNITS           8
+#define OPTION_DEFAULT      { [0 ... MAX_UNITS-1] = -1}
+
+#define REV_ID_VT6110       (0)
+#define DEVICE_ID           (0x3119)
+
+#define BYTE_REG_BITS_ON(x,p)       do { writeb(readb((p))|(x),(p));} while (0)
+#define WORD_REG_BITS_ON(x,p)       do { writew(readw((p))|(x),(p));} while (0)
+#define DWORD_REG_BITS_ON(x,p)      do { writel(readl((p))|(x),(p));} while (0)
+
+#define BYTE_REG_BITS_IS_ON(x,p)    (readb((p)) & (x))
+#define WORD_REG_BITS_IS_ON(x,p)    (readw((p)) & (x))
+#define DWORD_REG_BITS_IS_ON(x,p)   (readl((p)) & (x))
+
+#define BYTE_REG_BITS_OFF(x,p)      do { writeb(readb((p)) & (~(x)),(p));} while (0)
+#define WORD_REG_BITS_OFF(x,p)      do { writew(readw((p)) & (~(x)),(p));} while (0)
+#define DWORD_REG_BITS_OFF(x,p)     do { writel(readl((p)) & (~(x)),(p));} while (0)
+
+#define BYTE_REG_BITS_SET(x,m,p)    do { writeb( (readb((p)) & (~(m))) |(x),(p));} while (0)
+#define WORD_REG_BITS_SET(x,m,p)    do { writew( (readw((p)) & (~(m))) |(x),(p));} while (0)
+#define DWORD_REG_BITS_SET(x,m,p)   do { writel( (readl((p)) & (~(m)))|(x),(p));}  while (0)
+
+#define VAR_USED(p)     do {(p)=(p);} while (0)
+
+/*
+ * Purpose: Structures for MAX RX/TX descriptors.
+ */
+
+
+#define B_OWNED_BY_CHIP     1
+#define B_OWNED_BY_HOST     0
+
+/*
+ * Bits in the RSR0 register
+ */
+
+#define RSR_DETAG          0x0080
+#define RSR_SNTAG          0x0040
+#define RSR_RXER           0x0020
+#define RSR_RL             0x0010
+#define RSR_CE             0x0008
+#define RSR_FAE            0x0004
+#define RSR_CRC            0x0002
+#define RSR_VIDM           0x0001
+
+/*
+ * Bits in the RSR1 register
+ */
+
+#define RSR_RXOK           0x8000	// rx OK
+#define RSR_PFT            0x4000	// Perfect filtering address match
+#define RSR_MAR            0x2000	// MAC accept multicast address packet
+#define RSR_BAR            0x1000	// MAC accept broadcast address packet
+#define RSR_PHY            0x0800	// MAC accept physical address packet
+#define RSR_VTAG           0x0400	// 802.1p/1q tagging packet indicator
+#define RSR_STP            0x0200	// start of packet
+#define RSR_EDP            0x0100	// end of packet
+
+/*
+ * Bits in the RSR1 register
+ */
+
+#define RSR1_RXOK           0x80	// rx OK
+#define RSR1_PFT            0x40	// Perfect filtering address match
+#define RSR1_MAR            0x20	// MAC accept multicast address packet
+#define RSR1_BAR            0x10	// MAC accept broadcast address packet
+#define RSR1_PHY            0x08	// MAC accept physical address packet
+#define RSR1_VTAG           0x04	// 802.1p/1q tagging packet indicator
+#define RSR1_STP            0x02	// start of packet
+#define RSR1_EDP            0x01	// end of packet
+
+/*
+ * Bits in the CSM register
+ */
+
+#define CSM_IPOK            0x40	//IP Checkusm validatiaon ok
+#define CSM_TUPOK           0x20	//TCP/UDP Checkusm validatiaon ok
+#define CSM_FRAG            0x10	//Fragment IP datagram
+#define CSM_IPKT            0x04	//Received an IP packet
+#define CSM_TCPKT           0x02	//Received a TCP packet
+#define CSM_UDPKT           0x01	//Received a UDP packet
+
+/*
+ * Bits in the TSR0 register
+ */
+
+#define TSR0_ABT            0x0080	// Tx abort because of excessive collision
+#define TSR0_OWT            0x0040	// Jumbo frame Tx abort
+#define TSR0_OWC            0x0020	// Out of window collision
+#define TSR0_COLS           0x0010	// experience collision in this transmit event
+#define TSR0_NCR3           0x0008	// collision retry counter[3]
+#define TSR0_NCR2           0x0004	// collision retry counter[2]
+#define TSR0_NCR1           0x0002	// collision retry counter[1]
+#define TSR0_NCR0           0x0001	// collision retry counter[0]
+#define TSR0_TERR           0x8000	//
+#define TSR0_FDX            0x4000	// current transaction is serviced by full duplex mode
+#define TSR0_GMII           0x2000	// current transaction is serviced by GMII mode
+#define TSR0_LNKFL          0x1000	// packet serviced during link down
+#define TSR0_SHDN           0x0400	// shutdown case
+#define TSR0_CRS            0x0200	// carrier sense lost
+#define TSR0_CDH            0x0100	// AQE test fail (CD heartbeat)
+
+/*
+ * Bits in the TSR1 register
+ */
+
+#define TSR1_TERR           0x80	//
+#define TSR1_FDX            0x40	// current transaction is serviced by full duplex mode
+#define TSR1_GMII           0x20	// current transaction is serviced by GMII mode
+#define TSR1_LNKFL          0x10	// packet serviced during link down
+#define TSR1_SHDN           0x04	// shutdown case
+#define TSR1_CRS            0x02	// carrier sense lost
+#define TSR1_CDH            0x01	// AQE test fail (CD heartbeat)
+
+//
+// Bits in the TCR0 register
+//
+#define TCR0_TIC            0x80	// assert interrupt immediately while descriptor has been send complete
+#define TCR0_PIC            0x40	// priority interrupt request, INA# is issued over adaptive interrupt scheme
+#define TCR0_VETAG          0x20	// enable VLAN tag
+#define TCR0_IPCK           0x10	// request IP  checksum calculation.
+#define TCR0_UDPCK          0x08	// request UDP checksum calculation.
+#define TCR0_TCPCK          0x04	// request TCP checksum calculation.
+#define TCR0_JMBO           0x02	// indicate a jumbo packet in GMAC side
+#define TCR0_CRC            0x01	// disable CRC generation
+
+#define TCPLS_NORMAL        3
+#define TCPLS_START         2
+#define TCPLS_END           1
+#define TCPLS_MED           0
+
+
+// max transmit or receive buffer size
+#define CB_RX_BUF_SIZE     2048UL	// max buffer size
+					// NOTE: must be multiple of 4
+
+#define CB_MAX_RD_NUM       512	// MAX # of RD
+#define CB_MAX_TD_NUM       256	// MAX # of TD
+
+#define CB_INIT_RD_NUM_3119 128	// init # of RD, for setup VT3119
+#define CB_INIT_TD_NUM_3119 64	// init # of TD, for setup VT3119
+
+#define CB_INIT_RD_NUM      128	// init # of RD, for setup default
+#define CB_INIT_TD_NUM      64	// init # of TD, for setup default
+
+// for 3119
+#define CB_TD_RING_NUM      4	// # of TD rings.
+#define CB_MAX_SEG_PER_PKT  7	// max data seg per packet (Tx)
+
+
+/*
+ *	If collisions excess 15 times , tx will abort, and
+ *	if tx fifo underflow, tx will fail
+ *	we should try to resend it
+ */
+
+#define CB_MAX_TX_ABORT_RETRY   3
+
+/*
+ *	Receive descriptor
+ */
+
+struct rdesc0 {
+	u16 RSR;		/* Receive status */
+	u16 len:14;		/* Received packet length */
+	u16 reserved:1;
+	u16 owner:1;		/* Who owns this buffer ? */
+};
+
+struct rdesc1 {
+	u16 PQTAG;
+	u8 CSM;
+	u8 IPKT;
+};
+
+struct rx_desc {
+	struct rdesc0 rdesc0;
+	struct rdesc1 rdesc1;
+	u32 pa_low;		/* Low 32 bit PCI address */
+	u16 pa_high;		/* Next 16 bit PCI address (48 total) */
+	u16 len:15;		/* Frame size */
+	u16 inten:1;		/* Enable interrupt */
+} __attribute__ ((__packed__));
+
+/*
+ *	Transmit descriptor
+ */
+
+struct tdesc0 {
+	u16 TSR;		/* Transmit status register */
+	u16 pktsize:14;		/* Size of frame */
+	u16 reserved:1;
+	u16 owner:1;		/* Who owns the buffer */
+};
+
+struct pqinf {			/* Priority queue info */
+	u16 VID:12;
+	u16 CFI:1;
+	u16 priority:3;
+} __attribute__ ((__packed__));
+
+struct tdesc1 {
+	struct pqinf pqinf;
+	u8 TCR;
+	u8 TCPLS:2;
+	u8 reserved:2;
+	u8 CMDZ:4;
+} __attribute__ ((__packed__));
+
+struct td_buf {
+	u32 pa_low;
+	u16 pa_high;
+	u16 bufsize:14;	
+	u16 reserved:1;
+	u16 queue:1;
+} __attribute__ ((__packed__));
+
+struct tx_desc {
+	struct tdesc0 tdesc0;
+	struct tdesc1 tdesc1;
+	struct td_buf td_buf[7];
+};
+
+struct velocity_rd_info {
+	struct sk_buff *skb;
+	dma_addr_t skb_dma;
+};
+
+/**
+ *	alloc_rd_info		-	allocate an rd info block
+ *
+ *	Alocate and initialize a receive info structure used for keeping
+ *	track of kernel side information related to each receive
+ *	descriptor we are using
+ */
+
+static inline struct velocity_rd_info *alloc_rd_info(void)
+{
+	struct velocity_rd_info *ptr;
+	if ((ptr = kmalloc(sizeof(struct velocity_rd_info), GFP_ATOMIC)) == NULL)
+		return NULL;
+	else {
+		memset(ptr, 0, sizeof(struct velocity_rd_info));
+		return ptr;
+	}
+}
+
+/*
+ *	Used to track transmit side buffers.
+ */
+
+struct velocity_td_info {
+	struct sk_buff *skb;
+	u8 *buf;
+	int nskb_dma;
+	dma_addr_t skb_dma[7];
+	dma_addr_t buf_dma;
+};
+
+enum {
+	OWNED_BY_HOST = 0,
+	OWNED_BY_NIC = 1
+} velocity_owner;
+
+
+/*
+ *	MAC registers and macros.
+ */
+
+
+#define MCAM_SIZE           64
+#define VCAM_SIZE           64
+#define TX_QUEUE_NO         4
+
+#define MAX_HW_MIB_COUNTER  32
+#define VELOCITY_MIN_MTU    (1514-14)
+#define VELOCITY_MAX_MTU    (9000)
+
+/*
+ *	Registers in the MAC
+ */
+
+#define MAC_REG_PAR         0x00	// physical address
+#define MAC_REG_RCR         0x06
+#define MAC_REG_TCR         0x07
+#define MAC_REG_CR0_SET     0x08
+#define MAC_REG_CR1_SET     0x09
+#define MAC_REG_CR2_SET     0x0A
+#define MAC_REG_CR3_SET     0x0B
+#define MAC_REG_CR0_CLR     0x0C
+#define MAC_REG_CR1_CLR     0x0D
+#define MAC_REG_CR2_CLR     0x0E
+#define MAC_REG_CR3_CLR     0x0F
+#define MAC_REG_MAR         0x10
+#define MAC_REG_CAM         0x10
+#define MAC_REG_DEC_BASE_HI 0x18
+#define MAC_REG_DBF_BASE_HI 0x1C
+#define MAC_REG_ISR_CTL     0x20
+#define MAC_REG_ISR_HOTMR   0x20
+#define MAC_REG_ISR_TSUPTHR 0x20
+#define MAC_REG_ISR_RSUPTHR 0x20
+#define MAC_REG_ISR_CTL1    0x21
+#define MAC_REG_TXE_SR      0x22
+#define MAC_REG_RXE_SR      0x23
+#define MAC_REG_ISR         0x24
+#define MAC_REG_ISR0        0x24
+#define MAC_REG_ISR1        0x25
+#define MAC_REG_ISR2        0x26
+#define MAC_REG_ISR3        0x27
+#define MAC_REG_IMR         0x28
+#define MAC_REG_IMR0        0x28
+#define MAC_REG_IMR1        0x29
+#define MAC_REG_IMR2        0x2A
+#define MAC_REG_IMR3        0x2B
+#define MAC_REG_TDCSR_SET   0x30
+#define MAC_REG_RDCSR_SET   0x32
+#define MAC_REG_TDCSR_CLR   0x34
+#define MAC_REG_RDCSR_CLR   0x36
+#define MAC_REG_RDBASE_LO   0x38
+#define MAC_REG_RDINDX      0x3C
+#define MAC_REG_TDBASE_LO   0x40
+#define MAC_REG_RDCSIZE     0x50
+#define MAC_REG_TDCSIZE     0x52
+#define MAC_REG_TDINDX      0x54
+#define MAC_REG_TDIDX0      0x54
+#define MAC_REG_TDIDX1      0x56
+#define MAC_REG_TDIDX2      0x58
+#define MAC_REG_TDIDX3      0x5A
+#define MAC_REG_PAUSE_TIMER 0x5C
+#define MAC_REG_RBRDU       0x5E
+#define MAC_REG_FIFO_TEST0  0x60
+#define MAC_REG_FIFO_TEST1  0x64
+#define MAC_REG_CAMADDR     0x68
+#define MAC_REG_CAMCR       0x69
+#define MAC_REG_GFTEST      0x6A
+#define MAC_REG_FTSTCMD     0x6B
+#define MAC_REG_MIICFG      0x6C
+#define MAC_REG_MIISR       0x6D
+#define MAC_REG_PHYSR0      0x6E
+#define MAC_REG_PHYSR1      0x6F
+#define MAC_REG_MIICR       0x70
+#define MAC_REG_MIIADR      0x71
+#define MAC_REG_MIIDATA     0x72
+#define MAC_REG_SOFT_TIMER0 0x74
+#define MAC_REG_SOFT_TIMER1 0x76
+#define MAC_REG_CFGA        0x78
+#define MAC_REG_CFGB        0x79
+#define MAC_REG_CFGC        0x7A
+#define MAC_REG_CFGD        0x7B
+#define MAC_REG_DCFG0       0x7C
+#define MAC_REG_DCFG1       0x7D
+#define MAC_REG_MCFG0       0x7E
+#define MAC_REG_MCFG1       0x7F
+
+#define MAC_REG_TBIST       0x80
+#define MAC_REG_RBIST       0x81
+#define MAC_REG_PMCC        0x82
+#define MAC_REG_STICKHW     0x83
+#define MAC_REG_MIBCR       0x84
+#define MAC_REG_EERSV       0x85
+#define MAC_REG_REVID       0x86
+#define MAC_REG_MIBREAD     0x88
+#define MAC_REG_BPMA        0x8C
+#define MAC_REG_EEWR_DATA   0x8C
+#define MAC_REG_BPMD_WR     0x8F
+#define MAC_REG_BPCMD       0x90
+#define MAC_REG_BPMD_RD     0x91
+#define MAC_REG_EECHKSUM    0x92
+#define MAC_REG_EECSR       0x93
+#define MAC_REG_EERD_DATA   0x94
+#define MAC_REG_EADDR       0x96
+#define MAC_REG_EMBCMD      0x97
+#define MAC_REG_JMPSR0      0x98
+#define MAC_REG_JMPSR1      0x99
+#define MAC_REG_JMPSR2      0x9A
+#define MAC_REG_JMPSR3      0x9B
+#define MAC_REG_CHIPGSR     0x9C
+#define MAC_REG_TESTCFG     0x9D
+#define MAC_REG_DEBUG       0x9E
+#define MAC_REG_CHIPGCR     0x9F
+#define MAC_REG_WOLCR0_SET  0xA0
+#define MAC_REG_WOLCR1_SET  0xA1
+#define MAC_REG_PWCFG_SET   0xA2
+#define MAC_REG_WOLCFG_SET  0xA3
+#define MAC_REG_WOLCR0_CLR  0xA4
+#define MAC_REG_WOLCR1_CLR  0xA5
+#define MAC_REG_PWCFG_CLR   0xA6
+#define MAC_REG_WOLCFG_CLR  0xA7
+#define MAC_REG_WOLSR0_SET  0xA8
+#define MAC_REG_WOLSR1_SET  0xA9
+#define MAC_REG_WOLSR0_CLR  0xAC
+#define MAC_REG_WOLSR1_CLR  0xAD
+#define MAC_REG_PATRN_CRC0  0xB0
+#define MAC_REG_PATRN_CRC1  0xB2
+#define MAC_REG_PATRN_CRC2  0xB4
+#define MAC_REG_PATRN_CRC3  0xB6
+#define MAC_REG_PATRN_CRC4  0xB8
+#define MAC_REG_PATRN_CRC5  0xBA
+#define MAC_REG_PATRN_CRC6  0xBC
+#define MAC_REG_PATRN_CRC7  0xBE
+#define MAC_REG_BYTEMSK0_0  0xC0
+#define MAC_REG_BYTEMSK0_1  0xC4
+#define MAC_REG_BYTEMSK0_2  0xC8
+#define MAC_REG_BYTEMSK0_3  0xCC
+#define MAC_REG_BYTEMSK1_0  0xD0
+#define MAC_REG_BYTEMSK1_1  0xD4
+#define MAC_REG_BYTEMSK1_2  0xD8
+#define MAC_REG_BYTEMSK1_3  0xDC
+#define MAC_REG_BYTEMSK2_0  0xE0
+#define MAC_REG_BYTEMSK2_1  0xE4
+#define MAC_REG_BYTEMSK2_2  0xE8
+#define MAC_REG_BYTEMSK2_3  0xEC
+#define MAC_REG_BYTEMSK3_0  0xF0
+#define MAC_REG_BYTEMSK3_1  0xF4
+#define MAC_REG_BYTEMSK3_2  0xF8
+#define MAC_REG_BYTEMSK3_3  0xFC
+
+/*
+ *	Bits in the RCR register
+ */
+
+#define RCR_AS              0x80
+#define RCR_AP              0x40
+#define RCR_AL              0x20
+#define RCR_PROM            0x10
+#define RCR_AB              0x08
+#define RCR_AM              0x04
+#define RCR_AR              0x02
+#define RCR_SEP             0x01
+
+/*
+ *	Bits in the TCR register
+ */
+
+#define TCR_TB2BDIS         0x80
+#define TCR_COLTMC1         0x08
+#define TCR_COLTMC0         0x04
+#define TCR_LB1             0x02	/* loopback[1] */
+#define TCR_LB0             0x01	/* loopback[0] */
+
+/*
+ *	Bits in the CR0 register
+ */
+
+#define CR0_TXON            0x00000008UL
+#define CR0_RXON            0x00000004UL
+#define CR0_STOP            0x00000002UL	/* stop MAC, default = 1 */
+#define CR0_STRT            0x00000001UL	/* start MAC */
+#define CR0_SFRST           0x00008000UL	/* software reset */
+#define CR0_TM1EN           0x00004000UL
+#define CR0_TM0EN           0x00002000UL
+#define CR0_DPOLL           0x00000800UL	/* disable rx/tx auto polling */
+#define CR0_DISAU           0x00000100UL
+#define CR0_XONEN           0x00800000UL
+#define CR0_FDXTFCEN        0x00400000UL	/* full-duplex TX flow control enable */
+#define CR0_FDXRFCEN        0x00200000UL	/* full-duplex RX flow control enable */
+#define CR0_HDXFCEN         0x00100000UL	/* half-duplex flow control enable */
+#define CR0_XHITH1          0x00080000UL	/* TX XON high threshold 1 */
+#define CR0_XHITH0          0x00040000UL	/* TX XON high threshold 0 */
+#define CR0_XLTH1           0x00020000UL	/* TX pause frame low threshold 1 */
+#define CR0_XLTH0           0x00010000UL	/* TX pause frame low threshold 0 */
+#define CR0_GSPRST          0x80000000UL
+#define CR0_FORSRST         0x40000000UL
+#define CR0_FPHYRST         0x20000000UL
+#define CR0_DIAG            0x10000000UL
+#define CR0_INTPCTL         0x04000000UL
+#define CR0_GINTMSK1        0x02000000UL
+#define CR0_GINTMSK0        0x01000000UL
+
+/*
+ *	Bits in the CR1 register
+ */
+
+#define CR1_SFRST           0x80	/* software reset */
+#define CR1_TM1EN           0x40
+#define CR1_TM0EN           0x20
+#define CR1_DPOLL           0x08	/* disable rx/tx auto polling */
+#define CR1_DISAU           0x01
+
+/*
+ *	Bits in the CR2 register
+ */
+
+#define CR2_XONEN           0x80
+#define CR2_FDXTFCEN        0x40	/* full-duplex TX flow control enable */
+#define CR2_FDXRFCEN        0x20	/* full-duplex RX flow control enable */
+#define CR2_HDXFCEN         0x10	/* half-duplex flow control enable */
+#define CR2_XHITH1          0x08	/* TX XON high threshold 1 */
+#define CR2_XHITH0          0x04	/* TX XON high threshold 0 */
+#define CR2_XLTH1           0x02	/* TX pause frame low threshold 1 */
+#define CR2_XLTH0           0x01	/* TX pause frame low threshold 0 */
+
+/*
+ *	Bits in the CR3 register
+ */
+
+#define CR3_GSPRST          0x80
+#define CR3_FORSRST         0x40
+#define CR3_FPHYRST         0x20
+#define CR3_DIAG            0x10
+#define CR3_INTPCTL         0x04
+#define CR3_GINTMSK1        0x02
+#define CR3_GINTMSK0        0x01
+
+#define ISRCTL_UDPINT       0x8000
+#define ISRCTL_TSUPDIS      0x4000
+#define ISRCTL_RSUPDIS      0x2000
+#define ISRCTL_PMSK1        0x1000
+#define ISRCTL_PMSK0        0x0800
+#define ISRCTL_INTPD        0x0400
+#define ISRCTL_HCRLD        0x0200
+#define ISRCTL_SCRLD        0x0100
+
+/*
+ *	Bits in the ISR_CTL1 register
+ */
+
+#define ISRCTL1_UDPINT      0x80
+#define ISRCTL1_TSUPDIS     0x40
+#define ISRCTL1_RSUPDIS     0x20
+#define ISRCTL1_PMSK1       0x10
+#define ISRCTL1_PMSK0       0x08
+#define ISRCTL1_INTPD       0x04
+#define ISRCTL1_HCRLD       0x02
+#define ISRCTL1_SCRLD       0x01
+
+/*
+ *	Bits in the TXE_SR register
+ */
+
+#define TXESR_TFDBS         0x08
+#define TXESR_TDWBS         0x04
+#define TXESR_TDRBS         0x02
+#define TXESR_TDSTR         0x01
+
+/*
+ *	Bits in the RXE_SR register
+ */
+
+#define RXESR_RFDBS         0x08
+#define RXESR_RDWBS         0x04
+#define RXESR_RDRBS         0x02
+#define RXESR_RDSTR         0x01
+
+/*
+ *	Bits in the ISR register
+ */
+
+#define ISR_ISR3            0x80000000UL
+#define ISR_ISR2            0x40000000UL
+#define ISR_ISR1            0x20000000UL
+#define ISR_ISR0            0x10000000UL
+#define ISR_TXSTLI          0x02000000UL
+#define ISR_RXSTLI          0x01000000UL
+#define ISR_HFLD            0x00800000UL
+#define ISR_UDPI            0x00400000UL
+#define ISR_MIBFI           0x00200000UL
+#define ISR_SHDNI           0x00100000UL
+#define ISR_PHYI            0x00080000UL
+#define ISR_PWEI            0x00040000UL
+#define ISR_TMR1I           0x00020000UL
+#define ISR_TMR0I           0x00010000UL
+#define ISR_SRCI            0x00008000UL
+#define ISR_LSTPEI          0x00004000UL
+#define ISR_LSTEI           0x00002000UL
+#define ISR_OVFI            0x00001000UL
+#define ISR_FLONI           0x00000800UL
+#define ISR_RACEI           0x00000400UL
+#define ISR_TXWB1I          0x00000200UL
+#define ISR_TXWB0I          0x00000100UL
+#define ISR_PTX3I           0x00000080UL
+#define ISR_PTX2I           0x00000040UL
+#define ISR_PTX1I           0x00000020UL
+#define ISR_PTX0I           0x00000010UL
+#define ISR_PTXI            0x00000008UL
+#define ISR_PRXI            0x00000004UL
+#define ISR_PPTXI           0x00000002UL
+#define ISR_PPRXI           0x00000001UL
+
+/*
+ *	Bits in the IMR register
+ */
+
+#define IMR_TXSTLM          0x02000000UL
+#define IMR_UDPIM           0x00400000UL
+#define IMR_MIBFIM          0x00200000UL
+#define IMR_SHDNIM          0x00100000UL
+#define IMR_PHYIM           0x00080000UL
+#define IMR_PWEIM           0x00040000UL
+#define IMR_TMR1IM          0x00020000UL
+#define IMR_TMR0IM          0x00010000UL
+
+#define IMR_SRCIM           0x00008000UL
+#define IMR_LSTPEIM         0x00004000UL
+#define IMR_LSTEIM          0x00002000UL
+#define IMR_OVFIM           0x00001000UL
+#define IMR_FLONIM          0x00000800UL
+#define IMR_RACEIM          0x00000400UL
+#define IMR_TXWB1IM         0x00000200UL
+#define IMR_TXWB0IM         0x00000100UL
+
+#define IMR_PTX3IM          0x00000080UL
+#define IMR_PTX2IM          0x00000040UL
+#define IMR_PTX1IM          0x00000020UL
+#define IMR_PTX0IM          0x00000010UL
+#define IMR_PTXIM           0x00000008UL
+#define IMR_PRXIM           0x00000004UL
+#define IMR_PPTXIM          0x00000002UL
+#define IMR_PPRXIM          0x00000001UL
+
+/* 0x0013FB0FUL  =  initial value of IMR */
+
+#define INT_MASK_DEF        (IMR_PPTXIM|IMR_PPRXIM|IMR_PTXIM|IMR_PRXIM|\
+                            IMR_PWEIM|IMR_TXWB0IM|IMR_TXWB1IM|IMR_FLONIM|\
+                            IMR_OVFIM|IMR_LSTEIM|IMR_LSTPEIM|IMR_SRCIM|IMR_MIBFIM|\
+                            IMR_SHDNIM|IMR_TMR1IM|IMR_TMR0IM|IMR_TXSTLM)
+
+/*
+ *	Bits in the TDCSR0/1, RDCSR0 register
+ */
+
+#define TRDCSR_DEAD         0x0008
+#define TRDCSR_WAK          0x0004
+#define TRDCSR_ACT          0x0002
+#define TRDCSR_RUN	    0x0001
+
+/*
+ *	Bits in the CAMADDR register
+ */
+
+#define CAMADDR_CAMEN       0x80
+#define CAMADDR_VCAMSL      0x40
+
+/*
+ *	Bits in the CAMCR register
+ */
+
+#define CAMCR_PS1           0x80
+#define CAMCR_PS0           0x40
+#define CAMCR_AITRPKT       0x20
+#define CAMCR_AITR16        0x10
+#define CAMCR_CAMRD         0x08
+#define CAMCR_CAMWR         0x04
+#define CAMCR_PS_CAM_MASK   0x40
+#define CAMCR_PS_CAM_DATA   0x80
+#define CAMCR_PS_MAR        0x00
+
+/*
+ *	Bits in the MIICFG register
+ */
+
+#define MIICFG_MPO1         0x80
+#define MIICFG_MPO0         0x40
+#define MIICFG_MFDC         0x20
+
+/*
+ *	Bits in the MIISR register
+ */
+
+#define MIISR_MIDLE         0x80
+
+/*
+ *	 Bits in the PHYSR0 register
+ */
+
+#define PHYSR0_PHYRST       0x80
+#define PHYSR0_LINKGD       0x40
+#define PHYSR0_FDPX         0x10
+#define PHYSR0_SPDG         0x08
+#define PHYSR0_SPD10        0x04
+#define PHYSR0_RXFLC        0x02
+#define PHYSR0_TXFLC        0x01
+
+/*
+ *	Bits in the PHYSR1 register
+ */
+
+#define PHYSR1_PHYTBI       0x01
+
+/*
+ *	Bits in the MIICR register
+ */
+
+#define MIICR_MAUTO         0x80
+#define MIICR_RCMD          0x40
+#define MIICR_WCMD          0x20
+#define MIICR_MDPM          0x10
+#define MIICR_MOUT          0x08
+#define MIICR_MDO           0x04
+#define MIICR_MDI           0x02
+#define MIICR_MDC           0x01
+
+/*
+ *	Bits in the MIIADR register
+ */
+
+#define MIIADR_SWMPL        0x80
+
+/*
+ *	Bits in the CFGA register
+ */
+
+#define CFGA_PMHCTG         0x08
+#define CFGA_GPIO1PD        0x04
+#define CFGA_ABSHDN         0x02
+#define CFGA_PACPI          0x01
+
+/*
+ *	Bits in the CFGB register
+ */
+
+#define CFGB_GTCKOPT        0x80
+#define CFGB_MIIOPT         0x40
+#define CFGB_CRSEOPT        0x20
+#define CFGB_OFSET          0x10
+#define CFGB_CRANDOM        0x08
+#define CFGB_CAP            0x04
+#define CFGB_MBA            0x02
+#define CFGB_BAKOPT         0x01
+
+/*
+ *	Bits in the CFGC register
+ */
+
+#define CFGC_EELOAD         0x80
+#define CFGC_BROPT          0x40
+#define CFGC_DLYEN          0x20
+#define CFGC_DTSEL          0x10
+#define CFGC_BTSEL          0x08
+#define CFGC_BPS2           0x04	/* bootrom select[2] */
+#define CFGC_BPS1           0x02	/* bootrom select[1] */
+#define CFGC_BPS0           0x01	/* bootrom select[0] */
+
+/*
+ * Bits in the CFGD register
+ */
+
+#define CFGD_IODIS          0x80
+#define CFGD_MSLVDACEN      0x40
+#define CFGD_CFGDACEN       0x20
+#define CFGD_PCI64EN        0x10
+#define CFGD_HTMRL4         0x08
+
+/*
+ *	Bits in the DCFG1 register
+ */
+
+#define DCFG_XMWI           0x8000
+#define DCFG_XMRM           0x4000
+#define DCFG_XMRL           0x2000
+#define DCFG_PERDIS         0x1000
+#define DCFG_MRWAIT         0x0400
+#define DCFG_MWWAIT         0x0200
+#define DCFG_LATMEN         0x0100
+
+/*
+ *	Bits in the MCFG0 register
+ */
+
+#define MCFG_RXARB          0x0080
+#define MCFG_RFT1           0x0020
+#define MCFG_RFT0           0x0010
+#define MCFG_LOWTHOPT       0x0008
+#define MCFG_PQEN           0x0004
+#define MCFG_RTGOPT         0x0002
+#define MCFG_VIDFR          0x0001
+
+/*
+ *	Bits in the MCFG1 register
+ */
+
+#define MCFG_TXARB          0x8000
+#define MCFG_TXQBK1         0x0800
+#define MCFG_TXQBK0         0x0400
+#define MCFG_TXQNOBK        0x0200
+#define MCFG_SNAPOPT        0x0100
+
+/*
+ *	Bits in the PMCC  register
+ */
+
+#define PMCC_DSI            0x80
+#define PMCC_D2_DIS         0x40
+#define PMCC_D1_DIS         0x20
+#define PMCC_D3C_EN         0x10
+#define PMCC_D3H_EN         0x08
+#define PMCC_D2_EN          0x04
+#define PMCC_D1_EN          0x02
+#define PMCC_D0_EN          0x01
+
+/*
+ *	Bits in STICKHW
+ */
+
+#define STICKHW_SWPTAG      0x10
+#define STICKHW_WOLSR       0x08
+#define STICKHW_WOLEN       0x04
+#define STICKHW_DS1         0x02	/* R/W by software/cfg cycle */
+#define STICKHW_DS0         0x01	/* suspend well DS write port */
+
+/*
+ *	Bits in the MIBCR register
+ */
+
+#define MIBCR_MIBISTOK      0x80
+#define MIBCR_MIBISTGO      0x40
+#define MIBCR_MIBINC        0x20
+#define MIBCR_MIBHI         0x10
+#define MIBCR_MIBFRZ        0x08
+#define MIBCR_MIBFLSH       0x04
+#define MIBCR_MPTRINI       0x02
+#define MIBCR_MIBCLR        0x01
+
+/*
+ *	Bits in the EERSV register
+ */
+
+#define EERSV_BOOT_RPL      ((u8) 0x01)	 /* Boot method selection for VT6110 */
+
+#define EERSV_BOOT_MASK     ((u8) 0x06)
+#define EERSV_BOOT_INT19    ((u8) 0x00)
+#define EERSV_BOOT_INT18    ((u8) 0x02)
+#define EERSV_BOOT_LOCAL    ((u8) 0x04)
+#define EERSV_BOOT_BEV      ((u8) 0x06)
+
+
+/*
+ *	Bits in BPCMD
+ */
+
+#define BPCMD_BPDNE         0x80
+#define BPCMD_EBPWR         0x02
+#define BPCMD_EBPRD         0x01
+
+/*
+ *	Bits in the EECSR register
+ */
+
+#define EECSR_EMBP          0x40	/* eeprom embeded programming */
+#define EECSR_RELOAD        0x20	/* eeprom content reload */
+#define EECSR_DPM           0x10	/* eeprom direct programming */
+#define EECSR_ECS           0x08	/* eeprom CS pin */
+#define EECSR_ECK           0x04	/* eeprom CK pin */
+#define EECSR_EDI           0x02	/* eeprom DI pin */
+#define EECSR_EDO           0x01	/* eeprom DO pin */
+
+/*
+ *	Bits in the EMBCMD register
+ */
+
+#define EMBCMD_EDONE        0x80
+#define EMBCMD_EWDIS        0x08
+#define EMBCMD_EWEN         0x04
+#define EMBCMD_EWR          0x02
+#define EMBCMD_ERD          0x01
+
+/*
+ *	Bits in TESTCFG register
+ */
+
+#define TESTCFG_HBDIS       0x80
+
+/*
+ *	Bits in CHIPGCR register
+ */
+
+#define CHIPGCR_FCGMII      0x80
+#define CHIPGCR_FCFDX       0x40
+#define CHIPGCR_FCRESV      0x20
+#define CHIPGCR_FCMODE      0x10
+#define CHIPGCR_LPSOPT      0x08
+#define CHIPGCR_TM1US       0x04
+#define CHIPGCR_TM0US       0x02
+#define CHIPGCR_PHYINTEN    0x01
+
+/*
+ *	Bits in WOLCR0
+ */
+
+#define WOLCR_MSWOLEN7      0x0080	/* enable pattern match filtering */
+#define WOLCR_MSWOLEN6      0x0040
+#define WOLCR_MSWOLEN5      0x0020
+#define WOLCR_MSWOLEN4      0x0010
+#define WOLCR_MSWOLEN3      0x0008
+#define WOLCR_MSWOLEN2      0x0004
+#define WOLCR_MSWOLEN1      0x0002
+#define WOLCR_MSWOLEN0      0x0001
+#define WOLCR_ARP_EN        0x0001
+
+/*
+ *	Bits in WOLCR1
+ */
+
+#define WOLCR_LINKOFF_EN      0x0800	/* link off detected enable */
+#define WOLCR_LINKON_EN       0x0400	/* link on detected enable */
+#define WOLCR_MAGIC_EN        0x0200	/* magic packet filter enable */
+#define WOLCR_UNICAST_EN      0x0100	/* unicast filter enable */
+
+
+/*
+ *	Bits in PWCFG
+ */
+
+#define PWCFG_PHYPWOPT          0x80	/* internal MII I/F timing */
+#define PWCFG_PCISTICK          0x40	/* PCI sticky R/W enable */
+#define PWCFG_WOLTYPE           0x20	/* pulse(1) or button (0) */
+#define PWCFG_LEGCY_WOL         0x10
+#define PWCFG_PMCSR_PME_SR      0x08
+#define PWCFG_PMCSR_PME_EN      0x04	/* control by PCISTICK */
+#define PWCFG_LEGACY_WOLSR      0x02	/* Legacy WOL_SR shadow */
+#define PWCFG_LEGACY_WOLEN      0x01	/* Legacy WOL_EN shadow */
+
+/*
+ *	Bits in WOLCFG
+ */
+
+#define WOLCFG_PMEOVR           0x80	/* for legacy use, force PMEEN always */
+#define WOLCFG_SAM              0x20	/* accept multicast case reset, default=0 */
+#define WOLCFG_SAB              0x10	/* accept broadcast case reset, default=0 */
+#define WOLCFG_SMIIACC          0x08	/* ?? */
+#define WOLCFG_SGENWH           0x02
+#define WOLCFG_PHYINTEN         0x01	/* 0:PHYINT trigger enable, 1:use internal MII
+					  to report status change */
+/*
+ *	Bits in WOLSR1
+ */
+
+#define WOLSR_LINKOFF_INT      0x0800
+#define WOLSR_LINKON_INT       0x0400
+#define WOLSR_MAGIC_INT        0x0200
+#define WOLSR_UNICAST_INT      0x0100
+
+/*
+ *	Ethernet address filter type
+ */
+
+#define PKT_TYPE_NONE               0x0000	/* Turn off receiver */
+#define PKT_TYPE_DIRECTED           0x0001	/* obselete, directed address is always accepted */
+#define PKT_TYPE_MULTICAST          0x0002
+#define PKT_TYPE_ALL_MULTICAST      0x0004
+#define PKT_TYPE_BROADCAST          0x0008
+#define PKT_TYPE_PROMISCUOUS        0x0020
+#define PKT_TYPE_LONG               0x2000	/* NOTE.... the definition of LONG is >2048 bytes in our chip */
+#define PKT_TYPE_RUNT               0x4000
+#define PKT_TYPE_ERROR              0x8000	/* Accept error packets, e.g. CRC error */
+
+/*
+ *	Loopback mode
+ */
+
+#define MAC_LB_NONE         0x00
+#define MAC_LB_INTERNAL     0x01
+#define MAC_LB_EXTERNAL     0x02
+
+/*
+ *	Enabled mask value of irq
+ */
+
+#if defined(_SIM)
+#define IMR_MASK_VALUE      0x0033FF0FUL	/* initial value of IMR
+						   set IMR0 to 0x0F according to spec */
+
+#else
+#define IMR_MASK_VALUE      0x0013FB0FUL	/* initial value of IMR
+						   ignore MIBFI,RACEI to
+						   reduce intr. frequency
+						   NOTE.... do not enable NoBuf int mask at driver driver
+						      when (1) NoBuf -> RxThreshold = SF
+							   (2) OK    -> RxThreshold = original value
+						 */
+#endif
+
+/*
+ *	Revision id
+ */
+
+#define REV_ID_VT3119_A0	0x00
+#define REV_ID_VT3119_A1	0x01
+#define REV_ID_VT3216_A0	0x10
+
+/*
+ *	Max time out delay time
+ */
+
+#define W_MAX_TIMEOUT       0x0FFFU
+
+
+/*
+ *	MAC registers as a structure. Cannot be directly accessed this
+ *	way but generates offsets for readl/writel() calls
+ */
+
+struct mac_regs {
+	volatile u8 PAR[6];		/* 0x00 */
+	volatile u8 RCR;
+	volatile u8 TCR;
+
+	volatile u32 CR0Set;		/* 0x08 */
+	volatile u32 CR0Clr;		/* 0x0C */
+
+	volatile u8 MARCAM[8];		/* 0x10 */
+
+	volatile u32 DecBaseHi;		/* 0x18 */
+	volatile u16 DbfBaseHi;		/* 0x1C */
+	volatile u16 reserved_1E;
+
+	volatile u16 ISRCTL;		/* 0x20 */
+	volatile u8 TXESR;
+	volatile u8 RXESR;
+
+	volatile u32 ISR;		/* 0x24 */
+	volatile u32 IMR;
+
+	volatile u32 TDStatusPort;	/* 0x2C */
+
+	volatile u16 TDCSRSet;		/* 0x30 */
+	volatile u8 RDCSRSet;
+	volatile u8 reserved_33;
+	volatile u16 TDCSRClr;
+	volatile u8 RDCSRClr;
+	volatile u8 reserved_37;
+
+	volatile u32 RDBaseLo;		/* 0x38 */
+	volatile u16 RDIdx;		/* 0x3C */
+	volatile u16 reserved_3E;
+
+	volatile u32 TDBaseLo[4];	/* 0x40 */
+
+	volatile u16 RDCSize;		/* 0x50 */
+	volatile u16 TDCSize;		/* 0x52 */
+	volatile u16 TDIdx[4];		/* 0x54 */
+	volatile u16 tx_pause_timer;	/* 0x5C */
+	volatile u16 RBRDU;		/* 0x5E */
+
+	volatile u32 FIFOTest0;		/* 0x60 */
+	volatile u32 FIFOTest1;		/* 0x64 */
+
+	volatile u8 CAMADDR;		/* 0x68 */
+	volatile u8 CAMCR;		/* 0x69 */
+	volatile u8 GFTEST;		/* 0x6A */
+	volatile u8 FTSTCMD;		/* 0x6B */
+
+	volatile u8 MIICFG;		/* 0x6C */
+	volatile u8 MIISR;
+	volatile u8 PHYSR0;
+	volatile u8 PHYSR1;
+	volatile u8 MIICR;
+	volatile u8 MIIADR;
+	volatile u16 MIIDATA;
+
+	volatile u16 SoftTimer0;	/* 0x74 */
+	volatile u16 SoftTimer1;
+
+	volatile u8 CFGA;		/* 0x78 */
+	volatile u8 CFGB;
+	volatile u8 CFGC;
+	volatile u8 CFGD;
+
+	volatile u16 DCFG;		/* 0x7C */
+	volatile u16 MCFG;
+
+	volatile u8 TBIST;		/* 0x80 */
+	volatile u8 RBIST;
+	volatile u8 PMCPORT;
+	volatile u8 STICKHW;
+
+	volatile u8 MIBCR;		/* 0x84 */
+	volatile u8 reserved_85;
+	volatile u8 rev_id;
+	volatile u8 PORSTS;
+
+	volatile u32 MIBData;		/* 0x88 */
+
+	volatile u16 EEWrData;
+
+	volatile u8 reserved_8E;
+	volatile u8 BPMDWr;
+	volatile u8 BPCMD;
+	volatile u8 BPMDRd;
+
+	volatile u8 EECHKSUM;		/* 0x92 */
+	volatile u8 EECSR;
+
+	volatile u16 EERdData;		/* 0x94 */
+	volatile u8 EADDR;
+	volatile u8 EMBCMD;
+
+
+	volatile u8 JMPSR0;		/* 0x98 */
+	volatile u8 JMPSR1;
+	volatile u8 JMPSR2;
+	volatile u8 JMPSR3;
+	volatile u8 CHIPGSR;		/* 0x9C */
+	volatile u8 TESTCFG;
+	volatile u8 DEBUG;
+	volatile u8 CHIPGCR;
+
+	volatile u16 WOLCRSet;		/* 0xA0 */
+	volatile u8 PWCFGSet;
+	volatile u8 WOLCFGSet;
+
+	volatile u16 WOLCRClr;		/* 0xA4 */
+	volatile u8 PWCFGCLR;
+	volatile u8 WOLCFGClr;
+
+	volatile u16 WOLSRSet;		/* 0xA8 */
+	volatile u16 reserved_AA;
+
+	volatile u16 WOLSRClr;		/* 0xAC */
+	volatile u16 reserved_AE;
+
+	volatile u16 PatternCRC[8];	/* 0xB0 */
+	volatile u32 ByteMask[4][4];	/* 0xC0 */
+} __attribute__ ((__packed__));
+
+
+enum hw_mib {
+	HW_MIB_ifRxAllPkts = 0,
+	HW_MIB_ifRxOkPkts,
+	HW_MIB_ifTxOkPkts,
+	HW_MIB_ifRxErrorPkts,
+	HW_MIB_ifRxRuntOkPkt,
+	HW_MIB_ifRxRuntErrPkt,
+	HW_MIB_ifRx64Pkts,
+	HW_MIB_ifTx64Pkts,
+	HW_MIB_ifRx65To127Pkts,
+	HW_MIB_ifTx65To127Pkts,
+	HW_MIB_ifRx128To255Pkts,
+	HW_MIB_ifTx128To255Pkts,
+	HW_MIB_ifRx256To511Pkts,
+	HW_MIB_ifTx256To511Pkts,
+	HW_MIB_ifRx512To1023Pkts,
+	HW_MIB_ifTx512To1023Pkts,
+	HW_MIB_ifRx1024To1518Pkts,
+	HW_MIB_ifTx1024To1518Pkts,
+	HW_MIB_ifTxEtherCollisions,
+	HW_MIB_ifRxPktCRCE,
+	HW_MIB_ifRxJumboPkts,
+	HW_MIB_ifTxJumboPkts,
+	HW_MIB_ifRxMacControlFrames,
+	HW_MIB_ifTxMacControlFrames,
+	HW_MIB_ifRxPktFAE,
+	HW_MIB_ifRxLongOkPkt,
+	HW_MIB_ifRxLongPktErrPkt,
+	HW_MIB_ifTXSQEErrors,
+	HW_MIB_ifRxNobuf,
+	HW_MIB_ifRxSymbolErrors,
+	HW_MIB_ifInRangeLengthErrors,
+	HW_MIB_ifLateCollisions,
+	HW_MIB_SIZE
+};
+
+enum chip_type {
+	CHIP_TYPE_VT6110 = 1,
+};
+
+struct velocity_info_tbl {
+	enum chip_type chip_id;
+	char *name;
+	int io_size;
+	int txqueue;
+	u32 flags;
+};
+
+#define mac_hw_mibs_init(regs) {\
+	BYTE_REG_BITS_ON(MIBCR_MIBFRZ,&((regs)->MIBCR));\
+	BYTE_REG_BITS_ON(MIBCR_MIBCLR,&((regs)->MIBCR));\
+	do {}\
+		while (BYTE_REG_BITS_IS_ON(MIBCR_MIBCLR,&((regs)->MIBCR)));\
+	BYTE_REG_BITS_OFF(MIBCR_MIBFRZ,&((regs)->MIBCR));\
+}
+
+#define mac_read_isr(regs)  		readl(&((regs)->ISR))
+#define mac_write_isr(regs, x)  	writel((x),&((regs)->ISR))
+#define mac_clear_isr(regs) 		writel(0xffffffffL,&((regs)->ISR))
+
+#define mac_write_int_mask(mask, regs) 	writel((mask),&((regs)->IMR));
+#define mac_disable_int(regs)       	writel(CR0_GINTMSK1,&((regs)->CR0Clr))
+#define mac_enable_int(regs)    	writel(CR0_GINTMSK1,&((regs)->CR0Set))
+
+#define mac_hw_mibs_read(regs, MIBs) {\
+	int i;\
+	BYTE_REG_BITS_ON(MIBCR_MPTRINI,&((regs)->MIBCR));\
+	for (i=0;i<HW_MIB_SIZE;i++) {\
+		(MIBs)[i]=readl(&((regs)->MIBData));\
+	}\
+}
+
+#define mac_set_dma_length(regs, n) {\
+	BYTE_REG_BITS_SET((n),0x07,&((regs)->DCFG));\
+}
+
+#define mac_set_rx_thresh(regs, n) {\
+	BYTE_REG_BITS_SET((n),(MCFG_RFT0|MCFG_RFT1),&((regs)->MCFG));\
+}
+
+#define mac_rx_queue_run(regs) {\
+	writeb(TRDCSR_RUN, &((regs)->RDCSRSet));\
+}
+
+#define mac_rx_queue_wake(regs) {\
+	writeb(TRDCSR_WAK, &((regs)->RDCSRSet));\
+}
+
+#define mac_tx_queue_run(regs, n) {\
+	writew(TRDCSR_RUN<<((n)*4),&((regs)->TDCSRSet));\
+}
+
+#define mac_tx_queue_wake(regs, n) {\
+	writew(TRDCSR_WAK<<(n*4),&((regs)->TDCSRSet));\
+}
+
+#define mac_eeprom_reload(regs) {\
+	int i=0;\
+	BYTE_REG_BITS_ON(EECSR_RELOAD,&((regs)->EECSR));\
+	do {\
+		udelay(10);\
+		if (i++>0x1000) {\
+			break;\
+		}\
+	}while (BYTE_REG_BITS_IS_ON(EECSR_RELOAD,&((regs)->EECSR)));\
+}
+
+enum velocity_cam_type {
+	VELOCITY_VLAN_ID_CAM = 0,
+	VELOCITY_MULTICAST_CAM
+};
+
+/**
+ *	mac_get_cam_mask	-	Read a CAM mask
+ *	@regs: register block for this velocity
+ *	@mask: buffer to store mask
+ *	@cam_type: CAM to fetch
+ *
+ *	Fetch the mask bits of the selected CAM and store them into the
+ *	provided mask buffer.
+ */
+
+static inline void mac_get_cam_mask(struct mac_regs * regs, u8 * mask, enum velocity_cam_type cam_type)
+{
+	int i;
+	/* Select CAM mask */
+	BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
+
+	if (cam_type == VELOCITY_VLAN_ID_CAM)
+		writeb(CAMADDR_VCAMSL, &regs->CAMADDR);
+	else
+		writeb(0, &regs->CAMADDR);
+
+	/* read mask */
+	for (i = 0; i < 8; i++)
+		*mask++ = readb(&(regs->MARCAM[i]));
+
+	/* disable CAMEN */
+	writeb(0, &regs->CAMADDR);
+
+	/* Select mar */
+	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
+
+}
+
+/**
+ *	mac_set_cam_mask	-	Set a CAM mask
+ *	@regs: register block for this velocity
+ *	@mask: CAM mask to load
+ *	@cam_type: CAM to store
+ *
+ *	Store a new mask into a CAM
+ */
+
+static inline void mac_set_cam_mask(struct mac_regs * regs, u8 * mask, enum velocity_cam_type cam_type)
+{
+	int i;
+	/* Select CAM mask */
+	BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
+
+	if (cam_type == VELOCITY_VLAN_ID_CAM)
+		writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL, &regs->CAMADDR);
+	else
+		writeb(CAMADDR_CAMEN, &regs->CAMADDR);
+
+	for (i = 0; i < 8; i++) {
+		writeb(*mask++, &(regs->MARCAM[i]));
+	}
+	/* disable CAMEN */
+	writeb(0, &regs->CAMADDR);
+
+	/* Select CAM mask */
+	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
+}
+
+/**
+ *	mac_set_cam	-	set CAM data
+ *	@regs: register block of this velocity
+ *	@idx: Cam index
+ *	@addr: 2 or 6 bytes of CAM data
+ *	@cam_type: CAM to load
+ *
+ *	Load an address or vlan tag into a CAM
+ */
+
+static inline void mac_set_cam(struct mac_regs * regs, int idx, u8 *addr, enum velocity_cam_type cam_type)
+{
+	int i;
+
+	/* Select CAM mask */
+	BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
+
+	idx &= (64 - 1);
+
+	if (cam_type == VELOCITY_VLAN_ID_CAM)
+		writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL | idx, &regs->CAMADDR);
+	else
+		writeb(CAMADDR_CAMEN | idx, &regs->CAMADDR);
+
+	if (cam_type == VELOCITY_VLAN_ID_CAM)
+		writew(*((u16 *) addr), &regs->MARCAM[0]);
+	else {
+		for (i = 0; i < 6; i++) {
+			writeb(*addr++, &(regs->MARCAM[i]));
+		}
+	}
+	BYTE_REG_BITS_ON(CAMCR_CAMWR, &regs->CAMCR);
+
+	udelay(10);
+
+	writeb(0, &regs->CAMADDR);
+
+	/* Select CAM mask */
+	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
+}
+
+/**
+ *	mac_get_cam	-	fetch CAM data
+ *	@regs: register block of this velocity
+ *	@idx: Cam index
+ *	@addr: buffer to hold up to 6 bytes of CAM data
+ *	@cam_type: CAM to load
+ *
+ *	Load an address or vlan tag from a CAM into the buffer provided by
+ *	the caller. VLAN tags are 2 bytes the address cam entries are 6.
+ */
+
+static inline void mac_get_cam(struct mac_regs * regs, int idx, u8 *addr, enum velocity_cam_type cam_type)
+{
+	int i;
+
+	/* Select CAM mask */
+	BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
+
+	idx &= (64 - 1);
+
+	if (cam_type == VELOCITY_VLAN_ID_CAM)
+		writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL | idx, &regs->CAMADDR);
+	else
+		writeb(CAMADDR_CAMEN | idx, &regs->CAMADDR);
+
+	BYTE_REG_BITS_ON(CAMCR_CAMRD, &regs->CAMCR);
+
+	udelay(10);
+
+	if (cam_type == VELOCITY_VLAN_ID_CAM)
+		*((u16 *) addr) = readw(&(regs->MARCAM[0]));
+	else
+		for (i = 0; i < 6; i++, addr++)
+			*((u8 *) addr) = readb(&(regs->MARCAM[i]));
+
+	writeb(0, &regs->CAMADDR);
+
+	/* Select CAM mask */
+	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
+}
+
+/**
+ *	mac_wol_reset	-	reset WOL after exiting low power
+ *	@regs: register block of this velocity
+ *
+ *	Called after we drop out of wake on lan mode in order to
+ *	reset the Wake on lan features. This function doesn't restore
+ *	the rest of the logic from the result of sleep/wakeup
+ */
+
+inline static void mac_wol_reset(struct mac_regs * regs)
+{
+
+	/* Turn off SWPTAG right after leaving power mode */
+	BYTE_REG_BITS_OFF(STICKHW_SWPTAG, &regs->STICKHW);
+	/* clear sticky bits */
+	BYTE_REG_BITS_OFF((STICKHW_DS1 | STICKHW_DS0), &regs->STICKHW);
+
+	BYTE_REG_BITS_OFF(CHIPGCR_FCGMII, &regs->CHIPGCR);
+	BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, &regs->CHIPGCR);
+	/* disable force PME-enable */
+	writeb(WOLCFG_PMEOVR, &regs->WOLCFGClr);
+	/* disable power-event config bit */
+	writew(0xFFFF, &regs->WOLCRClr);
+	/* clear power status */
+	writew(0xFFFF, &regs->WOLSRClr);
+}
+
+
+/*
+ * Header for WOL definitions. Used to compute hashes
+ */
+
+typedef u8 MCAM_ADDR[ETH_ALEN];
+
+struct arp_packet {
+	u8 dest_mac[ETH_ALEN];
+	u8 src_mac[ETH_ALEN];
+	u16 type;
+	u16 ar_hrd;
+	u16 ar_pro;
+	u8 ar_hln;
+	u8 ar_pln;
+	u16 ar_op;
+	u8 ar_sha[ETH_ALEN];
+	u8 ar_sip[4];
+	u8 ar_tha[ETH_ALEN];
+	u8 ar_tip[4];
+} __attribute__ ((__packed__));
+
+struct _magic_packet {
+	u8 dest_mac[6];
+	u8 src_mac[6];
+	u16 type;
+	u8 MAC[16][6];
+	u8 password[6];
+} __attribute__ ((__packed__));
+
+/*
+ *	Store for chip context when saving and restoring status. Not
+ *	all fields are saved/restored currently.
+ */
+
+struct velocity_context {
+	u8 mac_reg[256];
+	MCAM_ADDR cam_addr[MCAM_SIZE];
+	u16 vcam[VCAM_SIZE];
+	u32 cammask[2];
+	u32 patcrc[2];
+	u32 pattern[8];
+};
+
+
+/*
+ *	MII registers.
+ */
+
+
+/*
+ *	Registers in the MII (offset unit is WORD)
+ */
+
+#define MII_REG_BMCR        0x00	// physical address
+#define MII_REG_BMSR        0x01	//
+#define MII_REG_PHYID1      0x02	// OUI
+#define MII_REG_PHYID2      0x03	// OUI + Module ID + REV ID
+#define MII_REG_ANAR        0x04	//
+#define MII_REG_ANLPAR      0x05	//
+#define MII_REG_G1000CR     0x09	//
+#define MII_REG_G1000SR     0x0A	//
+#define MII_REG_MODCFG      0x10	//
+#define MII_REG_TCSR        0x16	//
+#define MII_REG_PLED        0x1B	//
+// NS, MYSON only
+#define MII_REG_PCR         0x17	//
+// ESI only
+#define MII_REG_PCSR        0x17	//
+#define MII_REG_AUXCR       0x1C	//
+
+// Marvell 88E1000/88E1000S
+#define MII_REG_PSCR        0x10	// PHY specific control register
+
+//
+// Bits in the BMCR register
+//
+#define BMCR_RESET          0x8000	//
+#define BMCR_LBK            0x4000	//
+#define BMCR_SPEED100       0x2000	//
+#define BMCR_AUTO           0x1000	//
+#define BMCR_PD             0x0800	//
+#define BMCR_ISO            0x0400	//
+#define BMCR_REAUTO         0x0200	//
+#define BMCR_FDX            0x0100	//
+#define BMCR_SPEED1G        0x0040	//
+//
+// Bits in the BMSR register
+//
+#define BMSR_AUTOCM         0x0020	//
+#define BMSR_LNK            0x0004	//
+
+//
+// Bits in the ANAR register
+//
+#define ANAR_ASMDIR         0x0800	// Asymmetric PAUSE support
+#define ANAR_PAUSE          0x0400	// Symmetric PAUSE Support
+#define ANAR_T4             0x0200	//
+#define ANAR_TXFD           0x0100	//
+#define ANAR_TX             0x0080	//
+#define ANAR_10FD           0x0040	//
+#define ANAR_10             0x0020	//
+//
+// Bits in the ANLPAR register
+//
+#define ANLPAR_ASMDIR       0x0800	// Asymmetric PAUSE support
+#define ANLPAR_PAUSE        0x0400	// Symmetric PAUSE Support
+#define ANLPAR_T4           0x0200	//
+#define ANLPAR_TXFD         0x0100	//
+#define ANLPAR_TX           0x0080	//
+#define ANLPAR_10FD         0x0040	//
+#define ANLPAR_10           0x0020	//
+
+//
+// Bits in the G1000CR register
+//
+#define G1000CR_1000FD      0x0200	// PHY is 1000-T Full-duplex capable
+#define G1000CR_1000        0x0100	// PHY is 1000-T Half-duplex capable
+
+//
+// Bits in the G1000SR register
+//
+#define G1000SR_1000FD      0x0800	// LP PHY is 1000-T Full-duplex capable
+#define G1000SR_1000        0x0400	// LP PHY is 1000-T Half-duplex capable
+
+#define TCSR_ECHODIS        0x2000	//
+#define AUXCR_MDPPS         0x0004	//
+
+// Bits in the PLED register
+#define PLED_LALBE			0x0004	//
+
+// Marvell 88E1000/88E1000S Bits in the PHY specific control register (10h)
+#define PSCR_ACRSTX         0x0800	// Assert CRS on Transmit
+
+#define PHYID_CICADA_CS8201 0x000FC410UL
+#define PHYID_VT3216_32BIT  0x000FC610UL
+#define PHYID_VT3216_64BIT  0x000FC600UL
+#define PHYID_MARVELL_1000  0x01410C50UL
+#define PHYID_MARVELL_1000S 0x01410C40UL
+
+#define PHYID_REV_ID_MASK   0x0000000FUL
+
+#define PHYID_GET_PHY_REV_ID(i)     ((i) & PHYID_REV_ID_MASK)
+#define PHYID_GET_PHY_ID(i)         ((i) & ~PHYID_REV_ID_MASK)
+
+#define MII_REG_BITS_ON(x,i,p) do {\
+    u16 w;\
+    velocity_mii_read((p),(i),&(w));\
+    (w)|=(x);\
+    velocity_mii_write((p),(i),(w));\
+} while (0)
+
+#define MII_REG_BITS_OFF(x,i,p) do {\
+    u16 w;\
+    velocity_mii_read((p),(i),&(w));\
+    (w)&=(~(x));\
+    velocity_mii_write((p),(i),(w));\
+} while (0)
+
+#define MII_REG_BITS_IS_ON(x,i,p) ({\
+    u16 w;\
+    velocity_mii_read((p),(i),&(w));\
+    ((int) ((w) & (x)));})
+
+#define MII_GET_PHY_ID(p) ({\
+    u32 id;\
+    velocity_mii_read((p),MII_REG_PHYID2,(u16 *) &id);\
+    velocity_mii_read((p),MII_REG_PHYID1,((u16 *) &id)+1);\
+    (id);})
+
+/*
+ * Inline debug routine
+ */
+
+
+enum velocity_msg_level {
+	MSG_LEVEL_ERR = 0,	//Errors that will cause abnormal operation.
+	MSG_LEVEL_NOTICE = 1,	//Some errors need users to be notified.
+	MSG_LEVEL_INFO = 2,	//Normal message.
+	MSG_LEVEL_VERBOSE = 3,	//Will report all trival errors.
+	MSG_LEVEL_DEBUG = 4	//Only for debug purpose.
+};
+
+#ifdef VELOCITY_DEBUG
+#define ASSERT(x) { \
+	if (!(x)) { \
+		printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x,\
+			__FUNCTION__, __LINE__);\
+		BUG(); \
+	}\
+}
+#define VELOCITY_DBG(p,args...) printk(p, ##args)
+#else
+#define ASSERT(x)
+#define VELOCITY_DBG(x)
+#endif
+
+#define VELOCITY_PRT(l, p, args...) do {if (l<=msglevel) printk( p ,##args);} while (0)
+
+#define VELOCITY_PRT_CAMMASK(p,t) {\
+	int i;\
+	if ((t)==VELOCITY_MULTICAST_CAM) {\
+        	for (i=0;i<(MCAM_SIZE/8);i++)\
+			printk("%02X",(p)->mCAMmask[i]);\
+	}\
+	else {\
+		for (i=0;i<(VCAM_SIZE/8);i++)\
+			printk("%02X",(p)->vCAMmask[i]);\
+	}\
+	printk("\n");\
+}
+
+
+
+#define     VELOCITY_WOL_MAGIC             0x00000000UL
+#define     VELOCITY_WOL_PHY               0x00000001UL
+#define     VELOCITY_WOL_ARP               0x00000002UL
+#define     VELOCITY_WOL_UCAST             0x00000004UL
+#define     VELOCITY_WOL_BCAST             0x00000010UL
+#define     VELOCITY_WOL_MCAST             0x00000020UL
+#define     VELOCITY_WOL_MAGIC_SEC         0x00000040UL
+
+/*
+ *	Flags for options
+ */
+
+#define     VELOCITY_FLAGS_TAGGING         0x00000001UL
+#define     VELOCITY_FLAGS_TX_CSUM         0x00000002UL
+#define     VELOCITY_FLAGS_RX_CSUM         0x00000004UL
+#define     VELOCITY_FLAGS_IP_ALIGN        0x00000008UL
+#define     VELOCITY_FLAGS_VAL_PKT_LEN     0x00000010UL
+
+#define     VELOCITY_FLAGS_FLOW_CTRL       0x01000000UL
+
+/*
+ *	Flags for driver status
+ */
+
+#define     VELOCITY_FLAGS_OPENED          0x00010000UL
+#define     VELOCITY_FLAGS_VMNS_CONNECTED  0x00020000UL
+#define     VELOCITY_FLAGS_VMNS_COMMITTED  0x00040000UL
+#define     VELOCITY_FLAGS_WOL_ENABLED     0x00080000UL
+
+/*
+ *	Flags for MII status
+ */
+
+#define     VELOCITY_LINK_FAIL             0x00000001UL
+#define     VELOCITY_SPEED_10              0x00000002UL
+#define     VELOCITY_SPEED_100             0x00000004UL
+#define     VELOCITY_SPEED_1000            0x00000008UL
+#define     VELOCITY_DUPLEX_FULL           0x00000010UL
+#define     VELOCITY_AUTONEG_ENABLE        0x00000020UL
+#define     VELOCITY_FORCED_BY_EEPROM      0x00000040UL
+
+/*
+ *	For velocity_set_media_duplex
+ */
+
+#define     VELOCITY_LINK_CHANGE           0x00000001UL
+
+enum speed_opt {
+	SPD_DPX_AUTO = 0,
+	SPD_DPX_100_HALF = 1,
+	SPD_DPX_100_FULL = 2,
+	SPD_DPX_10_HALF = 3,
+	SPD_DPX_10_FULL = 4
+};
+
+enum velocity_init_type {
+	VELOCITY_INIT_COLD = 0,
+	VELOCITY_INIT_RESET,
+	VELOCITY_INIT_WOL
+};
+
+enum velocity_flow_cntl_type {
+	FLOW_CNTL_DEFAULT = 1,
+	FLOW_CNTL_TX,
+	FLOW_CNTL_RX,
+	FLOW_CNTL_TX_RX,
+	FLOW_CNTL_DISABLE,
+};
+
+struct velocity_opt {
+	int numrx;			/* Number of RX descriptors */
+	int numtx;			/* Number of TX descriptors */
+	enum speed_opt spd_dpx;		/* Media link mode */
+	int vid;			/* vlan id */
+	int DMA_length;			/* DMA length */
+	int rx_thresh;			/* RX_THRESH */
+	int flow_cntl;
+	int wol_opts;			/* Wake on lan options */
+	int td_int_count;
+	int int_works;
+	int rx_bandwidth_hi;
+	int rx_bandwidth_lo;
+	int rx_bandwidth_en;
+	u32 flags;
+};
+
+struct velocity_info {
+	struct velocity_info *next;
+	struct velocity_info *prev;
+
+	struct pci_dev *pdev;
+	struct net_device *dev;
+	struct net_device_stats stats;
+
+#if CONFIG_PM
+	u32 pci_state[16];
+#endif
+
+	dma_addr_t rd_pool_dma;
+	dma_addr_t td_pool_dma[TX_QUEUE_NO];
+
+	dma_addr_t tx_bufs_dma;
+	u8 *tx_bufs;
+
+	u8 ip_addr[4];
+	enum chip_type chip_id;
+
+	struct mac_regs * mac_regs;
+	unsigned long memaddr;
+	unsigned long ioaddr;
+	u32 io_size;
+
+	u8 rev_id;
+
+#define AVAIL_TD(p,q)   ((p)->options.numtx-((p)->td_used[(q)]))
+
+	int num_txq;
+
+	volatile int td_used[TX_QUEUE_NO];
+	int td_curr[TX_QUEUE_NO];
+	int td_tail[TX_QUEUE_NO];
+	struct tx_desc *td_rings[TX_QUEUE_NO];
+	struct velocity_td_info *td_infos[TX_QUEUE_NO];
+
+	int rd_curr;
+	int rd_used;
+	struct rx_desc *rd_ring;
+	struct velocity_rd_info *rd_info;	/* It's an array */
+
+#define GET_RD_BY_IDX(vptr, idx)   (vptr->rd_ring[idx])
+	u32 mib_counter[MAX_HW_MIB_COUNTER];
+	struct velocity_opt options;
+
+	u32 int_mask;
+
+	u32 flags;
+
+	int rx_buf_sz;
+	u32 mii_status;
+	u32 phy_id;
+	int multicast_limit;
+
+	u8 vCAMmask[(VCAM_SIZE / 8)];
+	u8 mCAMmask[(MCAM_SIZE / 8)];
+
+	spinlock_t lock;
+	spinlock_t xmit_lock;
+
+	int wol_opts;
+	u8 wol_passwd[6];
+
+	struct velocity_context context;
+
+	u32 ticks;
+	u32 rx_bytes;
+
+};
+
+/**
+ *	velocity_get_ip		-	find an IP address for the device
+ *	@vptr: Velocity to query
+ *
+ *	Dig out an IP address for this interface so that we can
+ *	configure wakeup with WOL for ARP. If there are multiple IP
+ *	addresses on this chain then we use the first - multi-IP WOL is not
+ *	supported.
+ *
+ *	CHECK ME: locking
+ */
+
+inline static int velocity_get_ip(struct velocity_info *vptr)
+{
+	struct in_device *in_dev = (struct in_device *) vptr->dev->ip_ptr;
+	struct in_ifaddr *ifa;
+
+	if (in_dev != NULL) {
+		ifa = (struct in_ifaddr *) in_dev->ifa_list;
+		if (ifa != NULL) {
+			memcpy(vptr->ip_addr, &ifa->ifa_address, 4);
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+/**
+ *	velocity_update_hw_mibs	-	fetch MIB counters from chip
+ *	@vptr: velocity to update
+ *
+ *	The velocity hardware keeps certain counters in the hardware
+ * 	side. We need to read these when the user asks for statistics
+ *	or when they overflow (causing an interrupt). The read of the
+ *	statistic clears it, so we keep running master counters in user
+ *	space.
+ */
+
+static inline void velocity_update_hw_mibs(struct velocity_info *vptr)
+{
+	u32 tmp;
+	int i;
+	BYTE_REG_BITS_ON(MIBCR_MIBFLSH, &(vptr->mac_regs->MIBCR));
+
+	while (BYTE_REG_BITS_IS_ON(MIBCR_MIBFLSH, &(vptr->mac_regs->MIBCR)));
+
+	BYTE_REG_BITS_ON(MIBCR_MPTRINI, &(vptr->mac_regs->MIBCR));
+	for (i = 0; i < HW_MIB_SIZE; i++) {
+		tmp = readl(&(vptr->mac_regs->MIBData)) & 0x00FFFFFFUL;
+		vptr->mib_counter[i] += tmp;
+	}
+}
+
+/**
+ *	init_flow_control_register 	-	set up flow control
+ *	@vptr: velocity to configure
+ *
+ *	Configure the flow control registers for this velocity device.
+ */
+
+static inline void init_flow_control_register(struct velocity_info *vptr)
+{
+	struct mac_regs * regs = vptr->mac_regs;
+
+	/* Set {XHITH1, XHITH0, XLTH1, XLTH0} in FlowCR1 to {1, 0, 1, 1}
+	   depend on RD=64, and Turn on XNOEN in FlowCR1 */
+	writel((CR0_XONEN | CR0_XHITH1 | CR0_XLTH1 | CR0_XLTH0), &regs->CR0Set);
+	writel((CR0_FDXTFCEN | CR0_FDXRFCEN | CR0_HDXFCEN | CR0_XHITH0), &regs->CR0Clr);
+
+	/* Set TxPauseTimer to 0xFFFF */
+	writew(0xFFFF, &regs->tx_pause_timer);
+
+	/* Initialize RBRDU to Rx buffer count. */
+	writew(vptr->options.numrx, &regs->RBRDU);
+}
+
+
+#endif
diff -Nru a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
--- a/drivers/net/wan/Kconfig	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/wan/Kconfig	2004-06-23 19:04:26 -07:00
@@ -248,7 +248,7 @@
 
 config WANXL_BUILD_FIRMWARE
 	bool "rebuild wanXL firmware"
-	depends on WANXL
+	depends on WANXL && !PREVENT_FIRMWARE_BUILD
 	help
 	  Allows you to rebuild firmware run by the QUICC processor.
 	  It requires as68k, ld68k and hexdump programs.
diff -Nru a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
--- a/drivers/net/wan/c101.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/wan/c101.c	2004-06-23 19:04:28 -07:00
@@ -220,7 +220,8 @@
 static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	const size_t size = sizeof(sync_serial_settings);
-	sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
 	port_t *port = dev_to_port(dev);
 
 #ifdef DEBUG_RINGS
diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
--- a/drivers/net/wan/cosa.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/wan/cosa.c	2004-06-23 19:04:25 -07:00
@@ -301,9 +301,9 @@
 static int chrdev_rx_done(struct channel_data *channel);
 static int chrdev_tx_done(struct channel_data *channel, int size);
 static ssize_t cosa_read(struct file *file,
-	char *buf, size_t count, loff_t *ppos);
+	char __user *buf, size_t count, loff_t *ppos);
 static ssize_t cosa_write(struct file *file,
-	const char *buf, size_t count, loff_t *ppos);
+	const char __user *buf, size_t count, loff_t *ppos);
 static unsigned int cosa_poll(struct file *file, poll_table *poll);
 static int cosa_open(struct inode *inode, struct file *file);
 static int cosa_release(struct inode *inode, struct file *file);
@@ -330,13 +330,13 @@
 /* Ioctls */
 static int cosa_start(struct cosa_data *cosa, int address);
 static int cosa_reset(struct cosa_data *cosa);
-static int cosa_download(struct cosa_data *cosa, unsigned long a);
-static int cosa_readmem(struct cosa_data *cosa, unsigned long a);
+static int cosa_download(struct cosa_data *cosa, void __user *a);
+static int cosa_readmem(struct cosa_data *cosa, void __user *a);
 
 /* COSA/SRP ROM monitor */
-static int download(struct cosa_data *cosa, const char *data, int addr, int len);
+static int download(struct cosa_data *cosa, const char __user *data, int addr, int len);
 static int startmicrocode(struct cosa_data *cosa, int address);
-static int readmem(struct cosa_data *cosa, char *data, int addr, int len);
+static int readmem(struct cosa_data *cosa, char __user *data, int addr, int len);
 static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id);
 
 /* Auxilliary functions */
@@ -830,7 +830,7 @@
 }
 
 static ssize_t cosa_read(struct file *file,
-	char *buf, size_t count, loff_t *ppos)
+	char __user *buf, size_t count, loff_t *ppos)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
@@ -905,7 +905,7 @@
 
 
 static ssize_t cosa_write(struct file *file,
-	const char *buf, size_t count, loff_t *ppos)
+	const char __user *buf, size_t count, loff_t *ppos)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct channel_data *chan = file->private_data;
@@ -1066,7 +1066,7 @@
 }
 
 /* High-level function to download data into COSA memory. Calls download() */
-static inline int cosa_download(struct cosa_data *cosa, unsigned long arg)
+static inline int cosa_download(struct cosa_data *cosa, void __user *arg)
 {
 	struct cosa_download d;
 	int i;
@@ -1080,7 +1080,7 @@
 		return -EPERM;
 	}
 	
-	if (copy_from_user(&d, (void __user *) arg, sizeof(d)))
+	if (copy_from_user(&d, arg, sizeof(d)))
 		return -EFAULT;
 
 	if (d.addr < 0 || d.addr > COSA_MAX_FIRMWARE_SIZE)
@@ -1105,7 +1105,7 @@
 }
 
 /* High-level function to read COSA memory. Calls readmem() */
-static inline int cosa_readmem(struct cosa_data *cosa, unsigned long arg)
+static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg)
 {
 	struct cosa_download d;
 	int i;
@@ -1120,7 +1120,7 @@
 		return -EPERM;
 	}
 
-	if (copy_from_user(&d, (void __user *) arg, sizeof(d)))
+	if (copy_from_user(&d, arg, sizeof(d)))
 		return -EFAULT;
 
 	/* If something fails, force the user to reset the card */
@@ -1167,7 +1167,7 @@
 }
 		
 /* Buffer of size at least COSA_MAX_ID_STRING is expected */
-static inline int cosa_getidstr(struct cosa_data *cosa, char *string)
+static inline int cosa_getidstr(struct cosa_data *cosa, char __user *string)
 {
 	int l = strlen(cosa->id_string)+1;
 	if (copy_to_user(string, cosa->id_string, l))
@@ -1176,7 +1176,7 @@
 }
 
 /* Buffer of size at least COSA_MAX_ID_STRING is expected */
-static inline int cosa_gettype(struct cosa_data *cosa, char *string)
+static inline int cosa_gettype(struct cosa_data *cosa, char __user *string)
 {
 	int l = strlen(cosa->type)+1;
 	if (copy_to_user(string, cosa->type, l))
@@ -1187,6 +1187,7 @@
 static int cosa_ioctl_common(struct cosa_data *cosa,
 	struct channel_data *channel, unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
 	switch(cmd) {
 	case COSAIORSET:	/* Reset the device */
 		if (!capable(CAP_NET_ADMIN))
@@ -1200,15 +1201,15 @@
 		if (!capable(CAP_SYS_RAWIO))
 			return -EACCES;
 		
-		return cosa_download(cosa, arg);
+		return cosa_download(cosa, argp);
 	case COSAIORMEM:
 		if (!capable(CAP_SYS_RAWIO))
 			return -EACCES;
-		return cosa_readmem(cosa, arg);
+		return cosa_readmem(cosa, argp);
 	case COSAIORTYPE:
-		return cosa_gettype(cosa, (char *)arg);
+		return cosa_gettype(cosa, argp);
 	case COSAIORIDSTR:
-		return cosa_getidstr(cosa, (char *)arg);
+		return cosa_getidstr(cosa, argp);
 	case COSAIONRCARDS:
 		return nr_cards;
 	case COSAIONRCHANS:
@@ -1434,7 +1435,7 @@
  * by a single space. Monitor has to reply with a space. Now the download
  * begins. After the download monitor replies with "\r\n." (CR LF dot).
  */
-static int download(struct cosa_data *cosa, const char *microcode, int length, int address)
+static int download(struct cosa_data *cosa, const char __user *microcode, int length, int address)
 {
 	int i;
 
@@ -1508,7 +1509,7 @@
  * This routine is not needed during the normal operation and serves
  * for debugging purposes only.
  */
-static int readmem(struct cosa_data *cosa, char *microcode, int length, int address)
+static int readmem(struct cosa_data *cosa, char __user *microcode, int length, int address)
 {
 	if (put_wait_data(cosa, 'r') == -1) return -1;
 	if ((get_wait_data(cosa)) != 'r') return -2;
diff -Nru a/drivers/net/wan/cosa.h b/drivers/net/wan/cosa.h
--- a/drivers/net/wan/cosa.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/wan/cosa.h	2004-06-23 19:04:27 -07:00
@@ -66,7 +66,7 @@
 /* ioctls */
 struct cosa_download {
 	int addr, len;
-	char *code;
+	char __user *code;
 };
 
 /* Reset the device */
diff -Nru a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
--- a/drivers/net/wan/dscc4.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/net/wan/dscc4.c	2004-06-23 19:04:29 -07:00
@@ -1296,7 +1296,7 @@
 
 static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	sync_serial_settings *line = ifr->ifr_settings.ifs_ifsu.sync;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
 	struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
 	const size_t size = sizeof(dpriv->settings);
 	int ret = 0;
diff -Nru a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
--- a/drivers/net/wan/farsync.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/wan/farsync.c	2004-06-23 19:04:27 -07:00
@@ -1636,7 +1636,7 @@
 			 */
 			dbg(DBG_TX, "Tx underflow port %d\n", port->index);
                         hdlc_stats(port_to_dev(port))->tx_errors++;
-                        hdlc_stats(port_to_dev(port))->tx_fifo_errors;
+                        hdlc_stats(port_to_dev(port))->tx_fifo_errors++;
 			dbg(DBG_ASS, "Tx underflow on card %d port %d\n",
 			    card->card_no, port->index);
 			break;
diff -Nru a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
--- a/drivers/net/wan/hdlc_cisco.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/wan/hdlc_cisco.c	2004-06-23 19:04:26 -07:00
@@ -272,7 +272,7 @@
 
 int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
-	cisco_proto *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco;
+	cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco;
 	const size_t size = sizeof(cisco_proto);
 	cisco_proto new_settings;
 	hdlc_device *hdlc = dev_to_hdlc(dev);
diff -Nru a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
--- a/drivers/net/wan/hdlc_fr.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/wan/hdlc_fr.c	2004-06-23 19:04:28 -07:00
@@ -1137,7 +1137,7 @@
 
 int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
-	fr_proto *fr_s = ifr->ifr_settings.ifs_ifsu.fr;
+	fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr;
 	const size_t size = sizeof(fr_proto);
 	fr_proto new_settings;
 	hdlc_device *hdlc = dev_to_hdlc(dev);
diff -Nru a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c
--- a/drivers/net/wan/hdlc_raw.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/wan/hdlc_raw.c	2004-06-23 19:04:27 -07:00
@@ -34,7 +34,7 @@
 
 int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
-	raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
+	raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
 	const size_t size = sizeof(raw_hdlc_proto);
 	raw_hdlc_proto new_settings;
 	hdlc_device *hdlc = dev_to_hdlc(dev);
diff -Nru a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c
--- a/drivers/net/wan/hdlc_raw_eth.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/wan/hdlc_raw_eth.c	2004-06-23 19:04:26 -07:00
@@ -46,7 +46,7 @@
 
 int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
-	raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
+	raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
 	const size_t size = sizeof(raw_hdlc_proto);
 	raw_hdlc_proto new_settings;
 	hdlc_device *hdlc = dev_to_hdlc(dev);
diff -Nru a/drivers/net/wan/lmc/lmc_ioctl.h b/drivers/net/wan/lmc/lmc_ioctl.h
--- a/drivers/net/wan/lmc/lmc_ioctl.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/wan/lmc/lmc_ioctl.h	2004-06-23 19:04:25 -07:00
@@ -234,7 +234,7 @@
   int command;
   int address;
   int value;
-  char *data;
+  char __user *data;
 } lmc_t1f_control;
 
 enum lmc_xilinx_c {
@@ -246,7 +246,7 @@
 struct lmc_xilinx_control {
     enum lmc_xilinx_c command;
     int len;
-    char *data;
+    char __user *data;
 };
 
 /* ------------------ end T1 defs ------------------- */
diff -Nru a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
--- a/drivers/net/wan/n2.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/wan/n2.c	2004-06-23 19:04:26 -07:00
@@ -254,7 +254,8 @@
 static int n2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	const size_t size = sizeof(sync_serial_settings);
-	sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
 	port_t *port = dev_to_port(dev);
 
 #ifdef DEBUG_RINGS
diff -Nru a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
--- a/drivers/net/wan/pci200syn.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/wan/pci200syn.c	2004-06-23 19:04:25 -07:00
@@ -204,7 +204,8 @@
 static int pci200_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	const size_t size = sizeof(sync_serial_settings);
-	sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
 	port_t *port = dev_to_port(dev);
 
 #ifdef DEBUG_RINGS
diff -Nru a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
--- a/drivers/net/wan/x25_asy.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/wan/x25_asy.c	2004-06-23 19:04:25 -07:00
@@ -733,7 +733,7 @@
 
 	switch(cmd) {
 	case SIOCGIFNAME:
-		if (copy_to_user((void *)arg, sl->dev->name,
+		if (copy_to_user((void __user *)arg, sl->dev->name,
 					strlen(sl->dev->name) + 1))
 			return -EFAULT;
 		return 0;
diff -Nru a/drivers/net/wd.c b/drivers/net/wd.c
--- a/drivers/net/wd.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/wd.c	2004-06-23 19:04:25 -07:00
@@ -43,6 +43,8 @@
 
 #include "8390.h"
 
+#define DRV_NAME "wd"
+
 /* A zero-terminated list of I/O addresses to be probed. */
 static unsigned int wd_portlist[] __initdata =
 {0x300, 0x280, 0x380, 0x240, 0};
@@ -131,6 +133,7 @@
 	release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
 }
 
+#ifndef MODULE
 struct net_device * __init wd_probe(int unit)
 {
 	struct net_device *dev = alloc_ei_netdev();
@@ -155,6 +158,7 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
+#endif
 
 static int __init wd_probe1(struct net_device *dev, int ioaddr)
 {
@@ -300,7 +304,7 @@
 
 	/* Snarf the interrupt now.  There's no point in waiting since we cannot
 	   share and the board will usually be enabled. */
-	i = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
+	i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
 	if (i) {
 		printk (" unable to get IRQ %d.\n", dev->irq);
 		return i;
diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
--- a/drivers/net/wireless/airo.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/wireless/airo.c	2004-06-23 19:04:25 -07:00
@@ -1209,6 +1209,7 @@
 	SsidRid			*SSID;
 	APListRid		*APList;
 #define	PCI_SHARED_LEN		2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
+	u32			pci_state[16];
 };
 
 static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
@@ -1963,7 +1964,7 @@
 
 	if ((skb = skb_dequeue(&ai->txq)) == 0) {
 		printk (KERN_ERR
-			"airo_mpi: %s: Dequeue'd zero in send_packet()\n",
+			"airo: %s: Dequeue'd zero in send_packet()\n",
 			__FUNCTION__);
 		return 0;
 	}
@@ -2745,6 +2746,9 @@
 		SET_NETDEV_DEV(dev, &pci->dev);
 	}
 
+	if (test_bit(FLAG_MPI,&ai->flags))
+		reset_card (dev, 1);
+
 	rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev );
 	if (rc) {
 		printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc );
@@ -4047,7 +4051,8 @@
 		Resp rsp;
 
 		if (test_bit(FLAG_ENABLED, &ai->flags))
-			printk(KERN_ERR "%s: MAC should be disabled (rid=%d)\n",
+			printk(KERN_ERR
+				"%s: MAC should be disabled (rid=%04x)\n",
 				__FUNCTION__, rid);
 		memset(&cmd, 0, sizeof(cmd));
 		memset(&rsp, 0, sizeof(rsp));
@@ -4500,6 +4505,8 @@
 		len = priv->readlen - pos;
 	if (copy_to_user(buffer, priv->rbuffer + pos, len))
 		return -EFAULT;
+	if (pos + len > priv->writelen)
+		priv->writelen = pos + len;
 	*offset = pos + len;
 	return len;
 }
@@ -4527,6 +4534,8 @@
 		len = priv->maxwritelen - pos;
 	if (copy_from_user(priv->wbuffer + pos, buffer, len))
 		return -EFAULT;
+	if ( pos + len > priv->writelen )
+		priv->writelen = len + file->f_pos;
 	*offset = pos + len;
 	return len;
 }
@@ -5470,9 +5479,6 @@
 	Cmd cmd;
 	Resp rsp;
 
-	printk(KERN_DEBUG "%s: airo_mpi entering sleep mode (state=%d)\n",
-	       dev->name, state);
-
 	if ((ai->APList == NULL) &&
 		(ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
@@ -5490,7 +5496,10 @@
 	ai->power = state;
 	cmd.cmd=HOSTSLEEP;
 	issuecommand(ai, &cmd, &rsp);
-	return 0;
+
+	pci_enable_wake(pdev, state, 1);
+	pci_save_state(pdev, ai->pci_state);
+	return pci_set_power_state(pdev, state);
 }
 
 static int airo_pci_resume(struct pci_dev *pdev)
@@ -5499,12 +5508,12 @@
 	struct airo_info *ai = dev->priv;
 	Resp rsp;
 
-	printk(KERN_DEBUG "%s: airo_mpi waking up\n", dev->name);
-
-	if (!ai->power)
-		return 0;
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev, ai->pci_state);
+	pci_enable_wake(pdev, ai->power, 0);
 
 	if (ai->power > 1) {
+		reset_card(dev, 0);
 		mpi_init_descriptors(ai);
 		setup_card(ai, dev->dev_addr, 0);
 		clear_bit(FLAG_RADIO_OFF, &ai->flags);
@@ -7166,6 +7175,7 @@
 	unsigned char *iobuf;
 	int len;
 	struct airo_info *ai = dev->priv;
+	Resp rsp;
 
 	if (test_bit(FLAG_FLASHING, &ai->flags))
 		return -EIO;
@@ -7173,8 +7183,11 @@
 	switch(comp->command)
 	{
 	case AIROGCAP:      ridcode = RID_CAPABILITIES; break;
-	case AIROGCFG: writeConfigRid (ai, 1);
-			    ridcode = RID_CONFIG;       break;
+	case AIROGCFG:      ridcode = RID_CONFIG;
+		disable_MAC (ai, 1);
+		writeConfigRid (ai, 1);
+		enable_MAC (ai, &rsp, 1);
+		break;
 	case AIROGSLIST:    ridcode = RID_SSID;         break;
 	case AIROGVLIST:    ridcode = RID_APLIST;       break;
 	case AIROGDRVNAM:   ridcode = RID_DRVNAME;      break;
@@ -7562,6 +7575,11 @@
 	set_current_state (TASK_UNINTERRUPTIBLE);
 	schedule_timeout (HZ);          /* Added 12/7/00 */
 	clear_bit (FLAG_FLASHING, &ai->flags);
+	if (test_bit(FLAG_MPI, &ai->flags)) {
+		status = mpi_init_descriptors(ai);
+		if (status != SUCCESS)
+			return status;
+	}
 	status = setup_card(ai, dev->dev_addr, 1);
 
 	if (!test_bit(FLAG_MPI,&ai->flags))
diff -Nru a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
--- a/drivers/net/wireless/orinoco.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/net/wireless/orinoco.c	2004-06-23 19:04:29 -07:00
@@ -1519,7 +1519,8 @@
 
 static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
 {
-	printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
+	if (net_ratelimit())
+		printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
 }
 
 static void print_linkstatus(struct net_device *dev, u16 status)
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	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/wireless/prism54/isl_38xx.c	2004-06-23 19:04:27 -07:00
@@ -25,17 +25,11 @@
 #include <linux/types.h>
 #include <linux/delay.h>
 
-#include "isl_38xx.h"
-#include <linux/firmware.h>
-
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include <linux/config.h>
-#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE)
-#error No Firmware Loading configured in the kernel !
-#endif
-
+#include "prismcompat.h"
+#include "isl_38xx.h"
 #include "islpci_dev.h"
 #include "islpci_mgt.h"
 
@@ -233,130 +227,6 @@
 			ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP);
 	isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG);
 	udelay(ISL38XX_WRITEIO_DELAY);
-}
-
-int
-isl38xx_upload_firmware(char *fw_id, _REQ_FW_DEV_T dev, void *device_base,
-			dma_addr_t host_address)
-{
-	u32 reg, rc;
-
-#if VERBOSE > SHOW_ERROR_MESSAGES
-	DEBUG(SHOW_ERROR_MESSAGES, "isl38xx_upload_firmware(0x%lx, 0x%lx)\n",
-	      (long) device_base, (long) host_address);
-#endif
-
-	/* clear the RAMBoot and the Reset bit */
-	reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
-	reg &= ~ISL38XX_CTRL_STAT_RESET;
-	reg &= ~ISL38XX_CTRL_STAT_RAMBOOT;
-	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
-	wmb();
-	udelay(ISL38XX_WRITEIO_DELAY);
-
-	/* set the Reset bit without reading the register ! */
-	reg |= ISL38XX_CTRL_STAT_RESET;
-	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
-	wmb();
-	udelay(ISL38XX_WRITEIO_DELAY);
-
-	/* clear the Reset bit */
-	reg &= ~ISL38XX_CTRL_STAT_RESET;
-	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
-	wmb();
-
-	/* wait a while for the device to reboot */
-	mdelay(50);
-
-	{
-		const struct firmware *fw_entry = 0;
-		long fw_len;
-		const u32 *fw_ptr;
-
-		rc = request_firmware(&fw_entry, fw_id, dev);
-		if (rc) {
-			printk(KERN_ERR
-			       "%s: request_firmware() failed for '%s'\n",
-			       "prism54", fw_id);
-			return rc;
-		}
-		/* prepare the Direct Memory Base register */
-		reg = ISL38XX_DEV_FIRMWARE_ADDRES;
-
-		fw_ptr = (u32 *) fw_entry->data;
-		fw_len = fw_entry->size;
-
-		if (fw_len % 4) {
-			printk(KERN_ERR
-			       "%s: firmware '%s' size is not multiple of 32bit, aborting!\n",
-			       "prism54", fw_id);
-			release_firmware(fw_entry);
-			return EILSEQ; /* Illegal byte sequence  */;
-		}
-
-		while (fw_len > 0) {
-			long _fw_len =
-			    (fw_len >
-			     ISL38XX_MEMORY_WINDOW_SIZE) ?
-			    ISL38XX_MEMORY_WINDOW_SIZE : fw_len;
-			u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN;
-
-			/* set the cards base address for writting the data */
-			isl38xx_w32_flush(device_base, reg,
-					  ISL38XX_DIR_MEM_BASE_REG);
-			wmb();	/* be paranoid */
-
-			/* increment the write address for next iteration */
-			reg += _fw_len;
-			fw_len -= _fw_len;
-
-			/* write the data to the Direct Memory Window 32bit-wise */
-			/* memcpy_toio() doesn't guarantee 32bit writes :-| */
-			while (_fw_len > 0) {
-				/* use non-swapping writel() */
-				__raw_writel(*fw_ptr, dev_fw_ptr);
-				fw_ptr++, dev_fw_ptr++;
-				_fw_len -= 4;
-			}
-
-			/* flush PCI posting */
-			(void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH);
-			wmb();	/* be paranoid again */
-
-			BUG_ON(_fw_len != 0);
-		}
-
-		BUG_ON(fw_len != 0);
-
-		release_firmware(fw_entry);
-	}
-
-	/* now reset the device
-	 * clear the Reset & ClkRun bit, set the RAMBoot bit */
-	reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
-	reg &= ~ISL38XX_CTRL_STAT_CLKRUN;
-	reg &= ~ISL38XX_CTRL_STAT_RESET;
-	reg |= ISL38XX_CTRL_STAT_RAMBOOT;
-	isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG);
-	wmb();
-	udelay(ISL38XX_WRITEIO_DELAY);
-
-	/* set the reset bit latches the host override and RAMBoot bits
-	 * into the device for operation when the reset bit is reset */
-	reg |= ISL38XX_CTRL_STAT_RESET;
-	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
-	/* don't do flush PCI posting here! */
-	wmb();
-	udelay(ISL38XX_WRITEIO_DELAY);
-
-	/* clear the reset bit should start the whole circus */
-	reg &= ~ISL38XX_CTRL_STAT_RESET;
-	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
-	/* don't do flush PCI posting here! */
-	wmb();
-	udelay(ISL38XX_WRITEIO_DELAY);
-
-	return 0;
 }
 
 int
diff -Nru a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h
--- a/drivers/net/wireless/prism54/isl_38xx.h	2004-06-23 19:04:29 -07:00
+++ b/drivers/net/wireless/prism54/isl_38xx.h	2004-06-23 19:04:29 -07:00
@@ -22,14 +22,6 @@
 
 #include <linux/version.h>
 #include <asm/io.h>
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,75))
-#include <linux/device.h>
-# define _REQ_FW_DEV_T struct device *
-#else
-# define _REQ_FW_DEV_T char *
-#endif
-
 #include <asm/byteorder.h>
 
 #define ISL38XX_CB_RX_QSIZE                     8
@@ -173,7 +165,5 @@
 void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void *);
 void isl38xx_trigger_device(int, void *);
 void isl38xx_interface_reset(void *, dma_addr_t);
-
-int isl38xx_upload_firmware(char *, _REQ_FW_DEV_T, void *, dma_addr_t);
 
 #endif				/* _ISL_38XX_H */
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	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/wireless/prism54/isl_ioctl.c	2004-06-23 19:04:26 -07:00
@@ -25,10 +25,10 @@
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
 #include <linux/pci.h>
-#include <linux/moduleparam.h>
 
 #include <asm/uaccess.h>
 
+#include "prismcompat.h"
 #include "isl_ioctl.h"
 #include "islpci_mgt.h"
 #include "isl_oid.h"		/* additional types and defs for isl38xx fw */
@@ -166,21 +166,13 @@
 	 * for it save old values */
 	if (init_mode > IW_MODE_MONITOR || init_mode < IW_MODE_AUTO) {
 		printk(KERN_DEBUG "%s(): You passed a non-valid init_mode. "
-				"Using default mode\n", __FUNCTION__);
+		       "Using default mode\n", __FUNCTION__);
 		init_mode = CARD_DEFAULT_IW_MODE;
 	}
 	/* This sets all of the mode-dependent values */
 	prism54_mib_mode_helper(priv, init_mode);
 }
 
-void
-prism54_mib_init_work(islpci_private *priv)
-{
-	down_write(&priv->mib_sem);
-	mgt_commit(priv);
-	up_write(&priv->mib_sem);
-}
-
 /* this will be executed outside of atomic context thanks to
  * schedule_work(), thus we can as well use sleeping semaphore
  * locking */
@@ -195,16 +187,9 @@
 	if (down_interruptible(&priv->stats_sem))
 		return;
 
-/* missing stats are :
- *  iwstatistics.qual.updated
- *  iwstatistics.discard.nwid	    
- *  iwstatistics.discard.fragment	    
- *  iwstatistics.discard.misc
- *  iwstatistics.miss.beacon */
-
 /* Noise floor.
  * I'm not sure if the unit is dBm.
- * Note : If we are not connected, this value seems to be irrevelant. */
+ * Note : If we are not connected, this value seems to be irrelevant. */
 
 	mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r);
 	priv->local_iwstatistics.qual.noise = r.u;
@@ -216,8 +201,7 @@
 	data = r.ptr;
 
 	/* copy this MAC to the bss */
-	for (j = 0; j < 6; j++)
-		bss.address[j] = data[j];
+	memcpy(bss.address, data, 6);
 	kfree(data);
 
 	/* now ask for the corresponding bss */
@@ -426,7 +410,6 @@
 	/* by default  the card sets this to 20. */
 	sens = vwrq->disabled ? 20 : vwrq->value;
 
-	/* set the ed threshold. */
 	return mgt_set_request(priv, DOT11_OID_EDTHRESHOLD, 0, &sens);
 }
 
@@ -505,7 +488,7 @@
 		return 0;
 
 	/* Request the device for the supported frequencies
-	 * not really revelant since some devices will report the 5 GHz band
+	 * not really relevant since some devices will report the 5 GHz band
 	 * frequencies even if they don't support them.
 	 */
 	rvalue =
@@ -515,21 +498,12 @@
 	range->num_channels = freq->nr;
 	range->num_frequency = freq->nr;
 
-	/* Frequencies are not listed in the right order. The reordering is probably
-	 * firmware dependant and thus should work for everyone.
-	 */
 	m = min(IW_MAX_FREQUENCIES, (int) freq->nr);
-	for (i = 0; i < m - 12; i++) {
-		range->freq[i].m = freq->mhz[12 + i];
+	for (i = 0; i < m; i++) {
+		range->freq[i].m = freq->mhz[i];
 		range->freq[i].e = 6;
-		range->freq[i].i = i + 1;
+		range->freq[i].i = channel_of_freq(freq->mhz[i]);
 	}
-	for (i = m - 12; i < m; i++) {
-		range->freq[i].m = freq->mhz[i - m + 12];
-		range->freq[i].e = 6;
-		range->freq[i].i = i + 23;
-	}
-
 	kfree(freq);
 
 	rvalue |= mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r);
@@ -544,9 +518,7 @@
 		i++;
 		data++;
 	}
-
 	range->num_bitrates = i;
-
 	kfree(r.ptr);
 
 	return rvalue;
@@ -585,7 +557,6 @@
 	int rvalue;
 
 	rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r);
-
 	memcpy(awrq->sa_data, r.ptr, 6);
 	awrq->sa_family = ARPHRD_ETHER;
 	kfree(r.ptr);
@@ -658,8 +629,8 @@
 	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL);
 
 	/* Add frequency. (short) bss->channel is the frequency in MHz */
-	iwe.u.freq.m = bss->channel;
-	iwe.u.freq.e = 6;
+	iwe.u.freq.m = channel_of_freq(bss->channel);
+	iwe.u.freq.e = 0;
 	iwe.cmd = SIOCGIWFREQ;
 	current_ev =
 	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
@@ -695,7 +666,6 @@
 			kfree(buf);
 		}
 	}
-
 	return current_ev;
 }
 
@@ -722,7 +692,7 @@
 
 	/* Ask the device for a list of known bss. We can report at most
 	 * IW_MAX_AP=64 to the range struct. But the device won't repport anything
-	 * if you change the value of MAXBSS=24. Anyway 24 AP It is probably enough.
+	 * if you change the value of IWMAX_BSS=24.
 	 */
 	rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r);
 	bsslist = r.ptr;
@@ -757,7 +727,7 @@
 		memcpy(essid.octets, extra, dwrq->length);
 	} else
 		essid.length = 0;
-	
+
 	if (priv->iw_mode != IW_MODE_MONITOR)
 		return mgt_set_request(priv, DOT11_OID_SSID, 0, &essid);
 
@@ -843,21 +813,21 @@
 	char *data;
 	int ret, i;
 	union oid_res_t r;
-	
+
 	if (vwrq->value == -1) {
 		/* auto mode. No limit. */
 		profile = 1;
 		return mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile);
 	}
-	
+
 	if ((ret =
 	     mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r)))
 		return ret;
-		
+
 	rate = (u32) (vwrq->value / 500000);
 	data = r.ptr;
 	i = 0;
-	
+
 	while (data[i]) {
 		if (rate && (data[i] == rate)) {
 			break;
@@ -868,14 +838,14 @@
 		data[i] |= 0x80;
 		i++;
 	}
-		
+
 	if (!data[i]) {
 		return -EINVAL;
 	}
-	
+
 	data[i] |= 0x80;
 	data[i + 1] = 0;
-	
+
 	/* Now, check if we want a fixed or auto value */
 	if (vwrq->fixed) {
 		data[0] = data[i];
@@ -890,14 +860,14 @@
 		i++;
 	}
 	printk("0\n");
-*/	
+*/
 	profile = -1;
 	ret = mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile);
 	ret |= mgt_set_request(priv, DOT11_OID_EXTENDEDRATES, 0, data);
 	ret |= mgt_set_request(priv, DOT11_OID_RATES, 0, data);
-	
+
 	kfree(r.ptr);
-	
+
 	return ret;
 }
 
@@ -923,7 +893,7 @@
 	data = r.ptr;
 	vwrq->fixed = (data[0] != 0) && (data[1] == 0);
 	kfree(r.ptr);
-	
+
 	return 0;
 }
 
@@ -979,8 +949,6 @@
  * small frame <=>  smaller than the rts threshold
  * This is not really the behavior expected by the wireless tool but it seems
  * to be a common behavior in other drivers.
- * 
- * It seems that playing with this tends to hang the card -> DISABLED
  */
 
 static int
@@ -1012,18 +980,16 @@
 		lifetime = vwrq->value / 1024;
 
 	/* now set what is requested */
-
-	if (slimit != 0)
+	if (slimit)
 		rvalue =
 		    mgt_set_request(priv, DOT11_OID_SHORTRETRIES, 0, &slimit);
-	if (llimit != 0)
+	if (llimit)
 		rvalue |=
 		    mgt_set_request(priv, DOT11_OID_LONGRETRIES, 0, &llimit);
-	if (lifetime != 0)
+	if (lifetime)
 		rvalue |=
 		    mgt_set_request(priv, DOT11_OID_MAXTXLIFETIME, 0,
 				    &lifetime);
-
 	return rvalue;
 }
 
@@ -1119,8 +1085,7 @@
 			}
 		}
 	}
-
-	/* now read the flags     */
+	/* now read the flags */
 	if (dwrq->flags & IW_ENCODE_DISABLED) {
 		/* Encoding disabled, 
 		 * authen = DOT11_AUTH_OS;
@@ -1269,13 +1234,8 @@
 
 static int
 prism54_set_u32(struct net_device *ndev, struct iw_request_info *info,
-		   __u32 * uwrq, char *extra)
+		__u32 * uwrq, char *extra)
 {
-	/*
-	   u32 *i = (int *) extra;
-	   int param = *i;
-	   int u = *(i + 1);
-	 */
 	u32 oid = uwrq[0], u = uwrq[1];
 
 	return mgt_set_request((islpci_private *) ndev->priv, oid, 0, &u);
@@ -1846,9 +1806,7 @@
 				     0);
 		break;
 
-		/* Note : the following should never happen since we don't run the card in
-		 * extended mode.
-		 * Note : "mlme" is actually a "struct obj_mlmeex *" here, but this
+		/* Note : "mlme" is actually a "struct obj_mlmeex *" here, but this
 		 * is backward compatible layout-wise with "struct obj_mlme".
 		 */
 
@@ -1893,7 +1851,8 @@
 	struct net_device *ndev = frame->ndev;
 	enum oid_num_t n = mgt_oidtonum(frame->header->oid);
 
-	prism54_process_trap_helper(netdev_priv(ndev), n, frame->data);
+	if (n != OID_NUM_LAST)
+		prism54_process_trap_helper(netdev_priv(ndev), n, frame->data);
 	islpci_mgt_release(frame);
 }
 
@@ -1966,65 +1925,11 @@
 }
 
 int
-prism54_set_maxframeburst(struct net_device *ndev, struct iw_request_info *info,
-			  __u32 * uwrq, char *extra)
-{
-	islpci_private *priv = netdev_priv(ndev);
-	u32 max_burst;
-
-	max_burst = (*uwrq) ? *uwrq : CARD_DEFAULT_MAXFRAMEBURST;
-	mgt_set_request(priv, DOT11_OID_MAXFRAMEBURST, 0, &max_burst);
-
-	return -EINPROGRESS; /* Call commit handler */
-}
-
-int
-prism54_get_maxframeburst(struct net_device *ndev, struct iw_request_info *info,
-			  __u32 * uwrq, char *extra)
-{
-	islpci_private *priv = netdev_priv(ndev);
-	union oid_res_t r;
-	int rvalue;
-	
-	rvalue = mgt_get_request(priv, DOT11_OID_MAXFRAMEBURST, 0, NULL, &r);
-	*uwrq = r.u;
-	
-	return rvalue;
-}
-
-int
-prism54_set_profile(struct net_device *ndev, struct iw_request_info *info,
-		    __u32 * uwrq, char *extra)
-{
-	islpci_private *priv = netdev_priv(ndev);
-	u32 profile;
-
-	profile = (*uwrq) ? *uwrq : CARD_DEFAULT_PROFILE;
-	mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile);
-	
-	return -EINPROGRESS; /* Call commit handler */
-}
-
-int
-prism54_get_profile(struct net_device *ndev, struct iw_request_info *info,
-		    __u32 * uwrq, char *extra)
-{
-	islpci_private *priv = netdev_priv(ndev);
-	union oid_res_t r;
-	int rvalue;
-
-	rvalue = mgt_get_request(priv, DOT11_OID_PROFILES, 0, NULL, &r);
-	*uwrq = r.u;
-
-	return rvalue;
-}
-
-int
 prism54_debug_oid(struct net_device *ndev, struct iw_request_info *info,
 		  __u32 * uwrq, char *extra)
 {
 	islpci_private *priv = netdev_priv(ndev);
-	
+
 	priv->priv_oid = *uwrq;
 	printk("%s: oid 0x%08X\n", ndev->name, *uwrq);
 
@@ -2033,15 +1938,15 @@
 
 int
 prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info,
-		struct iw_point *data, char *extra)
+		      struct iw_point *data, char *extra)
 {
 	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_mgmtframe *response = NULL;
 	int ret = -EIO, response_op = PIMFOR_OP_ERROR;
-	
+
 	printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid);
 	data->length = 0;
-	
+
 	if (islpci_get_state(priv) >= PRV_STATE_INIT) {
 		ret =
 		    islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET,
@@ -2065,21 +1970,21 @@
 			printk("%s: len: %i\n", ndev->name, data->length);
 		}
 	}
-	
+
 	return ret;
 }
 
 int
 prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info,
-		struct iw_point *data, char *extra)
+		      struct iw_point *data, char *extra)
 {
 	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_mgmtframe *response = NULL;
 	int ret = 0, response_op = PIMFOR_OP_ERROR;
-	
+
 	printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid,
 	       data->length);
-	
+
 	if (islpci_get_state(priv) >= PRV_STATE_INIT) {
 		ret =
 		    islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET,
@@ -2094,11 +1999,11 @@
 		}
 		if (ret || response_op == PIMFOR_OP_ERROR) {
 			printk("%s: EIO\n", ndev->name);
-		        ret = -EIO;
+			ret = -EIO;
 		}
 	}
-	
-	return ret;
+
+	return (ret ? ret : -EINPROGRESS);
 }
 
 static int
@@ -2196,7 +2101,7 @@
 #define PRISM54_DBG_GET_OID	SIOCIWFIRSTPRIV+15
 #define PRISM54_DBG_SET_OID	SIOCIWFIRSTPRIV+16
 
-#define PRISM54_GET_OID	   SIOCIWFIRSTPRIV+17
+#define PRISM54_GET_OID		SIOCIWFIRSTPRIV+17
 #define PRISM54_SET_OID_U32	SIOCIWFIRSTPRIV+18
 #define	PRISM54_SET_OID_STR	SIOCIWFIRSTPRIV+20
 #define	PRISM54_SET_OID_ADDR	SIOCIWFIRSTPRIV+22
@@ -2204,16 +2109,16 @@
 #define PRISM54_GET_PRISMHDR	SIOCIWFIRSTPRIV+23
 #define PRISM54_SET_PRISMHDR	SIOCIWFIRSTPRIV+24
 
-#define IWPRIV_SET_U32(n,x)	{ n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x }
-#define IWPRIV_SET_SSID(n,x)	{ n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x }
-#define IWPRIV_SET_ADDR(n,x)	{ n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x }
-#define IWPRIV_GET(n,x)	{ n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "get_"x }
+#define IWPRIV_SET_U32(n,x)	{ n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x }
+#define IWPRIV_SET_SSID(n,x)	{ n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x }
+#define IWPRIV_SET_ADDR(n,x)	{ n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x }
+#define IWPRIV_GET(n,x)	{ n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "g_"x }
 
 #define IWPRIV_U32(n,x)		IWPRIV_SET_U32(n,x), IWPRIV_GET(n,x)
 #define IWPRIV_SSID(n,x)	IWPRIV_SET_SSID(n,x), IWPRIV_GET(n,x)
 #define IWPRIV_ADDR(n,x)	IWPRIV_SET_ADDR(n,x), IWPRIV_GET(n,x)
 
-/* Note : limited to 128 private ioctls */
+/* Note : limited to 128 private ioctls (wireless tools 26) */
 
 static const struct iw_priv_args prism54_private_args[] = {
 /*{ cmd, set_args, get_args, name } */
@@ -2241,7 +2146,7 @@
 	{PRISM54_DBG_OID, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
 	 "dbg_oid"},
 	{PRISM54_DBG_GET_OID, 0, IW_PRIV_TYPE_BYTE | 256, "dbg_get_oid"},
-	{PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_get_oid"},
+	{PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_set_oid"},
 	/* --- sub-ioctls handlers --- */
 	{PRISM54_GET_OID,
 	 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, ""},
@@ -2268,7 +2173,7 @@
 	IWPRIV_U32(DOT11_OID_AUTHENABLE, "authenable"),
 	IWPRIV_U32(DOT11_OID_PRIVACYINVOKED, "privinvok"),
 	IWPRIV_U32(DOT11_OID_EXUNENCRYPTED, "exunencrypt"),
-	
+
 	IWPRIV_U32(DOT11_OID_REKEYTHRESHOLD, "rekeythresh"),
 
 	IWPRIV_U32(DOT11_OID_MAXTXLIFETIME, "maxtxlife"),
@@ -2351,5 +2256,6 @@
 int
 prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
+
 	return -EOPNOTSUPP;
 }
diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h
--- a/drivers/net/wireless/prism54/isl_ioctl.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/wireless/prism54/isl_ioctl.h	2004-06-23 19:04:27 -07:00
@@ -30,7 +30,6 @@
 #define SUPPORTED_WIRELESS_EXT                  16
 
 void prism54_mib_init(islpci_private *);
-void prism54_mib_init_work(islpci_private *);
 
 struct iw_statistics *prism54_get_wireless_stats(struct net_device *);
 void prism54_update_stats(islpci_private *);
diff -Nru a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
--- a/drivers/net/wireless/prism54/islpci_dev.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/wireless/prism54/islpci_dev.c	2004-06-23 19:04:25 -07:00
@@ -30,6 +30,7 @@
 
 #include <asm/io.h>
 
+#include "prismcompat.h"
 #include "isl_38xx.h"
 #include "isl_ioctl.h"
 #include "islpci_dev.h"
@@ -37,12 +38,6 @@
 #include "islpci_eth.h"
 #include "oid_mgt.h"
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-#define prism54_synchronize_irq(irq) synchronize_irq()
-#else
-#define prism54_synchronize_irq(irq) synchronize_irq(irq)
-#endif
-
 #define ISL3877_IMAGE_FILE	"isl3877"
 #define ISL3890_IMAGE_FILE	"isl3890"
 
@@ -55,6 +50,125 @@
  * ndev->set_mac_address. Jean II */
 const unsigned char	dummy_mac[6] = { 0x00, 0x30, 0xB4, 0x00, 0x00, 0x00 };
 
+static int
+isl_upload_firmware(islpci_private *priv)
+{
+	u32 reg, rc;
+	void *device_base = priv->device_base;
+
+	/* clear the RAMBoot and the Reset bit */
+	reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
+	reg &= ~ISL38XX_CTRL_STAT_RESET;
+	reg &= ~ISL38XX_CTRL_STAT_RAMBOOT;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* set the Reset bit without reading the register ! */
+	reg |= ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* clear the Reset bit */
+	reg &= ~ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	wmb();
+
+	/* wait a while for the device to reboot */
+	mdelay(50);
+
+	{
+		const struct firmware *fw_entry = 0;
+		long fw_len;
+		const u32 *fw_ptr;
+
+		rc = request_firmware(&fw_entry, priv->firmware, PRISM_FW_PDEV);
+		if (rc) {
+			printk(KERN_ERR
+			       "%s: request_firmware() failed for '%s'\n",
+			       "prism54", priv->firmware);
+			return rc;
+		}
+		/* prepare the Direct Memory Base register */
+		reg = ISL38XX_DEV_FIRMWARE_ADDRES;
+
+		fw_ptr = (u32 *) fw_entry->data;
+		fw_len = fw_entry->size;
+
+		if (fw_len % 4) {
+			printk(KERN_ERR
+			       "%s: firmware '%s' size is not multiple of 32bit, aborting!\n",
+			       "prism54", priv->firmware);
+			release_firmware(fw_entry);
+			return EILSEQ; /* Illegal byte sequence  */;
+		}
+
+		while (fw_len > 0) {
+			long _fw_len =
+			    (fw_len >
+			     ISL38XX_MEMORY_WINDOW_SIZE) ?
+			    ISL38XX_MEMORY_WINDOW_SIZE : fw_len;
+			u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN;
+
+			/* set the cards base address for writting the data */
+			isl38xx_w32_flush(device_base, reg,
+					  ISL38XX_DIR_MEM_BASE_REG);
+			wmb();	/* be paranoid */
+
+			/* increment the write address for next iteration */
+			reg += _fw_len;
+			fw_len -= _fw_len;
+
+			/* write the data to the Direct Memory Window 32bit-wise */
+			/* memcpy_toio() doesn't guarantee 32bit writes :-| */
+			while (_fw_len > 0) {
+				/* use non-swapping writel() */
+				__raw_writel(*fw_ptr, dev_fw_ptr);
+				fw_ptr++, dev_fw_ptr++;
+				_fw_len -= 4;
+			}
+
+			/* flush PCI posting */
+			(void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH);
+			wmb();	/* be paranoid again */
+
+			BUG_ON(_fw_len != 0);
+		}
+
+		BUG_ON(fw_len != 0);
+
+		release_firmware(fw_entry);
+	}
+
+	/* now reset the device
+	 * clear the Reset & ClkRun bit, set the RAMBoot bit */
+	reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
+	reg &= ~ISL38XX_CTRL_STAT_CLKRUN;
+	reg &= ~ISL38XX_CTRL_STAT_RESET;
+	reg |= ISL38XX_CTRL_STAT_RAMBOOT;
+	isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG);
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* set the reset bit latches the host override and RAMBoot bits
+	 * into the device for operation when the reset bit is reset */
+	reg |= ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	/* don't do flush PCI posting here! */
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* clear the reset bit should start the whole circus */
+	reg &= ~ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	/* don't do flush PCI posting here! */
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	return 0;
+}
+
 /******************************************************************************
     Device Interrupt Handler
 ******************************************************************************/
@@ -74,7 +188,9 @@
 	if (reg & ISL38XX_CTRL_STAT_SLEEPMODE)
 		/* device is in sleep mode, IRQ was generated by someone else */
 	{
-		printk(KERN_DEBUG "Assuming someone else called the IRQ\n");
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n");
+#endif
 		return IRQ_NONE;
 	}
 
@@ -324,14 +440,7 @@
 
 	printk(KERN_DEBUG "%s: uploading firmware...\n", priv->ndev->name);
 
-	rc = isl38xx_upload_firmware(priv->firmware,
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,75))
-		&priv->pdev->dev,
-#else
-		pci_name(priv->pdev),
-#endif
-		priv->device_base,
-		priv->device_host_address);
+	rc = isl_upload_firmware(priv);
 	if (rc) {
 		/* error uploading the firmware */
 		printk(KERN_ERR "%s: could not upload firmware ('%s')\n",
@@ -357,15 +466,8 @@
 	int result = -ETIME;
 	int count;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-	/* This is 2.6 specific, nicer, shorter, but not in 2.4 yet */
 	DEFINE_WAIT(wait);
 	prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE);
-#else
-	DECLARE_WAITQUEUE(wait, current);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&priv->reset_done, &wait);
-#endif
 	
 	/* now the last step is to reset the interface */
 	isl38xx_interface_reset(priv->device_base, priv->device_host_address);
@@ -390,13 +492,7 @@
 
 	}
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-	/* 2.6 specific too */
 	finish_wait(&priv->reset_done, &wait);
-#else
-	remove_wait_queue(&priv->reset_done, &wait);
-	set_current_state(TASK_RUNNING);
-#endif
 
 	if(result)
 		return result;
@@ -410,7 +506,9 @@
 	 * the IRQ line until we know for sure the reset went through */
 	isl38xx_enable_common_interrupts(priv->device_base);
 
-	prism54_mib_init_work(priv);
+	down_write(&priv->mib_sem);
+	mgt_commit(priv);
+	up_write(&priv->mib_sem);
 
 	islpci_set_state(priv, PRV_STATE_READY);
 
@@ -448,9 +546,9 @@
 	/* reset the mgmt receive queue */
 	for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) {
 		isl38xx_fragment *frag = &cb->rx_data_mgmt[counter];
-		frag->size = MGMT_FRAME_SIZE;
+		frag->size = cpu_to_le16(MGMT_FRAME_SIZE);
 		frag->flags = 0;
-		frag->address = priv->mgmt_rx[counter].pci_addr;
+		frag->address = cpu_to_le32(priv->mgmt_rx[counter].pci_addr);
 	}
 
 	for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) {
@@ -580,6 +678,7 @@
 			skb = NULL;
 			goto out_free;
 		}
+		skb_reserve(skb, (4 - (long) skb->data) & 0x03);
 		/* add the new allocated sk_buff to the buffer array */
 		priv->data_low_rx[counter] = skb;
 
diff -Nru a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
--- a/drivers/net/wireless/prism54/islpci_dev.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/wireless/prism54/islpci_dev.h	2004-06-23 19:04:26 -07:00
@@ -29,20 +29,6 @@
 #include <net/iw_handler.h>
 #include <linux/list.h>
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
-# include <linux/workqueue.h>
-#else
-# include <linux/tqueue.h>
-# define work_struct tq_struct
-# define INIT_WORK INIT_TQUEUE
-# define schedule_work schedule_task
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
-#define free_netdev(x) kfree(x) 
-#define pci_name(x) x->slot_name 
-#endif
-
 #include "isl_38xx.h"
 #include "isl_oid.h"
 #include "islpci_mgt.h"
@@ -187,7 +173,7 @@
 	islpci_state_t state;
 	int state_off;		/* enumeration of off-state, if 0 then
 				 * we're not in any off-state */
-	
+
 	/* WPA stuff */
 	int wpa; /* WPA mode enabled */
 	struct list_head bss_wpa_list;
@@ -209,12 +195,6 @@
 islpci_state_t islpci_set_state(islpci_private *priv, islpci_state_t new_state);
 
 #define ISLPCI_TX_TIMEOUT               (2*HZ)
-
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,75))
-# define irqreturn_t void
-# define IRQ_HANDLED
-# define IRQ_NONE
-#endif
 
 irqreturn_t islpci_interrupt(int, void *, struct pt_regs *);
 
diff -Nru a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
--- a/drivers/net/wireless/prism54/islpci_eth.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/wireless/prism54/islpci_eth.c	2004-06-23 19:04:25 -07:00
@@ -26,6 +26,7 @@
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 
+#include "prismcompat.h"
 #include "isl_38xx.h"
 #include "islpci_eth.h"
 #include "islpci_mgt.h"
@@ -104,7 +105,7 @@
 
 	/* check whether the destination queue has enough fragments for the frame */
 	curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]);
-	if (curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE) {
+	if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) {
 		printk(KERN_ERR "%s: transmit device queue full when awake\n",
 		       ndev->name);
 		netif_stop_queue(ndev);
@@ -120,7 +121,7 @@
 	/* Check alignment and WDS frame formatting. The start of the packet should
 	 * be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes
 	 * and add WDS address information */
-	if (((long) skb->data & 0x03) | init_wds) {
+	if (unlikely(((long) skb->data & 0x03) | init_wds)) {
 		/* get the number of bytes to add and re-allign */
 		offset = (4 - (long) skb->data) & 0x03;
 		offset += init_wds ? 6 : 0;
@@ -191,7 +192,7 @@
 	pci_map_address = pci_map_single(priv->pdev,
 					 (void *) skb->data, skb->len,
 					 PCI_DMA_TODEVICE);
-	if (pci_map_address == 0) {
+	if (unlikely(pci_map_address == 0)) {
 		printk(KERN_WARNING "%s: cannot map buffer to PCI\n",
 		       ndev->name);
 
@@ -207,7 +208,7 @@
 	priv->data_low_tx[index] = skb;
 	/* set the proper fragment start address and size information */
 	fragment->size = cpu_to_le16(frame_size);
-	fragment->flags = cpu_to_le16(0);  /* set to 1 if more fragments */
+	fragment->flags = cpu_to_le16(0);	/* set to 1 if more fragments */
 	fragment->address = cpu_to_le32(pci_map_address);
 	curr_frag++;
 
@@ -217,7 +218,7 @@
 	cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ] = cpu_to_le32(curr_frag);
 
 	if (curr_frag - priv->free_data_tx + ISL38XX_MIN_QTHRESHOLD
-	                                           > ISL38XX_CB_TX_QSIZE) {
+	    > ISL38XX_CB_TX_QSIZE) {
 		/* stop sends from upper layers */
 		netif_stop_queue(ndev);
 
@@ -238,7 +239,7 @@
 
 	return 0;
 
- drop_free:
+      drop_free:
 	/* free the skbuf structure before aborting */
 	dev_kfree_skb(skb);
 	skb = NULL;
@@ -261,9 +262,9 @@
 	if (priv->ndev->type == ARPHRD_IEEE80211_PRISM) {
 		struct avs_80211_1_header *avs;
 		/* extract the relevant data from the header */
-		u32 clock = hdr->clock;
+		u32 clock = le32_to_cpu(hdr->clock);
 		u8 rate = hdr->rate;
-		u16 freq = be16_to_cpu(hdr->freq);
+		u16 freq = le16_to_cpu(hdr->freq);
 		u8 rssi = hdr->rssi;
 
 		skb_pull(*skb, sizeof (struct rfmon_header));
@@ -274,7 +275,7 @@
 									 avs_80211_1_header),
 								 0, GFP_ATOMIC);
 			if (newskb) {
-				kfree_skb(*skb);
+				dev_kfree_skb_irq(*skb);
 				*skb = newskb;
 			} else
 				return -1;
@@ -286,21 +287,21 @@
 		    (struct avs_80211_1_header *) skb_push(*skb,
 							   sizeof (struct
 								   avs_80211_1_header));
-
-		avs->version = htonl(P80211CAPTURE_VERSION);
-		avs->length = htonl(sizeof (struct avs_80211_1_header));
-		avs->mactime = __cpu_to_be64(clock);
-		avs->hosttime = __cpu_to_be64(jiffies);
-		avs->phytype = htonl(6);	/*OFDM: 6 for (g), 8 for (a) */
-		avs->channel = htonl(channel_of_freq(freq));
-		avs->datarate = htonl(rate * 5);
-		avs->antenna = htonl(0);	/*unknown */
-		avs->priority = htonl(0);	/*unknown */
-		avs->ssi_type = htonl(2);	/*2: dBm, 3: raw RSSI */
-		avs->ssi_signal = htonl(rssi);
-		avs->ssi_noise = htonl(priv->local_iwstatistics.qual.noise);	/*better than 'undefined', I assume */
-		avs->preamble = htonl(0);	/*unknown */
-		avs->encoding = htonl(0);	/*unknown */
+		
+		avs->version = cpu_to_be32(P80211CAPTURE_VERSION);
+		avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header));
+		avs->mactime = cpu_to_be64(le64_to_cpu(clock));
+		avs->hosttime = cpu_to_be64(jiffies);
+		avs->phytype = cpu_to_be32(6);	/*OFDM: 6 for (g), 8 for (a) */
+		avs->channel = cpu_to_be32(channel_of_freq(freq));
+		avs->datarate = cpu_to_be32(rate * 5);
+		avs->antenna = cpu_to_be32(0);	/*unknown */
+		avs->priority = cpu_to_be32(0);	/*unknown */
+		avs->ssi_type = cpu_to_be32(3);	/*2: dBm, 3: raw RSSI */
+		avs->ssi_signal = cpu_to_be32(rssi & 0x7f);
+		avs->ssi_noise = cpu_to_be32(priv->local_iwstatistics.qual.noise);	/*better than 'undefined', I assume */
+		avs->preamble = cpu_to_be32(0);	/*unknown */
+		avs->encoding = cpu_to_be32(0);	/*unknown */
 	} else
 		skb_pull(*skb, sizeof (struct rfmon_header));
 
@@ -381,10 +382,10 @@
 	skb->dev = ndev;
 
 	/* take care of monitor mode and spy monitoring. */
-	if (priv->iw_mode == IW_MODE_MONITOR)
+	if (unlikely(priv->iw_mode == IW_MODE_MONITOR))
 		discard = islpci_monitor_rx(priv, &skb);
 	else {
-		if (skb->data[2 * ETH_ALEN] == 0) {
+		if (unlikely(skb->data[2 * ETH_ALEN] == 0)) {
 			/* The packet has a rx_annex. Read it for spy monitoring, Then
 			 * remove it, while keeping the 2 leading MAC addr.
 			 */
@@ -417,8 +418,8 @@
 	     skb->data[0], skb->data[1], skb->data[2], skb->data[3],
 	     skb->data[4], skb->data[5]);
 #endif
-	if (discard) {
-		dev_kfree_skb(skb);
+	if (unlikely(discard)) {
+		dev_kfree_skb_irq(skb);
 		skb = NULL;
 	} else
 		netif_rx(skb);
@@ -433,11 +434,13 @@
 	       index - priv->free_data_rx < ISL38XX_CB_RX_QSIZE) {
 		/* allocate an sk_buff for received data frames storage
 		 * include any required allignment operations */
-		if (skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2), skb == NULL) {
+		skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2);
+		if (unlikely(skb == NULL)) {
 			/* error allocating an sk_buff structure elements */
 			DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n");
 			break;
 		}
+		skb_reserve(skb, (4 - (long) skb->data) & 0x03);
 		/* store the new skb structure pointer */
 		index = index % ISL38XX_CB_RX_QSIZE;
 		priv->data_low_rx[index] = skb;
@@ -453,13 +456,13 @@
 		    pci_map_single(priv->pdev, (void *) skb->data,
 				   MAX_FRAGMENT_SIZE_RX + 2,
 				   PCI_DMA_FROMDEVICE);
-		if (priv->pci_map_rx_address[index] == (dma_addr_t) NULL) {
+		if (unlikely(priv->pci_map_rx_address[index] == (dma_addr_t) NULL)) {
 			/* error mapping the buffer to device accessable memory address */
 			DEBUG(SHOW_ERROR_MESSAGES,
 			      "Error mapping DMA address\n");
 
 			/* free the skbuf structure before aborting */
-			dev_kfree_skb((struct sk_buff *) skb);
+			dev_kfree_skb_irq((struct sk_buff *) skb);
 			skb = NULL;
 			break;
 		}
@@ -484,10 +487,10 @@
 void
 islpci_do_reset_and_wake(void *data)
 {
-       islpci_private *priv = (islpci_private *) data;
-       islpci_reset(priv, 1);
-       netif_wake_queue(priv->ndev);
-       priv->reset_task_pending = 0;
+	islpci_private *priv = (islpci_private *) data;
+	islpci_reset(priv, 1);
+	netif_wake_queue(priv->ndev);
+	priv->reset_task_pending = 0;
 }
 
 void
diff -Nru a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
--- a/drivers/net/wireless/prism54/islpci_hotplug.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c	2004-06-23 19:04:27 -07:00
@@ -24,12 +24,13 @@
 #include <linux/delay.h>
 #include <linux/init.h> /* For __init, __exit */
 
+#include "prismcompat.h"
 #include "islpci_dev.h"
 #include "islpci_mgt.h"		/* for pc_debug */
 #include "isl_oid.h"
 
 #define DRV_NAME	"prism54"
-#define DRV_VERSION	"1.1"
+#define DRV_VERSION	"1.2"
 
 MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team <prism54-devel@prism54.org>");
 MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter");
diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
--- a/drivers/net/wireless/prism54/islpci_mgt.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/wireless/prism54/islpci_mgt.c	2004-06-23 19:04:27 -07:00
@@ -22,12 +22,12 @@
 #include <linux/netdevice.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/moduleparam.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 #include <linux/if_arp.h>
 
+#include "prismcompat.h"
 #include "isl_38xx.h"
 #include "islpci_mgt.h"
 #include "isl_oid.h"		/* additional types and defs for isl38xx fw */
@@ -63,7 +63,6 @@
     Queue handling for management frames
 ******************************************************************************/
 
-  
 /*
  * Helper function to create a PIMFOR management frame header.
  */
@@ -86,8 +85,8 @@
 {
 	pimfor_header_t *h = data;
 
-        while ((void *) h < data + len) {
-		if(h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) {
+	while ((void *) h < data + len) {
+		if (h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) {
 			le32_to_cpus(&h->oid);
 			le32_to_cpus(&h->length);
 		} else {
@@ -108,8 +107,8 @@
 islpci_mgmt_rx_fill(struct net_device *ndev)
 {
 	islpci_private *priv = netdev_priv(ndev);
-	isl38xx_control_block *cb =    /* volatile not needed */
-		(isl38xx_control_block *) priv->control_block;
+	isl38xx_control_block *cb =	/* volatile not needed */
+	    (isl38xx_control_block *) priv->control_block;
 	u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]);
 
 #if VERBOSE > SHOW_ERROR_MESSAGES
@@ -124,7 +123,8 @@
 		if (buf->mem == NULL) {
 			buf->mem = kmalloc(MGMT_FRAME_SIZE, GFP_ATOMIC);
 			if (!buf->mem) {
-				printk(KERN_WARNING "Error allocating management frame.\n");
+				printk(KERN_WARNING
+				       "Error allocating management frame.\n");
 				return -ENOMEM;
 			}
 			buf->size = MGMT_FRAME_SIZE;
@@ -133,24 +133,24 @@
 			buf->pci_addr = pci_map_single(priv->pdev, buf->mem,
 						       MGMT_FRAME_SIZE,
 						       PCI_DMA_FROMDEVICE);
-			if(!buf->pci_addr) {
-				printk(KERN_WARNING "Failed to make memory DMA'able\n.");
+			if (!buf->pci_addr) {
+				printk(KERN_WARNING
+				       "Failed to make memory DMA'able\n.");
 				return -ENOMEM;
 			}
 		}
 
-                /* be safe: always reset control block information */
+		/* be safe: always reset control block information */
 		frag->size = cpu_to_le16(MGMT_FRAME_SIZE);
 		frag->flags = 0;
 		frag->address = cpu_to_le32(buf->pci_addr);
 		curr++;
 
-                /* The fragment address in the control block must have
-                 * been written before announcing the frame buffer to
-                 * device */
+		/* The fragment address in the control block must have
+		 * been written before announcing the frame buffer to
+		 * device */
 		wmb();
-		cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] =
-			cpu_to_le32(curr);
+		cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = cpu_to_le32(curr);
 	}
 	return 0;
 }
@@ -168,7 +168,7 @@
 {
 	islpci_private *priv = netdev_priv(ndev);
 	isl38xx_control_block *cb =
-		(isl38xx_control_block *) priv->control_block;
+	    (isl38xx_control_block *) priv->control_block;
 	void *p;
 	int err = -EINVAL;
 	unsigned long flags;
@@ -242,25 +242,25 @@
 	priv->mgmt_tx[index] = buf;
 	frag = &cb->tx_data_mgmt[index];
 	frag->size = cpu_to_le16(frag_len);
-	frag->flags = 0;   /* for any other than the last fragment, set to 1 */
+	frag->flags = 0;	/* for any other than the last fragment, set to 1 */
 	frag->address = cpu_to_le32(buf.pci_addr);
 
 	/* The fragment address in the control block must have
 	 * been written before announcing the frame buffer to
 	 * device */
 	wmb();
-	cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag+1);
+	cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag + 1);
 	spin_unlock_irqrestore(&priv->slock, flags);
 
 	/* trigger the device */
 	islpci_trigger(priv);
 	return 0;
 
- error_unlock:
+      error_unlock:
 	spin_unlock_irqrestore(&priv->slock, flags);
- error_free:
+      error_free:
 	kfree(buf.mem);
- error:
+      error:
 	return err;
 }
 
@@ -274,50 +274,49 @@
 {
 	islpci_private *priv = netdev_priv(ndev);
 	isl38xx_control_block *cb =
-		(isl38xx_control_block *) priv->control_block;
+	    (isl38xx_control_block *) priv->control_block;
 	u32 curr_frag;
 
 #if VERBOSE > SHOW_ERROR_MESSAGES
 	DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n");
 #endif
 
-
-        /* Only once per interrupt, determine fragment range to
-         * process.  This avoids an endless loop (i.e. lockup) if
-         * frames come in faster than we can process them. */
+	/* Only once per interrupt, determine fragment range to
+	 * process.  This avoids an endless loop (i.e. lockup) if
+	 * frames come in faster than we can process them. */
 	curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_RX_MGMTQ]);
 	barrier();
 
-	for ( ; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) {
+	for (; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) {
 		pimfor_header_t *header;
 		u32 index = priv->index_mgmt_rx % ISL38XX_CB_MGMT_QSIZE;
 		struct islpci_membuf *buf = &priv->mgmt_rx[index];
 		u16 frag_len;
 		int size;
 		struct islpci_mgmtframe *frame;
-              
-                /* I have no idea (and no documentation) if flags != 0
-                 * is possible.  Drop the frame, reuse the buffer. */
-                if(le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) {
-                        printk(KERN_WARNING "%s: unknown flags 0x%04x\n",
-                               ndev->name,
-                               le16_to_cpu(cb->rx_data_mgmt[index].flags));
-                        continue;
-                }
+
+		/* I have no idea (and no documentation) if flags != 0
+		 * is possible.  Drop the frame, reuse the buffer. */
+		if (le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) {
+			printk(KERN_WARNING "%s: unknown flags 0x%04x\n",
+			       ndev->name,
+			       le16_to_cpu(cb->rx_data_mgmt[index].flags));
+			continue;
+		}
 
 		/* The device only returns the size of the header(s) here. */
 		frag_len = le16_to_cpu(cb->rx_data_mgmt[index].size);
 
 		/*
-                 * We appear to have no way to tell the device the
-                 * size of a receive buffer.  Thus, if this check
-                 * triggers, we likely have kernel heap corruption. */
-                if (frag_len > MGMT_FRAME_SIZE) {
-                        printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\
-n",
-                               ndev->name, frag_len, frag_len);
-                        frag_len = MGMT_FRAME_SIZE;
-                }
+		 * We appear to have no way to tell the device the
+		 * size of a receive buffer.  Thus, if this check
+		 * triggers, we likely have kernel heap corruption. */
+		if (frag_len > MGMT_FRAME_SIZE) {
+			printk(KERN_WARNING
+				"%s: Bogus packet size of %d (%#x).\n",
+				ndev->name, frag_len, frag_len);
+			frag_len = MGMT_FRAME_SIZE;
+		}
 
 		/* Ensure the results of device DMA are visible to the CPU. */
 		pci_dma_sync_single(priv->pdev, buf->pci_addr,
@@ -339,30 +338,32 @@
 #if VERBOSE > SHOW_ERROR_MESSAGES
 		DEBUG(SHOW_PIMFOR_FRAMES,
 		      "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n",
-		      header->operation, header->oid, header->device_id, 
+		      header->operation, header->oid, header->device_id,
 		      header->flags, header->length);
 
 		/* display the buffer contents for debugging */
 		display_buffer((char *) header, PIMFOR_HEADER_SIZE);
-		display_buffer((char *) header + PIMFOR_HEADER_SIZE, header->length);
+		display_buffer((char *) header + PIMFOR_HEADER_SIZE,
+			       header->length);
 #endif
 
 		/* nobody sends these */
 		if (header->flags & PIMFOR_FLAG_APPLIC_ORIGIN) {
-			printk(KERN_DEBUG "%s: errant PIMFOR application frame\n",
+			printk(KERN_DEBUG
+			       "%s: errant PIMFOR application frame\n",
 			       ndev->name);
 			continue;
 		}
 
 		/* Determine frame size, skipping OID_INL_TUNNEL headers. */
 		size = PIMFOR_HEADER_SIZE + header->length;
-		frame = kmalloc(sizeof(struct islpci_mgmtframe) + size,
+		frame = kmalloc(sizeof (struct islpci_mgmtframe) + size,
 				GFP_ATOMIC);
 		if (!frame) {
-			printk(KERN_WARNING "%s: Out of memory, cannot handle oid 0x%08x\n",
-
+			printk(KERN_WARNING
+			       "%s: Out of memory, cannot handle oid 0x%08x\n",
 			       ndev->name, header->oid);
-			continue;        
+			continue;
 		}
 		frame->ndev = ndev;
 		memcpy(&frame->buf, header, size);
@@ -382,7 +383,7 @@
 			       header->oid, header->device_id, header->flags,
 			       header->length);
 #endif
-                      
+
 			/* Create work to handle trap out of interrupt
 			 * context. */
 			INIT_WORK(&frame->ws, prism54_process_trap, frame);
@@ -392,14 +393,13 @@
 			/* Signal the one waiting process that a response
 			 * has been received. */
 			if ((frame = xchg(&priv->mgmt_received, frame)) != NULL) {
-				printk(KERN_WARNING "%s: mgmt response not collected\n",
+				printk(KERN_WARNING
+				       "%s: mgmt response not collected\n",
 				       ndev->name);
 				kfree(frame);
 			}
-                              
 #if VERBOSE > SHOW_ERROR_MESSAGES
-			DEBUG(SHOW_TRACING,
-			      "Wake up Mgmt Queue\n");
+			DEBUG(SHOW_TRACING, "Wake up Mgmt Queue\n");
 #endif
 			wake_up(&priv->mgmt_wqueue);
 		}
@@ -416,22 +416,22 @@
 islpci_mgt_cleanup_transmit(struct net_device *ndev)
 {
 	islpci_private *priv = netdev_priv(ndev);
-	isl38xx_control_block *cb =    /* volatile not needed */
-		(isl38xx_control_block *) priv->control_block;
+	isl38xx_control_block *cb =	/* volatile not needed */
+	    (isl38xx_control_block *) priv->control_block;
 	u32 curr_frag;
 
 #if VERBOSE > SHOW_ERROR_MESSAGES
-        DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n");
+	DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n");
 #endif
 
 	/* Only once per cleanup, determine fragment range to
 	 * process.  This avoids an endless loop (i.e. lockup) if
 	 * the device became confused, incrementing device_curr_frag
 	 * rapidly. */
-	curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]); 
+	curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]);
 	barrier();
 
-	for ( ; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) {
+	for (; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) {
 		int index = priv->index_mgmt_tx % ISL38XX_CB_MGMT_QSIZE;
 		struct islpci_membuf *buf = &priv->mgmt_tx[index];
 		pci_unmap_single(priv->pdev, buf->pci_addr, buf->size,
@@ -456,23 +456,14 @@
 	const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000;
 	long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies;
 	int err;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 	DEFINE_WAIT(wait);
-#else
-	DECLARE_WAITQUEUE(wait, current);
-#endif
 
 	if (down_interruptible(&priv->mgmt_sem))
 		return -ERESTARTSYS;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 	prepare_to_wait(&priv->mgmt_wqueue, &wait, TASK_UNINTERRUPTIBLE);
-#else
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&priv->mgmt_wqueue, &wait);
-#endif
 	err = islpci_mgt_transmit(ndev, operation, oid, senddata, sendlen);
-	if(err)
+	if (err)
 		goto out;
 
 	err = -ETIMEDOUT;
@@ -483,13 +474,24 @@
 		timeleft = schedule_timeout(wait_cycle_jiffies);
 		frame = xchg(&priv->mgmt_received, NULL);
 		if (frame) {
-			*recvframe = frame;
-			err = 0;
-			goto out;
-		}
-		if(timeleft == 0) {
-			printk(KERN_DEBUG "%s: timeout waiting for mgmt response %lu, trigging device\n",
-			       ndev->name, timeout_left);
+			if (frame->header->oid == oid) {
+				*recvframe = frame;
+				err = 0;
+				goto out;
+			} else {
+				printk(KERN_DEBUG
+				       "%s: expecting oid 0x%x, received 0x%x.\n",
+				       ndev->name, (unsigned int) oid,
+				       frame->header->oid);
+				kfree(frame);
+				frame = NULL;
+			}
+		}
+		if (timeleft == 0) {
+			printk(KERN_DEBUG
+				"%s: timeout waiting for mgmt response %lu, "
+				"triggering device\n",
+				ndev->name, timeout_left);
 			islpci_trigger(priv);
 		}
 		timeout_left += timeleft - wait_cycle_jiffies;
@@ -499,12 +501,7 @@
 
 	/* TODO: we should reset the device here */     
  out:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 	finish_wait(&priv->mgmt_wqueue, &wait);
-#else
-	remove_wait_queue(&priv->mgmt_wqueue, &wait);
-	set_current_state(TASK_RUNNING);
-#endif
 	up(&priv->mgmt_sem);
 	return err;
 }
diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h
--- a/drivers/net/wireless/prism54/islpci_mgt.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/net/wireless/prism54/islpci_mgt.h	2004-06-23 19:04:25 -07:00
@@ -24,15 +24,6 @@
 #include <linux/wireless.h>
 #include <linux/skbuff.h>
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
-# include <linux/workqueue.h>
-#else
-# include <linux/tqueue.h>
-# define work_struct tq_struct
-# define INIT_WORK INIT_TQUEUE
-# define schedule_work schedule_task
-#endif
-
 /*
  *  Function definitions
  */
@@ -43,7 +34,7 @@
 #define TRACE(devname)   K_DEBUG(SHOW_TRACING, VERBOSE, "%s:  -> " __FUNCTION__ "()\n", devname)
 
 extern int pc_debug;
-static const int init_wds = 0;	/* help compiler optimize away dead code */
+#define init_wds 0	/* help compiler optimize away dead code */
 
 
 /* General driver definitions */
diff -Nru a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
--- a/drivers/net/wireless/prism54/oid_mgt.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/wireless/prism54/oid_mgt.c	2004-06-23 19:04:28 -07:00
@@ -16,6 +16,7 @@
  *
  */
 
+#include "prismcompat.h"
 #include "islpci_dev.h"
 #include "islpci_mgt.h"
 #include "isl_oid.h"
@@ -39,17 +40,13 @@
 	if ((f >= 2412) && (f <= 2484)) {
 		while ((c < 14) && (f != frequency_list_bg[c]))
 			c++;
-		if (c >= 14)
-			return 0;
+		return (c >= 14) ? 0 : ++c;
 	} else if ((f >= (int) 5170) && (f <= (int) 5320)) {
 		while ((c < 12) && (f != frequency_list_a[c]))
 			c++;
-		if (c >= 12)
-			return 0;
+		return (c >= 12) ? 0 : (c + 37);
 	} else
 		return 0;
-
-	return ++c;
 }
 
 #define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t}
@@ -449,7 +446,7 @@
 	if (cache)
 		down_write(&priv->mib_sem);
 
-	if (islpci_get_state(priv) >= PRV_STATE_INIT) {
+	if (islpci_get_state(priv) >= PRV_STATE_READY) {
 		ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid,
 					     _data, dlen, &response);
 		if (!ret) {
@@ -457,7 +454,7 @@
 			islpci_mgt_release(response);
 		}
 		if (ret || response_op == PIMFOR_OP_ERROR)
-		        ret = -EIO;
+			ret = -EIO;
 	} else if (!cache)
 		ret = -EIO;
 
@@ -482,7 +479,7 @@
 	int ret = -EIO;
 	int reslen = 0;
 	struct islpci_mgmtframe *response = NULL;
-	
+
 	int dlen;
 	void *cache, *_res = NULL;
 	u32 oid;
@@ -503,11 +500,11 @@
 	if (cache)
 		down_read(&priv->mib_sem);
 
-	if (islpci_get_state(priv) >= PRV_STATE_INIT) {
+	if (islpci_get_state(priv) >= PRV_STATE_READY) {
 		ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET,
 					     oid, data, dlen, &response);
 		if (ret || !response ||
-			response->header->operation == PIMFOR_OP_ERROR) {
+		    response->header->operation == PIMFOR_OP_ERROR) {
 			if (response)
 				islpci_mgt_release(response);
 			ret = -EIO;
@@ -542,9 +539,9 @@
 	if (reslen > isl_oid[n].size)
 		printk(KERN_DEBUG
 		       "mgt_get_request(0x%x): received data length was bigger "
-		       "than expected (%d > %d). Memory is probably corrupted... ",
+		       "than expected (%d > %d). Memory is probably corrupted...",
 		       oid, reslen, isl_oid[n].size);
-	
+
 	return ret;
 }
 
@@ -564,11 +561,11 @@
 		while (j <= t->range) {
 			response = NULL;
 			ret |= islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET,
-			                              oid, data, t->size,
+						      oid, data, t->size,
 						      &response);
 			if (response) {
 				ret |= (response->header->operation ==
-				        PIMFOR_OP_ERROR);
+					PIMFOR_OP_ERROR);
 				islpci_mgt_release(response);
 			}
 			j++;
@@ -625,12 +622,32 @@
 	OID_INL_OUTPUTPOWER,
 };
 
+/* update the MAC addr. */
+static int
+mgt_update_addr(islpci_private *priv)
+{
+	struct islpci_mgmtframe *res;
+	int ret;
+
+	ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET,
+				     isl_oid[GEN_OID_MACADDRESS].oid, NULL,
+				     isl_oid[GEN_OID_MACADDRESS].size, &res);
+
+	if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR))
+		memcpy(priv->ndev->dev_addr, res->data, 6);
+	else
+		ret = -EIO;
+	if (res)
+		islpci_mgt_release(res);
+
+	return ret;
+}
+
 void
 mgt_commit(islpci_private *priv)
 {
 	int rvalue;
 	u32 u;
-	union oid_res_t r;
 
 	if (islpci_get_state(priv) < PRV_STATE_INIT)
 		return;
@@ -646,21 +663,14 @@
 
 	u = OID_INL_MODE;
 	rvalue |= mgt_commit_list(priv, &u, 1);
+	rvalue |= mgt_update_addr(priv);
 
 	if (rvalue) {
 		/* some request have failed. The device might be in an
 		   incoherent state. We should reset it ! */
 		printk(KERN_DEBUG "%s: mgt_commit has failed. Restart the "
-                "device \n", priv->ndev->name);
+		       "device \n", priv->ndev->name);
 	}
-
-	/* update the MAC addr. As it's not cached, no lock will be acquired by
-	 * the mgt_get_request
-	 */
-	mgt_get_request(priv, GEN_OID_MACADDRESS, 0, NULL, &r);
-	memcpy(priv->ndev->dev_addr, r.ptr, 6);
-	kfree(r.ptr);
-
 }
 
 /* This will tell you if you are allowed to answer a mlme(ex) request .*/
@@ -687,13 +697,13 @@
 {
 	int i;
 
-	for (i = 0; i < OID_NUM_LAST - 1; i++)
+	for (i = 0; i < OID_NUM_LAST; i++)
 		if (isl_oid[i].oid == oid)
 			return i;
 
 	printk(KERN_DEBUG "looking for an unknown oid 0x%x", oid);
 
-	return 0;
+	return OID_NUM_LAST;
 }
 
 int
@@ -713,8 +723,11 @@
 	case OID_TYPE_BSS:{
 			struct obj_bss *bss = r->ptr;
 			return snprintf(str, PRIV_STR_SIZE,
-					"age=%u\nchannel=%u\n\
-				        capinfo=0x%X\nrates=0x%X\nbasic_rates=0x%X\n", bss->age, bss->channel, bss->capinfo, bss->rates, bss->basic_rates);
+					"age=%u\nchannel=%u\n"
+					"capinfo=0x%X\nrates=0x%X\n"
+					"basic_rates=0x%X\n", bss->age,
+					bss->channel, bss->capinfo,
+					bss->rates, bss->basic_rates);
 		}
 		break;
 	case OID_TYPE_BSSLIST:{
@@ -723,7 +736,9 @@
 			k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr);
 			for (i = 0; i < list->nr; i++)
 				k += snprintf(str + k, PRIV_STR_SIZE - k,
-					      "bss[%u] : \nage=%u\nchannel=%u\ncapinfo=0x%X\nrates=0x%X\nbasic_rates=0x%X\n",
+					      "bss[%u] : \nage=%u\nchannel=%u\n"
+					      "capinfo=0x%X\nrates=0x%X\n"
+					      "basic_rates=0x%X\n",
 					      i, list->bsslist[i].age,
 					      list->bsslist[i].channel,
 					      list->bsslist[i].capinfo,
@@ -745,16 +760,17 @@
 		break;
 	case OID_TYPE_MLME:{
 			struct obj_mlme *mlme = r->ptr;
-			return snprintf(str, PRIV_STR_SIZE, "id=0x%X\nstate=0x%X\n\
-			         code=0x%X\n", mlme->id, mlme->state,
-					mlme->code);
+			return snprintf(str, PRIV_STR_SIZE,
+					"id=0x%X\nstate=0x%X\ncode=0x%X\n",
+					mlme->id, mlme->state, mlme->code);
 		}
 		break;
 	case OID_TYPE_MLMEEX:{
 			struct obj_mlmeex *mlme = r->ptr;
-			return snprintf(str, PRIV_STR_SIZE, "id=0x%X\nstate=0x%X\n\
-			         code=0x%X\nsize=0x%X\n", mlme->id, mlme->state,
-					mlme->code, mlme->size);
+			return snprintf(str, PRIV_STR_SIZE,
+					"id=0x%X\nstate=0x%X\n"
+					"code=0x%X\nsize=0x%X\n", mlme->id,
+					mlme->state, mlme->code, mlme->size);
 		}
 		break;
 	case OID_TYPE_SSID:{
diff -Nru a/drivers/net/wireless/prism54/oid_mgt.h b/drivers/net/wireless/prism54/oid_mgt.h
--- a/drivers/net/wireless/prism54/oid_mgt.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/net/wireless/prism54/oid_mgt.h	2004-06-23 19:04:28 -07:00
@@ -38,7 +38,7 @@
 int mgt_set_request(islpci_private *, enum oid_num_t, int, void *);
 
 int mgt_get_request(islpci_private *, enum oid_num_t, int, void *,
-                    union oid_res_t *);
+		    union oid_res_t *);
 
 int mgt_commit_list(islpci_private *, enum oid_num_t *, int);
 
diff -Nru a/drivers/net/wireless/prism54/prismcompat.h b/drivers/net/wireless/prism54/prismcompat.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/wireless/prism54/prismcompat.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,46 @@
+/*  
+ *  (C) 2004 Margit Schubert-While <margitsw@t-online.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
+ *
+ *  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
+ *
+ */
+
+/*  
+ *	Compatibility header file to aid support of different kernel versions
+ */
+
+#ifdef PRISM54_COMPAT24
+#include "prismcompat24.h"
+#else	/* PRISM54_COMPAT24 */
+
+#ifndef _PRISM_COMPAT_H
+#define _PRISM_COMPAT_H
+
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/config.h>
+#include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+#include <linux/compiler.h>
+
+#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE)
+#error Firmware Loading is not configured in the kernel !
+#endif
+
+#define prism54_synchronize_irq(irq) synchronize_irq(irq)
+
+#define PRISM_FW_PDEV		&priv->pdev->dev
+
+#endif				/* _PRISM_COMPAT_H */
+#endif				/* PRISM54_COMPAT24 */
diff -Nru a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
--- a/drivers/net/yellowfin.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/net/yellowfin.c	2004-06-23 19:04:26 -07:00
@@ -448,7 +448,7 @@
 
 	np = dev->priv;
 
-	if (pci_request_regions(pdev, dev->name))
+	if (pci_request_regions(pdev, DRV_NAME))
 		goto err_out_free_netdev;
 
 	pci_set_master (pdev);
@@ -1201,13 +1201,8 @@
 					break;
 				skb->dev = dev;
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
-#if HAS_IP_COPYSUM
 				eth_copy_and_sum(skb, rx_skb->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
-#else
-				memcpy(skb_put(skb, pkt_len), 
-					rx_skb->tail, pkt_len);
-#endif
 				pci_dma_sync_single_for_device(yp->pci_dev, desc->addr,
 											   yp->rx_buf_sz,
 											   PCI_DMA_FROMDEVICE);
diff -Nru a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
--- a/drivers/net/zorro8390.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/net/zorro8390.c	2004-06-23 19:04:27 -07:00
@@ -36,6 +36,8 @@
 #include "8390.h"
 
 
+#define DRV_NAME	"zorro8390"
+
 #define NE_BASE		(dev->base_addr)
 #define NE_CMD		(0x00*2)
 #define NE_DATAPORT	(0x10*2)	/* NatSemi-defined port window offset. */
@@ -115,7 +117,7 @@
     if (!dev)
 	return -ENOMEM;
     SET_MODULE_OWNER(dev);
-    if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) {
+    if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) {
 	free_netdev(dev);
 	return -EBUSY;
     }
@@ -198,7 +200,7 @@
     dev->irq = IRQ_AMIGA_PORTS;
 
     /* Install the Interrupt handler */
-    i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, dev->name, dev);
+    i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, DRV_NAME, dev);
     if (i) return i;
 
     for(i = 0; i < ETHER_ADDR_LEN; i++) {
diff -Nru a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
--- a/drivers/parisc/ccio-dma.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/parisc/ccio-dma.c	2004-06-23 19:04:25 -07:00
@@ -44,7 +44,6 @@
 #include <asm/byteorder.h>
 #include <asm/cache.h>		/* for L1_CACHE_BYTES */
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/page.h>
 #include <asm/dma.h>
 #include <asm/io.h>
diff -Nru a/drivers/parisc/ccio-rm-dma.c b/drivers/parisc/ccio-rm-dma.c
--- a/drivers/parisc/ccio-rm-dma.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/parisc/ccio-rm-dma.c	2004-06-23 19:04:26 -07:00
@@ -40,7 +40,6 @@
 #include <linux/pci.h>
 
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 
 #include <asm/io.h>
 #include <asm/hardware.h>
diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
--- a/drivers/pci/pci-driver.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/pci/pci-driver.c	2004-06-23 19:04:27 -07:00
@@ -539,6 +539,7 @@
 	.hotplug	= pci_hotplug,
 	.suspend	= pci_device_suspend,
 	.resume		= pci_device_resume,
+	.dev_attrs	= pci_dev_attrs,
 };
 
 static int __init pci_driver_init(void)
diff -Nru a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
--- a/drivers/pci/pci-sysfs.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/pci/pci-sysfs.c	2004-06-23 19:04:27 -07:00
@@ -23,14 +23,13 @@
 /* show configuration fields */
 #define pci_config_attr(field, format_string)				\
 static ssize_t								\
-show_##field (struct device *dev, char *buf)				\
+field##_show(struct device *dev, char *buf)				\
 {									\
 	struct pci_dev *pdev;						\
 									\
 	pdev = to_pci_dev (dev);					\
 	return sprintf (buf, format_string, pdev->field);		\
-}									\
-static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+}
 
 pci_config_attr(vendor, "0x%04x\n");
 pci_config_attr(device, "0x%04x\n");
@@ -41,7 +40,7 @@
 
 /* show resources */
 static ssize_t
-pci_show_resources(struct device * dev, char * buf)
+resource_show(struct device * dev, char * buf)
 {
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 	char * str = buf;
@@ -60,7 +59,16 @@
 	return (str - buf);
 }
 
-static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL);
+struct device_attribute pci_dev_attrs[] = {
+	__ATTR_RO(resource),
+	__ATTR_RO(vendor),
+	__ATTR_RO(device),
+	__ATTR_RO(subsystem_vendor),
+	__ATTR_RO(subsystem_device),
+	__ATTR_RO(class),
+	__ATTR_RO(irq),
+	__ATTR_NULL,
+};
 
 static ssize_t
 pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
@@ -180,21 +188,10 @@
 
 void pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
-	struct device *dev = &pdev->dev;
-
-	/* current configuration's attributes */
-	device_create_file (dev, &dev_attr_vendor);
-	device_create_file (dev, &dev_attr_device);
-	device_create_file (dev, &dev_attr_subsystem_vendor);
-	device_create_file (dev, &dev_attr_subsystem_device);
-	device_create_file (dev, &dev_attr_class);
-	device_create_file (dev, &dev_attr_irq);
-	device_create_file (dev, &dev_attr_resource);
-
 	if (pdev->cfg_size < 4096)
-		sysfs_create_bin_file(&dev->kobj, &pci_config_attr);
+		sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
 	else
-		sysfs_create_bin_file(&dev->kobj, &pcie_config_attr);
+		sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
 
 	/* add platform-specific attributes */
 	pcibios_add_platform_entries(pdev);
diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h
--- a/drivers/pci/pci.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/pci/pci.h	2004-06-23 19:04:26 -07:00
@@ -62,3 +62,4 @@
 extern spinlock_t pci_bus_lock;
 
 extern int pciehp_msi_quirk;
+extern struct device_attribute pci_dev_attrs[];
diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
--- a/drivers/pcmcia/i82365.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/pcmcia/i82365.c	2004-06-23 19:04:28 -07:00
@@ -65,7 +65,6 @@
 #include "cirrus.h"
 #include "vg468.h"
 #include "ricoh.h"
-#include "o2micro.h"
 
 #ifdef DEBUG
 static const char version[] =
@@ -1372,8 +1371,15 @@
 {
     int i, ret;
 
-    if (driver_register(&i82365_driver))
-	return -1;
+    ret = driver_register(&i82365_driver);
+    if (ret)
+	return ret;
+
+    ret = platform_device_register(&i82365_device);
+    if (ret) {
+	driver_unregister(&i82365_driver);
+	return ret;
+    }
 
     printk(KERN_INFO "Intel ISA PCIC probe: ");
     sockets = 0;
@@ -1382,11 +1388,10 @@
 
     if (sockets == 0) {
 	printk("not found.\n");
+	platform_device_unregister(&i82365_device);
 	driver_unregister(&i82365_driver);
 	return -ENODEV;
     }
-
-    platform_device_register(&i82365_device);
 
     /* Set up interrupt handler(s) */
     if (grab_irq != 0)
diff -Nru a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h
--- a/drivers/pcmcia/o2micro.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/pcmcia/o2micro.h	2004-06-23 19:04:28 -07:00
@@ -120,4 +120,30 @@
 #define  O2_MODE_E_LED_OUT	0x08
 #define  O2_MODE_E_SKTA_ACTV	0x10
 
+static int o2micro_override(struct yenta_socket *socket)
+{
+	/*
+	 * 'reserved' register at 0x94/D4. chaning it to 0xCA (8 bit) enables
+	 * read prefetching which for example makes the RME Hammerfall DSP
+	 * working. for some bridges it is at 0x94, for others at 0xD4. it's
+	 * ok to write to both registers on all O2 bridges.
+	 * from Eric Still, 02Micro.
+	 */
+	if (PCI_FUNC(socket->dev->devfn) == 0) {
+		config_writeb(socket, 0x94, 0xCA);
+		config_writeb(socket, 0xD4, 0xCA);
+	}
+
+	return 0;
+}
+
+static void o2micro_restore_state(struct yenta_socket *socket)
+{
+	/*
+	 * as long as read prefetch is the only thing in
+	 * o2micro_override, it's safe to call it from here
+	 */
+	o2micro_override(socket);
+}
+
 #endif /* _LINUX_O2MICRO_H */
diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
--- a/drivers/pcmcia/yenta_socket.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/pcmcia/yenta_socket.c	2004-06-23 19:04:27 -07:00
@@ -668,6 +668,7 @@
 #include "ti113x.h"
 #include "ricoh.h"
 #include "topic.h"
+#include "o2micro.h"
 
 enum {
 	CARDBUS_TYPE_DEFAULT = -1,
@@ -676,7 +677,8 @@
 	CARDBUS_TYPE_TI12XX,
 	CARDBUS_TYPE_TI1250,
 	CARDBUS_TYPE_RICOH,
-	CARDBUS_TYPE_TOPIC97
+	CARDBUS_TYPE_TOPIC97,
+	CARDBUS_TYPE_O2MICRO,
 };
 
 /*
@@ -716,6 +718,10 @@
 	[CARDBUS_TYPE_TOPIC97]	= {
 		.override	= topic97_override,
 	},
+	[CARDBUS_TYPE_O2MICRO]	= {
+		.override	= o2micro_override,
+		.restore_state	= o2micro_restore_state,
+	},
 };
 
 
@@ -1099,6 +1105,8 @@
 
 	CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97),
 	CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97),
+
+	CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO),
 
 	/* match any cardbus bridge */
 	CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT),
diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/pnp/isapnp/core.c	2004-06-23 19:04:27 -07:00
@@ -68,13 +68,8 @@
 MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");
 MODULE_LICENSE("GPL");
 
-#ifdef CONFIG_X86_PC9800
-#define _PIDXR		0x259
-#define _PNPWRP		0xa59
-#else
 #define _PIDXR		0x279
 #define _PNPWRP		0xa79
-#endif
 
 /* short tags */
 #define _STAG_PNPVERNO		0x01
diff -Nru a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/3w-9xxx.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,2153 @@
+/*
+   3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux.
+
+   Written By: Adam Radford <linuxraid@amcc.com>
+
+   Copyright (C) 2004 Applied Micro Circuits 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; version 2 of the License.
+
+   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.
+
+   NO WARRANTY
+   THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+   LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+   solely responsible for determining the appropriateness of using and
+   distributing the Program and assumes all risks associated with its
+   exercise of rights under this Agreement, including but not limited to
+   the risks and costs of program errors, damage to or loss of data,
+   programs or equipment, and unavailability or interruption of operations.
+
+   DISCLAIMER OF LIABILITY
+   NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+   HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+   You 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
+
+   Bugs/Comments/Suggestions should be mailed to:
+   linuxraid@amcc.com
+
+   For more information, goto:
+   http://www.amcc.com
+
+   Note: This version of the driver does not contain a bundled firmware
+         image.
+
+   History
+   -------
+   2.26.02.000 - Driver cleanup for kernel submission.
+   2.26.02.001 - Replace schedule_timeout() calls with msleep().
+*/
+
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_cmnd.h>
+#include "3w-9xxx.h"
+
+/* Globals */
+static const char *twa_driver_version="2.26.02.001";
+static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
+static unsigned int twa_device_extension_count;
+static int twa_major = -1;
+extern struct timezone sys_tz;
+
+/* Module parameters */
+MODULE_AUTHOR ("AMCC");
+MODULE_DESCRIPTION ("3ware 9000 Storage Controller Linux Driver");
+MODULE_LICENSE("GPL");
+
+/* Function prototypes */
+static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header);
+static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id);
+static char *twa_aen_severity_lookup(unsigned char severity_code);
+static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id);
+static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+static int twa_chrdev_open(struct inode *inode, struct file *file);
+static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host);
+static void twa_free_request_id(TW_Device_Extension *tw_dev,int request_id);
+static void twa_get_request_id(TW_Device_Extension *tw_dev, int *request_id);
+static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits,
+ 			      u32 set_features, unsigned short current_fw_srl, 
+			      unsigned short current_fw_arch_id, 
+			      unsigned short current_fw_branch, 
+			      unsigned short current_fw_build, 
+			      unsigned short *fw_on_ctlr_srl, 
+			      unsigned short *fw_on_ctlr_arch_id, 
+			      unsigned short *fw_on_ctlr_branch, 
+			      unsigned short *fw_on_ctlr_build, 
+			      u32 *init_connect_result);
+static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length);
+static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds);
+static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds);
+static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal);
+static int twa_reset_device_extension(TW_Device_Extension *tw_dev);
+static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
+static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Apache *sglistarg);
+static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
+static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
+static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
+
+/* Functions */
+
+/* Show some statistics about the card */
+static ssize_t twa_show_stats(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *host = class_to_shost(class_dev);
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+	unsigned long flags = 0;
+	ssize_t len;
+
+	spin_lock_irqsave(tw_dev->host->host_lock, flags);
+	len = snprintf(buf, PAGE_SIZE, "Driver version: %s\n"
+		       "Current commands posted:   %4d\n"
+		       "Max commands posted:       %4d\n"
+		       "Current pending commands:  %4d\n"
+		       "Max pending commands:      %4d\n"
+		       "Last sgl length:           %4d\n"
+		       "Max sgl length:            %4d\n"
+		       "Last sector count:         %4d\n"
+		       "Max sector count:          %4d\n"
+		       "SCSI Host Resets:          %4d\n"
+		       "SCSI Aborts/Timeouts:      %4d\n"
+		       "AEN's:                     %4d\n", 
+		       twa_driver_version,
+		       tw_dev->posted_request_count,
+		       tw_dev->max_posted_request_count,
+		       tw_dev->pending_request_count,
+		       tw_dev->max_pending_request_count,
+		       tw_dev->sgl_entries,
+		       tw_dev->max_sgl_entries,
+		       tw_dev->sector_count,
+		       tw_dev->max_sector_count,
+		       tw_dev->num_resets,
+		       tw_dev->num_aborts,
+		       tw_dev->aen_count);
+	spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+	return len;
+} /* End twa_show_stats() */
+
+/* This function will set a devices queue depth */
+static ssize_t twa_store_queue_depth(struct device *dev, const char *buf, size_t count)
+{
+	int queue_depth;
+	struct scsi_device *sdev = to_scsi_device(dev);
+
+	queue_depth = simple_strtoul(buf, NULL, 0);
+	if (queue_depth > TW_Q_LENGTH-2)
+		return -EINVAL;
+	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+
+	return count;
+} /* End twa_store_queue_depth() */
+
+/* Create sysfs 'queue_depth' entry */
+static struct device_attribute twa_queue_depth_attr = {
+	.attr = {
+		.name =		"queue_depth",
+		.mode =		S_IRUSR | S_IWUSR,
+	},
+	.store = twa_store_queue_depth
+};
+
+/* Device attributes initializer */
+static struct device_attribute *twa_dev_attrs[] = {
+	&twa_queue_depth_attr,
+	NULL,
+};
+
+/* Create sysfs 'stats' entry */
+static struct class_device_attribute twa_host_stats_attr = {
+	.attr = {
+		.name = 	"stats",
+		.mode =		S_IRUGO,
+	},
+	.show = twa_show_stats
+};
+
+/* Host attributes initializer */
+static struct class_device_attribute *twa_host_attrs[] = {
+	&twa_host_stats_attr,
+	NULL,
+};
+
+/* File operations struct for character device */
+static struct file_operations twa_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= twa_chrdev_ioctl,
+	.open		= twa_chrdev_open,
+	.release	= NULL
+};
+
+/* This function will complete an aen request from the isr */
+static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id)
+{
+	TW_Command_Full *full_command_packet;
+	TW_Command *command_packet;
+	TW_Command_Apache_Header *header;
+	unsigned short aen;
+	int retval = 1;
+
+	header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
+	tw_dev->posted_request_count--;
+	aen = header->status_block.error;
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	command_packet = &full_command_packet->command.oldcommand;
+
+	/* First check for internal completion of set param for time sync */
+	if (TW_OP_OUT(command_packet->opcode__sgloffset) == TW_OP_SET_PARAM) {
+		/* Keep reading the queue in case there are more aen's */
+		if (twa_aen_read_queue(tw_dev, request_id))
+			goto out2;
+	        else {
+			retval = 0;
+			goto out;
+		}
+	}
+
+	switch (aen) {
+	case TW_AEN_QUEUE_EMPTY:
+		/* Quit reading the queue if this is the last one */
+		break;
+	case TW_AEN_SYNC_TIME_WITH_HOST:
+		twa_aen_sync_time(tw_dev, request_id);
+		retval = 0;
+		goto out;
+	default:
+		twa_aen_queue_event(tw_dev, header);
+
+		/* If there are more aen's, keep reading the queue */
+		if (twa_aen_read_queue(tw_dev, request_id))
+			goto out2;
+		else {
+			retval = 0;
+			goto out;
+		}
+	}
+	retval = 0;
+out2:
+	tw_dev->state[request_id] = TW_S_COMPLETED;
+	twa_free_request_id(tw_dev, request_id);
+	clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
+out:
+	return retval;
+} /* End twa_aen_complete() */
+
+/* This function will drain aen queue */
+static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
+{
+	int request_id = 0;
+	char cdb[TW_MAX_CDB_LEN];
+	TW_SG_Apache sglist[1];
+	int finished = 0, count = 0;
+	TW_Command_Full *full_command_packet;
+	TW_Command_Apache_Header *header;
+	unsigned short aen;
+	int first_reset = 0, queue = 0, retval = 1;
+
+	if (no_check_reset)
+		first_reset = 0;
+	else
+		first_reset = 1;
+
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+
+	/* Initialize cdb */
+	memset(&cdb, 0, TW_MAX_CDB_LEN);
+	cdb[0] = REQUEST_SENSE; /* opcode */
+	cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
+
+	/* Initialize sglist */
+	memset(&sglist, 0, sizeof(TW_SG_Apache));
+	sglist[0].length = TW_SECTOR_SIZE;
+	sglist[0].address = tw_dev->generic_buffer_phys[request_id];
+
+	if (sglist[0].address & TW_ALIGNMENT_9000_SGL) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Found unaligned address during AEN drain");
+		goto out;
+	}
+
+	/* Mark internal command */
+	tw_dev->srb[request_id] = NULL;
+
+	do {
+		/* Send command to the board */
+		if (twa_scsiop_execute_scsi(tw_dev, request_id, cdb, 1, sglist)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2, "Error posting request sense");
+			goto out;
+		}
+
+		/* Now poll for completion */
+		if (twa_poll_response(tw_dev, request_id, 30)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x3, "No valid response while draining AEN queue");
+			tw_dev->posted_request_count--;
+			goto out;
+		}
+
+		tw_dev->posted_request_count--;
+		header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
+		aen = header->status_block.error;
+		queue = 0;
+		count++;
+
+		switch (aen) {
+		case TW_AEN_QUEUE_EMPTY:
+			if (first_reset != 1)
+				goto out;
+			else
+				finished = 1;
+			break;
+		case TW_AEN_SOFT_RESET:
+			if (first_reset == 0)
+				first_reset = 1;
+			else
+				queue = 1;
+			break;
+		case TW_AEN_SYNC_TIME_WITH_HOST:
+			break;
+		default:
+			queue = 1;
+		}
+
+		/* Now queue an event info */
+		if (queue)
+			twa_aen_queue_event(tw_dev, header);
+	} while ((finished == 0) && (count < TW_MAX_AEN_DRAIN));
+
+	if (count == TW_MAX_AEN_DRAIN)
+		goto out;
+
+	retval = 0;
+out:
+	tw_dev->state[request_id] = TW_S_INITIAL;
+	return retval;
+} /* End twa_aen_drain_queue() */
+
+/* This function will queue an event */
+static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header)
+{
+	u32 local_time;
+	struct timeval time;
+	TW_Event *event;
+	unsigned short aen;
+	char host[16];
+
+	tw_dev->aen_count++;
+
+	/* Fill out event info */
+	event = tw_dev->event_queue[tw_dev->error_index];
+
+	/* Check for clobber */
+	host[0] = '\0';
+	if (tw_dev->host) {
+		sprintf(host, " scsi%d:", tw_dev->host->host_no);
+		if (event->retrieved == TW_AEN_NOT_RETRIEVED)
+			tw_dev->aen_clobber = 1;
+	}
+
+	aen = header->status_block.error;
+	memset(event, 0, sizeof(TW_Event));
+
+	event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
+	do_gettimeofday(&time);
+	local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60));
+	event->time_stamp_sec = local_time;
+	event->aen_code = aen;
+	event->retrieved = TW_AEN_NOT_RETRIEVED;
+	event->sequence_id = tw_dev->error_sequence_id;
+	tw_dev->error_sequence_id++;
+
+	header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
+	event->parameter_len = strlen(header->err_specific_desc);
+	memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len);
+	if (event->severity != TW_AEN_SEVERITY_DEBUG)
+		printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n",
+		       host,
+		       twa_aen_severity_lookup(TW_SEV_OUT(header->status_block.severity__reserved)),
+		       TW_MESSAGE_SOURCE_CONTROLLER_EVENT, aen,
+		       twa_string_lookup(twa_aen_table, aen),
+		       header->err_specific_desc);
+	else
+		tw_dev->aen_count--;
+
+	if ((tw_dev->error_index + 1) == TW_Q_LENGTH)
+		tw_dev->event_queue_wrapped = 1;
+	tw_dev->error_index = (tw_dev->error_index + 1 ) % TW_Q_LENGTH;
+} /* End twa_aen_queue_event() */
+
+/* This function will read the aen queue from the isr */
+static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
+{
+	char cdb[TW_MAX_CDB_LEN];
+	TW_SG_Apache sglist[1];
+	TW_Command_Full *full_command_packet;
+	int retval = 1;
+
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+
+	/* Initialize cdb */
+	memset(&cdb, 0, TW_MAX_CDB_LEN);
+	cdb[0] = REQUEST_SENSE; /* opcode */
+	cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
+
+	/* Initialize sglist */
+	memset(&sglist, 0, sizeof(TW_SG_Apache));
+	sglist[0].length = TW_SECTOR_SIZE;
+	sglist[0].address = tw_dev->generic_buffer_phys[request_id];
+
+	/* Mark internal command */
+	tw_dev->srb[request_id] = NULL;
+
+	/* Now post the command packet */
+	if (twa_scsiop_execute_scsi(tw_dev, request_id, cdb, 1, sglist)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x4, "Post failed while reading AEN queue");
+		goto out;
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twa_aen_read_queue() */
+
+/* This function will look up an AEN severity string */
+static char *twa_aen_severity_lookup(unsigned char severity_code)
+{
+	char *retval = NULL;
+
+	if ((severity_code < (unsigned char) TW_AEN_SEVERITY_ERROR) ||
+	    (severity_code > (unsigned char) TW_AEN_SEVERITY_DEBUG))
+		goto out;
+
+	retval = twa_aen_severity_table[severity_code];
+out:
+	return retval;
+} /* End twa_aen_severity_lookup() */
+
+/* This function will sync firmware time with the host time */
+static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
+{
+	u32 schedulertime;
+	struct timeval utc;
+	TW_Command_Full *full_command_packet;
+	TW_Command *command_packet;
+	TW_Param_Apache *param;
+	u32 local_time;
+
+	/* Fill out the command packet */
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+	command_packet = &full_command_packet->command.oldcommand;
+	command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
+	command_packet->request_id = request_id;
+	command_packet->byte8_offset.param.sgl[0].address = tw_dev->generic_buffer_phys[request_id];
+	command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE;
+	command_packet->size = TW_COMMAND_SIZE;
+	command_packet->byte6_offset.parameter_count = 1;
+
+	/* Setup the param */
+	param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
+	memset(param, 0, TW_SECTOR_SIZE);
+	param->table_id = TW_TIMEKEEP_TABLE | 0x8000; /* Controller time keep table */
+	param->parameter_id = 0x3; /* SchedulerTime */
+	param->parameter_size_bytes = 4;
+
+	/* Convert system time in UTC to local time seconds since last 
+           Sunday 12:00AM */
+	do_gettimeofday(&utc);
+	local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
+	schedulertime = local_time - (3 * 86400);
+	schedulertime = schedulertime % 604800;
+
+	memcpy(param->data, &schedulertime, sizeof(u32));
+
+	/* Mark internal command */
+	tw_dev->srb[request_id] = NULL;
+
+	/* Now post the command */
+	twa_post_command_packet(tw_dev, request_id, 1);
+} /* End twa_aen_sync_time() */
+
+/* This function will allocate memory and check if it is correctly aligned */
+static int twa_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
+{
+	int i;
+	dma_addr_t dma_handle;
+	unsigned long *cpu_addr;
+	int retval = 1;
+
+	cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle);
+	if (!cpu_addr) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed");
+		goto out;
+	}
+
+	if ((unsigned long)cpu_addr % (TW_ALIGNMENT_9000)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x6, "Failed to allocate correctly aligned memory");
+		pci_free_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, cpu_addr, dma_handle);
+		goto out;
+	}
+
+	memset(cpu_addr, 0, size*TW_Q_LENGTH);
+
+	for (i = 0; i < TW_Q_LENGTH; i++) {
+		switch(which) {
+		case 0:
+			tw_dev->command_packet_phys[i] = dma_handle+(i*size);
+			tw_dev->command_packet_virt[i] = (TW_Command_Full *)((unsigned char *)cpu_addr + (i*size));
+			break;
+		case 1:
+			tw_dev->generic_buffer_phys[i] = dma_handle+(i*size);
+			tw_dev->generic_buffer_virt[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
+			break;
+		}
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twa_allocate_memory() */
+
+/* This function will check the status register for unexpected bits */
+static int twa_check_bits(u32 status_reg_value)
+{
+	int retval = 1;
+
+	if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS)
+		goto out;
+	if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0)
+		goto out;
+
+	retval = 0;
+out:
+	return retval;
+} /* End twa_check_bits() */
+
+/* This function will check the srl and decide if we are compatible  */
+static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed)
+{
+	int retval = 1;
+	unsigned short fw_on_ctlr_srl = 0, fw_on_ctlr_arch_id = 0;
+	unsigned short fw_on_ctlr_branch = 0, fw_on_ctlr_build = 0;
+	u32 init_connect_result = 0;
+
+	if (twa_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS,
+			       TW_EXTENDED_INIT_CONNECT, TW_CURRENT_FW_SRL,
+			       TW_9000_ARCH_ID, TW_CURRENT_FW_BRANCH,
+			       TW_CURRENT_FW_BUILD, &fw_on_ctlr_srl,
+			       &fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
+			       &fw_on_ctlr_build, &init_connect_result)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x7, "Initconnection failed while checking SRL");
+		goto out;
+	}
+
+	tw_dev->working_srl = TW_CURRENT_FW_SRL;
+	tw_dev->working_branch = TW_CURRENT_FW_BRANCH;
+	tw_dev->working_build = TW_CURRENT_FW_BUILD;
+
+	/* Try base mode compatibility */
+	if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) {
+		if (twa_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS,
+				       TW_EXTENDED_INIT_CONNECT,
+				       TW_BASE_FW_SRL, TW_9000_ARCH_ID,
+				       TW_BASE_FW_BRANCH, TW_BASE_FW_BUILD,
+				       &fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
+				       &fw_on_ctlr_branch, &fw_on_ctlr_build,
+				       &init_connect_result)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0xa, "Initconnection (base mode) failed while checking SRL");
+			goto out;
+		}
+		if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) {
+			if (TW_CURRENT_FW_SRL > fw_on_ctlr_srl) {
+				TW_PRINTK(tw_dev->host, TW_DRIVER, 0x32, "Firmware and driver incompatibility: please upgrade firmware");
+			} else {
+				TW_PRINTK(tw_dev->host, TW_DRIVER, 0x33, "Firmware and driver incompatibility: please upgrade driver");
+			}
+			goto out;
+		}
+		tw_dev->working_srl = TW_BASE_FW_SRL;
+		tw_dev->working_branch = TW_BASE_FW_BRANCH;
+		tw_dev->working_build = TW_BASE_FW_BUILD;
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twa_check_srl() */
+
+/* This function handles ioctl for the character device */
+static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long timeout;
+	unsigned long *cpu_addr, data_buffer_length_adjusted = 0, flags = 0;
+	dma_addr_t dma_handle;
+	int request_id = 0;
+	unsigned int sequence_id = 0;
+	unsigned char event_index, start_index;
+	TW_Ioctl_Driver_Command driver_command;
+	TW_Ioctl_Buf_Apache *tw_ioctl;
+	TW_Lock *tw_lock;
+	TW_Command_Full *full_command_packet;
+	TW_Compatibility_Info *tw_compat_info;
+	TW_Event *event;
+	struct timeval current_time;
+	u32 current_time_ms;
+	TW_Device_Extension *tw_dev = twa_device_extension_list[iminor(inode)];
+	int retval = TW_IOCTL_ERROR_OS_EFAULT;
+
+	/* Only let one of these through at a time */
+	if (down_interruptible(&tw_dev->ioctl_sem)) {
+		retval = TW_IOCTL_ERROR_OS_EINTR;
+		goto out;
+	}
+
+	/* First copy down the driver command */
+	if (copy_from_user(&driver_command, (void *)arg, sizeof(TW_Ioctl_Driver_Command)))
+		goto out2;
+
+	/* Check data buffer size */
+	if (driver_command.buffer_length > TW_MAX_SECTORS * 512) {
+		retval = TW_IOCTL_ERROR_OS_EINVAL;
+		goto out2;
+	}
+
+	/* Hardware can only do multiple of 512 byte transfers */
+	data_buffer_length_adjusted = (driver_command.buffer_length + 511) & ~511;
+
+	/* Now allocate ioctl buf memory */
+	cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, &dma_handle);
+	if (!cpu_addr) {
+		retval = TW_IOCTL_ERROR_OS_ENOMEM;
+		goto out2;
+	}
+
+	tw_ioctl = (TW_Ioctl_Buf_Apache *)cpu_addr;
+
+	/* Now copy down the entire ioctl */
+	if (copy_from_user(tw_ioctl, (void *)arg, driver_command.buffer_length + sizeof(TW_Ioctl_Buf_Apache) - 1))
+		goto out3;
+
+	/* See which ioctl we are doing */
+	switch (cmd) {
+	case TW_IOCTL_FIRMWARE_PASS_THROUGH:
+		spin_lock_irqsave(tw_dev->host->host_lock, flags);
+		twa_get_request_id(tw_dev, &request_id);
+
+		/* Flag internal command */
+		tw_dev->srb[request_id] = 0;
+
+		/* Flag chrdev ioctl */
+		tw_dev->chrdev_request_id = request_id;
+
+		full_command_packet = &tw_ioctl->firmware_command;
+
+		/* Load request id and sglist for both command types */
+		twa_load_sgl(full_command_packet, request_id, dma_handle, data_buffer_length_adjusted);
+
+		memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full));
+
+		/* Now post the command packet to the controller */
+		twa_post_command_packet(tw_dev, request_id, 1);
+		spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+
+		timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
+
+		/* Now wait for command to complete */
+		timeout = wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
+
+		/* Check if we timed out, got a signal, or didn't get
+                   an interrupt */
+		if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) {
+			/* Now we need to reset the board */
+			if (timeout == TW_IOCTL_ERROR_OS_ERESTARTSYS) {
+				retval = timeout;
+			} else {
+				printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n",
+				       tw_dev->host->host_no, TW_DRIVER, 0xc,
+				       cmd);
+				retval = TW_IOCTL_ERROR_OS_EIO;
+			}
+			spin_lock_irqsave(tw_dev->host->host_lock, flags);
+			tw_dev->state[request_id] = TW_S_COMPLETED;
+			twa_free_request_id(tw_dev, request_id);
+			tw_dev->posted_request_count--;
+			twa_reset_device_extension(tw_dev);
+			spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+			goto out3;
+		}
+
+		/* Now copy in the command packet response */
+		memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virt[request_id], sizeof(TW_Command_Full));
+		
+		/* Now complete the io */
+		spin_lock_irqsave(tw_dev->host->host_lock, flags);
+		tw_dev->posted_request_count--;
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		twa_free_request_id(tw_dev, request_id);
+		spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+		break;
+	case TW_IOCTL_GET_COMPATIBILITY_INFO:
+		tw_ioctl->driver_command.status = 0;
+		/* Copy compatiblity struct into ioctl data buffer */
+		tw_compat_info = (TW_Compatibility_Info *)tw_ioctl->data_buffer;
+		strncpy(tw_compat_info->driver_version, twa_driver_version, strlen(twa_driver_version));
+		tw_compat_info->working_srl = tw_dev->working_srl;
+		tw_compat_info->working_branch = tw_dev->working_branch;
+		tw_compat_info->working_build = tw_dev->working_build;
+		break;
+	case TW_IOCTL_GET_LAST_EVENT:
+		if (tw_dev->event_queue_wrapped) {
+			if (tw_dev->aen_clobber) {
+				tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_AEN_CLOBBER;
+				tw_dev->aen_clobber = 0;
+			} else
+				tw_ioctl->driver_command.status = 0;
+		} else {
+			if (!tw_dev->error_index) {
+				tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS;
+				break;
+			}
+			tw_ioctl->driver_command.status = 0;
+		}
+		event_index = (tw_dev->error_index - 1 + TW_Q_LENGTH) % TW_Q_LENGTH;
+		memcpy(tw_ioctl->data_buffer, tw_dev->event_queue[event_index], sizeof(TW_Event));
+		tw_dev->event_queue[event_index]->retrieved = TW_AEN_RETRIEVED;
+		break;
+	case TW_IOCTL_GET_FIRST_EVENT:
+		if (tw_dev->event_queue_wrapped) {
+			if (tw_dev->aen_clobber) {
+				tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_AEN_CLOBBER;
+				tw_dev->aen_clobber = 0;
+			} else 
+				tw_ioctl->driver_command.status = 0;
+			event_index = tw_dev->error_index;
+		} else {
+			if (!tw_dev->error_index) {
+				tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS;
+				break;
+			}
+			tw_ioctl->driver_command.status = 0;
+			event_index = 0;
+		}
+		memcpy(tw_ioctl->data_buffer, tw_dev->event_queue[event_index], sizeof(TW_Event));
+		tw_dev->event_queue[event_index]->retrieved = TW_AEN_RETRIEVED;
+		break;
+	case TW_IOCTL_GET_NEXT_EVENT:
+		event = (TW_Event *)tw_ioctl->data_buffer;
+		sequence_id = event->sequence_id;
+		tw_ioctl->driver_command.status = 0;
+
+		if (tw_dev->event_queue_wrapped) {
+			if (tw_dev->aen_clobber) {
+				tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_AEN_CLOBBER;
+				tw_dev->aen_clobber = 0;
+			}
+			start_index = tw_dev->error_index;
+		} else {
+			if (!tw_dev->error_index) {
+				tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS;
+				break;
+			}
+			start_index = 0;
+		}
+		event_index = (start_index + sequence_id - tw_dev->event_queue[start_index]->sequence_id + 1) % TW_Q_LENGTH;
+
+		if (!(tw_dev->event_queue[event_index]->sequence_id > sequence_id)) {
+			if (tw_ioctl->driver_command.status == TW_IOCTL_ERROR_STATUS_AEN_CLOBBER)
+				tw_dev->aen_clobber = 1;
+			tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS;
+			break;
+		}
+		memcpy(tw_ioctl->data_buffer, tw_dev->event_queue[event_index], sizeof(TW_Event));
+		tw_dev->event_queue[event_index]->retrieved = TW_AEN_RETRIEVED;
+		break;
+	case TW_IOCTL_GET_PREVIOUS_EVENT:
+		event = (TW_Event *)tw_ioctl->data_buffer;
+		sequence_id = event->sequence_id;
+		tw_ioctl->driver_command.status = 0;
+
+		if (tw_dev->event_queue_wrapped) {
+			if (tw_dev->aen_clobber) {
+				tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_AEN_CLOBBER;
+				tw_dev->aen_clobber = 0;
+			}
+			start_index = tw_dev->error_index;
+		} else {
+			if (!tw_dev->error_index) {
+				tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS;
+				break;
+			}
+			start_index = 0;
+		}
+		event_index = (start_index + sequence_id - tw_dev->event_queue[start_index]->sequence_id - 1) % TW_Q_LENGTH;
+
+		if (!(tw_dev->event_queue[event_index]->sequence_id < sequence_id)) {
+			if (tw_ioctl->driver_command.status == TW_IOCTL_ERROR_STATUS_AEN_CLOBBER)
+				tw_dev->aen_clobber = 1;
+			tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS;
+			break;
+		}
+		memcpy(tw_ioctl->data_buffer, tw_dev->event_queue[event_index], sizeof(TW_Event));
+		tw_dev->event_queue[event_index]->retrieved = TW_AEN_RETRIEVED;
+		break;
+	case TW_IOCTL_GET_LOCK:
+		tw_lock = (TW_Lock *)tw_ioctl->data_buffer;
+		do_gettimeofday(&current_time);
+		current_time_ms = (current_time.tv_sec * 1000) + (current_time.tv_usec / 1000);
+
+		if ((tw_lock->force_flag == 1) || (tw_dev->ioctl_sem_lock == 0) || (current_time_ms >= tw_dev->ioctl_msec)) {
+			tw_dev->ioctl_sem_lock = 1;
+			tw_dev->ioctl_msec = current_time_ms + tw_lock->timeout_msec;
+			tw_ioctl->driver_command.status = 0;
+			tw_lock->time_remaining_msec = tw_lock->timeout_msec;
+		} else {
+			tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_LOCKED;
+			tw_lock->time_remaining_msec = tw_dev->ioctl_msec - current_time_ms;
+		}
+		break;
+	case TW_IOCTL_RELEASE_LOCK:
+		if (tw_dev->ioctl_sem_lock == 1) {
+			tw_dev->ioctl_sem_lock = 0;
+			tw_ioctl->driver_command.status = 0;
+		} else {
+			tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NOT_LOCKED;
+		}
+		break;
+	default:
+		retval = TW_IOCTL_ERROR_OS_ENOTTY;
+		goto out3;
+	}
+
+	/* Now copy the entire response to userspace */
+	if (copy_to_user((void *)arg, tw_ioctl, sizeof(TW_Ioctl_Buf_Apache) + driver_command.buffer_length - 1) == 0)
+		retval = 0;
+out3:
+	/* Now free ioctl buf memory */
+	pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
+out2:
+	up(&tw_dev->ioctl_sem);
+out:
+	return retval;
+} /* End twa_chrdev_ioctl() */
+
+/* This function handles open for the character device */
+static int twa_chrdev_open(struct inode *inode, struct file *file)
+{
+	unsigned int minor_number;
+	int retval = TW_IOCTL_ERROR_OS_ENODEV;
+
+	minor_number = iminor(inode);
+	if (minor_number >= twa_device_extension_count)
+		goto out;
+	retval = 0;
+out:
+	return retval;
+} /* End twa_chrdev_open() */
+
+/* This function will print readable messages from status register errors */
+static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value)
+{
+	int retval = 1;
+
+	/* Check for various error conditions and handle them appropriately */
+	if (status_reg_value & TW_STATUS_PCI_PARITY_ERROR) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0xc, "PCI Parity Error: clearing");
+		writel(TW_CONTROL_CLEAR_PARITY_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
+	}
+
+	if (status_reg_value & TW_STATUS_PCI_ABORT) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0xd, "PCI Abort: clearing");
+		writel(TW_CONTROL_CLEAR_PCI_ABORT, TW_CONTROL_REG_ADDR(tw_dev));
+		pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT);
+	}
+
+	if (status_reg_value & TW_STATUS_QUEUE_ERROR) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing");
+		writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
+	}
+
+	if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0xf, "SBUF Write Error: clearing");
+		writel(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
+	}
+
+	if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) {
+		if (tw_dev->reset_print == 0) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Microcontroller Error: clearing");
+			tw_dev->reset_print = 1;
+		}
+		goto out;
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twa_decode_bits() */
+
+/* This function will empty the response queue */
+static int twa_empty_response_queue(TW_Device_Extension *tw_dev)
+{
+	u32 status_reg_value, response_que_value;
+	int count = 0, retval = 1;
+
+	status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+
+	while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) {
+		response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
+		status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+		count++;
+	}
+	if (count == TW_MAX_RESPONSE_DRAIN)
+		goto out;
+
+	retval = 0;
+out:
+	return retval;
+} /* End twa_empty_response_queue() */
+
+/* This function passes sense keys from firmware to scsi layer */
+static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host)
+{
+	TW_Command_Full *full_command_packet;
+	unsigned short error;
+	int retval = 1;
+
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	/* Don't print error for Logical unit not supported during rollcall */
+	error = full_command_packet->header.status_block.error;
+	if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) {
+		if (print_host)
+			printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n",
+			       tw_dev->host->host_no,
+			       TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
+			       full_command_packet->header.status_block.error,
+			       twa_string_lookup(twa_error_table,
+						 full_command_packet->header.status_block.error),
+			       full_command_packet->header.err_specific_desc);
+		else
+			printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s:%s.\n",
+			       TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
+			       full_command_packet->header.status_block.error,
+			       twa_string_lookup(twa_error_table,
+						 full_command_packet->header.status_block.error),
+			       full_command_packet->header.err_specific_desc);
+	}
+
+	if (copy_sense) {
+		memcpy(tw_dev->srb[request_id]->sense_buffer, full_command_packet->header.sense_data, TW_SENSE_DATA_LENGTH);
+		tw_dev->srb[request_id]->result = (full_command_packet->command.newcommand.status << 1);
+		retval = TW_ISR_DONT_RESULT;
+		goto out;
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twa_fill_sense() */
+
+/* This function will free up device extension resources */
+static void twa_free_device_extension(TW_Device_Extension *tw_dev)
+{
+	if (tw_dev->command_packet_virt[0])
+		pci_free_consistent(tw_dev->tw_pci_dev,
+				    sizeof(TW_Command_Full)*TW_Q_LENGTH,
+				    tw_dev->command_packet_virt[0],
+				    tw_dev->command_packet_phys[0]);
+
+	if (tw_dev->generic_buffer_virt[0])
+		pci_free_consistent(tw_dev->tw_pci_dev,
+				    TW_SECTOR_SIZE*TW_Q_LENGTH,
+				    tw_dev->generic_buffer_virt[0],
+				    tw_dev->generic_buffer_phys[0]);
+
+	if (tw_dev->event_queue[0])
+		kfree(tw_dev->event_queue[0]);
+} /* End twa_free_device_extension() */
+
+/* This function will free a request id */
+static void twa_free_request_id(TW_Device_Extension *tw_dev, int request_id)
+{
+	tw_dev->free_queue[tw_dev->free_tail] = request_id;
+	tw_dev->state[request_id] = TW_S_FINISHED;
+	tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH;
+} /* End twa_free_request_id() */
+
+/* This function will get parameter table entires from the firmware */
+static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes)
+{
+	TW_Command_Full *full_command_packet;
+	TW_Command *command_packet;
+	TW_Param_Apache *param;
+	unsigned long param_value;
+	void *retval = NULL;
+
+	/* Setup the command packet */
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+	command_packet = &full_command_packet->command.oldcommand;
+
+	command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
+	command_packet->size              = TW_COMMAND_SIZE;
+	command_packet->request_id        = request_id;
+	command_packet->byte6_offset.block_count = 1;
+
+	/* Now setup the param */
+	param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
+	memset(param, 0, TW_SECTOR_SIZE);
+	param->table_id = table_id | 0x8000;
+	param->parameter_id = parameter_id;
+	param->parameter_size_bytes = parameter_size_bytes;
+	param_value = tw_dev->generic_buffer_phys[request_id];
+
+	command_packet->byte8_offset.param.sgl[0].address = param_value;
+	command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE;
+
+	/* Post the command packet to the board */
+	twa_post_command_packet(tw_dev, request_id, 1);
+
+	/* Poll for completion */
+	if (twa_poll_response(tw_dev, request_id, 30))
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x13, "No valid response during get param")
+	else
+		retval = (void *)&(param->data[0]);
+
+	tw_dev->posted_request_count--;
+	tw_dev->state[request_id] = TW_S_INITIAL;
+
+	return retval;
+} /* End twa_get_param() */
+
+/* This function will assign an available request id */
+static void twa_get_request_id(TW_Device_Extension *tw_dev, int *request_id)
+{
+	*request_id = tw_dev->free_queue[tw_dev->free_head];
+	tw_dev->free_head = (tw_dev->free_head + 1) % TW_Q_LENGTH;
+	tw_dev->state[*request_id] = TW_S_STARTED;
+} /* End twa_get_request_id() */
+
+/* This function will send an initconnection command to controller */
+static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits,
+ 			      u32 set_features, unsigned short current_fw_srl, 
+			      unsigned short current_fw_arch_id, 
+			      unsigned short current_fw_branch, 
+			      unsigned short current_fw_build, 
+			      unsigned short *fw_on_ctlr_srl, 
+			      unsigned short *fw_on_ctlr_arch_id, 
+			      unsigned short *fw_on_ctlr_branch, 
+			      unsigned short *fw_on_ctlr_build, 
+			      u32 *init_connect_result)
+{
+	TW_Command_Full *full_command_packet;
+	TW_Initconnect *tw_initconnect;
+	int request_id = 0, retval = 1;
+
+	/* Initialize InitConnection command packet */
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+	full_command_packet->header.header_desc.size_header = 128;
+	
+	tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand;
+	tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION);
+	tw_initconnect->request_id = request_id;
+	tw_initconnect->message_credits = message_credits;
+	tw_initconnect->features = set_features;
+#if BITS_PER_LONG > 32
+	/* Turn on 64-bit sgl support */
+	tw_initconnect->features |= 1;
+#endif
+
+	if (set_features & TW_EXTENDED_INIT_CONNECT) {
+		tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
+		tw_initconnect->fw_srl = current_fw_srl;
+		tw_initconnect->fw_arch_id = current_fw_arch_id;
+		tw_initconnect->fw_branch = current_fw_branch;
+		tw_initconnect->fw_build = current_fw_build;
+	} else 
+		tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE;
+
+	/* Send command packet to the board */
+	twa_post_command_packet(tw_dev, request_id, 1);
+
+	/* Poll for completion */
+	if (twa_poll_response(tw_dev, request_id, 30)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response during init connection");
+	} else {
+		if (set_features & TW_EXTENDED_INIT_CONNECT) {
+			*fw_on_ctlr_srl = tw_initconnect->fw_srl;
+			*fw_on_ctlr_arch_id = tw_initconnect->fw_arch_id;
+			*fw_on_ctlr_branch = tw_initconnect->fw_branch;
+			*fw_on_ctlr_build = tw_initconnect->fw_build;
+			*init_connect_result = tw_initconnect->result;
+		}
+		retval = 0;
+	}
+
+	tw_dev->posted_request_count--;
+	tw_dev->state[request_id] = TW_S_INITIAL;
+
+	return retval;
+} /* End twa_initconnection() */
+
+/* This function will initialize the fields of a device extension */
+static int twa_initialize_device_extension(TW_Device_Extension *tw_dev)
+{
+	int i, retval = 1;
+
+	/* Initialize command packet buffers */
+	if (twa_allocate_memory(tw_dev, sizeof(TW_Command_Full), 0)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x16, "Command packet memory allocation failed");
+		goto out;
+	}
+
+	/* Initialize generic buffer */
+	if (twa_allocate_memory(tw_dev, TW_SECTOR_SIZE, 1)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x17, "Generic memory allocation failed");
+		goto out;
+	}
+
+	/* Allocate event info space */
+	tw_dev->event_queue[0] = kmalloc(sizeof(TW_Event) * TW_Q_LENGTH, GFP_KERNEL);
+	if (!tw_dev->event_queue[0]) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x18, "Event info memory allocation failed");
+		goto out;
+	}
+
+	memset(tw_dev->event_queue[0], 0, sizeof(TW_Event) * TW_Q_LENGTH);
+
+	for (i = 0; i < TW_Q_LENGTH; i++) {
+		tw_dev->event_queue[i] = (TW_Event *)((unsigned char *)tw_dev->event_queue[0] + (i * sizeof(TW_Event)));
+		tw_dev->free_queue[i] = i;
+		tw_dev->state[i] = TW_S_INITIAL;
+	}
+
+	tw_dev->pending_head = TW_Q_START;
+	tw_dev->pending_tail = TW_Q_START;
+	tw_dev->free_head = TW_Q_START;
+	tw_dev->free_tail = TW_Q_START;
+	tw_dev->error_sequence_id = 1;
+	tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+
+	init_MUTEX(&tw_dev->ioctl_sem);
+	init_waitqueue_head(&tw_dev->ioctl_wqueue);
+
+	retval = 0;
+out:
+	return retval;
+} /* End twa_initialize_device_extension() */
+
+/* This function is the interrupt service routine */
+static irqreturn_t twa_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	int request_id, error = 0;
+	u32 status_reg_value;
+	TW_Response_Queue response_que;
+	TW_Command_Full *full_command_packet;
+	TW_Command *command_packet;
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
+	int handled = 0;
+
+	/* Get the per adapter lock */
+	spin_lock(tw_dev->host->host_lock);
+
+	/* See if the interrupt matches this instance */
+	if (tw_dev->tw_pci_dev->irq == (unsigned int)irq) {
+
+		handled = 1;
+
+		/* Read the registers */
+		status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+
+		/* Check if this is our interrupt, otherwise bail */
+		if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+			goto twa_interrupt_bail;
+
+		/* Check controller for errors */
+		if (twa_check_bits(status_reg_value)) {
+			if (twa_decode_bits(tw_dev, status_reg_value)) {
+				TW_CLEAR_ALL_INTERRUPTS(tw_dev);
+				goto twa_interrupt_bail;
+			}
+		}
+
+		/* Handle host interrupt */
+		if (status_reg_value & TW_STATUS_HOST_INTERRUPT)
+			TW_CLEAR_HOST_INTERRUPT(tw_dev);
+
+		/* Handle attention interrupt */
+		if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
+			TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
+			if (!(test_and_set_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags))) {
+				twa_get_request_id(tw_dev, &request_id);
+
+				error = twa_aen_read_queue(tw_dev, request_id);
+				if (error) {
+					tw_dev->state[request_id] = TW_S_COMPLETED;
+					twa_free_request_id(tw_dev, request_id);
+					clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
+				}
+			}
+		}
+
+		/* Handle command interrupt */
+		if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
+			TW_MASK_COMMAND_INTERRUPT(tw_dev);
+			/* Drain as many pending commands as we can */
+			while (tw_dev->pending_request_count > 0) {
+				request_id = tw_dev->pending_queue[tw_dev->pending_head];
+				if (tw_dev->state[request_id] != TW_S_PENDING) {
+					TW_PRINTK(tw_dev->host, TW_DRIVER, 0x19, "Found request id that wasn't pending");
+					TW_CLEAR_ALL_INTERRUPTS(tw_dev);
+					goto twa_interrupt_bail;
+				}
+				if (twa_post_command_packet(tw_dev, request_id, 1)==0) {
+					tw_dev->pending_head = (tw_dev->pending_head + 1) % TW_Q_LENGTH;
+					tw_dev->pending_request_count--;
+				} else {
+					/* If we get here, we will continue re-posting on the next command interrupt */
+					break;
+				}
+			}
+		}
+
+		/* Handle response interrupt */
+		if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
+
+			/* Drain the response queue from the board */
+			while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+				/* Complete the response */
+				response_que.value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
+				request_id = TW_RESID_OUT(response_que.response_id);
+				full_command_packet = tw_dev->command_packet_virt[request_id];
+				error = 0;
+				command_packet = &full_command_packet->command.oldcommand;
+				/* Check for command packet errors */
+				if (full_command_packet->command.newcommand.status != 0) {
+					if (tw_dev->srb[request_id] != 0) {
+						error = twa_fill_sense(tw_dev, request_id, 1, 1);
+					} else {
+						/* Skip ioctl error prints */
+						if (request_id != tw_dev->chrdev_request_id) {
+							error = twa_fill_sense(tw_dev, request_id, 0, 1);
+						}
+					}
+				}
+
+				/* Check for correct state */
+				if (tw_dev->state[request_id] != TW_S_POSTED) {
+					if (tw_dev->srb[request_id] != 0) {
+						TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Received a request id that wasn't posted");
+					        TW_CLEAR_ALL_INTERRUPTS(tw_dev);
+						goto twa_interrupt_bail;
+					}
+				}
+
+				/* Check for internal command completion */
+				if (tw_dev->srb[request_id] == 0) {
+					if (request_id != tw_dev->chrdev_request_id) {
+						if (twa_aen_complete(tw_dev, request_id))
+							TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Error completing AEN during attention interrupt");
+					} else {
+						tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+						wake_up(&tw_dev->ioctl_wqueue);
+					}
+				} else {
+					twa_scsiop_execute_scsi_complete(tw_dev, request_id);
+					/* If no error command was a success */
+					if (error == 0) {
+						tw_dev->srb[request_id]->result = (DID_OK << 16);
+					}
+
+					/* If error, command failed */
+					if (error == 1) {
+						/* Ask for a host reset */
+						tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+					}
+
+					/* Now complete the io */
+					tw_dev->state[request_id] = TW_S_COMPLETED;
+					twa_free_request_id(tw_dev, request_id);
+					tw_dev->posted_request_count--;
+					tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+					twa_unmap_scsi_data(tw_dev, request_id);
+				}
+
+				/* Check for valid status after each drain */
+				status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+				if (twa_check_bits(status_reg_value)) {
+					if (twa_decode_bits(tw_dev, status_reg_value)) {
+						TW_CLEAR_ALL_INTERRUPTS(tw_dev);
+						goto twa_interrupt_bail;
+					}
+				}
+			}
+		}
+	}
+twa_interrupt_bail:
+	spin_unlock(tw_dev->host->host_lock);
+	return IRQ_RETVAL(handled);
+} /* End twa_interrupt() */
+
+/* This function will load the request id and various sgls for ioctls */
+static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length)
+{
+	TW_Command *oldcommand;
+	TW_Command_Apache *newcommand;
+	TW_SG_Entry *sgl;
+
+	if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
+		newcommand = &full_command_packet->command.newcommand;
+		newcommand->request_id = request_id;
+		newcommand->sg_list[0].address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
+		newcommand->sg_list[0].length = length;
+	} else {
+		oldcommand = &full_command_packet->command.oldcommand;
+		oldcommand->request_id = request_id;
+
+		if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
+			/* Load the sg list */
+			sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
+			sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
+			sgl->length = length;
+		}
+	}
+} /* End twa_load_sgl() */
+
+/* This function will perform a pci-dma mapping for a scatter gather list */
+static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
+{
+	int use_sg;
+	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+	struct pci_dev *pdev = tw_dev->tw_pci_dev;
+	int retval = 0;
+
+	if (cmd->use_sg == 0)
+		goto out;
+
+	use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
+
+	if (use_sg == 0) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
+		goto out;
+	}
+
+	cmd->SCp.phase = TW_PHASE_SGLIST;
+	cmd->SCp.have_data_in = use_sg;
+	retval = use_sg;
+out:
+	return retval;
+} /* End twa_map_scsi_sg_data() */
+
+/* This function will perform a pci-dma map for a single buffer */
+static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int request_id)
+{
+	dma_addr_t mapping;
+	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+	struct pci_dev *pdev = tw_dev->tw_pci_dev;
+	int retval = 0;
+
+	if (cmd->request_bufflen == 0) {
+		retval = 0;
+		goto out;
+	}
+
+	mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, DMA_BIDIRECTIONAL);
+
+	if (mapping == 0) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Failed to map page");
+		goto out;
+	}
+
+	cmd->SCp.phase = TW_PHASE_SINGLE;
+	cmd->SCp.have_data_in = mapping;
+	retval = mapping;
+out:
+	return retval;
+} /* End twa_map_scsi_single_data() */
+
+/* This function will poll for a response interrupt of a request */
+static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
+{
+	int retval = 1, found = 0, response_request_id;
+	TW_Response_Queue response_queue;
+	TW_Command_Full *full_command_packet = tw_dev->command_packet_virt[request_id];
+
+	if (twa_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, seconds) == 0) {
+		response_queue.value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
+		response_request_id = TW_RESID_OUT(response_queue.response_id);
+		if (request_id != response_request_id) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1e, "Found unexpected request id while polling for response");
+			goto out;
+		}
+		if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
+			if (full_command_packet->command.newcommand.status != 0) {
+				/* bad response */
+				twa_fill_sense(tw_dev, request_id, 0, 0);
+				goto out;
+			}
+			found = 1;
+		} else {
+			if (full_command_packet->command.oldcommand.status != 0) {
+				/* bad response */
+				twa_fill_sense(tw_dev, request_id, 0, 0);
+				goto out;
+			}
+			found = 1;
+		}
+	}
+
+	if (found)
+		retval = 0;
+out:
+	return retval;
+} /* End twa_poll_response() */
+
+/* This function will poll the status register for a flag */
+static int twa_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
+{
+	u32 status_reg_value; 
+	unsigned long before;
+	int retval = 1;
+
+	status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+	before = jiffies;
+
+	if (twa_check_bits(status_reg_value))
+		twa_decode_bits(tw_dev, status_reg_value);
+
+	while ((status_reg_value & flag) != flag) {
+		status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+
+		if (twa_check_bits(status_reg_value))
+			twa_decode_bits(tw_dev, status_reg_value);
+
+		if (time_after(jiffies, before + HZ * seconds))
+			goto out;
+
+		msleep(50);
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twa_poll_status() */
+
+/* This function will poll the status register for disappearance of a flag */
+static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds)
+{
+	u32 status_reg_value;
+	unsigned long before;
+	int retval = 1;
+
+	status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+	before = jiffies;
+
+	if (twa_check_bits(status_reg_value))
+		twa_decode_bits(tw_dev, status_reg_value);
+
+	while ((status_reg_value & flag) != 0) {
+		status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+		if (twa_check_bits(status_reg_value))
+			twa_decode_bits(tw_dev, status_reg_value);
+
+		if (time_after(jiffies, before + HZ * seconds))
+			goto out;
+
+		msleep(50);
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twa_poll_status_gone() */
+
+/* This function will attempt to post a command packet to the board */
+static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal)
+{
+	u32 status_reg_value;
+	unsigned long command_que_value;
+	int retval = 1;
+
+	command_que_value = tw_dev->command_packet_phys[request_id];
+	status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+
+	if (twa_check_bits(status_reg_value))
+		twa_decode_bits(tw_dev, status_reg_value);
+
+	if (((tw_dev->pending_request_count > 0) && (tw_dev->state[request_id] != TW_S_PENDING)) || (status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL)) {
+
+		/* Only pend internal driver commands */
+		if (!internal) {
+			retval = SCSI_MLQUEUE_HOST_BUSY;
+			goto out;
+		}
+
+		/* Couldn't post the command packet, so we do it later */
+		if (tw_dev->state[request_id] != TW_S_PENDING) {
+			tw_dev->state[request_id] = TW_S_PENDING;
+			tw_dev->pending_request_count++;
+			if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) {
+				tw_dev->max_pending_request_count = tw_dev->pending_request_count;
+			}
+			tw_dev->pending_queue[tw_dev->pending_tail] = request_id;
+			tw_dev->pending_tail = (tw_dev->pending_tail + 1) % TW_Q_LENGTH;
+		}
+		TW_UNMASK_COMMAND_INTERRUPT(tw_dev);
+		goto out;
+	} else {
+		/* We successfully posted the command packet */
+#if BITS_PER_LONG > 32
+		writeq(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
+#else
+		writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
+#endif
+		tw_dev->state[request_id] = TW_S_POSTED;
+		tw_dev->posted_request_count++;
+		if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) {
+			tw_dev->max_posted_request_count = tw_dev->posted_request_count;
+		}
+	}
+	retval = 0;
+out:
+	return retval;
+} /* End twa_post_command_packet() */
+
+/* This function will reset a device extension */
+static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
+{
+	int i = 0;
+	int retval = 1;
+
+	/* Abort all requests that are in progress */
+	for (i = 0; i < TW_Q_LENGTH; i++) {
+		if ((tw_dev->state[i] != TW_S_FINISHED) &&
+		    (tw_dev->state[i] != TW_S_INITIAL) &&
+		    (tw_dev->state[i] != TW_S_COMPLETED)) {
+			if (tw_dev->srb[i]) {
+				tw_dev->srb[i]->result = (DID_RESET << 16);
+				tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
+				twa_unmap_scsi_data(tw_dev, i);
+			}
+		}
+	}
+
+	/* Reset queues and counts */
+	for (i = 0; i < TW_Q_LENGTH; i++) {
+		tw_dev->free_queue[i] = i;
+		tw_dev->state[i] = TW_S_INITIAL;
+	}
+	tw_dev->free_head = TW_Q_START;
+	tw_dev->free_tail = TW_Q_START;
+	tw_dev->posted_request_count = 0;
+	tw_dev->pending_request_count = 0;
+	tw_dev->pending_head = TW_Q_START;
+	tw_dev->pending_tail = TW_Q_START;
+	tw_dev->reset_print = 0;
+	tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+	tw_dev->flags = 0;
+
+	TW_DISABLE_INTERRUPTS(tw_dev);
+
+	if (twa_reset_sequence(tw_dev, 1))
+		goto out;
+
+        TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+
+	retval = 0;
+out:
+	return retval;
+} /* End twa_reset_device_extension() */
+
+/* This function will reset a controller */
+static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset)
+{
+	int tries = 0, retval = 1, flashed = 0, do_soft_reset = soft_reset;
+
+	while (tries < TW_MAX_RESET_TRIES) {
+		if (do_soft_reset)
+			TW_SOFT_RESET(tw_dev);
+
+		/* Make sure controller is in a good state */
+		if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 30)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1f, "Microcontroller not ready during reset sequence");
+			do_soft_reset = 1;
+			tries++;
+			continue;
+		}
+
+		/* Empty response queue */
+		if (twa_empty_response_queue(tw_dev)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x20, "Response queue empty failed during reset sequence");
+			do_soft_reset = 1;
+			tries++;
+			continue;
+		}
+
+		flashed = 0;
+
+		/* Check for compatibility/flash */
+		if (twa_check_srl(tw_dev, &flashed)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x21, "Compatibility check failed during reset sequence");
+			do_soft_reset = 1;
+			tries++;
+			continue;
+		} else {
+			if (flashed) {
+				tries++;
+				continue;
+			}
+		}
+
+		/* Drain the AEN queue */
+		if (twa_aen_drain_queue(tw_dev, soft_reset)) {
+			TW_PRINTK(tw_dev->host, TW_DRIVER, 0x22, "AEN drain failed during reset sequence");
+			do_soft_reset = 1;
+			tries++;
+			continue;
+		}
+
+		/* If we got here, controller is in a good state */
+		retval = 0;
+		goto out;
+	}
+out:
+	return retval;
+} /* End twa_reset_sequence() */
+
+/* This funciton returns unit geometry in cylinders/heads/sectors */
+static int twa_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[])
+{
+	int heads, sectors, cylinders;
+	TW_Device_Extension *tw_dev;
+
+	tw_dev = (TW_Device_Extension *)sdev->host->hostdata;
+
+	if (capacity >= 0x200000) {
+		heads = 255;
+		sectors = 63;
+		cylinders = sector_div(capacity, heads * sectors);
+	} else {
+		heads = 64;
+		sectors = 32;
+		cylinders = sector_div(capacity, heads * sectors);
+	}
+
+	geom[0] = heads;
+	geom[1] = sectors;
+	geom[2] = cylinders;
+
+	return 0;
+} /* End twa_scsi_biosparam() */
+
+/* This is the new scsi eh abort function */
+static int twa_scsi_eh_abort(struct scsi_cmnd *SCpnt)
+{
+	int i;
+	TW_Device_Extension *tw_dev = NULL;
+	int retval = FAILED;
+
+	tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+
+	spin_unlock_irq(tw_dev->host->host_lock);
+
+	tw_dev->num_aborts++;
+
+	/* If we find any IO's in process, we have to reset the card */
+	for (i = 0; i < TW_Q_LENGTH; i++) {
+		if ((tw_dev->state[i] != TW_S_FINISHED) && (tw_dev->state[i] != TW_S_INITIAL)) {
+			printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n",
+			       tw_dev->host->host_no, TW_DRIVER, 0x2c,
+			       SCpnt->device->id, SCpnt->cmnd[0]);
+			if (twa_reset_device_extension(tw_dev)) {
+				TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2a, "Controller reset failed during scsi abort");
+				goto out;
+			}
+			break;
+		}
+	}
+	retval = SUCCESS;
+out:
+	spin_lock_irq(tw_dev->host->host_lock);
+	return retval;
+} /* End twa_scsi_eh_abort() */
+
+/* This is the new scsi eh reset function */
+static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
+{
+	TW_Device_Extension *tw_dev = NULL;
+	int retval = FAILED;
+
+	tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+
+	spin_unlock_irq(tw_dev->host->host_lock);
+
+	tw_dev->num_resets++;
+
+	printk(KERN_WARNING "3w-9xxx: scsi%d: SCSI host reset started.\n", tw_dev->host->host_no);
+
+	/* Now reset the card and some of the device extension data */
+	if (twa_reset_device_extension(tw_dev)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset");
+		goto out;
+	}
+	printk(KERN_WARNING "3w-9xxx: scsi%d: SCSI host reset succeeded.\n", tw_dev->host->host_no);
+	retval = SUCCESS;
+out:
+	spin_lock_irq(tw_dev->host->host_lock);
+	return retval;
+} /* End twa_scsi_eh_reset() */
+
+/* This is the main scsi queue function to handle scsi opcodes */
+static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+	int request_id, retval;
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+
+	/* Save done function into scsi_cmnd struct */
+	SCpnt->scsi_done = done;
+		
+	/* Get a free request id */
+	twa_get_request_id(tw_dev, &request_id);
+
+	/* Save the scsi command for use by the ISR */
+	tw_dev->srb[request_id] = SCpnt;
+
+	/* Initialize phase to zero */
+	SCpnt->SCp.phase = TW_PHASE_INITIAL;
+
+	retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
+	switch (retval) {
+	case SCSI_MLQUEUE_HOST_BUSY:
+		twa_free_request_id(tw_dev, request_id);
+		break;
+	case 1:
+		tw_dev->state[request_id] = TW_S_COMPLETED;
+		twa_free_request_id(tw_dev, request_id);
+		SCpnt->result = (DID_ERROR << 16);
+		done(SCpnt);
+	}
+
+	return retval;
+} /* End twa_scsi_queue() */
+
+/* This function hands scsi cdb's to the firmware */
+static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Apache *sglistarg)
+{
+	TW_Command_Full *full_command_packet;
+	TW_Command_Apache *command_packet;
+	u32 num_sectors = 0x0;
+	int i, sg_count;
+	struct scsi_cmnd *srb = NULL;
+	struct scatterlist *sglist = NULL;
+	u32 buffaddr = 0x0;
+	int retval = 1;
+
+	if (tw_dev->srb[request_id]) {
+		if (tw_dev->srb[request_id]->request_buffer) {
+			sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+		}
+		srb = tw_dev->srb[request_id];
+	}
+
+	/* Initialize command packet */
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	full_command_packet->header.header_desc.size_header = 128;
+	full_command_packet->header.status_block.error = 0;
+	full_command_packet->header.status_block.severity__reserved = 0;
+
+	command_packet = &full_command_packet->command.newcommand;
+	command_packet->status = 0;
+	command_packet->opcode__reserved = TW_OPRES_IN(0, TW_OP_EXECUTE_SCSI);
+
+	/* We forced 16 byte cdb use earlier */
+	if (!cdb)
+		memcpy(command_packet->cdb, srb->cmnd, TW_MAX_CDB_LEN);
+	else
+		memcpy(command_packet->cdb, cdb, TW_MAX_CDB_LEN);
+
+	if (srb)
+		command_packet->unit = srb->device->id;
+	else
+		command_packet->unit = 0;
+
+	command_packet->request_id = request_id;
+	command_packet->sgl_offset = 16;
+
+	if (!sglistarg) {
+		/* Map sglist from scsi layer to cmd packet */
+		if (tw_dev->srb[request_id]->use_sg == 0) {
+			if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
+				command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
+				command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
+			} else {
+				buffaddr = twa_map_scsi_single_data(tw_dev, request_id);
+				if (buffaddr == 0)
+					goto out;
+
+				command_packet->sg_list[0].address = buffaddr;
+				command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen;
+			}
+			command_packet->sgl_entries = 1;
+
+			if (command_packet->sg_list[0].address & TW_ALIGNMENT_9000_SGL) {
+				TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
+				goto out;
+			}
+		}
+
+		if (tw_dev->srb[request_id]->use_sg > 0) {
+			sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
+			if (sg_count == 0)
+				goto out;
+
+			for (i = 0; i < sg_count; i++) {
+				command_packet->sg_list[i].address = sg_dma_address(&sglist[i]);
+				command_packet->sg_list[i].length = sg_dma_len(&sglist[i]);
+				if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
+					TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
+					goto out;
+				}
+			}
+			command_packet->sgl_entries = tw_dev->srb[request_id]->use_sg;
+		}
+	} else {
+		/* Internal cdb post */
+		for (i = 0; i < use_sg; i++) {
+			command_packet->sg_list[i].address = sglistarg[i].address;
+			command_packet->sg_list[i].length = sglistarg[i].length;
+			if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
+				TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post");
+				goto out;
+			}
+		}
+		command_packet->sgl_entries = use_sg;
+	}
+
+	if (srb) {
+		if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6)
+			num_sectors = (u32)srb->cmnd[4];
+
+		if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10)
+			num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8);
+	}
+
+	/* Update sector statistic */
+	tw_dev->sector_count = num_sectors;
+	if (tw_dev->sector_count > tw_dev->max_sector_count)
+		tw_dev->max_sector_count = tw_dev->sector_count;
+
+	/* Update SG statistics */
+	if (srb) {
+		tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
+		if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
+			tw_dev->max_sgl_entries = tw_dev->sgl_entries;
+	}
+
+	/* Now post the command to the board */
+	if (srb) {
+		retval = twa_post_command_packet(tw_dev, request_id, 0);
+	} else {
+		twa_post_command_packet(tw_dev, request_id, 1);
+		retval = 0;
+	}
+out:
+	return retval;
+} /* End twa_scsiop_execute_scsi() */
+
+/* This function completes an execute scsi operation */
+static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)
+{
+	/* Copy the response if too small */
+	if ((tw_dev->srb[request_id]->request_buffer) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
+		memcpy(tw_dev->srb[request_id]->request_buffer,
+		       tw_dev->generic_buffer_virt[request_id],
+		       tw_dev->srb[request_id]->request_bufflen);
+	}
+} /* End twa_scsiop_execute_scsi_complete() */
+
+/* This function tells the controller to shut down */
+static void __twa_shutdown(TW_Device_Extension *tw_dev)
+{
+	/* Disable interrupts */
+	TW_DISABLE_INTERRUPTS(tw_dev);
+
+	printk(KERN_WARNING "3w-9xxx: Shutting down host %d.\n", tw_dev->host->host_no);
+
+	/* Tell the card we are shutting down */
+	if (twa_initconnection(tw_dev, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x31, "Connection shutdown failed");
+	} else {
+		printk(KERN_WARNING "3w-9xxx: Shutdown complete.\n");
+	}
+
+	/* Clear all interrupts just before exit */
+	TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+} /* End __twa_shutdown() */
+
+/* Wrapper for __twa_shutdown */
+static void twa_shutdown(struct device *dev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev));
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+
+	__twa_shutdown(tw_dev);
+} /* End twa_shutdown() */
+
+/* This function will look up a string */
+static char *twa_string_lookup(twa_message_type *table, unsigned int code)
+{
+	int index;
+
+	for (index = 0; ((code != table[index].code) &&
+		      (table[index].text != (char *)0)); index++);
+	return(table[index].text);
+} /* End twa_string_lookup() */
+
+/* This function will perform a pci-dma unmap */
+static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
+{
+	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+	struct pci_dev *pdev = tw_dev->tw_pci_dev;
+
+	switch(cmd->SCp.phase) {
+	case TW_PHASE_SINGLE:
+		pci_unmap_single(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
+		break;
+	case TW_PHASE_SGLIST:
+		pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
+		break;
+	}
+} /* End twa_unmap_scsi_data() */
+
+/* scsi_host_template initializer */
+static struct scsi_host_template driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "3ware 9000 Storage Controller",
+	.queuecommand		= twa_scsi_queue,
+	.eh_abort_handler	= twa_scsi_eh_abort,
+	.eh_host_reset_handler	= twa_scsi_eh_reset,
+	.bios_param		= twa_scsi_biosparam,
+	.can_queue		= TW_Q_LENGTH-2,
+	.this_id		= -1,
+	.sg_tablesize		= TW_APACHE_MAX_SGL_LENGTH,
+	.max_sectors		= TW_MAX_SECTORS,
+	.cmd_per_lun		= TW_MAX_CMDS_PER_LUN,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.shost_attrs		= twa_host_attrs,
+	.sdev_attrs		= twa_dev_attrs,
+	.emulated		= 1
+};
+
+/* This function will probe and initialize a card */
+static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
+{
+	struct Scsi_Host *host = NULL;
+	TW_Device_Extension *tw_dev;
+	u32 mem_addr;
+	int retval = -ENODEV;
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		TW_PRINTK(host, TW_DRIVER, 0x34, "Failed to enable pci device");
+		goto out_disable_device;
+	}
+
+	pci_set_master(pdev);
+
+	retval = pci_set_dma_mask(pdev, TW_DMA_MASK);
+	if (retval) {
+		TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
+		goto out_disable_device;
+	}
+
+	host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension));
+	if (!host) {
+		TW_PRINTK(host, TW_DRIVER, 0x24, "Failed to allocate memory for device extension");
+		retval = -ENOMEM;
+		goto out_disable_device;
+	}
+	tw_dev = (TW_Device_Extension *)host->hostdata;
+
+	memset(tw_dev, 0, sizeof(TW_Device_Extension));
+
+	/* Save values to device extension */
+	tw_dev->host = host;
+	tw_dev->tw_pci_dev = pdev;
+
+	if (twa_initialize_device_extension(tw_dev)) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x25, "Failed to initialize device extension");
+		goto out_free_device_extension;
+	}
+
+	/* Request IO regions */
+	retval = pci_request_regions(pdev, "3w-9xxx");
+	if (retval) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x26, "Failed to get mem region");
+		goto out_free_device_extension;
+	}
+
+	mem_addr = pci_resource_start(pdev, 1);
+
+	/* Save base address */
+	tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE);
+	if (!tw_dev->base_addr) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x35, "Failed to ioremap");
+		goto out_release_mem_region;
+	}
+
+	/* Disable interrupts on the card */
+	TW_DISABLE_INTERRUPTS(tw_dev);
+
+	/* Initialize the card */
+	if (twa_reset_sequence(tw_dev, 0))
+		goto out_release_mem_region;
+
+	/* Set host specific parameters */
+	host->max_id = TW_MAX_UNITS;
+	host->max_cmd_len = TW_MAX_CDB_LEN;
+
+	/* Luns and channels aren't supported by adapter */
+	host->max_lun = 0;
+	host->max_channel = 0;
+
+	/* Register the card with the kernel SCSI layer */
+	retval = scsi_add_host(host, &pdev->dev);
+	if (retval) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x27, "scsi add host failed");
+		goto out_release_mem_region;
+	}
+
+	pci_set_drvdata(pdev, host);
+
+	printk(KERN_WARNING "3w-9xxx: scsi%d: Found a 3ware 9000 Storage Controller at 0x%x, IRQ: %d.\n",
+	       host->host_no, mem_addr, pdev->irq);
+	printk(KERN_WARNING "3w-9xxx: scsi%d: Firmware %s, BIOS %s, Ports: %d.\n",
+	       host->host_no,
+	       (char *)twa_get_param(tw_dev, 0, TW_VERSION_TABLE,
+				     TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH),
+	       (char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE,
+				     TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH),
+	       *(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
+				     TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH));
+
+	/* Now setup the interrupt handler */
+	retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev);
+	if (retval) {
+		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x30, "Error requesting IRQ");
+		goto out_remove_host;
+	}
+
+	twa_device_extension_list[twa_device_extension_count] = tw_dev;
+	twa_device_extension_count++;
+
+	/* Re-enable interrupts on the card */
+	TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+
+	/* Finally, scan the host */
+	scsi_scan_host(host);
+
+	if (twa_major == -1) {
+		if ((twa_major = register_chrdev (0, "twa", &twa_fops)) < 0)
+			TW_PRINTK(host, TW_DRIVER, 0x29, "Failed to register character device");
+	}
+	return 0;
+
+out_remove_host:
+	scsi_remove_host(host);
+out_release_mem_region:
+	pci_release_regions(pdev);
+out_free_device_extension:
+	twa_free_device_extension(tw_dev);
+	scsi_host_put(host);
+out_disable_device:
+	pci_disable_device(pdev);
+
+	return retval;
+} /* End twa_probe() */
+
+/* This function is called to remove a device */
+static void twa_remove(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+
+	scsi_remove_host(tw_dev->host);
+
+	__twa_shutdown(tw_dev);
+
+	/* Free up the IRQ */
+	free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+
+	/* Free up the mem region */
+	pci_release_regions(pdev);
+
+	/* Free up device extension resources */
+	twa_free_device_extension(tw_dev);
+
+	/* Unregister character device */
+	if (twa_major >= 0) {
+		unregister_chrdev(twa_major, "twa");
+		twa_major = -1;
+	}
+
+	scsi_host_put(tw_dev->host);
+	pci_disable_device(pdev);
+	twa_device_extension_count--;
+} /* End twa_remove() */
+
+/* PCI Devices supported by this driver */
+static struct pci_device_id twa_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, twa_pci_tbl);
+
+/* pci_driver initializer */
+static struct pci_driver twa_driver = {
+	.name		= "3w-9xxx",
+	.id_table	= twa_pci_tbl,
+	.probe		= twa_probe,
+	.remove		= twa_remove,
+	.driver		= {
+		.shutdown = twa_shutdown
+	}
+};
+
+/* This function is called on driver initialization */
+static int __init twa_init(void)
+{
+	printk(KERN_WARNING "3ware 9000 Storage Controller device driver for Linux v%s.\n", twa_driver_version);
+
+	return pci_module_init(&twa_driver);
+} /* End twa_init() */
+
+/* This function is called on driver exit */
+static void __exit twa_exit(void)
+{
+	pci_unregister_driver(&twa_driver);
+} /* End twa_exit() */
+
+module_init(twa_init);
+module_exit(twa_exit);
+
diff -Nru a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/3w-9xxx.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,704 @@
+/*
+   3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux.
+
+   Written By: Adam Radford <linuxraid@amcc.com>
+
+   Copyright (C) 2004 Applied Micro Circuits 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; version 2 of the License.
+
+   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.
+
+   NO WARRANTY
+   THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+   LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+   solely responsible for determining the appropriateness of using and
+   distributing the Program and assumes all risks associated with its
+   exercise of rights under this Agreement, including but not limited to
+   the risks and costs of program errors, damage to or loss of data,
+   programs or equipment, and unavailability or interruption of operations.
+
+   DISCLAIMER OF LIABILITY
+   NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+   HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+   You 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
+
+   Bugs/Comments/Suggestions should be mailed to:
+   linuxraid@amcc.com
+
+   For more information, goto:
+   http://www.amcc.com
+*/
+
+#ifndef _3W_9XXX_H
+#define _3W_9XXX_H
+
+/* AEN string type */
+typedef struct TAG_twa_message_type {
+  unsigned int   code;
+  char*          text;
+} twa_message_type;
+
+/* AEN strings */
+static twa_message_type twa_aen_table[] = {
+	{0x0000, "AEN queue empty"},
+	{0x0001, "Controller reset occurred"},
+	{0x0002, "Degraded unit detected"},
+	{0x0003, "Controller error occured"},
+	{0x0004, "Background rebuild failed"},
+	{0x0005, "Background rebuild done"},
+	{0x0006, "Incomplete unit detected"},
+	{0x0007, "Background initialize done"},
+	{0x0008, "Unclean shutdown detected"},
+	{0x0009, "Drive timeout detected"},
+	{0x000A, "Drive error detected"},
+	{0x000B, "Rebuild started"},
+	{0x000C, "Background initialize started"},
+	{0x000D, "Entire logical unit was deleted"},
+	{0x000E, "Background initialize failed"},
+	{0x000F, "SMART attribute exceeded threshold"},
+	{0x0010, "Power supply reported AC under range"},
+	{0x0011, "Power supply reported DC out of range"},
+	{0x0012, "Power supply reported a malfunction"},
+	{0x0013, "Power supply predicted malfunction"},
+	{0x0014, "Battery charge is below threshold"},
+	{0x0015, "Fan speed is below threshold"},
+	{0x0016, "Temperature sensor is above threshold"},
+	{0x0017, "Power supply was removed"},
+	{0x0018, "Power supply was inserted"},
+	{0x0019, "Drive was removed from a bay"},
+	{0x001A, "Drive was inserted into a bay"},
+	{0x001B, "Drive bay cover door was opened"},
+	{0x001C, "Drive bay cover door was closed"},
+	{0x001D, "Product case was opened"},
+	{0x0020, "Prepare for shutdown (power-off)"},
+	{0x0021, "Downgrade UDMA mode to lower speed"},
+	{0x0022, "Upgrade UDMA mode to higher speed"},
+	{0x0023, "Sector repair completed"},
+	{0x0024, "Sbuf memory test failed"},
+	{0x0025, "Error flushing cached write data to array"},
+	{0x0026, "Drive reported data ECC error"},
+	{0x0027, "DCB has checksum error"},
+	{0x0028, "DCB version is unsupported"},
+	{0x0029, "Background verify started"},
+	{0x002A, "Background verify failed"},
+	{0x002B, "Background verify done"},
+	{0x002C, "Bad sector overwritten during rebuild"},
+	{0x002D, "Background rebuild error on source drive"},
+	{0x002E, "Replace failed because replacement drive too small"},
+	{0x002F, "Verify failed because array was never initialized"},
+	{0x0030, "Unsupported ATA drive"},
+	{0x0031, "Synchronize host/controller time"},
+	{0x0032, "Spare capacity is inadequate for some units"},
+	{0x0033, "Background migration started"},
+	{0x0034, "Background migration failed"},
+	{0x0035, "Background migration done"},
+	{0x0036, "Verify detected and fixed data/parity mismatch"},
+	{0x0037, "SO-DIMM incompatible"},
+	{0x0038, "SO-DIMM not detected"},
+	{0x0039, "Corrected Sbuf ECC error"},
+	{0x003A, "Drive power on reset detected"},
+	{0x003B, "Background rebuild paused"},
+	{0x003C, "Background initialize paused"},
+	{0x003D, "Background verify paused"},
+	{0x003E, "Background migration paused"},
+	{0x003F, "Corrupt flash file system detected"},
+	{0x0040, "Flash file system repaired"},
+	{0x0041, "Unit number assignments were lost"},
+	{0x0042, "Error during read of primary DCB"},
+	{0x0043, "Latent error found in backup DCB"},
+	{0x00FC, "Recovered/finished array membership update"},
+	{0x00FD, "Handler lockup"},
+	{0x00FE, "Retrying PCI transfer"},
+	{0x00FF, "AEN queue is full"},
+	{0xFFFFFFFF, (char*) 0}
+};
+
+/* AEN severity table */
+static char *twa_aen_severity_table[] =
+{
+	"None", "ERROR", "WARNING", "INFO", "DEBUG", (char*) 0
+};
+
+/* Error strings */
+static twa_message_type twa_error_table[] = {
+	{0x0100, "SGL entry contains zero data"},
+	{0x0101, "Invalid command opcode"},
+	{0x0102, "SGL entry has unaligned address"},
+	{0x0103, "SGL size does not match command"},
+	{0x0104, "SGL entry has illegal length"},
+	{0x0105, "Command packet is not aligned"},
+	{0x0106, "Invalid request ID"},
+	{0x0107, "Duplicate request ID"},
+	{0x0108, "ID not locked"},
+	{0x0109, "LBA out of range"},
+	{0x010A, "Logical unit not supported"},
+	{0x010B, "Parameter table does not exist"},
+	{0x010C, "Parameter index does not exist"},
+	{0x010D, "Invalid field in CDB"},
+	{0x010E, "Specified port has invalid drive"},
+	{0x010F, "Parameter item size mismatch"},
+	{0x0110, "Failed memory allocation"},
+	{0x0111, "Memory request too large"},
+	{0x0112, "Out of memory segments"},
+	{0x0113, "Invalid address to deallocate"},
+	{0x0114, "Out of memory"},
+	{0x0115, "Out of heap"},
+	{0x0120, "Double degrade"},
+	{0x0121, "Drive not degraded"},
+	{0x0122, "Reconstruct error"},
+	{0x0123, "Replace not accepted"},
+	{0x0124, "Replace drive capacity too small"},
+	{0x0125, "Sector count not allowed"},
+	{0x0126, "No spares left"},
+	{0x0127, "Reconstruct error"},
+	{0x0128, "Unit is offline"},
+	{0x0129, "Cannot update status to DCB"},
+	{0x0130, "Invalid stripe handle"},
+	{0x0131, "Handle that was not locked"},
+	{0x0132, "Handle that was not empty"},
+	{0x0133, "Handle has different owner"},
+	{0x0140, "IPR has parent"},
+	{0x0150, "Illegal Pbuf address alignment"},
+	{0x0151, "Illegal Pbuf transfer length"},
+	{0x0152, "Illegal Sbuf address alignment"},
+	{0x0153, "Illegal Sbuf transfer length"},
+	{0x0160, "Command packet too large"},
+	{0x0161, "SGL exceeds maximum length"},
+	{0x0162, "SGL has too many entries"},
+	{0x0170, "Insufficient resources for rebuilder"},
+	{0x0171, "Verify error (data != parity)"},
+	{0x0180, "Requested segment not in directory of this DCB"},
+	{0x0181, "DCB segment has unsupported version"},
+	{0x0182, "DCB segment has checksum error"},
+	{0x0183, "DCB support (settings) segment invalid"},
+	{0x0184, "DCB UDB (unit descriptor block) segment invalid"},
+	{0x0185, "DCB GUID (globally unique identifier) segment invalid"},
+	{0x01A0, "Could not clear Sbuf"},
+	{0x01C0, "Flash identify failed"},
+	{0x01C1, "Flash out of bounds"},
+	{0x01C2, "Flash verify error"},
+	{0x01C3, "Flash file object not found"},
+	{0x01C4, "Flash file already present"},
+	{0x01C5, "Flash file system full"},
+	{0x01C6, "Flash file not present"},
+	{0x01C7, "Flash file size error"},
+	{0x01C8, "Bad flash file checksum"},
+	{0x01CA, "Corrupt flash file system detected"},
+	{0x01D0, "Invalid field in parameter list"},
+	{0x01D1, "Parameter list length error"},
+	{0x01D2, "Parameter item is not changeable"},
+	{0x01D3, "Parameter item is not saveable"},
+	{0x0200, "UDMA CRC error"},
+	{0x0201, "Internal CRC error"},
+	{0x0202, "Data ECC error"},
+	{0x0203, "ADP level 1 error"},
+	{0x0204, "Port timeout"},
+	{0x0205, "Drive power on reset"},
+	{0x0206, "ADP level 2 error"},
+	{0x0207, "Soft reset failed"},
+	{0x0208, "Drive not ready"},
+	{0x0209, "Unclassified port error"},
+	{0x020A, "Drive aborted command"},
+	{0x0210, "Internal CRC error"},
+	{0x0211, "PCI abort error"},
+	{0x0212, "PCI parity error"},
+	{0x0213, "Port handler error"},
+	{0x0214, "Token interrupt count error"},
+	{0x0215, "Timeout waiting for PCI transfer"},
+	{0x0216, "Corrected buffer ECC"},
+	{0x0217, "Uncorrected buffer ECC"},
+	{0x0230, "Unsupported command during flash recovery"},
+	{0x0231, "Next image buffer expected"},
+	{0x0232, "Binary image architecture incompatible"},
+	{0x0233, "Binary image has no signature"},
+	{0x0234, "Binary image has bad checksum"},
+	{0x0235, "Image downloaded overflowed buffer"},
+	{0x0240, "I2C device not found"},
+	{0x0241, "I2C transaction aborted"},
+	{0x0242, "SO-DIMM parameter(s) incompatible using defaults"},
+	{0x0243, "SO-DIMM unsupported"},
+	{0x0248, "SPI transfer status error"},
+	{0x0249, "SPI transfer timeout error"},
+	{0x0250, "Invalid unit descriptor size in CreateUnit"},
+	{0x0251, "Unit descriptor size exceeds data buffer in CreateUnit"},
+	{0x0252, "Invalid value in CreateUnit descriptor"},
+	{0x0253, "Inadequate disk space to support descriptor in CreateUnit"},
+	{0x0254, "Unable to create data channel for this unit descriptor"},
+	{0x0255, "CreateUnit descriptor specifies a drive already in use"},
+	{0x0256, "Unable to write configuration to all disks during CreateUnit"},
+	{0x0257, "CreateUnit does not support this descriptor version"},
+	{0x0258, "Invalid subunit for RAID 0 or 5 in CreateUnit"},
+	{0x0259, "Too many descriptors in CreateUnit"},
+	{0x025A, "Invalid configuration specified in CreateUnit descriptor"},
+	{0x025B, "Invalid LBA offset specified in CreateUnit descriptor"},
+	{0x025C, "Invalid stripelet size specified in CreateUnit descriptor"},
+	{0x0260, "SMART attribute exceeded threshold"},
+	{0xFFFFFFFF, (char*) 0}
+};
+
+/* Control register bit definitions */
+#define TW_CONTROL_CLEAR_HOST_INTERRUPT	       0x00080000
+#define TW_CONTROL_CLEAR_ATTENTION_INTERRUPT   0x00040000
+#define TW_CONTROL_MASK_COMMAND_INTERRUPT      0x00020000
+#define TW_CONTROL_MASK_RESPONSE_INTERRUPT     0x00010000
+#define TW_CONTROL_UNMASK_COMMAND_INTERRUPT    0x00008000
+#define TW_CONTROL_UNMASK_RESPONSE_INTERRUPT   0x00004000
+#define TW_CONTROL_CLEAR_ERROR_STATUS	       0x00000200
+#define TW_CONTROL_ISSUE_SOFT_RESET	       0x00000100
+#define TW_CONTROL_ENABLE_INTERRUPTS	       0x00000080
+#define TW_CONTROL_DISABLE_INTERRUPTS	       0x00000040
+#define TW_CONTROL_ISSUE_HOST_INTERRUPT	       0x00000020
+#define TW_CONTROL_CLEAR_PARITY_ERROR          0x00800000
+#define TW_CONTROL_CLEAR_QUEUE_ERROR           0x00400000
+#define TW_CONTROL_CLEAR_PCI_ABORT             0x00100000
+#define TW_CONTROL_CLEAR_SBUF_WRITE_ERROR      0x00000008
+
+/* Status register bit definitions */
+#define TW_STATUS_MAJOR_VERSION_MASK	       0xF0000000
+#define TW_STATUS_MINOR_VERSION_MASK	       0x0F000000
+#define TW_STATUS_PCI_PARITY_ERROR	       0x00800000
+#define TW_STATUS_QUEUE_ERROR		       0x00400000
+#define TW_STATUS_MICROCONTROLLER_ERROR	       0x00200000
+#define TW_STATUS_PCI_ABORT		       0x00100000
+#define TW_STATUS_HOST_INTERRUPT	       0x00080000
+#define TW_STATUS_ATTENTION_INTERRUPT	       0x00040000
+#define TW_STATUS_COMMAND_INTERRUPT	       0x00020000
+#define TW_STATUS_RESPONSE_INTERRUPT	       0x00010000
+#define TW_STATUS_COMMAND_QUEUE_FULL	       0x00008000
+#define TW_STATUS_RESPONSE_QUEUE_EMPTY	       0x00004000
+#define TW_STATUS_MICROCONTROLLER_READY	       0x00002000
+#define TW_STATUS_COMMAND_QUEUE_EMPTY	       0x00001000
+#define TW_STATUS_EXPECTED_BITS		       0x00002000
+#define TW_STATUS_UNEXPECTED_BITS	       0x00F00008
+#define TW_STATUS_SBUF_WRITE_ERROR             0x00000008
+#define TW_STATUS_VALID_INTERRUPT              0x00DF0008
+
+/* RESPONSE QUEUE BIT DEFINITIONS */
+#define TW_RESPONSE_ID_MASK		       0x00000FF0
+
+/* PCI related defines */
+#define TW_DEVICE_NAME			       "3w-9xxx"
+#define TW_NUMDEVICES 1
+#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100
+#define TW_PCI_CLEAR_PCI_ABORT     0x2000
+
+/* Command packet opcodes used by the driver */
+#define TW_OP_INIT_CONNECTION 0x1
+#define TW_OP_GET_PARAM	      0x12
+#define TW_OP_SET_PARAM	      0x13
+#define TW_OP_EXECUTE_SCSI    0x10
+#define TW_OP_DOWNLOAD_FIRMWARE 0x16
+#define TW_OP_RESET             0x1C
+
+/* Asynchronous Event Notification (AEN) codes used by the driver */
+#define TW_AEN_QUEUE_EMPTY       0x0000
+#define TW_AEN_SOFT_RESET        0x0001
+#define TW_AEN_SYNC_TIME_WITH_HOST 0x031
+#define TW_AEN_SEVERITY_ERROR    0x1
+#define TW_AEN_SEVERITY_DEBUG    0x4
+#define TW_AEN_NOT_RETRIEVED 0x1
+#define TW_AEN_RETRIEVED 0x2
+
+/* Command state defines */
+#define TW_S_INITIAL   0x1  /* Initial state */
+#define TW_S_STARTED   0x2  /* Id in use */
+#define TW_S_POSTED    0x4  /* Posted to the controller */
+#define TW_S_PENDING   0x8  /* Waiting to be posted in isr */
+#define TW_S_COMPLETED 0x10 /* Completed by isr */
+#define TW_S_FINISHED  0x20 /* I/O completely done */
+
+/* Compatibility defines */
+#define TW_9000_ARCH_ID 0x5
+#define TW_CURRENT_FW_SRL 24
+#define TW_CURRENT_FW_BUILD 5
+#define TW_CURRENT_FW_BRANCH 1
+
+/* Phase defines */
+#define TW_PHASE_INITIAL 0
+#define TW_PHASE_SINGLE  1
+#define TW_PHASE_SGLIST  2
+
+/* Misc defines */
+#define TW_SECTOR_SIZE                        512
+#define TW_ALIGNMENT_9000                     4  /* 4 bytes */
+#define TW_ALIGNMENT_9000_SGL                 0x3
+#define TW_MAX_UNITS			      16
+#define TW_INIT_MESSAGE_CREDITS		      0x100
+#define TW_INIT_COMMAND_PACKET_SIZE	      0x3
+#define TW_INIT_COMMAND_PACKET_SIZE_EXTENDED  0x6
+#define TW_EXTENDED_INIT_CONNECT	      0x2
+#define TW_BUNDLED_FW_SAFE_TO_FLASH	      0x4
+#define TW_CTLR_FW_RECOMMENDS_FLASH	      0x8
+#define TW_CTLR_FW_COMPATIBLE		      0x2
+#define TW_BASE_FW_SRL			      0x17
+#define TW_BASE_FW_BRANCH		      0
+#define TW_BASE_FW_BUILD		      1
+#if BITS_PER_LONG > 32
+#define TW_APACHE_MAX_SGL_LENGTH 72
+#define TW_ESCALADE_MAX_SGL_LENGTH 41
+#define TW_APACHE_CMD_PKT_SIZE 5
+#else
+#define TW_APACHE_MAX_SGL_LENGTH 109
+#define TW_ESCALADE_MAX_SGL_LENGTH 62
+#define TW_APACHE_CMD_PKT_SIZE 4
+#endif
+#define TW_ATA_PASS_SGL_MAX                   60
+#define TW_Q_LENGTH			      256
+#define TW_Q_START			      0
+#define TW_MAX_SLOT			      32
+#define TW_MAX_RESET_TRIES		      2
+#define TW_MAX_CMDS_PER_LUN		      254
+#define TW_MAX_RESPONSE_DRAIN		      256
+#define TW_MAX_AEN_DRAIN		      40
+#define TW_IN_IOCTL                           2
+#define TW_IN_CHRDEV_IOCTL                    3
+#define TW_IN_ATTENTION_LOOP		      4
+#define TW_MAX_SECTORS                        256
+#define TW_AEN_WAIT_TIME                      1000
+#define TW_IOCTL_WAIT_TIME                    (1 * HZ) /* 1 second */
+#define TW_MAX_CDB_LEN                        16
+#define TW_ISR_DONT_COMPLETE                  2
+#define TW_ISR_DONT_RESULT                    3
+#define TW_IOCTL_CHRDEV_TIMEOUT               60 /* 60 seconds */
+#define TW_IOCTL_CHRDEV_FREE                  -1
+#define TW_COMMAND_OFFSET                     128 /* 128 bytes */
+#define TW_VERSION_TABLE                      0x0402
+#define TW_TIMEKEEP_TABLE		      0x040A
+#define TW_INFORMATION_TABLE		      0x0403
+#define TW_PARAM_FWVER			      3
+#define TW_PARAM_FWVER_LENGTH		      16
+#define TW_PARAM_BIOSVER		      4
+#define TW_PARAM_BIOSVER_LENGTH		      16
+#define TW_PARAM_PORTCOUNT		      3
+#define TW_PARAM_PORTCOUNT_LENGTH	      1
+#define TW_MIN_SGL_LENGTH                     0x200 /* 512 bytes */
+#define TW_MAX_SENSE_LENGTH                   256
+#define TW_EVENT_SOURCE_AEN                   0x1000
+#define TW_EVENT_SOURCE_COMMAND               0x1001
+#define TW_EVENT_SOURCE_PCHIP                 0x1002
+#define TW_EVENT_SOURCE_DRIVER                0x1003
+#define TW_IOCTL_GET_COMPATIBILITY_INFO	      0x101
+#define TW_IOCTL_GET_LAST_EVENT               0x102
+#define TW_IOCTL_GET_FIRST_EVENT              0x103
+#define TW_IOCTL_GET_NEXT_EVENT               0x104
+#define TW_IOCTL_GET_PREVIOUS_EVENT           0x105
+#define TW_IOCTL_GET_LOCK                     0x106
+#define TW_IOCTL_RELEASE_LOCK                 0x107
+#define TW_IOCTL_FIRMWARE_PASS_THROUGH        0x108
+#define TW_IOCTL_ERROR_STATUS_NOT_LOCKED      0x1001 // Not locked
+#define TW_IOCTL_ERROR_STATUS_LOCKED          0x1002 // Already locked
+#define TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS  0x1003 // No more events
+#define TW_IOCTL_ERROR_STATUS_AEN_CLOBBER     0x1004 // AEN clobber occurred
+#define TW_IOCTL_ERROR_OS_EFAULT	      -EFAULT // Bad address
+#define TW_IOCTL_ERROR_OS_EINTR		      -EINTR  // Interrupted system call
+#define TW_IOCTL_ERROR_OS_EINVAL	      -EINVAL // Invalid argument
+#define TW_IOCTL_ERROR_OS_ENOMEM	      -ENOMEM // Out of memory
+#define TW_IOCTL_ERROR_OS_ERESTARTSYS	      -ERESTARTSYS // Restart system call
+#define TW_IOCTL_ERROR_OS_EIO		      -EIO // I/O error
+#define TW_IOCTL_ERROR_OS_ENOTTY	      -ENOTTY // Not a typewriter
+#define TW_IOCTL_ERROR_OS_ENODEV	      -ENODEV // No such device
+#define TW_ALLOCATION_LENGTH		      128
+#define TW_SENSE_DATA_LENGTH		      18
+#define TW_STATUS_CHECK_CONDITION	      2
+#define TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED   0x10a
+#define TW_ERROR_UNIT_OFFLINE                 0x128
+#define TW_MESSAGE_SOURCE_CONTROLLER_ERROR    3
+#define TW_MESSAGE_SOURCE_CONTROLLER_EVENT    4
+#define TW_MESSAGE_SOURCE_LINUX_DRIVER        6
+#define TW_DRIVER TW_MESSAGE_SOURCE_LINUX_DRIVER
+#define TW_MESSAGE_SOURCE_LINUX_OS            9
+#define TW_OS TW_MESSAGE_SOURCE_LINUX_OS
+#if BITS_PER_LONG > 32
+#define TW_COMMAND_SIZE			      5
+#define TW_DMA_MASK			      DMA_64BIT_MASK
+#else
+#define TW_COMMAND_SIZE			      4
+#define TW_DMA_MASK			      DMA_32BIT_MASK
+#endif
+#ifndef PCI_DEVICE_ID_3WARE_9000
+#define PCI_DEVICE_ID_3WARE_9000 0x1002
+#endif
+
+/* Bitmask macros to eliminate bitfields */
+
+/* opcode: 5, reserved: 3 */
+#define TW_OPRES_IN(x,y) ((x << 5) | (y & 0x1f))
+#define TW_OP_OUT(x) (x & 0x1f)
+
+/* opcode: 5, sgloffset: 3 */
+#define TW_OPSGL_IN(x,y) ((x << 5) | (y & 0x1f))
+#define TW_SGL_OUT(x) ((x >> 5) & 0x7)
+
+/* severity: 3, reserved: 5 */
+#define TW_SEV_OUT(x) (x & 0x7)
+
+/* reserved_1: 4, response_id: 8, reserved_2: 20 */
+#define TW_RESID_OUT(x) ((x >> 4) & 0xff)
+
+/* Macros */
+#define TW_CONTROL_REG_ADDR(x) (x->base_addr)
+#define TW_STATUS_REG_ADDR(x) ((unsigned char *)x->base_addr + 0x4)
+#if BITS_PER_LONG > 32
+#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char *)x->base_addr + 0x20)
+#else
+#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char *)x->base_addr + 0x8)
+#endif
+#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char *)x->base_addr + 0xC)
+#define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
+#define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
+#define TW_CLEAR_HOST_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
+#define TW_DISABLE_INTERRUPTS(x) (writel(TW_CONTROL_DISABLE_INTERRUPTS, TW_CONTROL_REG_ADDR(x)))
+#define TW_ENABLE_AND_CLEAR_INTERRUPTS(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT | TW_CONTROL_UNMASK_RESPONSE_INTERRUPT | TW_CONTROL_ENABLE_INTERRUPTS, TW_CONTROL_REG_ADDR(x)))
+#define TW_MASK_COMMAND_INTERRUPT(x) (writel(TW_CONTROL_MASK_COMMAND_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
+#define TW_UNMASK_COMMAND_INTERRUPT(x) (writel(TW_CONTROL_UNMASK_COMMAND_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
+#define TW_SOFT_RESET(x) (writel(TW_CONTROL_ISSUE_SOFT_RESET | \
+			TW_CONTROL_CLEAR_HOST_INTERRUPT | \
+			TW_CONTROL_CLEAR_ATTENTION_INTERRUPT | \
+			TW_CONTROL_MASK_COMMAND_INTERRUPT | \
+			TW_CONTROL_MASK_RESPONSE_INTERRUPT | \
+			TW_CONTROL_CLEAR_ERROR_STATUS | \
+			TW_CONTROL_DISABLE_INTERRUPTS, TW_CONTROL_REG_ADDR(x)))
+#define TW_PRINTK(h,a,b,c) { \
+if (h) \
+printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s.\n",h->host_no,a,b,c); \
+else \
+printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s.\n",a,b,c); \
+}
+
+#pragma pack(1)
+
+/* Scatter Gather List Entry */
+typedef struct TAG_TW_SG_Entry {
+	unsigned long address;
+	u32 length;
+} TW_SG_Entry;
+
+/* Command Packet */
+typedef struct TW_Command {
+	unsigned char opcode__sgloffset;
+	unsigned char size;
+	unsigned char request_id;
+	unsigned char unit__hostid;
+	/* Second DWORD */
+	unsigned char status;
+	unsigned char flags;
+	union {
+		unsigned short block_count;
+		unsigned short parameter_count;
+	} byte6_offset;
+	union {
+		struct {
+			u32 lba;
+			TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH];
+#if BITS_PER_LONG > 32
+			u32 padding[2];	/* pad to 512 bytes */
+#else
+			u32 padding;
+#endif
+		} io;
+		struct {
+			TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH];
+#if BITS_PER_LONG > 32
+			u32 padding[3];
+#else
+			u32 padding[2];
+#endif
+		} param;
+	} byte8_offset;
+} TW_Command;
+
+/* Scatter gather element for 9000+ controllers */
+typedef struct TAG_TW_SG_Apache {
+	unsigned long address;
+	u32 length;
+} TW_SG_Apache;
+
+/* Command Packet for 9000+ controllers */
+typedef struct TAG_TW_Command_Apache {
+	unsigned char opcode__reserved;
+	unsigned char unit;
+	unsigned short request_id;
+	unsigned char status;
+	unsigned char sgl_offset;
+	unsigned short sgl_entries;
+	unsigned char cdb[16];
+	TW_SG_Apache sg_list[TW_APACHE_MAX_SGL_LENGTH];
+#if BITS_PER_LONG > 32
+	unsigned char padding[8];
+#endif
+} TW_Command_Apache;
+
+/* New command packet header */
+typedef struct TAG_TW_Command_Apache_Header {
+	unsigned char sense_data[TW_SENSE_DATA_LENGTH];
+	struct {
+		char reserved[4];
+		unsigned short error;
+		unsigned char padding;
+		unsigned char severity__reserved;
+	} status_block;
+	unsigned char err_specific_desc[98];
+	struct {
+		unsigned char size_header;
+		unsigned short reserved;
+		unsigned char size_sense;
+	} header_desc;
+} TW_Command_Apache_Header;
+
+/* This struct is a union of the 2 command packets */
+typedef struct TAG_TW_Command_Full {
+	TW_Command_Apache_Header header;
+	union {
+		TW_Command oldcommand;
+		TW_Command_Apache newcommand;
+	} command;
+} TW_Command_Full;
+
+/* Initconnection structure */
+typedef struct TAG_TW_Initconnect {
+	unsigned char opcode__reserved;
+	unsigned char size;
+	unsigned char request_id;
+	unsigned char res2;
+	unsigned char status;
+	unsigned char flags;
+	unsigned short message_credits;
+	u32 features;
+	unsigned short fw_srl;
+	unsigned short fw_arch_id;
+	unsigned short fw_branch;
+	unsigned short fw_build;
+	u32 result;
+} TW_Initconnect;
+
+/* Event info structure */
+typedef struct TAG_TW_Event
+{
+	unsigned int sequence_id;
+	unsigned int time_stamp_sec;
+	unsigned short aen_code;
+	unsigned char severity;
+	unsigned char retrieved;
+	unsigned char repeat_count;
+	unsigned char parameter_len;
+	unsigned char parameter_data[98];
+} TW_Event;
+
+typedef struct TAG_TW_Ioctl_Driver_Command {
+	unsigned int control_code;
+	unsigned int status;
+	unsigned int unique_id;
+	unsigned int sequence_id;
+	unsigned int os_specific;
+	unsigned int buffer_length;
+} TW_Ioctl_Driver_Command;
+
+typedef struct TAG_TW_Ioctl_Apache {
+	TW_Ioctl_Driver_Command driver_command;
+        char padding[488];
+	TW_Command_Full firmware_command;
+	char data_buffer[1];
+} TW_Ioctl_Buf_Apache;
+
+/* Lock structure for ioctl get/release lock */
+typedef struct TAG_TW_Lock {
+	unsigned long timeout_msec;
+	unsigned long time_remaining_msec;
+	unsigned long force_flag;
+} TW_Lock;
+
+/* GetParam descriptor */
+typedef struct {
+	unsigned short	table_id;
+	unsigned short	parameter_id;
+	unsigned short	parameter_size_bytes;
+	unsigned short  actual_parameter_size_bytes;
+	unsigned char	data[1];
+} TW_Param_Apache, *PTW_Param_Apache;
+
+/* Response queue */
+typedef union TAG_TW_Response_Queue {
+	u32 response_id;
+	u32 value;
+} TW_Response_Queue;
+
+typedef struct TAG_TW_Info {
+	char *buffer;
+	int length;
+	int offset;
+	int position;
+} TW_Info;
+
+/* Compatibility information structure */
+typedef struct TAG_TW_Compatibility_Info
+{
+	char driver_version[32];
+	unsigned short working_srl;
+	unsigned short working_branch;
+	unsigned short working_build;
+} TW_Compatibility_Info;
+
+typedef struct TAG_TW_Device_Extension {
+	u32                     *base_addr;
+	unsigned long	       	*generic_buffer_virt[TW_Q_LENGTH];
+	unsigned long	       	generic_buffer_phys[TW_Q_LENGTH];
+	TW_Command_Full	       	*command_packet_virt[TW_Q_LENGTH];
+	unsigned long		command_packet_phys[TW_Q_LENGTH];
+	struct pci_dev		*tw_pci_dev;
+	struct scsi_cmnd	*srb[TW_Q_LENGTH];
+	unsigned char		free_queue[TW_Q_LENGTH];
+	unsigned char		free_head;
+	unsigned char		free_tail;
+	unsigned char		pending_queue[TW_Q_LENGTH];
+	unsigned char		pending_head;
+	unsigned char		pending_tail;
+	int     		state[TW_Q_LENGTH];
+	unsigned int		posted_request_count;
+	unsigned int		max_posted_request_count;
+	unsigned int	        pending_request_count;
+	unsigned int		max_pending_request_count;
+	unsigned int		max_sgl_entries;
+	unsigned int		sgl_entries;
+	unsigned int		num_aborts;
+	unsigned int		num_resets;
+	unsigned int		sector_count;
+	unsigned int		max_sector_count;
+	unsigned int		aen_count;
+	struct Scsi_Host	*host;
+	long			flags;
+	int			reset_print;
+	TW_Event                *event_queue[TW_Q_LENGTH];
+	unsigned char           error_index;
+	unsigned char		event_queue_wrapped;
+	unsigned int            error_sequence_id;
+	int                     ioctl_sem_lock;
+	u32                     ioctl_msec;
+	int			chrdev_request_id;
+	wait_queue_head_t	ioctl_wqueue;
+	struct semaphore	ioctl_sem;
+	char			aen_clobber;
+	unsigned short		working_srl;
+	unsigned short		working_branch;
+	unsigned short		working_build;
+} TW_Device_Extension;
+
+#pragma pack()
+
+#endif /* _3W_9XXX_H */
+
diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
--- a/drivers/scsi/3w-xxxx.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/3w-xxxx.c	2004-06-23 19:04:28 -07:00
@@ -220,7 +220,7 @@
 #define __3W_C			/* let 3w-xxxx.h know it is use */
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "3w-xxxx.h"
 
diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
--- a/drivers/scsi/53c700.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/53c700.c	2004-06-23 19:04:25 -07:00
@@ -125,18 +125,21 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/blkdev.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/byteorder.h>
-#include <linux/blkdev.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-
-#include "scsi.h"
-#include "hosts.h"
 
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_spi.h>
 
@@ -164,15 +167,15 @@
 #include "53c700_d.h"
 
 
-STATIC int NCR_700_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-STATIC int NCR_700_abort(Scsi_Cmnd * SCpnt);
-STATIC int NCR_700_bus_reset(Scsi_Cmnd * SCpnt);
-STATIC int NCR_700_dev_reset(Scsi_Cmnd * SCpnt);
-STATIC int NCR_700_host_reset(Scsi_Cmnd * SCpnt);
+STATIC int NCR_700_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *));
+STATIC int NCR_700_abort(struct scsi_cmnd * SCpnt);
+STATIC int NCR_700_bus_reset(struct scsi_cmnd * SCpnt);
+STATIC int NCR_700_dev_reset(struct scsi_cmnd * SCpnt);
+STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt);
 STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
 STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
-STATIC int NCR_700_slave_configure(Scsi_Device *SDpnt);
-STATIC void NCR_700_slave_destroy(Scsi_Device *SDpnt);
+STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt);
+STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt);
 
 STATIC struct device_attribute *NCR_700_dev_attrs[];
 
@@ -279,7 +282,7 @@
 }
 
 static inline __u8
-NCR_700_get_SXFER(Scsi_Device *SDp)
+NCR_700_get_SXFER(struct scsi_device *SDp)
 {
 	struct NCR_700_Host_Parameters *hostdata = 
 		(struct NCR_700_Host_Parameters *)SDp->host->hostdata[0];
@@ -289,7 +292,7 @@
 }
 
 struct Scsi_Host *
-NCR_700_detect(Scsi_Host_Template *tpnt,
+NCR_700_detect(struct scsi_host_template *tpnt,
 	       struct NCR_700_Host_Parameters *hostdata)
 {
 	dma_addr_t pScript, pSlots;
@@ -561,7 +564,7 @@
    the ITL and (if tagged) the ITLQ lists in _queuecommand */
 STATIC void
 save_for_reselection(struct NCR_700_Host_Parameters *hostdata,
-		     Scsi_Cmnd *SCp, __u32 dsp)
+		     struct scsi_cmnd *SCp, __u32 dsp)
 {
 	/* Its just possible that this gets executed twice */
 	if(SCp != NULL) {
@@ -575,27 +578,25 @@
 }
 
 STATIC inline void
-NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp,
+NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, struct scsi_cmnd *SCp,
 	      struct NCR_700_command_slot *slot)
 {
-	if(SCp->sc_data_direction != SCSI_DATA_NONE &&
-	   SCp->sc_data_direction != SCSI_DATA_UNKNOWN) {
-		enum dma_data_direction direction = SCp->sc_data_direction;
+	if(SCp->sc_data_direction != DMA_NONE &&
+	   SCp->sc_data_direction != DMA_BIDIRECTIONAL) {
 		if(SCp->use_sg) {
 			dma_unmap_sg(hostdata->dev, SCp->buffer,
-				     SCp->use_sg, direction);
+				     SCp->use_sg, SCp->sc_data_direction);
 		} else {
-			dma_unmap_single(hostdata->dev,
-					 slot->dma_handle,
+			dma_unmap_single(hostdata->dev, slot->dma_handle,
 					 SCp->request_bufflen,
-					 direction);
+					 SCp->sc_data_direction);
 		}
 	}
 }
 
 STATIC inline void
 NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
-	       Scsi_Cmnd *SCp, int result)
+	       struct scsi_cmnd *SCp, int result)
 {
 	hostdata->state = NCR_700_HOST_FREE;
 	hostdata->cmd = NULL;
@@ -611,7 +612,7 @@
 #ifdef NCR_700_DEBUG
 			printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n",
 			       SCp, SCp->cmnd[7], result);
-			print_sense("53c700", SCp);
+			scsi_print_sense("53c700", SCp);
 
 #endif
 			/* restore the old result if the request sense was
@@ -780,7 +781,7 @@
 STATIC __u32
 process_extended_message(struct Scsi_Host *host, 
 			 struct NCR_700_Host_Parameters *hostdata,
-			 Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps)
+			 struct scsi_cmnd *SCp, __u32 dsp, __u32 dsps)
 {
 	__u32 resume_offset = dsp, temp = dsp + 8;
 	__u8 pun = 0xff, lun = 0xff;
@@ -849,7 +850,7 @@
 		printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ",
 		       host->host_no, pun, lun,
 		       NCR_700_phase[(dsps & 0xf00) >> 8]);
-		print_msg(hostdata->msgin);
+		scsi_print_msg(hostdata->msgin);
 		printk("\n");
 		/* just reject it */
 		hostdata->msgout[0] = A_REJECT_MSG;
@@ -865,7 +866,7 @@
 
 STATIC __u32
 process_message(struct Scsi_Host *host,	struct NCR_700_Host_Parameters *hostdata,
-		Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps)
+		struct scsi_cmnd *SCp, __u32 dsp, __u32 dsps)
 {
 	/* work out where to return to */
 	__u32 temp = dsp + 8, resume_offset = dsp;
@@ -879,7 +880,7 @@
 #ifdef NCR_700_DEBUG
 	printk("scsi%d (%d:%d): message %s: ", host->host_no, pun, lun,
 	       NCR_700_phase[(dsps & 0xf00) >> 8]);
-	print_msg(hostdata->msgin);
+	scsi_print_msg(hostdata->msgin);
 	printk("\n");
 #endif
 
@@ -927,7 +928,7 @@
 		       host->host_no, pun, lun,
 		       NCR_700_phase[(dsps & 0xf00) >> 8]);
 
-		print_msg(hostdata->msgin);
+		scsi_print_msg(hostdata->msgin);
 		printk("\n");
 		/* just reject it */
 		hostdata->msgout[0] = A_REJECT_MSG;
@@ -946,7 +947,7 @@
 }
 
 STATIC __u32
-process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp,
+process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
 			 struct Scsi_Host *host,
 			 struct NCR_700_Host_Parameters *hostdata)
 {
@@ -975,7 +976,7 @@
 				NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]);
 			} else {
 #ifdef NCR_DEBUG
-				print_command(SCp->cmnd);
+				scsi_print_command(SCp);
 				printk("  cmd %p has status %d, requesting sense\n",
 				       SCp, hostdata->status[0]);
 #endif
@@ -1004,7 +1005,7 @@
 				SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC;
 				SCp->cmnd[7] = hostdata->status[0];
 				SCp->use_sg = 0;
-				SCp->sc_data_direction = SCSI_DATA_READ;
+				SCp->sc_data_direction = DMA_FROM_DEVICE;
 				dma_sync_single_for_device(hostdata->dev, slot->pCmd,
 							   SCp->cmd_len, DMA_TO_DEVICE);
 				SCp->request_bufflen = sizeof(SCp->sense_buffer);
@@ -1053,7 +1054,7 @@
 		       NCR_700_phase[i],
 		       sbcl_to_string(NCR_700_readb(host, SBCL_REG)));
 		printk(KERN_ERR "         len = %d, cmd =", SCp->cmd_len);
-		print_command(SCp->cmnd);
+		scsi_print_command(SCp);
 
 		NCR_700_internal_bus_reset(host);
 	} else if((dsps & 0xfffff000) == A_FATAL) {
@@ -1080,7 +1081,7 @@
 		__u8 lun;
 		struct NCR_700_command_slot *slot;
 		__u8 reselection_id = hostdata->reselection_id;
-		Scsi_Device *SDp;
+		struct scsi_device *SDp;
 
 		lun = hostdata->msgin[0] & 0x1f;
 
@@ -1095,7 +1096,7 @@
 			BUG();
 		}
 		if(hostdata->msgin[1] == A_SIMPLE_TAG_MSG) {
-			Scsi_Cmnd *SCp = scsi_find_tag(SDp, hostdata->msgin[2]);
+			struct scsi_cmnd *SCp = scsi_find_tag(SDp, hostdata->msgin[2]);
 			if(unlikely(SCp == NULL)) {
 				printk(KERN_ERR "scsi%d: (%d:%d) no saved request for tag %d\n", 
 				       host->host_no, reselection_id, lun, hostdata->msgin[2]);
@@ -1107,7 +1108,7 @@
 			       host->host_no, SDp->id, SDp->lun,
 			       hostdata->msgin[2], slot, slot->tag));
 		} else {
-			Scsi_Cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG);
+			struct scsi_cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG);
 			if(unlikely(SCp == NULL)) {
 				printk(KERN_ERR "scsi%d: (%d:%d) no saved request for untagged cmd\n", 
 				       host->host_no, reselection_id, lun);
@@ -1234,7 +1235,7 @@
 		       host->host_no, pun, lun, NCR_700_condition[i],
 		       NCR_700_phase[j], dsp - hostdata->pScript);
 		if(SCp != NULL) {
-			print_command(SCp->cmnd);
+			scsi_print_command(SCp);
 
 			if(SCp->use_sg) {
 				for(i = 0; i < SCp->use_sg + 1; i++) {
@@ -1270,7 +1271,7 @@
 	__u32 resume_offset = 0;
 	struct NCR_700_Host_Parameters *hostdata =
 		(struct NCR_700_Host_Parameters *)host->hostdata[0];
-	Scsi_Cmnd *SCp = hostdata->cmd;
+	struct scsi_cmnd *SCp = hostdata->cmd;
 	__u8 sbcl;
 
 	for(count = 0; count < 5; count++) {
@@ -1373,7 +1374,7 @@
 /* The queue lock with interrupts disabled must be held on entry to
  * this function */
 STATIC int
-NCR_700_start_command(Scsi_Cmnd *SCp)
+NCR_700_start_command(struct scsi_cmnd *SCp)
 {
 	struct NCR_700_command_slot *slot =
 		(struct NCR_700_command_slot *)SCp->host_scribble;
@@ -1481,7 +1482,7 @@
 		__u32 dsps;
 		__u8 sstat0 = 0, dstat = 0;
 		__u32 dsp;
-		Scsi_Cmnd *SCp = hostdata->cmd;
+		struct scsi_cmnd *SCp = hostdata->cmd;
 		enum NCR_700_Host_State state;
 
 		handled = 1;
@@ -1514,7 +1515,7 @@
 		}
 
 		if(sstat0 & SCSI_RESET_DETECTED) {
-			Scsi_Device *SDp;
+			struct scsi_device *SDp;
 			int i;
 
 			hostdata->state = NCR_700_HOST_BUSY;
@@ -1530,7 +1531,7 @@
 			
 			/* clear all the slots and their pending commands */
 			for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) {
-				Scsi_Cmnd *SCp;
+				struct scsi_cmnd *SCp;
 				struct NCR_700_command_slot *slot =
 					&hostdata->slots[i];
 
@@ -1590,7 +1591,7 @@
 				printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x\n",
 				       host->host_no, pun, lun,
 				       SGcount, data_transfer);
-				print_command(SCp->cmnd);
+				scsi_print_command(SCp);
 				if(residual) {
 					printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x, residual %d\n",
 				       host->host_no, pun, lun,
@@ -1731,7 +1732,7 @@
 }
 
 STATIC int
-NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *))
+NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 {
 	struct NCR_700_Host_Parameters *hostdata = 
 		(struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0];
@@ -1781,7 +1782,7 @@
 
 #ifdef NCR_700_DEBUG
 	printk("53c700: scsi%d, command ", SCp->device->host->host_no);
-	print_command(SCp->cmnd);
+	scsi_print_command(SCp);
 #endif
 	if(SCp->device->tagged_supported && !SCp->device->simple_tags
 	   && (hostdata->tag_negotiated &(1<<SCp->device->id)) == 0
@@ -1827,13 +1828,13 @@
 	/* sanity check: some of the commands generated by the mid-layer
 	 * have an eccentric idea of their sc_data_direction */
 	if(!SCp->use_sg && !SCp->request_bufflen 
-	   && SCp->sc_data_direction != SCSI_DATA_NONE) {
+	   && SCp->sc_data_direction != DMA_NONE) {
 #ifdef NCR_700_DEBUG
 		printk("53c700: Command");
-		print_command(SCp->cmnd);
+		scsi_print_command(SCp);
 		printk("Has wrong data direction %d\n", SCp->sc_data_direction);
 #endif
-		SCp->sc_data_direction = SCSI_DATA_NONE;
+		SCp->sc_data_direction = DMA_NONE;
 	}
 
 	switch (SCp->cmnd[0]) {
@@ -1844,20 +1845,20 @@
 	default:
 		/* OK, get it from the command */
 		switch(SCp->sc_data_direction) {
-		case SCSI_DATA_UNKNOWN:
+		case DMA_BIDIRECTIONAL:
 		default:
 			printk(KERN_ERR "53c700: Unknown command for data direction ");
-			print_command(SCp->cmnd);
+			scsi_print_command(SCp);
 			
 			move_ins = 0;
 			break;
-		case SCSI_DATA_NONE:
+		case DMA_NONE:
 			move_ins = 0;
 			break;
-		case SCSI_DATA_READ:
+		case DMA_FROM_DEVICE:
 			move_ins = SCRIPT_MOVE_DATA_IN;
 			break;
-		case SCSI_DATA_WRITE:
+		case DMA_TO_DEVICE:
 			move_ins = SCRIPT_MOVE_DATA_OUT;
 			break;
 		}
@@ -1914,13 +1915,13 @@
 }
 
 STATIC int
-NCR_700_abort(Scsi_Cmnd * SCp)
+NCR_700_abort(struct scsi_cmnd * SCp)
 {
 	struct NCR_700_command_slot *slot;
 
 	printk(KERN_INFO "scsi%d (%d:%d) New error handler wants to abort command\n\t",
 	       SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
-	print_command(SCp->cmnd);
+	scsi_print_command(SCp);
 
 	slot = (struct NCR_700_command_slot *)SCp->host_scribble;
 
@@ -1946,7 +1947,7 @@
 }
 
 STATIC int
-NCR_700_bus_reset(Scsi_Cmnd * SCp)
+NCR_700_bus_reset(struct scsi_cmnd * SCp)
 {
 	DECLARE_COMPLETION(complete);
 	struct NCR_700_Host_Parameters *hostdata = 
@@ -1954,7 +1955,7 @@
 
 	printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t",
 	       SCp->device->host->host_no, SCp->device->id, SCp->device->lun, SCp);
-	print_command(SCp->cmnd);
+	scsi_print_command(SCp);
 	/* In theory, eh_complete should always be null because the
 	 * eh is single threaded, but just in case we're handling a
 	 * reset via sg or something */
@@ -1976,21 +1977,21 @@
 }
 
 STATIC int
-NCR_700_dev_reset(Scsi_Cmnd * SCp)
+NCR_700_dev_reset(struct scsi_cmnd * SCp)
 {
 	printk(KERN_INFO "scsi%d (%d:%d) New error handler wants device reset\n\t",
 	       SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
-	print_command(SCp->cmnd);
+	scsi_print_command(SCp);
 	
 	return FAILED;
 }
 
 STATIC int
-NCR_700_host_reset(Scsi_Cmnd * SCp)
+NCR_700_host_reset(struct scsi_cmnd * SCp)
 {
 	printk(KERN_INFO "scsi%d (%d:%d) New error handler wants HOST reset\n\t",
 	       SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
-	print_command(SCp->cmnd);
+	scsi_print_command(SCp);
 
 	NCR_700_internal_bus_reset(SCp->device->host);
 	NCR_700_chip_reset(SCp->device->host);
@@ -2043,7 +2044,7 @@
 
 
 STATIC int
-NCR_700_slave_configure(Scsi_Device *SDp)
+NCR_700_slave_configure(struct scsi_device *SDp)
 {
 	struct NCR_700_Host_Parameters *hostdata = 
 		(struct NCR_700_Host_Parameters *)SDp->host->hostdata[0];
@@ -2066,7 +2067,7 @@
 }
 
 STATIC void
-NCR_700_slave_destroy(Scsi_Device *SDp)
+NCR_700_slave_destroy(struct scsi_device *SDp)
 {
 	/* to do here: deallocate memory */
 }
diff -Nru a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
--- a/drivers/scsi/53c700.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/53c700.h	2004-06-23 19:04:25 -07:00
@@ -9,9 +9,11 @@
 #define _53C700_H
 
 #include <linux/interrupt.h>
-
 #include <asm/io.h>
 
+#include <scsi/scsi_device.h>
+
+
 #if defined(CONFIG_53C700_MEM_MAPPED) && defined(CONFIG_53C700_IO_MAPPED)
 #define CONFIG_53C700_BOTH_MAPPED
 #endif
@@ -57,7 +59,8 @@
 struct NCR_700_Host_Parameters;
 
 /* These are the externally used routines */
-struct Scsi_Host *NCR_700_detect(Scsi_Host_Template *, struct NCR_700_Host_Parameters *);
+struct Scsi_Host *NCR_700_detect(struct scsi_host_template *,
+		struct NCR_700_Host_Parameters *);
 int NCR_700_release(struct Scsi_Host *host);
 irqreturn_t NCR_700_intr(int, void *, struct pt_regs *);
 
@@ -102,7 +105,7 @@
 #define NCR_700_DEV_PRINT_SYNC_NEGOTIATION (1<<19)
 
 static inline void
-NCR_700_set_depth(Scsi_Device *SDp, __u8 depth)
+NCR_700_set_depth(struct scsi_device *SDp, __u8 depth)
 {
 	long l = (long)SDp->hostdata;
 
@@ -111,27 +114,27 @@
 	SDp->hostdata = (void *)l;
 }
 static inline __u8
-NCR_700_get_depth(Scsi_Device *SDp)
+NCR_700_get_depth(struct scsi_device *SDp)
 {
 	return ((((unsigned long)SDp->hostdata) & 0xff00)>>8);
 }
 static inline int
-NCR_700_is_flag_set(Scsi_Device *SDp, __u32 flag)
+NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag)
 {
 	return (((unsigned long)SDp->hostdata) & flag) == flag;
 }
 static inline int
-NCR_700_is_flag_clear(Scsi_Device *SDp, __u32 flag)
+NCR_700_is_flag_clear(struct scsi_device *SDp, __u32 flag)
 {
 	return (((unsigned long)SDp->hostdata) & flag) == 0;
 }
 static inline void
-NCR_700_set_flag(Scsi_Device *SDp, __u32 flag)
+NCR_700_set_flag(struct scsi_device *SDp, __u32 flag)
 {
 	SDp->hostdata = (void *)((long)SDp->hostdata | (flag & 0xffff0000));
 }
 static inline void
-NCR_700_clear_flag(Scsi_Device *SDp, __u32 flag)
+NCR_700_clear_flag(struct scsi_device *SDp, __u32 flag)
 {
 	SDp->hostdata = (void *)((long)SDp->hostdata & ~(flag & 0xffff0000));
 }
@@ -147,7 +150,7 @@
 	__u8	state;
 	int	tag;
 	__u32	resume_offset;
-	Scsi_Cmnd	*cmnd;
+	struct scsi_cmnd *cmnd;
 	/* The pci_mapped address of the actual command in cmnd */
 	dma_addr_t	pCmd;
 	__u32		temp;
@@ -185,7 +188,7 @@
 	__u32	pScript;		/* physical mem addr of script */
 
 	enum NCR_700_Host_State state; /* protected by state lock */
-	Scsi_Cmnd *cmd;
+	struct scsi_cmnd *cmd;
 	/* Note: pScript contains the single consistent block of
 	 * memory.  All the msgin, msgout and status are allocated in
 	 * this memory too (at separate cache lines).  TOTAL_MEM_SIZE
diff -Nru a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
--- a/drivers/scsi/53c7xx.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/53c7xx.c	2004-06-23 19:04:29 -07:00
@@ -280,7 +280,7 @@
 #endif
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "53c7xx.h"
 #include <linux/stat.h>
 #include <linux/stddef.h>
diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
--- a/drivers/scsi/BusLogic.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/BusLogic.c	2004-06-23 19:04:28 -07:00
@@ -48,7 +48,7 @@
 #include <asm/system.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "BusLogic.h"
 #include "FlashPoint.c"
 
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/Kconfig	2004-06-23 19:04:28 -07:00
@@ -227,7 +227,7 @@
 	depends on DECSTATION && SCSI
 
 config BLK_DEV_3W_XXXX_RAID
-	tristate "3ware Hardware ATA-RAID support"
+	tristate "3ware 5/6/7/8xxx ATA-RAID support"
 	depends on PCI && SCSI
 	help
 	  3ware is the only hardware ATA-Raid product in Linux to date.
@@ -239,6 +239,17 @@
 	  Please read the comments at the top of
 	  <file:drivers/scsi/3w-xxxx.c>.
 
+config SCSI_3W_9XXX
+	tristate "3ware 9xxx SATA-RAID support"
+	depends on PCI && SCSI
+	help
+	  This driver supports the 9000 series 3ware SATA-RAID cards.
+
+	  <http://www.amcc.com>
+
+	  Please read the comments at the top of
+	  <file:drivers/scsi/3w-9xxx.c>.
+
 config SCSI_7000FASST
 	tristate "7000FASST SCSI support"
 	depends on ISA && SCSI
@@ -422,6 +433,14 @@
 
 	  If unsure, say N.
 
+config SCSI_SATA_NV
+	tristate "NVIDIA SATA support"
+	depends on SCSI_SATA && PCI && EXPERIMENTAL
+	help
+	  This option enables support for NVIDIA Serial ATA.
+
+	  If unsure, say N.
+
 config SCSI_SATA_PROMISE
 	tristate "Promise SATA TX2/TX4 support"
 	depends on SCSI_SATA && PCI
@@ -478,9 +497,7 @@
 	  Adapters. Consult the SCSI-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>, and the files
 	  <file:Documentation/scsi/BusLogic.txt> and
-	  <file:Documentation/scsi/FlashPoint.txt> for more information. If this
-	  driver does not work correctly without modification, please contact
-	  the author, Leonard N. Zubkoff, by email to lnz@dandelion.com.
+	  <file:Documentation/scsi/FlashPoint.txt> for more information.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called BusLogic.
@@ -1715,18 +1732,6 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called esp.
-
-config SCSI_PC980155
-	tristate "NEC PC-9801-55 SCSI support"
-	depends on X86_PC9800 && SCSI
-	help
-	  If you have the NEC PC-9801-55 SCSI interface card or compatibles
-	  for NEC PC-9801/PC-9821, say Y.
-
-config WD33C93_PIO
-	bool
-	depends on SCSI_PC980155
-	default y
 
 #      bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI
 
diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/Makefile	2004-06-23 19:04:28 -07:00
@@ -34,7 +34,6 @@
 obj-$(CONFIG_A3000_SCSI)	+= a3000.o	wd33c93.o
 obj-$(CONFIG_A2091_SCSI)	+= a2091.o	wd33c93.o
 obj-$(CONFIG_GVP11_SCSI)	+= gvp11.o	wd33c93.o
-obj-$(CONFIG_SCSI_PC980155)	+= pc980155.o	wd33c93.o
 obj-$(CONFIG_MVME147_SCSI)	+= mvme147.o	wd33c93.o
 obj-$(CONFIG_SGIWD93_SCSI)	+= sgiwd93.o	wd33c93.o
 obj-$(CONFIG_CYBERSTORM_SCSI)	+= NCR53C9x.o	cyberstorm.o
@@ -109,6 +108,7 @@
 obj-$(CONFIG_SCSI_PLUTO)	+= pluto.o
 obj-$(CONFIG_SCSI_DECNCR)	+= NCR53C9x.o	dec_esp.o
 obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
+obj-$(CONFIG_SCSI_3W_9XXX)	+= 3w-9xxx.o
 obj-$(CONFIG_SCSI_PPA)		+= ppa.o
 obj-$(CONFIG_SCSI_IMM)		+= imm.o
 obj-$(CONFIG_JAZZ_ESP)		+= NCR53C9x.o	jazz_esp.o
@@ -127,6 +127,7 @@
 obj-$(CONFIG_SCSI_SATA_VITESSE)	+= libata.o sata_vsc.o
 obj-$(CONFIG_SCSI_SATA_SIS)	+= libata.o sata_sis.o
 obj-$(CONFIG_SCSI_SATA_SX4)	+= libata.o sata_sx4.o
+obj-$(CONFIG_SCSI_SATA_NV)	+= libata.o sata_nv.o
 
 obj-$(CONFIG_ARM)		+= arm/
 
@@ -142,7 +143,6 @@
 				   scsi_devinfo.o
 scsi_mod-$(CONFIG_SYSCTL)	+= scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
-scsi_mod-$(CONFIG_X86_PC9800)	+= scsi_pc98.o
 
 sd_mod-objs	:= sd.o
 sr_mod-objs	:= sr.o sr_ioctl.o sr_vendor.o
diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
--- a/drivers/scsi/NCR53C9x.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/NCR53C9x.c	2004-06-23 19:04:26 -07:00
@@ -36,7 +36,7 @@
 #include <linux/init.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <asm/system.h>
@@ -3645,5 +3645,16 @@
 	esps_running = esps_in_use;
 }
 #endif
+
+EXPORT_SYMBOL(esp_abort);
+EXPORT_SYMBOL(esp_allocate);
+EXPORT_SYMBOL(esp_deallocate);
+EXPORT_SYMBOL(esp_initialize);
+EXPORT_SYMBOL(esp_intr);
+EXPORT_SYMBOL(esp_queue);
+EXPORT_SYMBOL(esp_reset);
+EXPORT_SYMBOL(esp_slave_alloc);
+EXPORT_SYMBOL(esp_slave_destroy);
+EXPORT_SYMBOL(esps_in_use);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
--- a/drivers/scsi/NCR53c406a.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/NCR53c406a.c	2004-06-23 19:04:27 -07:00
@@ -54,7 +54,7 @@
 #include <linux/blkdev.h>
 #include <linux/spinlock.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 /* ============================================================= */
 
diff -Nru a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
--- a/drivers/scsi/NCR_D700.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/NCR_D700.c	2004-06-23 19:04:25 -07:00
@@ -98,9 +98,7 @@
 #include <linux/module.h>
 #include <linux/mca.h>
 #include <asm/io.h>
-
-#include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "53c700.h"
 #include "NCR_D700.h"
@@ -156,7 +154,7 @@
 
 /* Host template.  The 53c700 routine NCR_700_detect will
  * fill in all of the missing routines */
-static Scsi_Host_Template NCR_D700_driver_template = {
+static struct scsi_host_template NCR_D700_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= "NCR Dual 700 MCA",
 	.proc_name		= "NCR_D700",
diff -Nru a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c
--- a/drivers/scsi/NCR_Q720.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/NCR_Q720.c	2004-06-23 19:04:25 -07:00
@@ -16,7 +16,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "ncr53c8xx.h"
 
diff -Nru a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
--- a/drivers/scsi/a2091.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/a2091.c	2004-06-23 19:04:27 -07:00
@@ -16,7 +16,7 @@
 #include <linux/spinlock.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "wd33c93.h"
 #include "a2091.h"
 
diff -Nru a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
--- a/drivers/scsi/a3000.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/a3000.c	2004-06-23 19:04:28 -07:00
@@ -15,7 +15,7 @@
 #include <asm/irq.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "wd33c93.h"
 #include "a3000.h"
 
diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
--- a/drivers/scsi/advansys.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/advansys.c	2004-06-23 19:04:26 -07:00
@@ -756,27 +756,6 @@
 
 */
 
-
-/*
- * --- Linux Version
- */
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif /* LINUX_VERSION_CODE */
-
-/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */
-#define ASC_LINUX_VERSION(V, P, S)    (((V) * 65536) + ((P) * 256) + (S))
-#define ASC_LINUX_KERNEL22 (LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0))
-#define ASC_LINUX_KERNEL24 (LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,4,0))
-
-/* Driver supported only in version 2.2 and version >= 2.4. */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,2,0) || \
-    (LINUX_VERSION_CODE > ASC_LINUX_VERSION(2,3,0) && \
-     LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0))
-#error "AdvanSys driver supported only in 2.2 and 2.4 or greater kernels."
-#endif
-
 /*
  * --- Linux Include Files
  */
@@ -801,13 +780,14 @@
 #include <linux/blkdev.h>
 #include <linux/stat.h>
 #include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/dma.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "advansys.h"
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
@@ -874,9 +854,6 @@
 
 typedef unsigned char uchar;
 
-#ifndef NULL
-#define NULL     (0)
-#endif
 #ifndef TRUE
 #define TRUE     (1)
 #endif
@@ -986,49 +963,6 @@
 #define ASC_MIN_SENSE_LEN   14
 #define ASC_MAX_CDB_LEN     12
 #define ASC_SCSI_RESET_HOLD_TIME_US  60
-#define SCSICMD_TestUnitReady     0x00
-#define SCSICMD_Rewind            0x01
-#define SCSICMD_Rezero            0x01
-#define SCSICMD_RequestSense      0x03
-#define SCSICMD_Format            0x04
-#define SCSICMD_FormatUnit        0x04
-#define SCSICMD_Read6             0x08
-#define SCSICMD_Write6            0x0A
-#define SCSICMD_Seek6             0x0B
-#define SCSICMD_Inquiry           0x12
-#define SCSICMD_Verify6           0x13
-#define SCSICMD_ModeSelect6       0x15
-#define SCSICMD_ModeSense6        0x1A
-#define SCSICMD_StartStopUnit     0x1B
-#define SCSICMD_LoadUnloadTape    0x1B
-#define SCSICMD_ReadCapacity      0x25
-#define SCSICMD_Read10            0x28
-#define SCSICMD_Write10           0x2A
-#define SCSICMD_Seek10            0x2B
-#define SCSICMD_Erase10           0x2C
-#define SCSICMD_WriteAndVerify10  0x2E
-#define SCSICMD_Verify10          0x2F
-#define SCSICMD_WriteBuffer       0x3B
-#define SCSICMD_ReadBuffer        0x3C
-#define SCSICMD_ReadLong          0x3E
-#define SCSICMD_WriteLong         0x3F
-#define SCSICMD_ReadTOC           0x43
-#define SCSICMD_ReadHeader        0x44
-#define SCSICMD_ModeSelect10      0x55
-#define SCSICMD_ModeSense10       0x5A
-
-/* Inquiry Data Peripheral Device Types */
-#define SCSI_TYPE_DASD     0x00
-#define SCSI_TYPE_SASD     0x01
-#define SCSI_TYPE_PRN      0x02
-#define SCSI_TYPE_PROC     0x03
-#define SCSI_TYPE_WORM     0x04
-#define SCSI_TYPE_CDROM    0x05
-#define SCSI_TYPE_SCANNER  0x06
-#define SCSI_TYPE_OPTMEM   0x07
-#define SCSI_TYPE_MED_CHG  0x08
-#define SCSI_TYPE_COMM     0x09
-#define SCSI_TYPE_UNKNOWN  0x1F
 
 #define ADV_INQ_CLOCKING_ST_ONLY    0x0
 #define ADV_INQ_CLOCKING_DT_ONLY    0x1
@@ -1047,36 +981,11 @@
 #define ASC_SCSIDIR_T2H      0x08
 #define ASC_SCSIDIR_H2T      0x10
 #define ASC_SCSIDIR_NODATA   0x18
-#define SCSI_SENKEY_NO_SENSE      0x00
-#define SCSI_SENKEY_UNDEFINED     0x01
-#define SCSI_SENKEY_NOT_READY     0x02
-#define SCSI_SENKEY_MEDIUM_ERR    0x03
-#define SCSI_SENKEY_HW_ERR        0x04
-#define SCSI_SENKEY_ILLEGAL       0x05
-#define SCSI_SENKEY_ATTENTION     0x06
-#define SCSI_SENKEY_PROTECTED     0x07
-#define SCSI_SENKEY_BLANK         0x08
-#define SCSI_SENKEY_V_UNIQUE      0x09
-#define SCSI_SENKEY_CPY_ABORT     0x0A
-#define SCSI_SENKEY_ABORT         0x0B
-#define SCSI_SENKEY_EQUAL         0x0C
-#define SCSI_SENKEY_VOL_OVERFLOW  0x0D
-#define SCSI_SENKEY_MISCOMP       0x0E
-#define SCSI_SENKEY_RESERVED      0x0F
 #define SCSI_ASC_NOMEDIA          0x3A
 #define ASC_SRB_HOST(x)  ((uchar)((uchar)(x) >> 4))
 #define ASC_SRB_TID(x)   ((uchar)((uchar)(x) & (uchar)0x0F))
 #define ASC_SRB_LUN(x)   ((uchar)((uint)(x) >> 13))
 #define PUT_CDB1(x)   ((uchar)((uint)(x) >> 8))
-#define SS_GOOD              0x00
-#define SS_CHK_CONDITION     0x02
-#define SS_CONDITION_MET     0x04
-#define SS_TARGET_BUSY       0x08
-#define SS_INTERMID          0x10
-#define SS_INTERMID_COND_MET 0x14
-#define SS_RSERV_CONFLICT    0x18
-#define SS_CMD_TERMINATED    0x22
-#define SS_QUEUE_FULL        0x28
 #define MS_CMD_DONE    0x00
 #define MS_EXTEND      0x01
 #define MS_SDTR_LEN    0x03
@@ -1085,26 +994,6 @@
 #define MS_WDTR_CODE   0x03
 #define MS_MDP_LEN    0x05
 #define MS_MDP_CODE   0x00
-#define M1_SAVE_DATA_PTR        0x02
-#define M1_RESTORE_PTRS         0x03
-#define M1_DISCONNECT           0x04
-#define M1_INIT_DETECTED_ERR    0x05
-#define M1_ABORT                0x06
-#define M1_MSG_REJECT           0x07
-#define M1_NO_OP                0x08
-#define M1_MSG_PARITY_ERR       0x09
-#define M1_LINK_CMD_DONE        0x0A
-#define M1_LINK_CMD_DONE_WFLAG  0x0B
-#define M1_BUS_DVC_RESET        0x0C
-#define M1_ABORT_TAG            0x0D
-#define M1_CLR_QUEUE            0x0E
-#define M1_INIT_RECOVERY        0x0F
-#define M1_RELEASE_RECOVERY     0x10
-#define M1_KILL_IO_PROC         0x11
-#define M2_QTAG_MSG_SIMPLE      0x20
-#define M2_QTAG_MSG_HEAD        0x21
-#define M2_QTAG_MSG_ORDERED     0x22
-#define M2_IGNORE_WIDE_RESIDUE  0x23
 
 /*
  * Inquiry data structure and bitfield macros
@@ -1576,7 +1465,7 @@
     uchar               sdtr_period_offset[ASC_MAX_TID + 1];
     ushort              pci_slot_info;
     uchar               adapter_info[6];
-    struct pci_dev	*pci_dev;
+    struct device	*dev;
 } ASC_DVC_CFG;
 
 #define ASC_DEF_DVC_CNTL       0xFFFF
@@ -3082,7 +2971,7 @@
   ushort serial1;           /* EEPROM serial number word 1 */
   ushort serial2;           /* EEPROM serial number word 2 */
   ushort serial3;           /* EEPROM serial number word 3 */
-  struct pci_dev *pci_dev;  /* pointer to the pci dev structure for this board */
+  struct device *dev;  /* pointer to the pci dev structure for this board */
 } ADV_DVC_CFG;
 
 struct adv_dvc_var;
@@ -3581,19 +3470,6 @@
 
 #define NO_ISA_DMA              0xff        /* No ISA DMA Channel Used */
 
-/*
- * If the Linux kernel version supports freeing initialization code
- * and data after loading, define macros for this purpose. These macros
- * are not used when the driver is built as a module, cf. linux/init.h.
- */
-#if ASC_LINUX_KERNEL24
-#define ASC_INITFUNC(type, func)        type __init func
-#elif ASC_LINUX_KERNEL22
-#define ASC_INITFUNC(type, func)        __initfunc(type func)
-#endif
-#define ASC_INITDATA                    __initdata
-#define ASC_INIT                        __init
-
 #define ASC_INFO_SIZE           128            /* advansys_info() line size */
 
 #ifdef CONFIG_PROC_FS
@@ -3610,8 +3486,6 @@
         } \
         cp += len; \
     }
-
-#define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
 #endif /* CONFIG_PROC_FS */
 
 /* Asc Library return codes */
@@ -3685,53 +3559,6 @@
 /* Return non-zero, if the queue is empty. */
 #define ASC_QUEUE_EMPTY(ascq)    ((ascq)->q_tidmask == 0)
 
-/* PCI configuration declarations */
-
-#define PCI_BASE_CLASS_PREDEFINED               0x00
-#define PCI_BASE_CLASS_MASS_STORAGE             0x01
-#define PCI_BASE_CLASS_NETWORK                  0x02
-#define PCI_BASE_CLASS_DISPLAY                  0x03
-#define PCI_BASE_CLASS_MULTIMEDIA               0x04
-#define PCI_BASE_CLASS_MEMORY_CONTROLLER        0x05
-#define PCI_BASE_CLASS_BRIDGE_DEVICE            0x06
-
-/* MASS STORAGE */
-#define PCI_SUB_CLASS_SCSI_CONTROLLER           0x00
-#define PCI_SUB_CLASS_IDE_CONTROLLER            0x01
-#define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER    0x02
-#define PCI_SUB_CLASS_IPI_BUS_CONTROLLER        0x03
-#define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER     0x80
-
-/* NETWORK CONTROLLER */
-#define PCI_SUB_CLASS_ETHERNET_CONTROLLER       0x00
-#define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER     0x01
-#define PCI_SUB_CLASS_FDDI_CONTROLLER           0x02
-#define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER  0x80
-
-/* DISPLAY CONTROLLER */
-#define PCI_SUB_CLASS_VGA_CONTROLLER            0x00
-#define PCI_SUB_CLASS_XGA_CONTROLLER            0x01
-#define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER  0x80
-
-/* MULTIMEDIA CONTROLLER */
-#define PCI_SUB_CLASS_VIDEO_DEVICE              0x00
-#define PCI_SUB_CLASS_AUDIO_DEVICE              0x01
-#define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE   0x80
-
-/* MEMORY CONTROLLER */
-#define PCI_SUB_CLASS_RAM_CONTROLLER            0x00
-#define PCI_SUB_CLASS_FLASH_CONTROLLER          0x01
-#define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER   0x80
-
-/* BRIDGE CONTROLLER */
-#define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER    0x00
-#define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER     0x01
-#define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER    0x02
-#define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER      0x03
-#define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER    0x04
-#define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER  0x05
-#define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER   0x80
-
 #define PCI_MAX_SLOT            0x1F
 #define PCI_MAX_BUS             0xFF
 #define PCI_IOADDRESS_MASK      0xFFFE
@@ -3744,25 +3571,6 @@
 #define ASC_PCI_DEVICE_ID_2500  0x2500  /* ASC-38C0800 */
 #define ASC_PCI_DEVICE_ID_2700  0x2700  /* ASC-38C1600 */
 
-/* PCI IO Port Addresses to generate special cycle */
-
-#define PCI_CONFIG_ADDRESS_MECH1          0x0CF8
-#define PCI_CONFIG_DATA_MECH1             0x0CFC
-
-#define PCI_CONFIG_FORWARD_REGISTER       0x0CFA    /* 0=type 0; 1=type 1; */
-
-#define PCI_CONFIG_BUS_NUMBER_MASK        0x00FF0000
-#define PCI_CONFIG_DEVICE_FUNCTION_MASK   0x0000FF00
-#define PCI_CONFIG_REGISTER_NUMBER_MASK   0x000000F8
-
-#define PCI_DEVICE_FOUND                0x0000
-#define PCI_DEVICE_NOT_FOUND            0xffff
-
-#define SUBCLASS_OFFSET         0x0A
-#define CLASSCODE_OFFSET        0x0B
-#define VENDORID_OFFSET         0x00
-#define DEVICEID_OFFSET         0x02
-
 #ifndef ADVANSYS_STATS
 #define ASC_STATS(shp, counter)
 #define ASC_STATS_ADD(shp, counter, count)
@@ -4145,19 +3953,6 @@
 
 /* Note: All driver global data should be initialized. */
 
-#if ASC_LINUX_KERNEL22
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry proc_scsi_advansys =
-{
-    PROC_SCSI_ADVANSYS,              /* unsigned short low_ino */
-    8,                               /* unsigned short namelen */
-    "advansys",                      /* const char *name */
-    S_IFDIR | S_IRUGO | S_IXUGO,     /* mode_t mode */
-    2                                /* nlink_t nlink */
-};
-#endif /* CONFIG_PROC_FS */
-#endif /* ASC_LINUX_KERNEL22 */
-
 /* Number of boards detected in system. */
 STATIC int asc_board_count = 0;
 STATIC struct Scsi_Host    *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
@@ -4172,7 +3967,7 @@
 STATIC ASC_SG_HEAD asc_sg_head = { 0 };
 
 /* List of supported bus types. */
-STATIC ushort asc_bus[ASC_NUM_BUS] ASC_INITDATA = {
+STATIC ushort asc_bus[ASC_NUM_BUS] __initdata = {
     ASC_IS_ISA,
     ASC_IS_VL,
     ASC_IS_EISA,
@@ -4210,11 +4005,11 @@
 
 STATIC irqreturn_t advansys_interrupt(int, void *, struct pt_regs *);
 STATIC int	  advansys_slave_configure(Scsi_Device *);
-STATIC void       asc_scsi_done_list(Scsi_Cmnd *, int from_isr);
+STATIC void       asc_scsi_done_list(Scsi_Cmnd *);
 STATIC int        asc_execute_scsi_cmnd(Scsi_Cmnd *);
 STATIC int        asc_build_req(asc_board_t *, Scsi_Cmnd *);
 STATIC int        adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **);
-STATIC int        adv_get_sglist(asc_board_t *, adv_req_t *, Scsi_Cmnd *);
+STATIC int        adv_get_sglist(asc_board_t *, adv_req_t *, Scsi_Cmnd *, int);
 STATIC void       asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
 STATIC void       adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
 STATIC void       adv_async_callback(ADV_DVC_VAR *, uchar);
@@ -4505,10 +4300,8 @@
  * it must not call SCSI mid-level functions including scsi_malloc()
  * and scsi_free().
  */
-ASC_INITFUNC(
-int,
+int __init
 advansys_detect(Scsi_Host_Template *tpnt)
-)
 {
     static int          detect_called = ASC_FALSE;
     int                 iop;
@@ -4526,6 +4319,7 @@
     struct pci_dev      *pci_devicep[ASC_NUM_BOARD_SUPPORTED];
     int                 pci_card_cnt_max = 0;
     int                 pci_card_cnt = 0;
+    struct device	*dev = NULL;
     struct pci_dev      *pci_devp = NULL;
     int                 pci_device_id_cnt = 0;
     unsigned int        pci_device_id[ASC_PCI_DEVICE_ID_CNT] = {
@@ -4550,12 +4344,6 @@
 
     ASC_DBG(1, "advansys_detect: begin\n");
 
-#if ASC_LINUX_KERNEL24
-    tpnt->proc_name = "advansys";
-#elif ASC_LINUX_KERNEL22
-    tpnt->proc_dir = &proc_scsi_advansys;
-#endif
-
     asc_board_count = 0;
 
     /*
@@ -4681,13 +4469,9 @@
                             NULL) {
                             pci_device_id_cnt++;
                         } else {
-#if ASC_LINUX_KERNEL24
                             if (pci_enable_device(pci_devp) == 0) {
                                 pci_devicep[pci_card_cnt_max++] = pci_devp;
                             }
-#elif ASC_LINUX_KERNEL22
-                            pci_devicep[pci_card_cnt_max++] = pci_devp;
-#endif
                         }
                     }
 
@@ -4724,17 +4508,16 @@
                     ASC_DBG2(2,
                         "advansys_detect: devfn %d, bus number %d\n",
                         pci_devp->devfn, pci_devp->bus->number);
-#if ASC_LINUX_KERNEL24
                     iop = pci_resource_start(pci_devp, 0);
-#elif ASC_LINUX_KERNEL22
-                    iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK;
-#endif
                     ASC_DBG2(1,
                         "advansys_detect: vendorID %X, deviceID %X\n",
                         pci_devp->vendor, pci_devp->device);
                     ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
                         iop, pci_devp->irq);
                 }
+		if(pci_devp)
+		    dev = &pci_devp->dev;
+
 #endif /* CONFIG_PCI */
                 break;
 
@@ -4765,7 +4548,7 @@
                 continue;
             }
 
-	    scsi_set_device(shp, &pci_devp->dev);
+	    scsi_set_device(shp, dev);
 
             /* Save a pointer to the Scsi_Host of each board found. */
             asc_host[asc_board_count++] = shp;
@@ -4849,11 +4632,7 @@
                     iolen = ADV_38C1600_IOLEN;
                 }
 #ifdef CONFIG_PCI
-#if ASC_LINUX_KERNEL24
                 pci_memory_address = pci_resource_start(pci_devp, 1);
-#elif ASC_LINUX_KERNEL22
-                pci_memory_address = pci_devp->base_address[1];
-#endif
                 ASC_DBG1(1, "advansys_detect: pci_memory_address: 0x%lx\n",
                     (ulong) pci_memory_address);
                 if ((boardp->ioremap_addr =
@@ -4904,7 +4683,8 @@
 #endif /* CONFIG_PROC_FS */
 
             if (ASC_NARROW_BOARD(boardp)) {
-                /*
+		asc_dvc_varp->cfg->dev = dev;
+		/*
                  * Set the board bus type and PCI IRQ before
                  * calling AscInitGetConfig().
                  */
@@ -4926,7 +4706,6 @@
 #ifdef CONFIG_PCI
                 case ASC_IS_PCI:
                     shp->irq = asc_dvc_varp->irq_no = pci_devp->irq;
-                    asc_dvc_varp->cfg->pci_dev = pci_devp;
                     asc_dvc_varp->cfg->pci_slot_info =
                         ASC_PCI_MKID(pci_devp->bus->number,
                             PCI_SLOT(pci_devp->devfn),
@@ -4944,13 +4723,13 @@
                     break;
                 }
             } else {
+                adv_dvc_varp->cfg->dev = dev;
                 /*
                  * For Wide boards set PCI information before calling
                  * AdvInitGetConfig().
                  */
 #ifdef CONFIG_PCI
                 shp->irq = adv_dvc_varp->irq_no = pci_devp->irq;
-                adv_dvc_varp->cfg->pci_dev = pci_devp;
                 adv_dvc_varp->cfg->pci_slot_info =
                     ASC_PCI_MKID(pci_devp->bus->number,
                         PCI_SLOT(pci_devp->devfn),
@@ -5321,11 +5100,7 @@
 
             /* BIOS start address. */
             if (ASC_NARROW_BOARD(boardp)) {
-#if ASC_LINUX_KERNEL24
                 shp->base =
-#elif ASC_LINUX_KERNEL22
-                shp->base = (char *)
-#endif
                         ((ulong) AscGetChipBiosAddress(
                             asc_dvc_varp->iop_base,
                             asc_dvc_varp->bus_type));
@@ -5360,11 +5135,7 @@
                      * Convert x86 realmode code segment to a linear
                      * address by shifting left 4.
                      */
-                    shp->base =
-#if ASC_LINUX_KERNEL22
-                        (char *)
-#endif
-                        ((ulong) boardp->bios_codeseg << 4);
+                    shp->base = ((ulong) boardp->bios_codeseg << 4);
                 } else {
                     shp->base = 0;
                 }
@@ -5385,7 +5156,6 @@
             ASC_DBG2(2,
                 "advansys_detect: request_region port 0x%lx, len 0x%x\n",
                 (ulong) shp->io_port, boardp->asc_n_io_port);
-#if ASC_LINUX_KERNEL24
             if (request_region(shp->io_port, boardp->asc_n_io_port,
                                "advansys") == NULL) {
                 ASC_PRINT3(
@@ -5398,9 +5168,6 @@
                 asc_board_count--;
                 continue;
             }
-#elif ASC_LINUX_KERNEL22
-            request_region(shp->io_port, boardp->asc_n_io_port, "advansys");
-#endif
 
             /* Register DMA Channel for Narrow boards. */
             shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
@@ -5880,7 +5647,7 @@
     default:
         done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
         /* Interrupts could be enabled here. */
-        asc_scsi_done_list(done_scp, 0);
+        asc_scsi_done_list(done_scp);
         break;
     }
     spin_unlock_irqrestore(&boardp->lock, flags);
@@ -6063,7 +5830,7 @@
      * Complete all the 'done_scp' requests.
      */
     if (done_scp != NULL) {
-        asc_scsi_done_list(done_scp, 0);
+        asc_scsi_done_list(done_scp);
     }
 
     ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
@@ -6149,10 +5916,8 @@
  * ints[2] - second argument
  * ...
  */
-ASC_INITFUNC(
-void,
+void __init
 advansys_setup(char *str, int *ints)
-)
 {
     int    i;
 
@@ -6328,7 +6093,7 @@
      * Complete all requests on the done list.
      */
 
-    asc_scsi_done_list(done_scp, 1);
+    asc_scsi_done_list(done_scp);
 
     ASC_DBG(1, "advansys_interrupt: end\n");
     return IRQ_HANDLED;
@@ -6374,23 +6139,38 @@
  * Interrupts can be enabled on entry.
  */
 STATIC void
-asc_scsi_done_list(Scsi_Cmnd *scp, int from_isr)
+asc_scsi_done_list(Scsi_Cmnd *scp)
 {
     Scsi_Cmnd    *tscp;
-    ulong	  flags = 0;
 
     ASC_DBG(2, "asc_scsi_done_list: begin\n");
     while (scp != NULL) {
+	asc_board_t *boardp;
+	struct device *dev;
+
         ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong) scp);
         tscp = REQPNEXT(scp);
         scp->host_scribble = NULL;
+
+	boardp = ASC_BOARDP(scp->device->host);
+
+	if (ASC_NARROW_BOARD(boardp))
+	    dev = boardp->dvc_cfg.asc_dvc_cfg.dev;
+	else
+	    dev = boardp->dvc_cfg.adv_dvc_cfg.dev;
+
+	if (scp->use_sg)
+	    dma_unmap_sg(dev, (struct scatterlist *)scp->request_buffer,
+			 scp->use_sg, scp->sc_data_direction);
+	else if (scp->request_bufflen)
+	    dma_unmap_single(dev, scp->SCp.dma_handle,
+			     scp->request_bufflen, scp->sc_data_direction);
+
         ASC_STATS(scp->device->host, done);
         ASC_ASSERT(scp->scsi_done != NULL);
-	if (from_isr)
-	    spin_lock_irqsave(scp->device->host->host_lock, flags);
+
         scp->scsi_done(scp);
-	if (from_isr)
-	    spin_unlock_irqrestore(scp->device->host->host_lock, flags);
+
         scp = tscp;
     }
     ASC_DBG(2, "asc_scsi_done_list: done\n");
@@ -6619,6 +6399,8 @@
 STATIC int
 asc_build_req(asc_board_t *boardp, Scsi_Cmnd *scp)
 {
+    struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev;
+
     /*
      * Mutually exclusive access is required to 'asc_scsi_q' and
      * 'asc_sg_head' until after the request is started.
@@ -6665,9 +6447,9 @@
      */
     if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
         (boardp->reqcnt[scp->device->id] % 255) == 0) {
-        asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
+        asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
     } else {
-        asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
+        asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
     }
 
     /*
@@ -6679,8 +6461,10 @@
          * CDB request of single contiguous buffer.
          */
         ASC_STATS(scp->device->host, cont_cnt);
-        asc_scsi_q.q1.data_addr =
-            cpu_to_le32(virt_to_bus(scp->request_buffer));
+	scp->SCp.dma_handle = scp->request_bufflen ?
+	    dma_map_single(dev, scp->request_buffer,
+			   scp->request_bufflen, scp->sc_data_direction) : 0;
+	asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
         asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
         ASC_STATS_ADD(scp->device->host, cont_xfer,
                       ASC_CEILING(scp->request_bufflen, 512));
@@ -6691,12 +6475,17 @@
          * CDB scatter-gather request list.
          */
         int                     sgcnt;
+	int			use_sg;
         struct scatterlist      *slp;
 
-        if (scp->use_sg > scp->device->host->sg_tablesize) {
+	slp = (struct scatterlist *)scp->request_buffer;
+	use_sg = dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
+
+	if (use_sg > scp->device->host->sg_tablesize) {
             ASC_PRINT3(
 "asc_build_req: board %d: use_sg %d > sg_tablesize %d\n",
-                boardp->id, scp->use_sg, scp->device->host->sg_tablesize);
+		boardp->id, use_sg, scp->device->host->sg_tablesize);
+	    dma_unmap_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
             scp->result = HOST_BYTE(DID_ERROR);
             asc_enqueue(&boardp->done, scp, ASC_BACK);
             return ASC_ERROR;
@@ -6715,19 +6504,16 @@
         asc_scsi_q.q1.data_cnt = 0;
         asc_scsi_q.q1.data_addr = 0;
         /* This is a byte value, otherwise it would need to be swapped. */
-        asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg;
+	asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
         ASC_STATS_ADD(scp->device->host, sg_elem, asc_sg_head.entry_cnt);
 
         /*
          * Convert scatter-gather list into ASC_SG_HEAD list.
          */
-        slp = (struct scatterlist *) scp->request_buffer;
-        for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
-            asc_sg_head.sg_list[sgcnt].addr =
-                cpu_to_le32(virt_to_bus(
-		(unsigned char *)page_address(slp->page) + slp->offset));
-            asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(slp->length);
-            ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(slp->length, 512));
+	for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
+	    asc_sg_head.sg_list[sgcnt].addr = cpu_to_le32(sg_dma_address(slp));
+	    asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(sg_dma_len(slp));
+	    ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512));
         }
     }
 
@@ -6755,6 +6541,7 @@
     ADV_SCSI_REQ_Q      *scsiqp;
     int                 i;
     int                 ret;
+    struct device	*dev = boardp->dvc_cfg.adv_dvc_cfg.dev;
 
     /*
      * Allocate an adv_req_t structure from the board to execute
@@ -6827,15 +6614,23 @@
      * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
      * buffer command.
      */
-    scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
-    scsiqp->vdata_addr = scp->request_buffer;
-    scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
 
     if (scp->use_sg == 0) {
         /*
          * CDB request of single contiguous buffer.
          */
         reqp->sgblkp = NULL;
+	scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
+	if (scp->request_bufflen) {
+	    scsiqp->vdata_addr = scp->request_buffer;
+	    scp->SCp.dma_handle =
+	        dma_map_single(dev, scp->request_buffer,
+			       scp->request_bufflen, scp->sc_data_direction);
+	} else {
+	    scsiqp->vdata_addr = 0;
+	    scp->SCp.dma_handle = 0;
+	}
+	scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
         scsiqp->sg_list_ptr = NULL;
         scsiqp->sg_real_addr = 0;
         ASC_STATS(scp->device->host, cont_cnt);
@@ -6845,10 +6640,21 @@
         /*
          * CDB scatter-gather request list.
          */
-        if (scp->use_sg > ADV_MAX_SG_LIST) {
+	struct scatterlist *slp;
+	int use_sg;
+
+	scsiqp->data_cnt = 0;
+	scsiqp->vdata_addr = 0;
+	scsiqp->data_addr = 0;
+
+	slp = (struct scatterlist *)scp->request_buffer;
+	use_sg = dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
+
+	if (use_sg > ADV_MAX_SG_LIST) {
             ASC_PRINT3(
 "adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n",
-                boardp->id, scp->use_sg, scp->device->host->sg_tablesize);
+		boardp->id, use_sg, scp->device->host->sg_tablesize);
+	    dma_unmap_sg(dev, slp, scp->use_sg, scp->sc_data_direction);
             scp->result = HOST_BYTE(DID_ERROR);
             asc_enqueue(&boardp->done, scp, ASC_BACK);
 
@@ -6862,7 +6668,7 @@
             return ASC_ERROR;
         }
 
-        if ((ret = adv_get_sglist(boardp, reqp, scp)) != ADV_SUCCESS) {
+	if ((ret = adv_get_sglist(boardp, reqp, scp, use_sg)) != ADV_SUCCESS) {
             /*
              * Free the adv_req_t structure by adding it back to the
              * board free list.
@@ -6874,7 +6680,7 @@
         }
 
         ASC_STATS(scp->device->host, sg_cnt);
-        ASC_STATS_ADD(scp->device->host, sg_elem, scp->use_sg);
+	ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
     }
 
     ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
@@ -6898,7 +6704,7 @@
  *      ADV_ERROR(-1) - SG List creation failed
  */
 STATIC int
-adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, Scsi_Cmnd *scp)
+adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, Scsi_Cmnd *scp, int use_sg)
 {
     adv_sgblk_t         *sgblkp;
     ADV_SCSI_REQ_Q      *scsiqp;
@@ -6910,7 +6716,7 @@
 
     scsiqp = (ADV_SCSI_REQ_Q *) ADV_32BALIGN(&reqp->scsi_req_q);
     slp = (struct scatterlist *) scp->request_buffer;
-    sg_elem_cnt = scp->use_sg;
+    sg_elem_cnt = use_sg;
     prev_sg_block = NULL;
     reqp->sgblkp = NULL;
 
@@ -6982,11 +6788,9 @@
 
         for (i = 0; i < NO_OF_SG_PER_BLOCK; i++)
         {
-            sg_block->sg_list[i].sg_addr =
-                cpu_to_le32(virt_to_bus(
-                   (unsigned char *)page_address(slp->page) + slp->offset));
-            sg_block->sg_list[i].sg_count = cpu_to_le32(slp->length);
-            ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(slp->length, 512));
+	    sg_block->sg_list[i].sg_addr = cpu_to_le32(sg_dma_address(slp));
+	    sg_block->sg_list[i].sg_count = cpu_to_le32(sg_dma_len(slp));
+	    ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512));
 
             if (--sg_elem_cnt == 0)
             {   /* Last ADV_SG_BLOCK and scatter-gather entry. */
@@ -7079,14 +6883,13 @@
          * If an INQUIRY command completed successfully, then call
          * the AscInquiryHandling() function to set-up the device.
          */
-        if (scp->cmnd[0] == SCSICMD_Inquiry && scp->device->lun == 0 &&
+        if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 &&
             (scp->request_bufflen - qdonep->remain_bytes) >= 8)
         {
             AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7,
                 (ASC_SCSI_INQUIRY *) scp->request_buffer);
         }
 
-#if ASC_LINUX_KERNEL24
         /*
          * Check for an underrun condition.
          *
@@ -7099,15 +6902,14 @@
             (unsigned) qdonep->remain_bytes);
             scp->resid = qdonep->remain_bytes;
         }
-#endif
         break;
 
     case QD_WITH_ERROR:
         ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
         switch (qdonep->d3.host_stat) {
         case QHSTA_NO_ERROR:
-            if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
-                ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
+            if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
+                ASC_DBG(2, "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
                 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
                     sizeof(scp->sense_buffer));
                 /*
@@ -7185,9 +6987,7 @@
     Scsi_Cmnd           *scp;
     struct Scsi_Host    *shp;
     int                 i;
-#if ASC_LINUX_KERNEL24
     ADV_DCNT            resid_cnt;
-#endif
 
 
     ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
@@ -7270,7 +7070,6 @@
         ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
         scp->result = 0;
 
-#if ASC_LINUX_KERNEL24
         /*
          * Check for an underrun condition.
          *
@@ -7284,15 +7083,14 @@
                 (ulong) resid_cnt);
             scp->resid = resid_cnt;
         }
-#endif
         break;
 
     case QD_WITH_ERROR:
         ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
         switch (scsiqp->host_status) {
         case QHSTA_NO_ERROR:
-            if (scsiqp->scsi_status == SS_CHK_CONDITION) {
-                ASC_DBG(2, "adv_isr_callback: SS_CHK_CONDITION\n");
+            if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
+                ASC_DBG(2, "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
                 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
                     sizeof(scp->sense_buffer));
                 /*
@@ -8858,7 +8656,7 @@
             (unsigned) offset, (unsigned) advoffset, cplen);
     if (offset <= advoffset) {
         /* Read offset below current offset, copy everything. */
-        cnt = ASC_MIN(cplen, leftlen);
+        cnt = min(cplen, leftlen);
         ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
                 (ulong) curbuf, (ulong) cp, cnt);
         memcpy(curbuf, cp, cnt);
@@ -8866,7 +8664,7 @@
         /* Read offset within current range, partial copy. */
         cnt = (advoffset + cplen) - offset;
         cp = (cp + cplen) - cnt;
-        cnt = ASC_MIN(cnt, leftlen);
+        cnt = min(cnt, leftlen);
         ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
                 (ulong) curbuf, (ulong) cp, cnt);
         memcpy(curbuf, cp, cnt);
@@ -8899,7 +8697,7 @@
         (void) printk(s);
         ret = 0;
     } else {
-        ret = ASC_MIN(buflen, ret);
+        ret = min(buflen, ret);
         memcpy(buf, s, ret);
     }
     va_end(args);
@@ -9002,16 +8800,14 @@
 /*
  * Read a PCI configuration byte.
  */
-ASC_INITFUNC(
-STATIC uchar,
+STATIC uchar __init
 DvcReadPCIConfigByte(
         ASC_DVC_VAR *asc_dvc,
         ushort offset)
-)
 {
 #ifdef CONFIG_PCI
     uchar byte_data;
-    pci_read_config_byte(asc_dvc->cfg->pci_dev, offset, &byte_data);
+    pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data);
     return byte_data;
 #else /* !defined(CONFIG_PCI) */
     return 0;
@@ -9021,16 +8817,14 @@
 /*
  * Write a PCI configuration byte.
  */
-ASC_INITFUNC(
-STATIC void,
+STATIC void __init
 DvcWritePCIConfigByte(
         ASC_DVC_VAR *asc_dvc,
         ushort offset,
         uchar  byte_data)
-)
 {
 #ifdef CONFIG_PCI
-    pci_write_config_byte(asc_dvc->cfg->pci_dev, offset, byte_data);
+    pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data);
 #endif /* CONFIG_PCI */
 }
 
@@ -9038,13 +8832,10 @@
  * Return the BIOS address of the adapter at the specified
  * I/O port and with the specified bus type.
  */
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscGetChipBiosAddress(
         PortAddr iop_base,
-        ushort bus_type
-)
-)
+        ushort bus_type)
 {
     ushort  cfg_lsw;
     ushort  bios_addr;
@@ -9119,16 +8910,14 @@
 /*
  * Read a PCI configuration byte.
  */
-ASC_INITFUNC(
-STATIC uchar,
+STATIC uchar __init
 DvcAdvReadPCIConfigByte(
         ADV_DVC_VAR *asc_dvc,
         ushort offset)
-)
 {
 #ifdef CONFIG_PCI
     uchar byte_data;
-    pci_read_config_byte(asc_dvc->cfg->pci_dev, offset, &byte_data);
+    pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data);
     return byte_data;
 #else /* CONFIG_PCI */
     return 0;
@@ -9138,16 +8927,14 @@
 /*
  * Write a PCI configuration byte.
  */
-ASC_INITFUNC(
-STATIC void,
+STATIC void __init
 DvcAdvWritePCIConfigByte(
         ADV_DVC_VAR *asc_dvc,
         ushort offset,
         uchar  byte_data)
-)
 {
 #ifdef CONFIG_PCI
-    pci_write_config_byte(asc_dvc->cfg->pci_dev, offset, byte_data);
+    pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data);
 #else /* CONFIG_PCI */
     return 0;
 #endif /* CONFIG_PCI */
@@ -9358,16 +9145,6 @@
         s->host_busy, s->host_no,
         (unsigned) s->last_reset);
 
-#if ASC_LINUX_KERNEL24
-    printk(
-" hostt 0x%lx\n",
-        (ulong) s->hostt);
-#elif ASC_LINUX_KERNEL22
-    printk(
-" host_queue 0x%lx, hostt 0x%lx, block 0x%lx,\n",
-        (ulong) s->host_queue, (ulong) s->hostt, (ulong) s->block);
-#endif
-
     printk(
 " base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n",
         (ulong) s->base, (ulong) s->io_port, s->n_io_port, s->irq);
@@ -9404,11 +9181,9 @@
 
     asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
 
-#if ASC_LINUX_KERNEL24
     printk (
 "sc_data_direction %u, resid %d\n",
         s->sc_data_direction, s->resid);
-#endif
 
     printk(
 " use_sg %u, sglist_len %u, abort_reason 0x%x\n",
@@ -9423,15 +9198,9 @@
 " timeout_per_command %d, timeout_total %d, timeout %d\n",
         s->timeout_per_command, s->timeout_total, s->timeout);
 
-#if ASC_LINUX_KERNEL24
     printk(
 " internal_timeout %u, flags %u\n",
         s->internal_timeout, s->flags);
-#elif ASC_LINUX_KERNEL22
-    printk(
-" internal_timeout %u, flags %u, this_count %d\n",
-        s->internal_timeout, s->flags,s->this_count);
-#endif
 
     printk(
 " scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
@@ -9507,7 +9276,8 @@
 
     printk(
 " pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
-          h->pci_dev->device, h->lib_serial_no, h->lib_version, h->mcode_date);
+	   to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
+	   h->mcode_date);
 
     printk(
 " mcode_version %d, overrun_buf 0x%lx\n",
@@ -9632,7 +9402,7 @@
 
     printk(
 "  mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
-       h->mcode_version, h->pci_dev->device, h->lib_version);
+       h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
 
     printk(
 "  control_flag 0x%x, pci_slot_info 0x%x\n",
@@ -9787,12 +9557,9 @@
  * --- Asc Library Functions
  */
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscGetEisaChipCfg(
-                     PortAddr iop_base
-)
-)
+                     PortAddr iop_base)
 {
     PortAddr            eisa_cfg_iop;
 
@@ -9801,13 +9568,11 @@
     return (inpw(eisa_cfg_iop));
 }
 
-ASC_INITFUNC(
-STATIC uchar,
+STATIC uchar __init
 AscSetChipScsiID(
                     PortAddr iop_base,
                     uchar new_host_id
 )
-)
 {
     ushort              cfg_lsw;
 
@@ -9821,12 +9586,9 @@
     return (AscGetChipScsiID(iop_base));
 }
 
-ASC_INITFUNC(
-STATIC uchar,
+STATIC uchar __init
 AscGetChipScsiCtrl(
-                      PortAddr iop_base
-)
-)
+		PortAddr iop_base)
 {
     uchar               sc;
 
@@ -9836,13 +9598,11 @@
     return (sc);
 }
 
-ASC_INITFUNC(
-STATIC uchar,
+STATIC uchar __init
 AscGetChipVersion(
                      PortAddr iop_base,
                      ushort bus_type
 )
-)
 {
     if ((bus_type & ASC_IS_EISA) != 0) {
         PortAddr            eisa_iop;
@@ -9855,12 +9615,9 @@
     return (AscGetChipVerNo(iop_base));
 }
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscGetChipBusType(
-                     PortAddr iop_base
-)
-)
+                     PortAddr iop_base)
 {
     ushort              chip_ver;
 
@@ -9940,22 +9697,19 @@
     return (0);
 }
 
-STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] ASC_INITDATA =
+STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __initdata =
 {
     0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
     ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
 };
 
 #ifdef CONFIG_ISA
-STATIC uchar _isa_pnp_inited ASC_INITDATA = 0;
+STATIC uchar _isa_pnp_inited __initdata = 0;
 
-ASC_INITFUNC(
-STATIC PortAddr,
+STATIC PortAddr __init
 AscSearchIOPortAddr(
                        PortAddr iop_beg,
-                       ushort bus_type
-)
-)
+                       ushort bus_type)
 {
     if (bus_type & ASC_IS_VL) {
         while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
@@ -9986,12 +9740,10 @@
     return (0);
 }
 
-ASC_INITFUNC(
-STATIC PortAddr,
+STATIC PortAddr __init
 AscSearchIOPortAddr11(
                          PortAddr s_addr
 )
-)
 {
     int                 i;
     PortAddr            iop_base;
@@ -10017,11 +9769,8 @@
     return (0);
 }
 
-ASC_INITFUNC(
-STATIC void,
-AscSetISAPNPWaitForKey(
-    void)
-)
+STATIC void __init
+AscSetISAPNPWaitForKey(void)
 {
     outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
     outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
@@ -10029,25 +9778,20 @@
 }
 #endif /* CONFIG_ISA */
 
-ASC_INITFUNC(
-STATIC void,
+STATIC void __init
 AscToggleIRQAct(
                    PortAddr iop_base
 )
-)
 {
     AscSetChipStatus(iop_base, CIW_IRQ_ACT);
     AscSetChipStatus(iop_base, 0);
     return;
 }
 
-ASC_INITFUNC(
-STATIC uchar,
+STATIC uchar __init
 AscGetChipIRQ(
                  PortAddr iop_base,
-                 ushort bus_type
-)
-)
+                 ushort bus_type)
 {
     ushort              cfg_lsw;
     uchar               chip_irq;
@@ -10077,14 +9821,11 @@
     return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
 }
 
-ASC_INITFUNC(
-STATIC uchar,
+STATIC uchar __init
 AscSetChipIRQ(
                  PortAddr iop_base,
                  uchar irq_no,
-                 ushort bus_type
-)
-)
+                 ushort bus_type)
 {
     ushort              cfg_lsw;
 
@@ -10119,12 +9860,9 @@
 }
 
 #ifdef CONFIG_ISA
-ASC_INITFUNC(
-STATIC void,
+STATIC void __init
 AscEnableIsaDma(
-                   uchar dma_channel
-)
-)
+                   uchar dma_channel)
 {
     if (dma_channel < 4) {
         outp(0x000B, (ushort) (0xC0 | dma_channel));
@@ -10285,7 +10023,7 @@
             return (0);
         } else {
 
-            ext_msg.msg_type = M1_MSG_REJECT;
+            ext_msg.msg_type = MESSAGE_REJECT;
             AscMemWordCopyPtrToLram(iop_base,
                                  ASCV_MSGOUT_BEG,
                                  (uchar *) &ext_msg,
@@ -10385,7 +10123,7 @@
                              (ushort) ASCV_SCSIBUSY_B, scsi_busy);
             asc_dvc->queue_full_or_busy |= target_id;
 
-            if (scsi_status == SS_QUEUE_FULL) {
+            if (scsi_status == SAM_STAT_TASK_SET_FULL) {
                 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
                     cur_dvc_qng -= 1;
                     asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
@@ -10732,7 +10470,7 @@
             } else {
                 if ((AscReadLramByte(iop_base,
                           (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
-                     SCSICMD_StartStopUnit)) {
+                     START_STOP)) {
                     asc_dvc->unit_not_ready &= ~target_id;
                     if (scsiq->d3.done_stat != QD_NO_ERROR) {
                         asc_dvc->start_motor &= ~target_id;
@@ -11005,14 +10743,14 @@
 #define ASC_SYN_OFFSET_ONE_DISABLE_LIST  16
 STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] =
 {
-    SCSICMD_Inquiry,
-    SCSICMD_RequestSense,
-    SCSICMD_ReadCapacity,
-    SCSICMD_ReadTOC,
-    SCSICMD_ModeSelect6,
-    SCSICMD_ModeSense6,
-    SCSICMD_ModeSelect10,
-    SCSICMD_ModeSense10,
+    INQUIRY,
+    REQUEST_SENSE,
+    READ_CAPACITY,
+    READ_TOC,
+    MODE_SELECT,
+    MODE_SENSE,
+    MODE_SELECT_10,
+    MODE_SENSE_10,
     0xFF,
     0xFF,
     0xFF,
@@ -11065,7 +10803,7 @@
     target_ix = scsiq->q2.target_ix;
     tid_no = ASC_TIX_TO_TID(target_ix);
     n_q_required = 1;
-    if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
+    if (scsiq->cdbptr[0] == REQUEST_SENSE) {
         if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
             asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
             sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
@@ -11134,7 +10872,7 @@
         }
     }
     if (disable_syn_offset_one_fix) {
-        scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
+        scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
         scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
                                ASC_TAG_FLAG_DISABLE_DISCONNECT);
     } else {
@@ -11143,8 +10881,8 @@
     if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
         if (asc_dvc->bug_fix_cntl) {
             if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
-                if ((scsi_cmd == SCSICMD_Read6) ||
-                    (scsi_cmd == SCSICMD_Read10)) {
+                if ((scsi_cmd == READ_6) ||
+                    (scsi_cmd == READ_10)) {
                     addr =
                         (ADV_PADDR) le32_to_cpu(
                             sg_head->sg_list[sg_entry_cnt_minus_one].addr) +
@@ -11193,8 +10931,8 @@
     } else {
         if (asc_dvc->bug_fix_cntl) {
             if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
-                if ((scsi_cmd == SCSICMD_Read6) ||
-                    (scsi_cmd == SCSICMD_Read10)) {
+                if ((scsi_cmd == READ_6) ||
+                    (scsi_cmd == READ_10)) {
                     addr = le32_to_cpu(scsiq->q1.data_addr) +
                         le32_to_cpu(scsiq->q1.data_cnt);
                     extra_bytes = (uchar) ((ushort) addr & 0x0003);
@@ -11365,7 +11103,7 @@
     }
     q_addr = ASC_QNO_TO_QADDR(q_no);
     if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
-        scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
+        scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG ;
     }
     scsiq->q1.status = QS_FREE;
     AscMemWordCopyPtrToLram(iop_base,
@@ -11862,12 +11600,9 @@
 }
 
 #ifdef CONFIG_ISA
-ASC_INITFUNC(
-STATIC ASC_DCNT,
+STATIC ASC_DCNT __init
 AscGetEisaProductID(
-                       PortAddr iop_base
-)
-)
+                       PortAddr iop_base)
 {
     PortAddr            eisa_iop;
     ushort              product_id_high, product_id_low;
@@ -11881,12 +11616,9 @@
     return (product_id);
 }
 
-ASC_INITFUNC(
-STATIC PortAddr,
+STATIC PortAddr __init
 AscSearchIOPortAddrEISA(
-                           PortAddr iop_base
-)
-)
+                           PortAddr iop_base)
 {
     ASC_DCNT            eisa_product_id;
 
@@ -12080,12 +11812,9 @@
     return (AscIsChipHalted(iop_base));
 }
 
-ASC_INITFUNC(
-STATIC ASC_DCNT,
+STATIC ASC_DCNT __init
 AscGetMaxDmaCount(
-                     ushort bus_type
-)
-)
+                     ushort bus_type)
 {
     if (bus_type & ASC_IS_ISA)
         return (ASC_MAX_ISA_DMA_COUNT);
@@ -12095,12 +11824,9 @@
 }
 
 #ifdef CONFIG_ISA
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscGetIsaDmaChannel(
-                       PortAddr iop_base
-)
-)
+                       PortAddr iop_base)
 {
     ushort              channel;
 
@@ -12112,13 +11838,10 @@
     return (channel + 4);
 }
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscSetIsaDmaChannel(
                        PortAddr iop_base,
-                       ushort dma_channel
-)
-)
+                       ushort dma_channel)
 {
     ushort              cfg_lsw;
     uchar               value;
@@ -12136,13 +11859,10 @@
     return (0);
 }
 
-ASC_INITFUNC(
-STATIC uchar,
+STATIC uchar __init
 AscSetIsaDmaSpeed(
                      PortAddr iop_base,
-                     uchar speed_value
-)
-)
+                     uchar speed_value)
 {
     speed_value &= 0x07;
     AscSetBank(iop_base, 1);
@@ -12151,12 +11871,10 @@
     return (AscGetIsaDmaSpeed(iop_base));
 }
 
-ASC_INITFUNC(
-STATIC uchar,
+STATIC uchar __init
 AscGetIsaDmaSpeed(
                      PortAddr iop_base
 )
-)
 {
     uchar               speed_value;
 
@@ -12168,12 +11886,10 @@
 }
 #endif /* CONFIG_ISA */
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscReadPCIConfigWord(
     ASC_DVC_VAR *asc_dvc,
     ushort pci_config_offset)
-)
 {
     uchar       lsb, msb;
 
@@ -12182,12 +11898,10 @@
     return ((ushort) ((msb << 8) | lsb));
 }
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscInitGetConfig(
         ASC_DVC_VAR *asc_dvc
 )
-)
 {
     ushort              warn_code;
     PortAddr            iop_base;
@@ -12267,12 +11981,10 @@
     return(warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscInitSetConfig(
                     ASC_DVC_VAR *asc_dvc
 )
-)
 {
     ushort              warn_code = 0;
 
@@ -12288,12 +12000,10 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscInitFromAscDvcVar(
                         ASC_DVC_VAR *asc_dvc
 )
-)
 {
     PortAddr            iop_base;
     ushort              cfg_msw;
@@ -12301,7 +12011,7 @@
     ushort              pci_device_id;
 
     iop_base = asc_dvc->iop_base;
-    pci_device_id = asc_dvc->cfg->pci_dev->device;
+    pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device;
     warn_code = 0;
     cfg_msw = AscGetChipCfgMsw(iop_base);
     if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
@@ -12393,12 +12103,9 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscInitAscDvcVar(
-                    ASC_DVC_VAR *asc_dvc
-)
-)
+                    ASC_DVC_VAR *asc_dvc)
 {
     int                 i;
     PortAddr            iop_base;
@@ -12508,12 +12215,8 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort,
-AscInitFromEEP(
-                  ASC_DVC_VAR *asc_dvc
-)
-)
+STATIC ushort __init
+AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
 {
     ASCEEP_CONFIG       eep_config_buf;
     ASCEEP_CONFIG       *eep_config;
@@ -12729,12 +12432,9 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC int,
+STATIC int __init
 AscTestExternalLram(
-                       ASC_DVC_VAR *asc_dvc
-)
-)
+                       ASC_DVC_VAR *asc_dvc)
 {
     PortAddr            iop_base;
     ushort              q_addr;
@@ -12756,13 +12456,11 @@
     return (sta);
 }
 
-ASC_INITFUNC(
-STATIC int,
+STATIC int __init
 AscWriteEEPCmdReg(
                      PortAddr iop_base,
                      uchar cmd_reg
 )
-)
 {
     uchar               read_back;
     int                 retry;
@@ -12781,13 +12479,11 @@
     }
 }
 
-ASC_INITFUNC(
-STATIC int,
+STATIC int __init
 AscWriteEEPDataReg(
                       PortAddr iop_base,
                       ushort data_reg
 )
-)
 {
     ushort              read_back;
     int                 retry;
@@ -12806,35 +12502,24 @@
     }
 }
 
-ASC_INITFUNC(
-STATIC void,
-AscWaitEEPRead(
-                  void
-)
-)
+STATIC void __init
+AscWaitEEPRead(void)
 {
     DvcSleepMilliSecond(1);
     return;
 }
 
-ASC_INITFUNC(
-STATIC void,
-AscWaitEEPWrite(
-                   void
-)
-)
+STATIC void __init
+AscWaitEEPWrite(void)
 {
     DvcSleepMilliSecond(20);
     return;
 }
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscReadEEPWord(
                   PortAddr iop_base,
-                  uchar addr
-)
-)
+                  uchar addr)
 {
     ushort              read_wval;
     uchar               cmd_reg;
@@ -12849,14 +12534,11 @@
     return (read_wval);
 }
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscWriteEEPWord(
                    PortAddr iop_base,
                    uchar addr,
-                   ushort word_val
-)
-)
+                   ushort word_val)
 {
     ushort              read_wval;
 
@@ -12876,13 +12558,10 @@
     return (read_wval);
 }
 
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AscGetEEPConfig(
                    PortAddr iop_base,
-                   ASCEEP_CONFIG * cfg_buf, ushort bus_type
-)
-)
+                   ASCEEP_CONFIG * cfg_buf, ushort bus_type)
 {
     ushort              wval;
     ushort              sum;
@@ -12928,13 +12607,10 @@
     return (sum);
 }
 
-ASC_INITFUNC(
-STATIC int,
+STATIC int __init
 AscSetEEPConfigOnce(
                        PortAddr iop_base,
-                       ASCEEP_CONFIG * cfg_buf, ushort bus_type
-)
-)
+                       ASCEEP_CONFIG * cfg_buf, ushort bus_type)
 {
     int                 n_error;
     ushort              *wbuf;
@@ -13026,13 +12702,11 @@
     return (n_error);
 }
 
-ASC_INITFUNC(
-STATIC int,
+STATIC int __init
 AscSetEEPConfig(
                    PortAddr iop_base,
                    ASCEEP_CONFIG * cfg_buf, ushort bus_type
 )
-)
 {
     int            retry;
     int            n_error;
@@ -13066,17 +12740,17 @@
     {
         if (!(asc_dvc->init_sdtr & tid_bits))
         {
-            if ((dvc_type == SCSI_TYPE_CDROM) &&
+            if ((dvc_type == TYPE_ROM) &&
                 (AscCompareString((uchar *) inq->vendor_id,
                     (uchar *) "HP ", 3) == 0))
             {
                 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
             }
             asc_dvc->pci_fix_asyn_xfer |= tid_bits;
-            if ((dvc_type == SCSI_TYPE_PROC) ||
-                (dvc_type == SCSI_TYPE_SCANNER) ||
-                (dvc_type == SCSI_TYPE_CDROM) ||
-                (dvc_type == SCSI_TYPE_SASD))
+            if ((dvc_type == TYPE_PROCESSOR) ||
+                (dvc_type == TYPE_SCANNER) ||
+                (dvc_type == TYPE_ROM) ||
+                (dvc_type == TYPE_TAPE))
             {
                 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
             }
@@ -14470,7 +14144,7 @@
  * unswapped on big-endian platforms.
  */
 STATIC ADVEEP_3550_CONFIG
-Default_3550_EEPROM_Config ASC_INITDATA = {
+Default_3550_EEPROM_Config __initdata = {
     ADV_EEPROM_BIOS_ENABLE,     /* cfg_lsw */
     0x0000,                     /* cfg_msw */
     0xFFFF,                     /* disc_enable */
@@ -14508,7 +14182,7 @@
 };
 
 STATIC ADVEEP_3550_CONFIG
-ADVEEP_3550_Config_Field_IsChar ASC_INITDATA = {
+ADVEEP_3550_Config_Field_IsChar __initdata = {
     0,                          /* cfg_lsw */
     0,                          /* cfg_msw */
     0,                          /* -disc_enable */
@@ -14546,7 +14220,7 @@
 };
 
 STATIC ADVEEP_38C0800_CONFIG
-Default_38C0800_EEPROM_Config ASC_INITDATA = {
+Default_38C0800_EEPROM_Config __initdata = {
     ADV_EEPROM_BIOS_ENABLE,     /* 00 cfg_lsw */
     0x0000,                     /* 01 cfg_msw */
     0xFFFF,                     /* 02 disc_enable */
@@ -14611,7 +14285,7 @@
 };
 
 STATIC ADVEEP_38C0800_CONFIG
-ADVEEP_38C0800_Config_Field_IsChar ASC_INITDATA = {
+ADVEEP_38C0800_Config_Field_IsChar __initdata = {
     0,                          /* 00 cfg_lsw */
     0,                          /* 01 cfg_msw */
     0,                          /* 02 disc_enable */
@@ -14676,7 +14350,7 @@
 };
 
 STATIC ADVEEP_38C1600_CONFIG
-Default_38C1600_EEPROM_Config ASC_INITDATA = {
+Default_38C1600_EEPROM_Config __initdata = {
     ADV_EEPROM_BIOS_ENABLE,     /* 00 cfg_lsw */
     0x0000,                     /* 01 cfg_msw */
     0xFFFF,                     /* 02 disc_enable */
@@ -14741,7 +14415,7 @@
 };
 
 STATIC ADVEEP_38C1600_CONFIG
-ADVEEP_38C1600_Config_Field_IsChar ASC_INITDATA = {
+ADVEEP_38C1600_Config_Field_IsChar __initdata = {
     0,                          /* 00 cfg_lsw */
     0,                          /* 01 cfg_msw */
     0,                          /* 02 disc_enable */
@@ -14813,10 +14487,8 @@
  * For a non-fatal error return a warning code. If there are no warnings
  * then 0 is returned.
  */
-ASC_INITFUNC(
-STATIC int,
+STATIC int __init
 AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
-)
 {
     ushort      warn_code;
     AdvPortAddr iop_base;
@@ -16800,10 +16472,8 @@
  *
  * Note: Chip is stopped on entry.
  */
-ASC_INITFUNC(
-STATIC int,
+STATIC int __init
 AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
-)
 {
     AdvPortAddr         iop_base;
     ushort              warn_code;
@@ -16974,10 +16644,8 @@
  *
  * Note: Chip is stopped on entry.
  */
-ASC_INITFUNC(
-STATIC int,
+STATIC int __init
 AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
-)
 {
     AdvPortAddr              iop_base;
     ushort                   warn_code;
@@ -17209,10 +16877,8 @@
  *
  * Note: Chip is stopped on entry.
  */
-ASC_INITFUNC(
-STATIC int,
+STATIC int __init
 AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
-)
 {
     AdvPortAddr              iop_base;
     ushort                   warn_code;
@@ -17477,10 +17143,8 @@
  *
  * Return a checksum based on the EEPROM configuration read.
  */
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
-)
 {
     ushort              wval, chksum;
     ushort              *wbuf;
@@ -17525,11 +17189,9 @@
  *
  * Return a checksum based on the EEPROM configuration read.
  */
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AdvGet38C0800EEPConfig(AdvPortAddr iop_base,
                        ADVEEP_38C0800_CONFIG *cfg_buf)
-)
 {
     ushort              wval, chksum;
     ushort              *wbuf;
@@ -17574,11 +17236,9 @@
  *
  * Return a checksum based on the EEPROM configuration read.
  */
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AdvGet38C1600EEPConfig(AdvPortAddr iop_base,
                        ADVEEP_38C1600_CONFIG *cfg_buf)
-)
 {
     ushort              wval, chksum;
     ushort              *wbuf;
@@ -17621,10 +17281,8 @@
 /*
  * Read the EEPROM from specified location
  */
-ASC_INITFUNC(
-STATIC ushort,
+STATIC ushort __init
 AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
-)
 {
     AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
         ASC_EEP_CMD_READ | eep_word_addr);
@@ -17635,10 +17293,8 @@
 /*
  * Wait for EEPROM command to complete
  */
-ASC_INITFUNC(
-STATIC void,
+STATIC void __init
 AdvWaitEEPCmd(AdvPortAddr iop_base)
-)
 {
     int eep_delay_ms;
 
@@ -18290,7 +17946,7 @@
          * the device, otherwise may erroneously set *_able bits.
          */
         if (scsiq->done_status == QD_NO_ERROR &&
-            scsiq->cdb[0] == SCSICMD_Inquiry &&
+            scsiq->cdb[0] == INQUIRY &&
             scsiq->target_lun == 0 &&
             (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT)
                 == ADV_INQ_RTN_STD_INQUIRY_DATA)
diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
--- a/drivers/scsi/aha1542.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/aha1542.c	2004-06-23 19:04:27 -07:00
@@ -47,7 +47,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "aha1542.h"
 
 #define SCSI_BUF_PA(address)	isa_virt_to_bus(address)
diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
--- a/drivers/scsi/aha1740.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/aha1740.c	2004-06-23 19:04:29 -07:00
@@ -56,7 +56,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "aha1740.h"
 
 /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h	2004-06-23 19:04:27 -07:00
@@ -68,7 +68,7 @@
 /* Core SCSI definitions */
 #define AIC_LIB_PREFIX ahd
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 /* Name space conflict with BSD queue macros */
 #ifdef LIST_HEAD
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h	2004-06-23 19:04:26 -07:00
@@ -85,7 +85,7 @@
 /* Core SCSI definitions */
 #define AIC_LIB_PREFIX ahc
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 /* Name space conflict with BSD queue macros */
 #ifdef LIST_HEAD
diff -Nru a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c
--- a/drivers/scsi/aic7xxx/aiclib.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/aic7xxx/aiclib.c	2004-06-23 19:04:27 -07:00
@@ -36,7 +36,7 @@
 
 /* Core SCSI definitions */
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "aiclib.h"
 #include "cam.h"
 
diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
--- a/drivers/scsi/aic7xxx_old.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/aic7xxx_old.c	2004-06-23 19:04:26 -07:00
@@ -239,7 +239,7 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "aic7xxx_old/aic7xxx.h"
 
 #include "aic7xxx_old/sequencer.h"
diff -Nru a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c
--- a/drivers/scsi/amiga7xx.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/amiga7xx.c	2004-06-23 19:04:26 -07:00
@@ -25,7 +25,7 @@
 #include <asm/irq.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "53c7xx.h"
 #include "amiga7xx.h"
 
diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/ata_piix.c	2004-06-23 19:04:27 -07:00
@@ -57,6 +57,7 @@
 	ich5_pata		= 0,
 	ich5_sata		= 1,
 	piix4_pata		= 2,
+	ich6_sata		= 3,
 };
 
 static int piix_init_one (struct pci_dev *pdev,
@@ -91,10 +92,8 @@
 	 * and enhanced mode, with queueing and other fancy stuff.
 	 * This is distinguished by PCI class code.
 	 */
-	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID,
-	  PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich5_sata },
-	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID,
-	  PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich5_sata },
+	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
 
 	{ }	/* terminate list */
 };
@@ -138,7 +137,7 @@
 
 	.bmdma_setup		= ata_bmdma_setup_pio,
 	.bmdma_start		= ata_bmdma_start_pio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
 	.eng_timeout		= ata_eng_timeout,
 
 	.irq_handler		= ata_interrupt,
@@ -161,7 +160,7 @@
 
 	.bmdma_setup		= ata_bmdma_setup_pio,
 	.bmdma_start		= ata_bmdma_start_pio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
 	.eng_timeout		= ata_eng_timeout,
 
 	.irq_handler		= ata_interrupt,
@@ -199,6 +198,17 @@
 		.udma_mask	= ATA_UDMA_MASK_40C, /* FIXME: cbl det */
 		.port_ops	= &piix_pata_ops,
 	},
+
+	/* ich6_sata */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
+				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
+				  ATA_FLAG_SLAVE_POSS,
+		.pio_mask	= 0x03,	/* pio3-4 */
+		.udma_mask	= 0x7f,	/* udma0-6 ; FIXME */
+		.port_ops	= &piix_sata_ops,
+	},
 };
 
 static struct pci_bits piix_enable_bits[] = {
@@ -327,13 +337,6 @@
 
 static void piix_sata_phy_reset(struct ata_port *ap)
 {
-	if (!pci_test_config_bits(ap->host_set->pdev,
-				  &piix_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return;
-	}
-
 	if (!piix_sata_probe(ap)) {
 		ata_port_disable(ap);
 		printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
diff -Nru a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
--- a/drivers/scsi/atari_scsi.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/atari_scsi.c	2004-06-23 19:04:29 -07:00
@@ -102,7 +102,7 @@
 #include <asm/bitops.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "atari_scsi.h"
 #include "NCR5380.h"
 #include <asm/atari_stdma.h>
diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
--- a/drivers/scsi/atp870u.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/atp870u.c	2004-06-23 19:04:26 -07:00
@@ -35,7 +35,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "atp870u.h"
 
 /*
diff -Nru a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c
--- a/drivers/scsi/blz1230.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/blz1230.c	2004-06-23 19:04:27 -07:00
@@ -28,7 +28,7 @@
 #include <linux/interrupt.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <linux/zorro.h>
diff -Nru a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c
--- a/drivers/scsi/blz2060.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/blz2060.c	2004-06-23 19:04:26 -07:00
@@ -28,7 +28,7 @@
 #include <linux/interrupt.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <linux/zorro.h>
diff -Nru a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c
--- a/drivers/scsi/bvme6000.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/bvme6000.c	2004-06-23 19:04:25 -07:00
@@ -17,7 +17,7 @@
 #include <asm/irq.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "53c7xx.h"
 #include "bvme6000.h"
 
diff -Nru a/drivers/scsi/constants.c b/drivers/scsi/constants.c
--- a/drivers/scsi/constants.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/constants.c	2004-06-23 19:04:28 -07:00
@@ -12,7 +12,7 @@
 #include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #define CONST_COMMAND   0x01
 #define CONST_STATUS    0x02
@@ -154,7 +154,7 @@
 }
 #endif  
 
-void print_command (unsigned char *command) {
+void __scsi_print_command (unsigned char *command) {
     int i,s;
     print_opcode(command[0]);
     for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) 
@@ -173,7 +173,7 @@
  *	(e.g. "0x2" for Check Condition).
  **/
 void
-print_status(unsigned char scsi_status) {
+scsi_print_status(unsigned char scsi_status) {
 #if (CONSTANTS & CONST_STATUS)
 	const char * ccp;
 
@@ -1014,12 +1014,12 @@
 #endif
 }
 
-void print_sense(const char *devclass, struct scsi_cmnd *cmd)
+void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd)
 {
 	print_sense_internal(devclass, cmd->sense_buffer, cmd->request);
 }
 
-void print_req_sense(const char *devclass, struct scsi_request *sreq)
+void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq)
 {
 	print_sense_internal(devclass, sreq->sr_sense_buffer, sreq->sr_request);
 }
@@ -1051,7 +1051,7 @@
 #define NO_EXTENDED_MSGS (sizeof(two_byte_msgs)  / sizeof (const char *))
 #endif /* (CONSTANTS & CONST_MSG) */
 
-int print_msg (const unsigned char *msg) {
+int scsi_print_msg (const unsigned char *msg) {
     int len = 0, i;
     if (msg[0] == EXTENDED_MESSAGE) {
 	len = 3 + msg[1];
@@ -1124,13 +1124,13 @@
     return len;
 }
 
-void print_Scsi_Cmnd(struct scsi_cmnd *cmd) {
+void scsi_print_command(struct scsi_cmnd *cmd) {
     printk("scsi%d : destination target %d, lun %d\n", 
 	   cmd->device->host->host_no, 
 	   cmd->device->id, 
 	   cmd->device->lun);
     printk("        command = ");
-    print_command(cmd->cmnd);
+    __scsi_print_command(cmd->cmnd);
 }
 
 #if (CONSTANTS & CONST_HOST)
@@ -1139,7 +1139,7 @@
 "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
 "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", NULL};
 
-void print_hostbyte(int scsiresult)
+void scsi_print_hostbyte(int scsiresult)
 {   static int maxcode=0;
     int i;
    
@@ -1155,7 +1155,7 @@
     printk("(%s) ",hostbyte_table[host_byte(scsiresult)]);
 }
 #else
-void print_hostbyte(int scsiresult)
+void scsi_print_hostbyte(int scsiresult)
 {   printk("Hostbyte=0x%02x ",host_byte(scsiresult));
 }
 #endif
@@ -1170,7 +1170,7 @@
 unknown,unknown,unknown, "SUGGEST_SENSE",NULL};
 
 
-void print_driverbyte(int scsiresult)
+void scsi_print_driverbyte(int scsiresult)
 {   static int driver_max=0,suggest_max=0;
     int i,dr=driver_byte(scsiresult)&DRIVER_MASK, 
 	su=(driver_byte(scsiresult)&SUGGEST_MASK)>>4;
@@ -1187,7 +1187,7 @@
 	su<suggest_max ? driversuggest_table[su]:"invalid");
 }
 #else
-void print_driverbyte(int scsiresult)
+void scsi_print_driverbyte(int scsiresult)
 {   printk("Driverbyte=0x%02x ",driver_byte(scsiresult));
 }
 #endif
diff -Nru a/drivers/scsi/cpqfcTScontrol.c b/drivers/scsi/cpqfcTScontrol.c
--- a/drivers/scsi/cpqfcTScontrol.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/cpqfcTScontrol.c	2004-06-23 19:04:25 -07:00
@@ -45,7 +45,7 @@
 #include <linux/spinlock.h>
 
 #include "scsi.h"
-#include "hosts.h"   // Scsi_Host definition for INT handler
+#include <scsi/scsi_host.h>   // Scsi_Host definition for INT handler
 #include "cpqfcTSchip.h"
 #include "cpqfcTSstructs.h"
 
diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
--- a/drivers/scsi/cpqfcTSinit.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/cpqfcTSinit.c	2004-06-23 19:04:25 -07:00
@@ -51,7 +51,7 @@
 #include <asm/irq.h>
 #include <linux/spinlock.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include "cpqfcTSchip.h"
 #include "cpqfcTSstructs.h"
@@ -1266,7 +1266,7 @@
 
 
 
-// The file "hosts.h" says not to call scsi_done from
+// The file <scsi/scsi_host.h> says not to call scsi_done from
 // inside _queuecommand, so we'll do it from the heartbeat timer
 // (clarification: Turns out it's ok to call scsi_done from queuecommand 
 // for cases that don't go to the hardware like scsi cmds destined
diff -Nru a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c
--- a/drivers/scsi/cpqfcTSworker.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/cpqfcTSworker.c	2004-06-23 19:04:28 -07:00
@@ -39,7 +39,7 @@
 #include <asm/dma.h>
 
 #include "scsi.h"
-#include "hosts.h"   // struct Scsi_Host definition for T handler
+#include <scsi/scsi_host.h>   // struct Scsi_Host definition for T handler
 #include "cpqfcTSchip.h"
 #include "cpqfcTSstructs.h"
 #include "cpqfcTStrigger.h"
diff -Nru a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c
--- a/drivers/scsi/cyberstorm.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/cyberstorm.c	2004-06-23 19:04:28 -07:00
@@ -31,7 +31,7 @@
 #include <linux/interrupt.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <linux/zorro.h>
diff -Nru a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c
--- a/drivers/scsi/cyberstormII.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/cyberstormII.c	2004-06-23 19:04:28 -07:00
@@ -27,7 +27,7 @@
 #include <linux/interrupt.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <linux/zorro.h>
diff -Nru a/drivers/scsi/dc390.h b/drivers/scsi/dc390.h
--- a/drivers/scsi/dc390.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/dc390.h	2004-06-23 19:04:25 -07:00
@@ -14,12 +14,9 @@
 #define DC390_H
 
 #include <linux/version.h>
-#ifndef KERNEL_VERSION
-# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
 
 #define DC390_BANNER "Tekram DC390/AM53C974"
-#define DC390_VERSION "2.1b 2004-04-13"
+#define DC390_VERSION "2.1d 2004-05-27"
 
 /* We don't have eh_abort_handler, eh_device_reset_handler, 
  * eh_bus_reset_handler, eh_host_reset_handler yet! 
@@ -32,14 +29,4 @@
 # define NEW_EH use_new_eh_code: 1,
 # define USE_NEW_EH
 #endif
-
-static int DC390_detect(Scsi_Host_Template *psht);
-static int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *));
-static int DC390_abort(Scsi_Cmnd *cmd);
-static int DC390_reset(Scsi_Cmnd *cmd);
-static int DC390_bios_param(struct scsi_device *sdev, struct block_device *dev,
-		sector_t capacity, int geom[]);
-
-static int DC390_release(struct Scsi_Host *);
-
 #endif /* DC390_H */
diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
--- a/drivers/scsi/dc395x.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/dc395x.c	2004-06-23 19:04:25 -07:00
@@ -53,7 +53,7 @@
 #include <linux/blkdev.h>
 #include <asm/io.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "dc395x.h"
 #include <scsi/scsicam.h>	/* needed for scsicam_bios_param */
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
--- a/drivers/scsi/dec_esp.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/dec_esp.c	2004-06-23 19:04:27 -07:00
@@ -29,7 +29,7 @@
 #include <linux/stat.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <asm/irq.h>
diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
--- a/drivers/scsi/dmx3191d.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/dmx3191d.c	2004-06-23 19:04:27 -07:00
@@ -34,7 +34,7 @@
 #include <linux/delay.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "dmx3191d.h"
 
diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
--- a/drivers/scsi/dpt_i2o.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/dpt_i2o.c	2004-06-23 19:04:28 -07:00
@@ -68,8 +68,11 @@
 #include <asm/pgtable.h>
 #include <asm/io.h>		/* for virt_to_bus, etc. */
 
-#include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
 
 #include "dpt/dptsig.h"
 #include "dpti.h"
@@ -86,9 +89,9 @@
 #elif defined(__ia64__)
 	PROC_INTEL, PROC_IA64,
 #elif defined(__sparc__)
-	PROC_ULTRASPARC,
+	PROC_ULTRASPARC, PROC_ULTRASPARC,
 #elif defined(__alpha__)
-	PROC_ALPHA ,
+	PROC_ALPHA, PROC_ALPHA,
 #else
 	(-1),(-1),
 #endif
@@ -173,7 +176,7 @@
 };
 MODULE_DEVICE_TABLE(pci,dptids);
 
-static int adpt_detect(Scsi_Host_Template* sht)
+static int adpt_detect(struct scsi_host_template* sht)
 {
 	struct pci_dev *pDev = NULL;
 	adpt_hba* pHba;
@@ -362,7 +365,7 @@
 }
 
 
-static int adpt_slave_configure(Scsi_Device * device)
+static int adpt_slave_configure(struct scsi_device * device)
 {
 	struct Scsi_Host *host = device->host;
 	adpt_hba* pHba;
@@ -378,7 +381,7 @@
 	return 0;
 }
 
-static int adpt_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
+static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
 {
 	adpt_hba* pHba = NULL;
 	struct adpt_device* pDev = NULL;	/* dpt per device information */
@@ -643,7 +646,7 @@
  *===========================================================================
  */
 
-static int adpt_abort(Scsi_Cmnd * cmd)
+static int adpt_abort(struct scsi_cmnd * cmd)
 {
 	adpt_hba* pHba = NULL;	/* host bus adapter structure */
 	struct adpt_device* dptdevice;	/* dpt per device information */
@@ -683,7 +686,7 @@
 // This is the same for BLK and SCSI devices
 // NOTE this is wrong in the i2o.h definitions
 // This is not currently supported by our adapter but we issue it anyway
-static int adpt_device_reset(Scsi_Cmnd* cmd)
+static int adpt_device_reset(struct scsi_cmnd* cmd)
 {
 	adpt_hba* pHba;
 	u32 msg[4];
@@ -723,7 +726,7 @@
 
 #define I2O_HBA_BUS_RESET 0x87
 // This version of bus reset is called by the eh_error handler
-static int adpt_bus_reset(Scsi_Cmnd* cmd)
+static int adpt_bus_reset(struct scsi_cmnd* cmd)
 {
 	adpt_hba* pHba;
 	u32 msg[4];
@@ -745,7 +748,7 @@
 }
 
 // This version of reset is called by the eh_error_handler
-static int adpt_reset(Scsi_Cmnd* cmd)
+static int adpt_reset(struct scsi_cmnd* cmd)
 {
 	adpt_hba* pHba;
 	int rcode;
@@ -860,7 +863,7 @@
 #endif
 
 
-static int adpt_install_hba(Scsi_Host_Template* sht, struct pci_dev* pDev) 
+static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) 
 {
 
 	adpt_hba* pHba = NULL;
@@ -1997,7 +2000,7 @@
 
 static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	Scsi_Cmnd* cmd;
+	struct scsi_cmnd* cmd;
 	adpt_hba* pHba = dev_id;
 	u32 m;
 	ulong reply;
@@ -2059,14 +2062,14 @@
 				status = I2O_POST_WAIT_OK;
 			}
 			if(!(context & 0x40000000)) {
-				cmd = (Scsi_Cmnd*) readl(reply+12); 
+				cmd = (struct scsi_cmnd*) readl(reply+12); 
 				if(cmd != NULL) {
 					printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context);
 				}
 			}
 			adpt_i2o_post_wait_complete(context, status);
 		} else { // SCSI message
-			cmd = (Scsi_Cmnd*) readl(reply+12); 
+			cmd = (struct scsi_cmnd*) readl(reply+12); 
 			if(cmd != NULL){
 				if(cmd->serial_number != 0) { // If not timedout
 					adpt_i2o_to_scsi(reply, cmd);
@@ -2083,7 +2086,7 @@
 	return IRQ_RETVAL(handled);
 }
 
-static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d)
+static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* d)
 {
 	int i;
 	u32 msg[MAX_MESSAGE_SIZE];
@@ -2108,16 +2111,16 @@
 		 * cmd->cmnd[0] is an unsigned char
 		 */
 		switch(cmd->sc_data_direction){
-		case SCSI_DATA_READ:
+		case DMA_FROM_DEVICE:
 			scsidir  =0x40000000;	// DATA IN  (iop<--dev)
 			break;
-		case SCSI_DATA_WRITE:
+		case DMA_TO_DEVICE:
 			direction=0x04000000;	// SGL OUT
 			scsidir  =0x80000000;	// DATA OUT (iop-->dev)
 			break;
-		case SCSI_DATA_NONE:
+		case DMA_NONE:
 			break;
-		case SCSI_DATA_UNKNOWN:
+		case DMA_BIDIRECTIONAL:
 			scsidir  =0x40000000;	// DATA IN  (iop<--dev)
 			// Assume In - and continue;
 			break;
@@ -2156,7 +2159,7 @@
 	if(cmd->use_sg) {
 		struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;
 		int sg_count = pci_map_sg(pHba->pDev, sg, cmd->use_sg,
-                        scsi_to_pci_dma_dir(cmd->sc_data_direction));
+				cmd->sc_data_direction);
 
 
 		len = 0;
@@ -2184,7 +2187,7 @@
 			*mptr++ = pci_map_single(pHba->pDev,
 				cmd->request_buffer,
 				cmd->request_bufflen,
-				scsi_to_pci_dma_dir(cmd->sc_data_direction));
+				cmd->sc_data_direction);
 		}
 	}
 	
@@ -2200,7 +2203,7 @@
 }
 
 
-static s32 adpt_scsi_register(adpt_hba* pHba,Scsi_Host_Template * sht)
+static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht)
 {
 	struct Scsi_Host *host = NULL;
 
@@ -2231,7 +2234,7 @@
 }
 
 
-static s32 adpt_i2o_to_scsi(ulong reply, Scsi_Cmnd* cmd)
+static s32 adpt_i2o_to_scsi(ulong reply, struct scsi_cmnd* cmd)
 {
 	adpt_hba* pHba;
 	u32 hba_status;
@@ -2533,8 +2536,8 @@
 
 static void adpt_fail_posted_scbs(adpt_hba* pHba)
 {
-	Scsi_Cmnd* 	cmd = NULL;
-	Scsi_Device* 	d = NULL;
+	struct scsi_cmnd* 	cmd = NULL;
+	struct scsi_device* 	d = NULL;
 
 	shost_for_each_device(d, pHba->host) {
 		unsigned long flags;
@@ -3358,7 +3361,7 @@
 
 #endif
 
-static Scsi_Host_Template driver_template = {
+static struct scsi_host_template driver_template = {
 	.name			= "dpt_i2o",
 	.proc_name		= "dpt_i2o",
 	.proc_info		= adpt_proc_info,
diff -Nru a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h
--- a/drivers/scsi/dpti.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/dpti.h	2004-06-23 19:04:25 -07:00
@@ -37,19 +37,19 @@
  * SCSI interface function Prototypes
  */
 
-static int adpt_detect(Scsi_Host_Template * sht);
-static int adpt_queue(Scsi_Cmnd * cmd, void (*cmdcomplete) (Scsi_Cmnd *));
-static int adpt_abort(Scsi_Cmnd * cmd);
-static int adpt_reset(Scsi_Cmnd* cmd);
+static int adpt_detect(struct scsi_host_template * sht);
+static int adpt_queue(struct scsi_cmnd * cmd, void (*cmdcomplete) (struct scsi_cmnd *));
+static int adpt_abort(struct scsi_cmnd * cmd);
+static int adpt_reset(struct scsi_cmnd* cmd);
 static int adpt_release(struct Scsi_Host *host);
-static int adpt_slave_configure(Scsi_Device *);
+static int adpt_slave_configure(struct scsi_device *);
 
 static const char *adpt_info(struct Scsi_Host *pSHost);
 static int adpt_bios_param(struct scsi_device * sdev, struct block_device *dev,
 		sector_t, int geom[]);
 
-static int adpt_bus_reset(Scsi_Cmnd* cmd);
-static int adpt_device_reset(Scsi_Cmnd* cmd);
+static int adpt_bus_reset(struct scsi_cmnd* cmd);
+static int adpt_device_reset(struct scsi_cmnd* cmd);
 
 
 /*
@@ -198,7 +198,7 @@
 	u8	state;
 	u16	tid;
 	struct i2o_device* pI2o_dev;
-	Scsi_Device *pScsi_dev;
+	struct scsi_device *pScsi_dev;
 };
 
 struct adpt_channel {
@@ -296,9 +296,9 @@
 static s32 adpt_i2o_status_get(adpt_hba* pHba);
 static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba);
 static s32 adpt_i2o_hrt_get(adpt_hba* pHba);
-static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* dptdevice);
-static s32 adpt_i2o_to_scsi(ulong reply, Scsi_Cmnd* cmd);
-static s32 adpt_scsi_register(adpt_hba* pHba,Scsi_Host_Template * sht);
+static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice);
+static s32 adpt_i2o_to_scsi(ulong reply, struct scsi_cmnd* cmd);
+static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht);
 static s32 adpt_hba_reset(adpt_hba* pHba);
 static s32 adpt_i2o_reset_hba(adpt_hba* pHba);
 static s32 adpt_rescan(adpt_hba* pHba);
@@ -308,7 +308,7 @@
 static void adpt_inquiry(adpt_hba* pHba);
 static void adpt_fail_posted_scbs(adpt_hba* pHba);
 static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun);
-static int adpt_install_hba(Scsi_Host_Template* sht, struct pci_dev* pDev) ;
+static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ;
 static int adpt_i2o_online_hba(adpt_hba* pHba);
 static void adpt_i2o_post_wait_complete(u32, int);
 static int adpt_i2o_systab_send(adpt_hba* pHba);
diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
--- a/drivers/scsi/dtc.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/dtc.c	2004-06-23 19:04:28 -07:00
@@ -84,7 +84,7 @@
 #include <linux/interrupt.h>
 #include <asm/io.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "dtc.h"
 #define AUTOPROBE_IRQ
 #include "NCR5380.h"
diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c
--- a/drivers/scsi/eata.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/eata.c	2004-06-23 19:04:28 -07:00
@@ -495,7 +495,7 @@
 #include <linux/spinlock.h>
 #include <scsi/scsicam.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 
diff -Nru a/drivers/scsi/eata_generic.h b/drivers/scsi/eata_generic.h
--- a/drivers/scsi/eata_generic.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/eata_generic.h	2004-06-23 19:04:27 -07:00
@@ -317,7 +317,7 @@
     __u8 rw_latency;
     __u8 retries;
     __u8 status;	      /* status of this queueslot		*/
-    Scsi_Cmnd *cmd;	      /* address of cmd				*/
+    struct scsi_cmnd *cmd;    /* address of cmd				*/
     struct eata_sg_list *sg_list;
 };
 
diff -Nru a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
--- a/drivers/scsi/eata_pio.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/eata_pio.c	2004-06-23 19:04:27 -07:00
@@ -46,6 +46,7 @@
  *  last change: 2002/11/02               OS: Linux 2.5.45  *
  ************************************************************/
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -56,15 +57,14 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/interrupt.h>
-#include <linux/stat.h>
-#include <linux/config.h>
 #include <linux/blkdev.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
-#include "scsi.h"
-#include "hosts.h"
-#include <scsi/scsicam.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
 
 #include "eata_generic.h"
 #include "eata_pio.h"
@@ -91,6 +91,8 @@
 static unsigned long int_counter;
 static unsigned long queue_counter;
 
+static struct scsi_host_template driver_template;
+
 /*
  * eata_proc_info
  * inout : decides on the direction of the dataflow and the meaning of the 
@@ -170,15 +172,15 @@
 		if (sh->io_port && sh->n_io_port)
 			release_region(sh->io_port, sh->n_io_port);
 	}
-	return (TRUE);
+	return 1;
 }
 
-static void IncStat(Scsi_Pointer * SCp, uint Increment)
+static void IncStat(struct scsi_pointer *SCp, uint Increment)
 {
 	SCp->ptr += Increment;
 	if ((SCp->this_residual -= Increment) == 0) {
 		if ((--SCp->buffers_residual) == 0)
-			SCp->Status = FALSE;
+			SCp->Status = 0;
 		else {
 			SCp->buffer++;
 			SCp->ptr = page_address(SCp->buffer->page) + SCp->buffer->offset;
@@ -204,7 +206,7 @@
 static void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	uint eata_stat = 0xfffff;
-	Scsi_Cmnd *cmd;
+	struct scsi_cmnd *cmd;
 	hostdata *hd;
 	struct eata_ccb *cp;
 	uint base;
@@ -233,12 +235,12 @@
 			if (stat & HA_SDRQ) {
 				if (cp->DataIn) {
 					z = 256;
-					odd = FALSE;
+					odd = 0;
 					while ((cmd->SCp.Status) && ((z > 0) || (odd))) {
 						if (odd) {
 							*(cmd->SCp.ptr) = zwickel >> 8;
 							IncStat(&cmd->SCp, 1);
-							odd = FALSE;
+							odd = 0;
 						}
 						x = min_t(unsigned int, z, cmd->SCp.this_residual / 2);
 						insw(base + HA_RDATA, cmd->SCp.ptr, x);
@@ -249,7 +251,7 @@
 							*(cmd->SCp.ptr) = zwickel & 0xff;
 							IncStat(&cmd->SCp, 1);
 							z--;
-							odd = TRUE;
+							odd = 1;
 						}
 					}
 					while (z > 0) {
@@ -258,7 +260,7 @@
 					}
 				} else {	/* cp->DataOut */
 
-					odd = FALSE;
+					odd = 0;
 					z = 256;
 					while ((cmd->SCp.Status) && ((z > 0) || (odd))) {
 						if (odd) {
@@ -266,7 +268,7 @@
 							IncStat(&cmd->SCp, 1);
 							outw(zwickel, base + HA_RDATA);
 							z--;
-							odd = FALSE;
+							odd = 0;
 						}
 						x = min_t(unsigned int, z, cmd->SCp.this_residual / 2);
 						outsw(base + HA_RDATA, cmd->SCp.ptr, x);
@@ -276,13 +278,13 @@
 							zwickel = *(cmd->SCp.ptr);
 							zwickel &= 0xff;
 							IncStat(&cmd->SCp, 1);
-							odd = TRUE;
+							odd = 1;
 						}
 					}
 					while (z > 0 || odd) {
 						outw(zwickel, base + HA_RDATA);
 						z--;
-						odd = FALSE;
+						odd = 0;
 					}
 				}
 			}
@@ -331,7 +333,7 @@
 
 	while (inb(base + HA_RSTATUS) & HA_SBUSY)
 		if (--loop == 0)
-			return (TRUE);
+			return 1;
 
 	/* Enable interrupts for HBA.  It is not the best way to do it at this
 	 * place, but I hope that it doesn't interfere with the IDE driver 
@@ -340,10 +342,11 @@
 	outb(HA_CTRL_8HEADS, base + HA_CTRLREG);
 
 	outb(command, base + HA_WCOMMAND);
-	return (FALSE);
+	return 0;
 }
 
-static int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
+static int eata_pio_queue(struct scsi_cmnd *cmd,
+		void (*done)(struct scsi_cmnd *))
 {
 	uint x, y;
 	uint base;
@@ -383,21 +386,21 @@
 
 	cmd->scsi_done = (void *) done;
 
-	if(cmd->sc_data_direction == SCSI_DATA_WRITE)
-		cp->DataOut = TRUE;	/* Output mode */
+	if (cmd->sc_data_direction == DMA_TO_DEVICE)
+		cp->DataOut = 1;	/* Output mode */
 	else
-		cp->DataIn = TRUE;	/* Input mode  */
+		cp->DataIn = 0;	/* Input mode  */
 
 	cp->Interpret = (cmd->device->id == hd->hostid);
 	cp->cp_datalen = htonl((unsigned long) cmd->request_bufflen);
-	cp->Auto_Req_Sen = FALSE;
+	cp->Auto_Req_Sen = 0;
 	cp->cp_reqDMA = htonl(0);
 	cp->reqlen = 0;
 
 	cp->cp_id = cmd->device->id;
 	cp->cp_lun = cmd->device->lun;
-	cp->cp_dispri = FALSE;
-	cp->cp_identify = TRUE;
+	cp->cp_dispri = 0;
+	cp->cp_identify = 1;
 	memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
 
 	cp->cp_statDMA = htonl(0);
@@ -440,7 +443,7 @@
 	return (0);
 }
 
-static int eata_pio_abort(Scsi_Cmnd * cmd)
+static int eata_pio_abort(struct scsi_cmnd *cmd)
 {
 	uint loop = HZ;
 
@@ -472,11 +475,11 @@
 	panic("eata_pio: abort: invalid slot status\n");
 }
 
-static int eata_pio_host_reset(Scsi_Cmnd * cmd)
+static int eata_pio_host_reset(struct scsi_cmnd *cmd)
 {
 	uint x, limit = 0;
-	unsigned char success = FALSE;
-	Scsi_Cmnd *sp;
+	unsigned char success = 0;
+	struct scsi_cmnd *sp;
 	struct Scsi_Host *host = cmd->device->host;
 
 	DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" " %x lun: %x reason %x\n", cmd->pid, cmd->device->id, cmd->device->lun, cmd->abort_reason));
@@ -530,7 +533,7 @@
 		sp->scsi_done(sp);
 	}
 
-	HD(cmd)->state = FALSE;
+	HD(cmd)->state = 0;
 
 	if (success) {		/* hmmm... */
 		DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n"));
@@ -550,8 +553,8 @@
 	memset(&cp, 0, sizeof(struct eata_ccb));
 	memset(buff, 0, sizeof(buff));
 
-	cp.DataIn = TRUE;
-	cp.Interpret = TRUE;	/* Interpret command */
+	cp.DataIn = 1;
+	cp.Interpret = 1;	/* Interpret command */
 
 	cp.cp_datalen = htonl(254);
 	cp.cp_dataDMA = htonl(0);
@@ -593,14 +596,14 @@
 	int z;
 	unsigned short *p;
 
-	if (check_region(base, 9))
-		return (FALSE);
+	if (!request_region(base, 9, "eata_pio"))
+		return 0;
 
 	memset(buf, 0, sizeof(struct get_conf));
 
 	while (inb(base + HA_RSTATUS) & HA_SBUSY)
 		if (--loop == 0)
-			return (FALSE);
+			goto fail;
 
 	DBG(DBG_PIO && DBG_PROBE, printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base));
 	eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG);
@@ -609,30 +612,40 @@
 	for (p = (unsigned short *) buf; (long) p <= ((long) buf + (sizeof(struct get_conf) / 2)); p++) {
 		while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
 			if (--loop == 0)
-				return (FALSE);
+				goto fail;
 
 		loop = HZ / 2;
 		*p = inw(base + HA_RDATA);
 	}
-	if (!(inb(base + HA_RSTATUS) & HA_SERROR)) {	/* Error ? */
-		if (htonl(EATA_SIGNATURE) == buf->signature) {
-			DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found " "at %#4x EATA Level: %x\n", base, (uint) (buf->version)));
-
-			while (inb(base + HA_RSTATUS) & HA_SDRQ)
-				inw(base + HA_RDATA);
-			if (ALLOW_DMA_BOARDS == FALSE) {
-				for (z = 0; z < MAXISA; z++)
-					if (base == ISAbases[z]) {
-						buf->IRQ = ISAirqs[z];
-						break;
-					}
+	if (inb(base + HA_RSTATUS) & HA_SERROR) {
+		DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during "
+					"transfer for HBA at %x\n", base));
+		goto fail;
+	}
+
+	if (htonl(EATA_SIGNATURE) != buf->signature)
+		goto fail;
+
+	DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found "
+				"at %#4x EATA Level: %x\n",
+				base, (uint) (buf->version)));
+
+	while (inb(base + HA_RSTATUS) & HA_SDRQ)
+		inw(base + HA_RDATA);
+
+	if (!ALLOW_DMA_BOARDS) {
+		for (z = 0; z < MAXISA; z++)
+			if (base == ISAbases[z]) {
+				buf->IRQ = ISAirqs[z];
+				break;
 			}
-			return (TRUE);
-		}
-	} else {
-		DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer " "for HBA at %x\n", base));
 	}
-	return (FALSE);
+
+	return 1;
+
+ fail:
+	release_region(base, 9);
+	return 0;
 }
 
 static void print_pio_config(struct get_conf *gc)
@@ -670,7 +683,7 @@
 	return (!(inb(base + HA_RSTATUS) & HA_SERROR));
 }
 
-static int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
+static int register_pio_HBA(long base, struct get_conf *gc)
 {
 	unsigned long size = 0;
 	char *buff;
@@ -681,47 +694,41 @@
 
 	DBG(DBG_REGISTER, print_pio_config(gc));
 
-	if (gc->DMA_support == TRUE) {
+	if (gc->DMA_support) {
 		printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n", base);
-		if (ALLOW_DMA_BOARDS == FALSE)
-			return (FALSE);
+		if (!ALLOW_DMA_BOARDS)
+			return 0;
 	}
 
 	if ((buff = get_pio_board_data((uint) base, gc->IRQ, gc->scsi_id[3], cplen = (htonl(gc->cplen) + 1) / 2, cppadlen = (htons(gc->cppadlen) + 1) / 2)) == NULL) {
 		printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (unsigned long) base);
-		return (FALSE);
+		return 0;
 	}
 
-	if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE) {
+	if (!print_selftest(base) && !ALLOW_DMA_BOARDS) {
 		printk("HBA at %#lx failed while performing self test & setup.\n", (unsigned long) base);
-		return (FALSE);
+		return 0;
 	}
 
-	request_region(base, 8, "eata_pio");
-
 	size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz));
 
-	sh = scsi_register(tpnt, size);
-	if (sh == NULL) {
-		release_region(base, 8);
-		return FALSE;
-	}
+	sh = scsi_register(&driver_template, size);
+	if (sh == NULL)
+		return 0;
 
 	if (!reg_IRQ[gc->IRQ]) {	/* Interrupt already registered ? */
 		if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", sh)) {
 			reg_IRQ[gc->IRQ]++;
 			if (!gc->IRQ_TR)
-				reg_IRQL[gc->IRQ] = TRUE;	/* IRQ is edge triggered */
+				reg_IRQL[gc->IRQ] = 1;	/* IRQ is edge triggered */
 		} else {
 			printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ);
-			release_region(base, 8);
-			return (FALSE);
+			return 0;
 		}
 	} else {		/* More than one HBA on this IRQ */
-		if (reg_IRQL[gc->IRQ] == TRUE) {
+		if (reg_IRQL[gc->IRQ]) {
 			printk("Can't support more than one HBA on this IRQ,\n" "  if the IRQ is edge triggered. Sorry.\n");
-			release_region(base, 8);
-			return (FALSE);
+			return 0;
 		} else
 			reg_IRQ[gc->IRQ]++;
 	}
@@ -757,9 +764,9 @@
 	}
 
 	if (ntohl(gc->len) >= 0x22) {
-		if (gc->is_PCI == TRUE)
+		if (gc->is_PCI)
 			hd->bustype = IS_PCI;
-		else if (gc->is_EISA == TRUE)
+		else if (gc->is_EISA)
 			hd->bustype = IS_EISA;
 		else
 			hd->bustype = IS_ISA;
@@ -780,7 +787,7 @@
 	sh->unique_id = base;
 	sh->base = base;
 	sh->io_port = base;
-	sh->n_io_port = 8;
+	sh->n_io_port = 9;
 	sh->irq = gc->IRQ;
 	sh->dma_channel = PIO;
 	sh->this_id = gc->scsi_id[3];
@@ -794,11 +801,11 @@
 	sh->max_lun = 8;
 
 	if (gc->SECOND)
-		hd->primary = FALSE;
+		hd->primary = 0;
 	else
-		hd->primary = TRUE;
+		hd->primary = 1;
 
-	sh->unchecked_isa_dma = FALSE;	/* We can only do PIO */
+	sh->unchecked_isa_dma = 0;	/* We can only do PIO */
 
 	hd->next = NULL;	/* build a linked list of all HBAs */
 	hd->prev = last_HBA;
@@ -811,22 +818,24 @@
 	return (1);
 }
 
-static void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt)
+static void find_pio_ISA(struct get_conf *buf)
 {
 	int i;
 
 	for (i = 0; i < MAXISA; i++) {
-		if (ISAbases[i]) {
-			if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE) {
-				register_pio_HBA(ISAbases[i], buf, tpnt);
-			}
+		if (!ISAbases[i])
+			continue;
+		if (!get_pio_conf_PIO(ISAbases[i], buf))
+			continue;
+		if (!register_pio_HBA(ISAbases[i], buf))
+			release_region(ISAbases[i], 9);
+		else
 			ISAbases[i] = 0;
-		}
 	}
 	return;
 }
 
-static void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt)
+static void find_pio_EISA(struct get_conf *buf)
 {
 	u32 base;
 	int i;
@@ -836,7 +845,7 @@
 #endif
 
 	for (i = 0; i < MAXEISA; i++) {
-		if (EISAbases[i] == TRUE) {	/* Still a possibility ?          */
+		if (EISAbases[i]) {	/* Still a possibility ?          */
 
 			base = 0x1c88 + (i * 0x1000);
 #if CHECKPAL
@@ -847,12 +856,15 @@
 			if (((pal1 == 0x12) && (pal2 == 0x14)) || ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) {
 				DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: " "%x %x %x \n", (int) pal1, (int) pal2, (int) pal3));
 #endif
-				if (get_pio_conf_PIO(base, buf) == TRUE) {
+				if (get_pio_conf_PIO(base, buf)) {
 					DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf));
 					if (buf->IRQ) {
-						register_pio_HBA(base, buf, tpnt);
-					} else
+						if (!register_pio_HBA(base, buf))
+							release_region(base, 9);
+					} else {
 						printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " "removed from list\n");
+						release_region(base, 9);
+					}
 				}
 				/* Nothing found here so we take it from the list */
 				EISAbases[i] = 0;
@@ -864,7 +876,7 @@
 	return;
 }
 
-static void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
+static void find_pio_PCI(struct get_conf *buf)
 {
 #ifndef CONFIG_PCI
 	printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");
@@ -889,16 +901,21 @@
 		base += 0x10;	/* Now, THIS is the real address */
 		if (base != 0x1f8) {
 			/* We didn't find it in the primary search */
-			if (get_pio_conf_PIO(base, buf) == TRUE) {
-				if (buf->FORCADR)	/* If the address is forced */
+			if (get_pio_conf_PIO(base, buf)) {
+				if (buf->FORCADR) {	/* If the address is forced */
+					release_region(base, 9);
 					continue;	/* we'll find it later      */
+				}
 
 				/* OK. We made it till here, so we can go now  
 				 * and register it. We  only have to check and 
 				 * eventually remove it from the EISA and ISA list 
 				 */
 
-				register_pio_HBA(base, buf, tpnt);
+				if (!register_pio_HBA(base, buf)) {
+					release_region(base, 9);
+					continue;
+				}
 
 				if (base < 0x1000) {
 					for (x = 0; x < MAXISA; ++x) {
@@ -913,7 +930,7 @@
 				}
 			}
 #if CHECK_BLINK
-			else if (check_blink_state(base) == TRUE) {
+			else if (check_blink_state(base)) {
 				printk("eata_pio: HBA is in BLINK state.\n" "Consult your HBAs manual to correct this.\n");
 			}
 #endif
@@ -922,20 +939,15 @@
 #endif				/* #ifndef CONFIG_PCI */
 }
 
-
-static int eata_pio_detect(Scsi_Host_Template * tpnt)
+static int eata_pio_detect(struct scsi_host_template *tpnt)
 {
 	struct Scsi_Host *HBA_ptr;
 	struct get_conf gc;
 	int i;
 
-	tpnt->proc_name = "eata_pio";
-
-	find_pio_PCI(&gc, tpnt);
-
-	find_pio_EISA(&gc, tpnt);
-
-	find_pio_ISA(&gc, tpnt);
+	find_pio_PCI(&gc);
+	find_pio_EISA(&gc);
+	find_pio_ISA(&gc);
 
 	for (i = 0; i <= MAXIRQ; i++)
 		if (reg_IRQ[i])
@@ -955,16 +967,19 @@
 			       HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
 			       SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P') ?
 			       "PCI " : (SD(HBA_ptr)->bustype == 'E') ? "EISA" : "ISA ",
-			       (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE) ? 'Y' : 'N', HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
+			       (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, HBA_ptr->this_id,
+			       SD(HBA_ptr)->primary ? 'Y' : 'N', HBA_ptr->can_queue,
+			       HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
 			HBA_ptr = SD(HBA_ptr)->next;
 		}
 	}
 	return (registered_HBAs);
 }
 
-static Scsi_Host_Template driver_template = {
-	.proc_info         	= eata_pio_proc_info,
+static struct scsi_host_template driver_template = {
+	.proc_name		= "eata_pio",
 	.name              	= "EATA (Extended Attachment) PIO driver",
+	.proc_info         	= eata_pio_proc_info,
 	.detect            	= eata_pio_detect,
 	.release           	= eata_pio_release,
 	.queuecommand      	= eata_pio_queue,
diff -Nru a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c
--- a/drivers/scsi/fastlane.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/fastlane.c	2004-06-23 19:04:26 -07:00
@@ -36,7 +36,7 @@
 #include <linux/interrupt.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <linux/zorro.h>
diff -Nru a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
--- a/drivers/scsi/fcal.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/fcal.c	2004-06-23 19:04:25 -07:00
@@ -21,7 +21,7 @@
 #include <asm/irq.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "../fc4/fcp_impl.h"
 #include "fcal.h"
 
diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
--- a/drivers/scsi/fd_mcs.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/fd_mcs.c	2004-06-23 19:04:26 -07:00
@@ -87,13 +87,14 @@
 #include <linux/delay.h>
 #include <linux/mca.h>
 #include <linux/spinlock.h>
+#include <scsi/scsicam.h>
 #include <linux/mca-legacy.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "fd_mcs.h"
 
 #define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
@@ -1337,23 +1338,14 @@
 static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
 			    sector_t capacity, int *info_array) 
 {
-	unsigned char buf[512 + sizeof(int) * 2];
+	unsigned char *p = scsi_bios_ptable(bdev);
 	int size = capacity;
-	int *sizes = (int *) buf;
-	unsigned char *data = (unsigned char *) (sizes + 2);
-	unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 };
-	int retcode;
 
 	/* BIOS >= 3.4 for MCA cards */
 	/* This algorithm was provided by Future Domain (much thanks!). */
 
-	sizes[0] = 0;	/* zero bytes out */
-	sizes[1] = 512;	/* one sector in */
-	memcpy(data, do_read, sizeof(do_read));
-	retcode = kernel_scsi_ioctl(disk, SCSI_IOCTL_SEND_COMMAND, (void *) buf);
-	if (!retcode	/* SCSI command ok */
-	    && data[511] == 0xaa && data[510] == 0x55	/* Partition table valid */
-	    && data[0x1c2]) {	/* Partition type */
+	if (p && p[65] == 0xaa && p[64] == 0x55	/* Partition table valid */
+	    && p[4]) {	/* Partition type */
 		/* The partition table layout is as follows:
 
 		   Start: 0x1b3h
@@ -1383,8 +1375,8 @@
 		   Future Domain algorithm, but it seemed to be a reasonable thing
 		   to do, especially in the Linux and BSD worlds. */
 
-		info_array[0] = data[0x1c3] + 1;	/* heads */
-		info_array[1] = data[0x1c4] & 0x3f;	/* sectors */
+		info_array[0] = p[5] + 1;	/* heads */
+		info_array[1] = p[6] & 0x3f;	/* sectors */
 	} else {
 		/* Note that this new method guarantees that there will always be
 		   less than 1024 cylinders on a platter.  This is good for drives
@@ -1403,6 +1395,7 @@
 	}
 	/* For both methods, compute the cylinders */
 	info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]);
+	kfree(p);
 	return 0;
 }
 
diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
--- a/drivers/scsi/fdomain.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/fdomain.c	2004-06-23 19:04:28 -07:00
@@ -279,12 +279,13 @@
 #include <linux/pci.h>
 #include <linux/stat.h>
 #include <linux/delay.h>
+#include <scsi/scsicam.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 MODULE_AUTHOR("Rickard E. Faith");
 MODULE_DESCRIPTION("Future domain SCSI driver");
@@ -1564,12 +1565,7 @@
 		sector_t capacity, int *info_array)
 {
    int              drive;
-   unsigned char    buf[512 + sizeof (Scsi_Ioctl_Command)];
-   Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;
    int		    size      = capacity;
-   unsigned char    *data     = sic->data;
-   unsigned char    do_read[] = { READ_6, 0, 0, 0, 1, 0 };
-   int              retcode;
    unsigned long    offset;
    struct drive_info {
       unsigned short cylinders;
@@ -1657,16 +1653,10 @@
       info_array[2] = i.cylinders;
    } else {			/* 3.4 BIOS (and up?) */
       /* This algorithm was provided by Future Domain (much thanks!). */
+      unsigned char *p = scsi_bios_ptable(bdev);
 
-      sic->inlen  = 0;		/* zero bytes out */
-      sic->outlen = 512;		/* one sector in */
-      memcpy( data, do_read, sizeof( do_read ) );
-      retcode = kernel_scsi_ioctl( sdev,
-				   SCSI_IOCTL_SEND_COMMAND,
-				   sic );
-      if (!retcode				    /* SCSI command ok */
-	  && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
-	  && data[0x1c2]) {			    /* Partition type */
+      if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */
+	  && p[4]) {			    /* Partition type */
 
 	 /* The partition table layout is as follows:
 
@@ -1697,8 +1687,8 @@
 	    Future Domain algorithm, but it seemed to be a reasonable thing
 	    to do, especially in the Linux and BSD worlds. */
 
-	 info_array[0] = data[0x1c3] + 1;	    /* heads */
-	 info_array[1] = data[0x1c4] & 0x3f;	    /* sectors */
+	 info_array[0] = p[5] + 1;	    /* heads */
+	 info_array[1] = p[6] & 0x3f;	    /* sectors */
       } else {
 
  	 /* Note that this new method guarantees that there will always be
@@ -1718,6 +1708,7 @@
       }
 				/* For both methods, compute the cylinders */
       info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
+      kfree(p);
    }
    
    return 0;
diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
--- a/drivers/scsi/g_NCR5380.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/g_NCR5380.c	2004-06-23 19:04:25 -07:00
@@ -107,7 +107,7 @@
 #include <linux/sched.h>
 #include <linux/blkdev.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "g_NCR5380.h"
 #include "NCR5380.h"
 #include <linux/stat.h>
diff -Nru a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
--- a/drivers/scsi/gvp11.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/gvp11.c	2004-06-23 19:04:28 -07:00
@@ -16,7 +16,7 @@
 #include <linux/spinlock.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "wd33c93.h"
 #include "gvp11.h"
 
diff -Nru a/drivers/scsi/i60uscsi.c b/drivers/scsi/i60uscsi.c
--- a/drivers/scsi/i60uscsi.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/i60uscsi.c	2004-06-23 19:04:25 -07:00
@@ -81,7 +81,7 @@
 #include <asm/io.h>
 #include <linux/blkdev.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "inia100.h"
 
 #define JIFFIES_TO_MS(t) ((t) * 1000 / HZ)
diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
--- a/drivers/scsi/ibmmca.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/ibmmca.c	2004-06-23 19:04:25 -07:00
@@ -45,7 +45,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "ibmmca.h"
 
 /* current version of this driver-source: */
diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
--- a/drivers/scsi/ide-scsi.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/ide-scsi.c	2004-06-23 19:04:27 -07:00
@@ -51,7 +51,7 @@
 #include <asm/uaccess.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/sg.h>
 
 #define IDESCSI_DEBUG_LOG		0
diff -Nru a/drivers/scsi/imm.h b/drivers/scsi/imm.h
--- a/drivers/scsi/imm.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/imm.h	2004-06-23 19:04:25 -07:00
@@ -79,7 +79,7 @@
 #include  <linux/interrupt.h>
 
 #include  <asm/io.h>
-#include  "hosts.h"
+#include  <scsi/scsi_host.h>
 /* batteries not included :-) */
 
 /*
diff -Nru a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
--- a/drivers/scsi/in2000.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/in2000.c	2004-06-23 19:04:28 -07:00
@@ -126,7 +126,7 @@
 #include <asm/system.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #define IN2000_VERSION    "1.33-2.5"
 #define IN2000_DATE       "2002/11/03"
diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c
--- a/drivers/scsi/ini9100u.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/ini9100u.c	2004-06-23 19:04:26 -07:00
@@ -136,7 +136,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "ini9100u.h"
 
 #ifdef DEBUG_i91u
diff -Nru a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
--- a/drivers/scsi/ipr.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/ipr.c	2004-06-23 19:04:29 -07:00
@@ -2884,6 +2884,7 @@
 		    (res->cfgte.res_addr.lun == sdev->lun)) {
 			res->sdev = sdev;
 			res->add_to_ml = 0;
+			res->in_erp = 0;
 			sdev->hostdata = res;
 			res->needs_sync_complete = 1;
 			break;
@@ -3435,8 +3436,10 @@
 		       SCSI_SENSE_BUFFERSIZE);
 	}
 
-	if (res)
+	if (res) {
 		res->needs_sync_complete = 1;
+		res->in_erp = 0;
+	}
 	ipr_unmap_sglist(ioa_cfg, ipr_cmd);
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 	scsi_cmd->scsi_done(scsi_cmd);
@@ -3479,6 +3482,12 @@
 static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd)
 {
 	struct ipr_cmd_pkt *cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
+	u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+
+	if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
+		ipr_erp_done(ipr_cmd);
+		return;
+	}
 
 	ipr_reinit_ipr_cmnd_for_erp(ipr_cmd);
 
@@ -3756,6 +3765,7 @@
 			ipr_erp_cancel_all(ipr_cmd);
 			return;
 		}
+		res->needs_sync_complete = 1;
 		break;
 	case IPR_IOASC_NR_INIT_CMD_REQUIRED:
 		break;
@@ -4808,6 +4818,7 @@
 	ipr_cmd->timer.data = (unsigned long) ipr_cmd;
 	ipr_cmd->timer.expires = jiffies + IPR_OPERATIONAL_TIMEOUT;
 	ipr_cmd->timer.function = (void (*)(unsigned long))ipr_timeout;
+	ipr_cmd->done = ipr_reset_ioa_job;
 	add_timer(&ipr_cmd->timer);
 	list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
 
diff -Nru a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
--- a/drivers/scsi/ipr.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/ipr.h	2004-06-23 19:04:26 -07:00
@@ -36,8 +36,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.0.7"
-#define IPR_DRIVER_DATE "(May 21, 2004)"
+#define IPR_DRIVER_VERSION "2.0.9"
+#define IPR_DRIVER_DATE "(May 26, 2004)"
 
 /*
  * IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/ips.c	2004-06-23 19:04:25 -07:00
@@ -176,7 +176,7 @@
 #include <scsi/sg.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "ips.h"
 
 #include <linux/module.h>
diff -Nru a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
--- a/drivers/scsi/jazz_esp.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/jazz_esp.c	2004-06-23 19:04:25 -07:00
@@ -16,7 +16,7 @@
 #include <linux/stat.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <asm/irq.h>
diff -Nru a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
--- a/drivers/scsi/lasi700.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/lasi700.c	2004-06-23 19:04:25 -07:00
@@ -49,8 +49,7 @@
 #include <asm/parisc-device.h>
 #include <asm/delay.h>
 
-#include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "lasi700.h"
 #include "53c700.h"
@@ -65,7 +64,7 @@
 	{ 0 }
 };
 
-static Scsi_Host_Template lasi700_template = {
+static struct scsi_host_template lasi700_template = {
 	.name		= "LASI SCSI 53c700",
 	.proc_name	= "lasi700",
 	.this_id	= 7,
diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/libata-core.c	2004-06-23 19:04:25 -07:00
@@ -50,7 +50,6 @@
 				    unsigned long tmout_pat,
 			    	    unsigned long tmout);
 static void __ata_dev_select (struct ata_port *ap, unsigned int device);
-static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat);
 static void ata_host_set_pio(struct ata_port *ap);
 static void ata_host_set_udma(struct ata_port *ap);
 static void ata_dev_set_pio(struct ata_port *ap, unsigned int device);
@@ -65,37 +64,6 @@
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
 
-static const char * thr_state_name[] = {
-	"THR_UNKNOWN",
-	"THR_PORT_RESET",
-	"THR_AWAIT_DEATH",
-	"THR_PROBE_FAILED",
-	"THR_IDLE",
-	"THR_PROBE_SUCCESS",
-	"THR_PROBE_START",
-};
-
-/**
- *	ata_thr_state_name - convert thread state enum to string
- *	@thr_state: thread state to be converted to string
- *
- *	Converts the specified thread state id to a constant C string.
- *
- *	LOCKING:
- *	None.
- *
- *	RETURNS:
- *	The THR_xxx-prefixed string naming the specified thread
- *	state id, or the string "<invalid THR_xxx state>".
- */
-
-static const char *ata_thr_state_name(unsigned int thr_state)
-{
-	if (thr_state < ARRAY_SIZE(thr_state_name))
-		return thr_state_name[thr_state];
-	return "<invalid THR_xxx state>";
-}
-
 /**
  *	ata_tf_load_pio - send taskfile registers to host controller
  *	@ap: Port to which output is sent
@@ -1150,13 +1118,16 @@
 }
 
 /**
- *	ata_port_reset -
- *	@ap:
+ *	ata_bus_probe - Reset and probe ATA bus
+ *	@ap: Bus to probe
  *
  *	LOCKING:
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
  */
 
-static void ata_port_reset(struct ata_port *ap)
+static int ata_bus_probe(struct ata_port *ap)
 {
 	unsigned int i, found = 0;
 
@@ -1180,14 +1151,12 @@
 	if (ap->flags & ATA_FLAG_PORT_DISABLED)
 		goto err_out_disable;
 
-	ap->thr_state = THR_PROBE_SUCCESS;
-
-	return;
+	return 0;
 
 err_out_disable:
 	ap->ops->port_disable(ap);
 err_out:
-	ap->thr_state = THR_PROBE_FAILED;
+	return -1;
 }
 
 /**
@@ -1806,13 +1775,13 @@
 }
 
 /**
- *	ata_fill_sg -
- *	@qc:
+ *	ata_fill_sg - Fill PCI IDE PRD table
+ *	@qc: Metadata associated with taskfile to be transferred
  *
  *	LOCKING:
  *
  */
-void ata_fill_sg(struct ata_queued_cmd *qc)
+static void ata_fill_sg(struct ata_queued_cmd *qc)
 {
 	struct scatterlist *sg = qc->sg;
 	struct ata_port *ap = qc->ap;
@@ -1854,6 +1823,21 @@
 }
 
 /**
+ *	ata_qc_prep - Prepare taskfile for submission
+ *	@qc: Metadata associated with taskfile to be prepared
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_prep(struct ata_queued_cmd *qc)
+{
+	if (!(qc->flags & ATA_QCFLAG_SG))
+		return;
+
+	ata_fill_sg(qc);
+}
+
+/**
  *	ata_sg_setup_one -
  *	@qc:
  *
@@ -1870,7 +1854,6 @@
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
 	struct scatterlist *sg = qc->sg;
-	unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
 	dma_addr_t dma_address;
 
 	assert(sg == &qc->sgent);
@@ -1880,9 +1863,6 @@
 	sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK;
 	sg_dma_len(sg) = cmd->request_bufflen;
 
-	if (!have_sg)
-		return 0;
-
 	dma_address = pci_map_single(ap->host_set->pdev, cmd->request_buffer,
 				     cmd->request_bufflen, dir);
 	if (pci_dma_mapping_error(dma_address))
@@ -1912,22 +1892,19 @@
 	struct ata_port *ap = qc->ap;
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct scatterlist *sg;
-	int n_elem;
-	unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
+	int n_elem, dir;
 
 	VPRINTK("ENTER, ata%u, use_sg %d\n", ap->id, cmd->use_sg);
 	assert(cmd->use_sg > 0);
 
 	sg = (struct scatterlist *)cmd->request_buffer;
-	if (have_sg) {
-		int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
-		n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir);
-		if (n_elem < 1)
-			return -1;
-		DPRINTK("%d sg elements mapped\n", n_elem);
-	} else {
-		n_elem = cmd->use_sg;
-	}
+	dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+	n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir);
+	if (n_elem < 1)
+		return -1;
+
+	DPRINTK("%d sg elements mapped\n", n_elem);
+
 	qc->n_elem = n_elem;
 
 	return 0;
@@ -2146,8 +2123,8 @@
 }
 
 /**
- *	ata_eng_timeout - Handle timeout of queued command
- *	@ap: Port on which timed-out command is active
+ *	ata_qc_timeout - Handle timeout of queued command
+ *	@qc: Command that timed out
  *
  *	Some part of the kernel (currently, only the SCSI layer)
  *	has noticed that the active command on port @ap has not
@@ -2161,23 +2138,15 @@
  *	transaction completed successfully.
  *
  *	LOCKING:
- *	Inherited from SCSI layer (none, can sleep)
  */
 
-void ata_eng_timeout(struct ata_port *ap)
+static void ata_qc_timeout(struct ata_queued_cmd *qc)
 {
-	u8 host_stat, drv_stat;
-	struct ata_queued_cmd *qc;
+	struct ata_port *ap = qc->ap;
+	u8 host_stat = 0, drv_stat;
 
 	DPRINTK("ENTER\n");
 
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	if (!qc) {
-		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
-		       ap->id);
-		goto out;
-	}
-
 	/* hack alert!  We cannot use the supplied completion
 	 * function from inside the ->eh_strategy_handler() thread.
 	 * libata is the only user of ->eh_strategy_handler() in
@@ -2187,38 +2156,69 @@
 	qc->scsidone = scsi_finish_command;
 
 	switch (qc->tf.protocol) {
+
 	case ATA_PROT_DMA:
-		if (ap->flags & ATA_FLAG_MMIO) {
-			void *mmio = (void *) ap->ioaddr.bmdma_addr;
-			host_stat = readb(mmio + ATA_DMA_STATUS);
-		} else
-			host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	case ATA_PROT_ATAPI_DMA:
+		host_stat = ata_bmdma_status(ap);
 
-		printk(KERN_ERR "ata%u: DMA timeout, stat 0x%x\n",
-		       ap->id, host_stat);
+		/* before we do anything else, clear DMA-Start bit */
+		ata_bmdma_stop(ap);
 
-		ata_dma_complete(qc, host_stat);
-		break;
+		/* fall through */
 
 	case ATA_PROT_NODATA:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+	default:
+		ata_altstatus(ap);
+		drv_stat = ata_chk_status(ap);
+
+		/* ack bmdma irq events */
+		ata_bmdma_ack_irq(ap);
 
-		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
+		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
+		       ap->id, qc->tf.command, drv_stat, host_stat);
 
+		/* complete taskfile transaction */
 		ata_qc_complete(qc, drv_stat);
 		break;
+	}
 
-	default:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+	DPRINTK("EXIT\n");
+}
 
-		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
+/**
+ *	ata_eng_timeout - Handle timeout of queued command
+ *	@ap: Port on which timed-out command is active
+ *
+ *	Some part of the kernel (currently, only the SCSI layer)
+ *	has noticed that the active command on port @ap has not
+ *	completed after a specified length of time.  Handle this
+ *	condition by disabling DMA (if necessary) and completing
+ *	transactions, with error if necessary.
+ *
+ *	This also handles the case of the "lost interrupt", where
+ *	for some reason (possibly hardware bug, possibly driver bug)
+ *	an interrupt was not delivered to the driver, even though the
+ *	transaction completed successfully.
+ *
+ *	LOCKING:
+ *	Inherited from SCSI layer (none, can sleep)
+ */
 
-		ata_qc_complete(qc, drv_stat);
-		break;
+void ata_eng_timeout(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+
+	DPRINTK("ENTER\n");
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	if (!qc) {
+		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+		       ap->id);
+		goto out;
 	}
 
+	ata_qc_timeout(qc);
+
 out:
 	DPRINTK("EXIT\n");
 }
@@ -2316,7 +2316,7 @@
 		qc->scsidone(cmd);
 	}
 
-	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	qc->flags = 0;
 	tag = qc->tag;
 	if (likely(ata_tag_valid(tag))) {
 		if (tag == ap->active_tag)
@@ -2362,10 +2362,10 @@
 			if (ata_sg_setup_one(qc))
 				goto err_out;
 		}
-
-		ap->ops->fill_sg(qc);
 	}
 
+	ap->ops->qc_prep(qc);
+
 	qc->ap->active_tag = qc->tag;
 	qc->flags |= ATA_QCFLAG_ACTIVE;
 
@@ -2446,7 +2446,7 @@
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-	u8 host_stat, dmactl;
+	u8 dmactl;
 	void *mmio = (void *) ap->ioaddr.bmdma_addr;
 
 	/* load PRD table addr. */
@@ -2460,10 +2460,6 @@
 		dmactl |= ATA_DMA_WR;
 	writeb(dmactl, mmio + ATA_DMA_CMD);
 
-	/* clear interrupt, error bits */
-	host_stat = readb(mmio + ATA_DMA_STATUS);
-	writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, mmio + ATA_DMA_STATUS);
-
 	/* issue r/w command */
 	ap->ops->exec_command(ap, &qc->tf);
 }
@@ -2511,7 +2507,7 @@
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-	u8 host_stat, dmactl;
+	u8 dmactl;
 
 	/* load PRD table addr. */
 	outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
@@ -2523,11 +2519,6 @@
 		dmactl |= ATA_DMA_WR;
 	outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 
-	/* clear interrupt, error bits */
-	host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-	outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-	     ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-
 	/* issue r/w command */
 	ap->ops->exec_command(ap, &qc->tf);
 }
@@ -2552,50 +2543,6 @@
 }
 
 /**
- *	ata_dma_complete - Complete an active ATA BMDMA command
- *	@qc: Command to complete
- *	@host_stat: BMDMA status register contents
- *
- *	LOCKING:
- */
-
-static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat)
-{
-	struct ata_port *ap = qc->ap;
-	VPRINTK("ENTER\n");
-
-	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
-
-		/* clear start/stop bit */
-		writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
-		       mmio + ATA_DMA_CMD);
-
-		/* ack intr, err bits */
-		writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-		       mmio + ATA_DMA_STATUS);
-	} else {
-		/* clear start/stop bit */
-		outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
-		     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-
-		/* ack intr, err bits */
-		outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-		     ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-	}
-
-
-	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-	ata_altstatus(ap);		/* dummy read */
-
-	DPRINTK("host %u, host_stat==0x%X, drv_stat==0x%X\n",
-		ap->id, (u32) host_stat, (u32) ata_chk_status(ap));
-
-	/* get drive status; clear intr; complete txn */
-	ata_qc_complete(qc, ata_wait_idle(ap));
-}
-
-/**
  *	ata_host_intr - Handle host interrupt for given (port, task)
  *	@ap: Port on which interrupt arrived (possibly...)
  *	@qc: Taskfile currently active in engine
@@ -2615,59 +2562,60 @@
 				   struct ata_queued_cmd *qc)
 {
 	u8 status, host_stat;
-	unsigned int handled = 0;
 
 	switch (qc->tf.protocol) {
 
-	/* BMDMA completion */
 	case ATA_PROT_DMA:
 	case ATA_PROT_ATAPI_DMA:
-		if (ap->flags & ATA_FLAG_MMIO) {
-			void *mmio = (void *) ap->ioaddr.bmdma_addr;
-			host_stat = readb(mmio + ATA_DMA_STATUS);
-		} else
-			host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+		/* check status of DMA engine */
+		host_stat = ata_bmdma_status(ap);
 		VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat);
 
-		if (!(host_stat & ATA_DMA_INTR)) {
-			ap->stats.idle_irq++;
-			break;
-		}
+		/* if it's not our irq... */
+		if (!(host_stat & ATA_DMA_INTR))
+			goto idle_irq;
 
-		ata_dma_complete(qc, host_stat);
-		handled = 1;
-		break;
+		/* before we do anything else, clear DMA-Start bit */
+		ata_bmdma_stop(ap);
+
+		/* fall through */
 
-	/* command completion, but no data xfer */
-	/* FIXME: a shared interrupt _will_ cause a non-data command
-	 * to be completed prematurely, with an error.
-	 *
-	 * This doesn't matter right now, since we aren't sending
-	 * non-data commands down this pipe except in development
-	 * situations.
-	 */
-	case ATA_PROT_ATAPI:
 	case ATA_PROT_NODATA:
-		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+		/* check altstatus */
+		status = ata_altstatus(ap);
+		if (status & ATA_BUSY)
+			goto idle_irq;
+
+		/* check main status, clearing INTRQ */
+		status = ata_chk_status(ap);
+		if (unlikely(status & ATA_BUSY))
+			goto idle_irq;
+		DPRINTK("BUS_NODATA (dev_stat 0x%X)\n", status);
+
+		/* ack bmdma irq events */
+		ata_bmdma_ack_irq(ap);
+
+		/* complete taskfile transaction */
 		ata_qc_complete(qc, status);
-		handled = 1;
 		break;
 
 	default:
-		ap->stats.idle_irq++;
+		goto idle_irq;
+	}
+
+	return 1;	/* irq handled */
+
+idle_irq:
+	ap->stats.idle_irq++;
 
 #ifdef ATA_IRQ_TRAP
-		if ((ap->stats.idle_irq % 1000) == 0) {
-			handled = 1;
-			ata_irq_ack(ap, 0); /* debug trap */
-			printk(KERN_WARNING "ata%d: irq trap\n", ap->id);
-		}
-#endif
-		break;
+	if ((ap->stats.idle_irq % 1000) == 0) {
+		handled = 1;
+		ata_irq_ack(ap, 0); /* debug trap */
+		printk(KERN_WARNING "ata%d: irq trap\n", ap->id);
 	}
-
-	return handled;
+#endif
+	return 0;	/* irq not handled */
 }
 
 /**
@@ -2701,7 +2649,7 @@
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
 			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
-				handled += ata_host_intr(ap, qc);
+				handled |= ata_host_intr(ap, qc);
 		}
 	}
 
@@ -2711,62 +2659,6 @@
 }
 
 /**
- *	ata_thread_iter -
- *	@ap:
- *
- *	LOCKING:
- *
- *	RETURNS:
- *
- */
-
-static unsigned long ata_thread_iter(struct ata_port *ap)
-{
-	long timeout = 0;
-
-	DPRINTK("ata%u: thr_state %s\n",
-		ap->id, ata_thr_state_name(ap->thr_state));
-
-	switch (ap->thr_state) {
-	case THR_UNKNOWN:
-		ap->thr_state = THR_PORT_RESET;
-		break;
-
-	case THR_PROBE_START:
-		ap->thr_state = THR_PORT_RESET;
-		break;
-
-	case THR_PORT_RESET:
-		ata_port_reset(ap);
-		break;
-
-	case THR_PROBE_SUCCESS:
-		up(&ap->probe_sem);
-		ap->thr_state = THR_IDLE;
-		break;
-
-	case THR_PROBE_FAILED:
-		up(&ap->probe_sem);
-		ap->thr_state = THR_AWAIT_DEATH;
-		break;
-
-	case THR_AWAIT_DEATH:
-	case THR_IDLE:
-		timeout = -1;
-		break;
-
-	default:
-		printk(KERN_DEBUG "ata%u: unknown thr state %s\n",
-		       ap->id, ata_thr_state_name(ap->thr_state));
-		break;
-	}
-
-	DPRINTK("ata%u: new thr_state %s, returning %ld\n",
-		ap->id, ata_thr_state_name(ap->thr_state), timeout);
-	return timeout;
-}
-
-/**
  *	atapi_packet_task - Write CDB bytes to hardware
  *	@_data: Port to which ATAPI device is attached.
  *
@@ -2847,21 +2739,6 @@
 	pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
 }
 
-static void ata_probe_task(void *_data)
-{
-	struct ata_port *ap = _data;
-	long timeout;
-
-	timeout = ata_thread_iter(ap);
-	if (timeout < 0)
-		return;
-
-	if (timeout > 0)
-		queue_delayed_work(ata_wq, &ap->probe_task, timeout);
-	else
-		queue_work(ata_wq, &ap->probe_task);
-}
-
 /**
  *	ata_host_remove - Unregister SCSI host structure with upper layers
  *	@ap: Port to unregister
@@ -2918,7 +2795,6 @@
 	ap->udma_mask = ent->udma_mask;
 	ap->flags |= ent->host_flags;
 	ap->ops = ent->port_ops;
-	ap->thr_state = THR_PROBE_START;
 	ap->cbl = ATA_CBL_NONE;
 	ap->device[0].flags = ATA_DFLAG_MASTER;
 	ap->active_tag = ATA_TAG_POISON;
@@ -2926,13 +2802,10 @@
 
 	INIT_WORK(&ap->packet_task, atapi_packet_task, ap);
 	INIT_WORK(&ap->pio_task, ata_pio_task, ap);
-	INIT_WORK(&ap->probe_task, ata_probe_task, ap);
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++)
 		ap->device[i].devno = i;
 
-	init_MUTEX_LOCKED(&ap->probe_sem);
-
 #ifdef ATA_IRQ_TRAP
 	ap->stats.unhandled_irq = 1;
 	ap->stats.idle_irq = 1;
@@ -3041,6 +2914,10 @@
 		return 0;
 	}
 
+	/* TODO: ack irq here, to ensure it won't scream
+	 * when we enable it?
+	 */
+
 	/* obtain irq, that is shared between channels */
 	if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
 			DRV_NAME, host_set))
@@ -3055,12 +2932,17 @@
 		ap = host_set->ports[i];
 
 		DPRINTK("ata%u: probe begin\n", ap->id);
-		queue_work(ata_wq, &ap->probe_task);	/* start probe */
-
-		DPRINTK("ata%u: probe-wait begin\n", ap->id);
-		down(&ap->probe_sem);	/* wait for end */
+		rc = ata_bus_probe(ap);
+		DPRINTK("ata%u: probe end\n", ap->id);
 
-		DPRINTK("ata%u: probe-wait end\n", ap->id);
+		if (rc) {
+			/* FIXME: do something useful here?
+			 * Current libata behavior will
+			 * tear down everything when
+			 * the module is removed
+			 * or the h/w is unplugged.
+			 */
+		}
 
 		rc = scsi_add_host(ap->host, &pdev->dev);
 		if (rc) {
@@ -3480,7 +3362,7 @@
 EXPORT_SYMBOL_GPL(ata_port_start);
 EXPORT_SYMBOL_GPL(ata_port_stop);
 EXPORT_SYMBOL_GPL(ata_interrupt);
-EXPORT_SYMBOL_GPL(ata_fill_sg);
+EXPORT_SYMBOL_GPL(ata_qc_prep);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio);
 EXPORT_SYMBOL_GPL(ata_bmdma_start_pio);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio);
diff -Nru a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
--- a/drivers/scsi/libata-scsi.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/libata-scsi.c	2004-06-23 19:04:26 -07:00
@@ -182,7 +182,8 @@
 		 * 65534 when Jens Axboe's patch for dynamically
 		 * determining max_sectors is merged.
 		 */
-		if (dev->flags & ATA_DFLAG_LBA48) {
+		if ((dev->flags & ATA_DFLAG_LBA48) &&
+		    ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) {
 			sdev->host->max_sectors = 2048;
 			blk_queue_max_sectors(sdev->request_queue, 2048);
 		}
diff -Nru a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
--- a/drivers/scsi/mac_esp.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/mac_esp.c	2004-06-23 19:04:27 -07:00
@@ -26,7 +26,7 @@
 #include <linux/interrupt.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <asm/io.h>
diff -Nru a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
--- a/drivers/scsi/mac_scsi.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/mac_scsi.c	2004-06-23 19:04:25 -07:00
@@ -52,7 +52,7 @@
 #include <asm/mac_via.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "mac_scsi.h"
 #include "NCR5380.h"
 
diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
--- a/drivers/scsi/mca_53c9x.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/mca_53c9x.c	2004-06-23 19:04:26 -07:00
@@ -43,7 +43,7 @@
 #include <linux/mca-legacy.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <asm/dma.h>
diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
--- a/drivers/scsi/megaraid.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/megaraid.c	2004-06-23 19:04:25 -07:00
@@ -49,7 +49,7 @@
 #include <scsi/scsicam.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "megaraid.h"
 
@@ -3815,7 +3815,8 @@
 
 			umc = MBOX_P(uiocp);
 
-			upthru = (mega_passthru *)umc->xferaddr;
+			if (get_user(upthru, (mega_passthru **)&umc->xferaddr))
+				return (-EFAULT);
 
 			if( put_user(mc->status, (u8 *)&upthru->scsistatus) )
 				return (-EFAULT);
@@ -3831,7 +3832,8 @@
 
 			umc = (megacmd_t *)uioc_mimd->mbox;
 
-			upthru = (mega_passthru *)umc->xferaddr;
+			if (get_user(upthru, (mega_passthru **)&umc->xferaddr))
+				return (-EFAULT);
 
 			if( put_user(mc->status, (u8 *)&upthru->scsistatus) )
 				return (-EFAULT);
@@ -4068,7 +4070,6 @@
 static int
 mega_del_logdrv(adapter_t *adapter, int logdrv)
 {
-	DECLARE_WAIT_QUEUE_HEAD(wq);
 	unsigned long flags;
 	scb_t *scb;
 	int rval;
@@ -4083,11 +4084,9 @@
 	 * Wait till all the issued commands are complete and there are no
 	 * commands in the pending queue
 	 */
-	while( atomic_read(&adapter->pend_cmds) > 0 ||
-			!list_empty(&adapter->pending_list) ) {
-
-		sleep_on_timeout( &wq, 1*HZ );	/* sleep for 1s */
-	}
+	while (atomic_read(&adapter->pend_cmds) > 0 ||
+	       !list_empty(&adapter->pending_list))
+		msleep(1000);	/* sleep for 1s */
 
 	rval = mega_do_del_logdrv(adapter, logdrv);
 
@@ -4610,6 +4609,26 @@
 
 	pci_bus = pdev->bus->number;
 	pci_dev_func = pdev->devfn;
+
+	/*
+	 * The megaraid3 stuff reports the ID of the Intel part which is not
+	 * remotely specific to the megaraid
+	 */
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+		u16 magic;
+		/*
+		 * Don't fall over the Compaq management cards using the same
+		 * PCI identifier
+		 */
+		if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ &&
+		    pdev->subsystem_device == 0xC000)
+		   	return -ENODEV;
+		/* Now check the magic signature byte */
+		pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic);
+		if (magic != HBA_SIGNATURE_471 && magic != HBA_SIGNATURE)
+			return -ENODEV;
+		/* Ok it is probably a megaraid */
+	}
 
 	/*
 	 * For these vendor and device ids, signature offsets are not
diff -Nru a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
--- a/drivers/scsi/mvme147.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/mvme147.c	2004-06-23 19:04:26 -07:00
@@ -11,7 +11,7 @@
 #include <asm/irq.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "wd33c93.h"
 #include "mvme147.h"
 
diff -Nru a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c
--- a/drivers/scsi/mvme16x.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/mvme16x.c	2004-06-23 19:04:28 -07:00
@@ -15,7 +15,7 @@
 #include <asm/irq.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "53c7xx.h"
 #include "mvme16x.h"
 
diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
--- a/drivers/scsi/ncr53c8xx.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/ncr53c8xx.c	2004-06-23 19:04:26 -07:00
@@ -138,7 +138,7 @@
 #include <asm/system.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "ncr53c8xx.h"
 
diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
--- a/drivers/scsi/nsp32.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/nsp32.c	2004-06-23 19:04:26 -07:00
@@ -44,7 +44,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi.h>
 
diff -Nru a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c
--- a/drivers/scsi/oktagon_esp.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/oktagon_esp.c	2004-06-23 19:04:25 -07:00
@@ -29,7 +29,7 @@
 
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <linux/zorro.h>
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/osst.c	2004-06-23 19:04:27 -07:00
@@ -61,7 +61,7 @@
 #define OSST_DEB_MSG  KERN_NOTICE
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsi_driver.h>
 #include <scsi/scsi_ioctl.h>
 
diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
--- a/drivers/scsi/pas16.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/pas16.c	2004-06-23 19:04:25 -07:00
@@ -125,7 +125,7 @@
 #include <linux/init.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "pas16.h"
 #define AUTOPROBE_IRQ
 #include "NCR5380.h"
diff -Nru a/drivers/scsi/pc980155.c b/drivers/scsi/pc980155.c
--- a/drivers/scsi/pc980155.c	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,299 +0,0 @@
-/*
- *
- *  drivers/scsi/pc980155.c
- *
- *  PC-9801-55 SCSI host adapter driver
- *
- *  Copyright (C) 1997-2003  Kyoto University Microcomputer Club
- *			     (Linux/98 project)
- *			     Tomoharu Ugawa <ohirune@kmc.gr.jp>
- *
- */
-
-#include <linux/module.h>
-#include <linux/blkdev.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-
-#include <asm/dma.h>
-
-#include "scsi.h"
-#include "hosts.h"
-#include "wd33c93.h"
-#include "pc980155.h"
-
-extern int pc98_bios_param(struct scsi_device *, struct block_device *,
-				sector_t, int *);
-static int scsi_pc980155_detect(Scsi_Host_Template *);
-static int scsi_pc980155_release(struct Scsi_Host *);
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 16
-#endif
-
-#undef PC_9801_55_DEBUG
-#undef PC_9801_55_DEBUG_VERBOSE
-
-#define NR_BASE_IOS 4
-static int nr_base_ios = NR_BASE_IOS;
-static unsigned int base_ios[NR_BASE_IOS] = {0xcc0, 0xcd0, 0xce0, 0xcf0};
-static wd33c93_regs init_regs;
-static int io;
-
-static struct Scsi_Host *pc980155_host = NULL;
-
-static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp);
-
-static inline void pc980155_dma_enable(unsigned int base_io)
-{
-	outb(0x01, REG_CWRITE);
-}
-
-static inline void pc980155_dma_disable(unsigned int base_io)
-{
-	outb(0x02, REG_CWRITE);
-}
-
-
-static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp)
-{
-	wd33c93_intr(pc980155_host);
-}
-
-static int dma_setup(Scsi_Cmnd *sc, int dir_in)
-{
-  /*
-   * sc->SCp.this_residual : transfer count
-   * sc->SCp.ptr : distination address (virtual address)
-   * dir_in : data direction (DATA_OUT_DIR:0 or DATA_IN_DIR:1)
-   *
-   * if success return 0
-   */
-
-   /*
-    * DMA WRITE MODE
-    * bit 7,6 01b single mode (this mode only)
-    * bit 5   inc/dec (default:0 = inc)
-    * bit 4   auto initialize (normaly:0 = off)
-    * bit 3,2 01b memory -> io
-    *         10b io -> memory
-    *         00b verify
-    * bit 1,0 channel
-    */
-	disable_dma(sc->device->host->dma_channel);
-	set_dma_mode(sc->device->host->dma_channel,
-			0x40 | (dir_in ? 0x04 : 0x08));
-	clear_dma_ff(sc->device->host->dma_channel);
-	set_dma_addr(sc->device->host->dma_channel, virt_to_phys(sc->SCp.ptr));
-	set_dma_count(sc->device->host->dma_channel, sc->SCp.this_residual);
-#ifdef PC_9801_55_DEBUG
-	printk("D%d(%x)D", sc->device->host->dma_channel,
-		sc->SCp.this_residual);
-#endif
-	enable_dma(sc->device->host->dma_channel);
-	pc980155_dma_enable(sc->device->host->io_port);
-	return 0;
-}
-
-static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *sc, int status)
-{
-  /*
-   * instance: Hostadapter's instance
-   * sc: scsi command
-   * status: True if success
-   */
-	pc980155_dma_disable(sc->device->host->io_port);
-	disable_dma(sc->device->host->dma_channel);
-}  
-
-/* return non-zero on detection */
-static inline int pc980155_test_port(wd33c93_regs regs)
-{
-	/* Quick and dirty test for presence of the card. */
-	if (inb(regs.SASR) == 0xff)
-		return 0;
-
-	return 1;
-}
-
-static inline int pc980155_getconfig(unsigned int base_io, wd33c93_regs regs,
-					unsigned char* irq, unsigned char* dma,
-					unsigned char* scsi_id)
-{
-	static unsigned char irqs[] = {3, 5, 6, 9, 12, 13};
-	unsigned char result;
-  
-	printk(KERN_DEBUG "PC-9801-55: base_io=%x SASR=%x SCMD=%x\n",
-		base_io, regs.SASR, regs.SCMD);
-	result = read_pc980155_resetint(regs);
-	printk(KERN_DEBUG "PC-9801-55: getting config (%x)\n", result);
-	*scsi_id = result & 0x07;
-	*irq = (result >> 3) & 0x07;
-	if (*irq > 5) {
-		printk(KERN_ERR "PC-9801-55 (base %#x): impossible IRQ (%d)"
-			" - other device here?\n", base_io, *irq);
-		return 0;
-	}
-
-	*irq = irqs[*irq];
-	result = inb(REG_STATRD);
-	*dma = result & 0x03;
-	if (*dma == 1) {
-		printk(KERN_ERR
-			"PC-9801-55 (base %#x): impossible DMA channl (%d)"
-			" - other device here?\n", base_io, *dma);
-		return 0;
-	}
-#ifdef PC_9801_55_DEBUG
-	printk("PC-9801-55: end of getconfig\n");
-#endif
-	return 1;
-}
-
-/* return non-zero on detection */
-static int scsi_pc980155_detect(Scsi_Host_Template* tpnt)
-{
-	unsigned int base_io;
-	unsigned char irq, dma, scsi_id;
-	int i;
-#ifdef PC_9801_55_DEBUG
-	unsigned char debug;
-#endif
-  
-	if (io) {
-		base_ios[0] = io;
-		nr_base_ios = 1;
-	}
-
-	for (i = 0; i < nr_base_ios; i++) {
-		base_io = base_ios[i];
-		init_regs.SASR = REG_ADDRST;
-		init_regs.SCMD = REG_CONTRL;
-#ifdef PC_9801_55_DEBUG
-		printk("PC-9801-55: SASR(%x = %x)\n", SASR, REG_ADDRST);
-#endif
-		if (!request_region(base_io, 6, "PC-9801-55"))
-			continue;
-
-		if (pc980155_test_port(init_regs) &&
-		    pc980155_getconfig(base_io, init_regs,
-					&irq, &dma, &scsi_id))
-			goto found;
-
-		release_region(base_io, 6);
-	}
-
-	printk("PC-9801-55: not found\n");
-	return 0;
-
-	found:
-#ifdef PC_9801_55_DEBUG
-	printk("PC-9801-55: config: base io = %x, irq = %d, dma channel = %d, scsi id = %d\n", base_io, irq, dma, scsi_id);
-#endif
-	if (request_irq(irq, pc980155_intr_handle, 0, "PC-9801-55", NULL)) {
-		printk(KERN_ERR "PC-9801-55: unable to allocate IRQ %d\n", irq);
-		goto err1;
-	}
-
-	if (request_dma(dma, "PC-9801-55")) {
-		printk(KERN_ERR "PC-9801-55: unable to allocate DMA channel %d\n", dma);
-		goto err2;
-	}
-
-	pc980155_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
-	if (pc980155_host) {
-		pc980155_host->this_id = scsi_id;
-		pc980155_host->io_port = base_io;
-		pc980155_host->n_io_port = 6;
-		pc980155_host->irq = irq;
-		pc980155_host->dma_channel = dma;
-		printk("PC-9801-55: scsi host found at %x irq = %d, use dma channel %d.\n", base_io, irq, dma);
-		pc980155_int_enable(init_regs);
-		wd33c93_init(pc980155_host, init_regs, dma_setup, dma_stop,
-				WD33C93_FS_12_15);
-		return 1;
-	}
-
-	printk(KERN_ERR "PC-9801-55: failed to register device\n");
-
-err2:
-	free_irq(irq, NULL);
-err1:
-	release_region(base_io, 6);
-	return 0;
-}
-
-static int scsi_pc980155_release(struct Scsi_Host *shost)
-{
-	struct WD33C93_hostdata *hostdata
-		= (struct WD33C93_hostdata *)shost->hostdata;
-
-	pc980155_int_disable(hostdata->regs);
-	release_region(shost->io_port, shost->n_io_port);
-	free_irq(shost->irq, NULL);
-	free_dma(shost->dma_channel);
-	wd33c93_release();
-	return 1;
-}
-
-static int pc980155_bus_reset(Scsi_Cmnd *cmd)
-{
-	struct WD33C93_hostdata *hostdata
-		= (struct WD33C93_hostdata *)cmd->device->host->hostdata;
-
-	pc980155_int_disable(hostdata->regs);
-	pc980155_assert_bus_reset(hostdata->regs);
-	udelay(50);
-	pc980155_negate_bus_reset(hostdata->regs);
-	(void) inb(hostdata->regs.SASR);
-	(void) read_pc980155(hostdata->regs, WD_SCSI_STATUS);
-	pc980155_int_enable(hostdata->regs);
-	wd33c93_host_reset(cmd);
-	return SUCCESS;
-}
-
-
-#ifndef MODULE
-static int __init pc980155_setup(char *str)
-{
-        int ints[4];
-
-        str = get_options(str, ARRAY_SIZE(ints), ints);
-        if (ints[0] > 0)
-		io = ints[1];
-        return 1;
-}
-__setup("pc980155_io=", pc980155_setup);
-#endif
-
-MODULE_PARM(io, "i");
-MODULE_AUTHOR("Tomoharu Ugawa <ohirune@kmc.gr.jp>");
-MODULE_DESCRIPTION("PC-9801-55 SCSI host adapter driver");
-MODULE_LICENSE("GPL");
-
-static Scsi_Host_Template driver_template = {
-	.proc_info		= wd33c93_proc_info,
-	.name			= "SCSI PC-9801-55",
-	.detect			= scsi_pc980155_detect,
-	.release		= scsi_pc980155_release,
-	.queuecommand		= wd33c93_queuecommand,
-	.eh_abort_handler	= wd33c93_abort,
-	.eh_bus_reset_handler	= pc980155_bus_reset,
-	.eh_host_reset_handler	= wd33c93_host_reset,
-	.bios_param		= pc98_bios_param,
-	.can_queue		= CAN_QUEUE,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= CMD_PER_LUN, /* dont use link command */
-	.unchecked_isa_dma	= 1, /* use dma **XXXX***/
-	.use_clustering		= ENABLE_CLUSTERING,
-	.proc_name		= "PC_9801_55",
-};
-
-#include "scsi_module.c"
diff -Nru a/drivers/scsi/pc980155.h b/drivers/scsi/pc980155.h
--- a/drivers/scsi/pc980155.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,52 +0,0 @@
-/*
- *
- *  drivers/scsi/pc980155.h
- *
- *  PC-9801-55 SCSI host adapter driver
- *
- *  Copyright (C) 1997-2003  Kyoto University Microcomputer Club
- *			     (Linux/98 project)
- *			     Tomoharu Ugawa <ohirune@kmc.gr.jp>
- *
- */
-
-#ifndef __PC980155_H
-#define __PC980155_H
-
-#include "wd33c93.h"
-
-#define REG_ADDRST (base_io)
-#define REG_CONTRL (base_io + 2)
-#define REG_CWRITE (base_io + 4)
-#define REG_STATRD (base_io + 4)
-
-#define WD_MEMORYBANK	0x30
-#define WD_RESETINT	0x33
-
-static inline uchar read_pc980155(const wd33c93_regs regs, uchar reg_num)
-{
-	outb(reg_num, regs.SASR);
-	return (uchar)inb(regs.SCMD);
-}
-
-static inline void write_memorybank(const wd33c93_regs regs, uchar value)
-{
-      outb(WD_MEMORYBANK, regs.SASR);
-      outb(value, regs.SCMD);
-}
-
-#define read_pc980155_resetint(regs) \
-	read_pc980155((regs), WD_RESETINT)
-#define pc980155_int_enable(regs) \
-	write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) | 0x04)
-
-#define pc980155_int_disable(regs) \
-	write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) & ~0x04)
-
-#define pc980155_assert_bus_reset(regs) \
-	write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) | 0x02)
-
-#define pc980155_negate_bus_reset(regs) \
-	write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) & ~0x02)
-
-#endif /* __PC980155_H */
diff -Nru a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c
--- a/drivers/scsi/pci2000.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/pci2000.c	2004-06-23 19:04:27 -07:00
@@ -54,7 +54,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "pci2000.h"
 #include "psi_roy.h"
 
diff -Nru a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c
--- a/drivers/scsi/pci2220i.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/pci2220i.c	2004-06-23 19:04:25 -07:00
@@ -59,7 +59,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "pci2220i.h"
 #include "psi_dale.h"
 
diff -Nru a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
--- a/drivers/scsi/pcmcia/aha152x_stub.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/pcmcia/aha152x_stub.c	2004-06-23 19:04:28 -07:00
@@ -47,7 +47,7 @@
 #include <scsi/scsi_ioctl.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "aha152x.h"
 
 #include <pcmcia/version.h>
diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
--- a/drivers/scsi/pcmcia/fdomain_stub.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/pcmcia/fdomain_stub.c	2004-06-23 19:04:27 -07:00
@@ -44,7 +44,7 @@
 #include <scsi/scsi_ioctl.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
--- a/drivers/scsi/pcmcia/nsp_cs.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/pcmcia/nsp_cs.c	2004-06-23 19:04:29 -07:00
@@ -1936,10 +1936,10 @@
 	nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
 
 	for (dev = host->host_queue; dev != NULL; dev = dev->next) {
-		unsigned long arg[2], id;
-		kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
-		id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) +
-			((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000);
+		unsigned long id;
+		id = (dev->id & 0x0f) + ((dev->lun & 0x0f) << 4) +
+			((dev->channel & 0x0f) << 8) +
+			((dev->host->host_no & 0x0f) << 12);
 		node = &info->node[info->ndev];
 		node->minor = 0;
 		switch (dev->type) {
diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
--- a/drivers/scsi/pcmcia/qlogic_stub.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/pcmcia/qlogic_stub.c	2004-06-23 19:04:27 -07:00
@@ -46,7 +46,7 @@
 #include <linux/interrupt.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "../qlogicfas408.h"
 
 #include <pcmcia/version.h>
diff -Nru a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
--- a/drivers/scsi/pluto.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/pluto.c	2004-06-23 19:04:26 -07:00
@@ -21,7 +21,7 @@
 #include <asm/irq.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "../fc4/fcp_impl.h"
 #include "pluto.h"
 
diff -Nru a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h
--- a/drivers/scsi/ppa.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/ppa.h	2004-06-23 19:04:28 -07:00
@@ -86,7 +86,7 @@
 #include  <linux/interrupt.h>
 
 #include  <asm/io.h>
-#include  "hosts.h"
+#include  <scsi/scsi_host.h>
 /* batteries not included :-) */
 
 /*
diff -Nru a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c
--- a/drivers/scsi/psi240i.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/psi240i.c	2004-06-23 19:04:27 -07:00
@@ -41,7 +41,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "psi240i.h"
 #include "psi_chip.h"
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/qla1280.c	2004-06-23 19:04:29 -07:00
@@ -357,7 +357,7 @@
 #else
 #include <linux/blk.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "sd.h"
 #endif
 
@@ -3119,6 +3119,7 @@
  * Returns:
  *      0 = success, was able to issue command.
  */
+#ifdef QLA_64BIT_PTR
 static int
 qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
 {
@@ -3381,9 +3382,8 @@
 
 	return status;
 }
+#else /* !QLA_64BIT_PTR */
 
-
-#ifndef QLA_64BIT_PTR
 /*
  * qla1280_32bit_start_scsi
  *      The start SCSI is responsible for building request packets on
diff -Nru a/drivers/scsi/qla2xxx/qla_os.h b/drivers/scsi/qla2xxx/qla_os.h
--- a/drivers/scsi/qla2xxx/qla_os.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/qla2xxx/qla_os.h	2004-06-23 19:04:26 -07:00
@@ -59,7 +59,7 @@
 #include <asm/uaccess.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include <scsi/scsicam.h>
 #include <scsi/scsi_ioctl.h>
diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
--- a/drivers/scsi/qlogicfas.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/qlogicfas.c	2004-06-23 19:04:29 -07:00
@@ -32,7 +32,7 @@
 #include <asm/dma.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "qlogicfas408.h"
 
 /* Set the following to 2 to use normal interrupt (active high/totempole-
diff -Nru a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
--- a/drivers/scsi/qlogicfas408.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/qlogicfas408.c	2004-06-23 19:04:26 -07:00
@@ -56,7 +56,7 @@
 #include <asm/dma.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "qlogicfas408.h"
 
 /*----------------------------------------------------------------*/
diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
--- a/drivers/scsi/qlogicfc.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/qlogicfc.c	2004-06-23 19:04:28 -07:00
@@ -64,7 +64,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #define pci64_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32)))
 #define pci64_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a)))))
@@ -100,6 +100,7 @@
 
 #define DEFAULT_LOOP_COUNT	1000000000
 
+#define ISP_TIMEOUT (2*HZ)
 /* End Configuration section ************************************************ */
 
 #include <linux/module.h>
@@ -1305,7 +1306,7 @@
 		cmd->control_flags = cpu_to_le16(CFLAG_READ);
 
 	if (Cmnd->device->tagged_supported) {
-		if ((jiffies - hostdata->tag_ages[Cmnd->device->id]) > (2 * SCSI_TIMEOUT)) {
+		if ((jiffies - hostdata->tag_ages[Cmnd->device->id]) > (2 * ISP_TIMEOUT)) {
 			cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
 			hostdata->tag_ages[Cmnd->device->id] = jiffies;
 		} else
diff -Nru a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c
--- a/drivers/scsi/qlogicisp.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/qlogicisp.c	2004-06-23 19:04:28 -07:00
@@ -36,7 +36,7 @@
 #include <asm/irq.h>
 #include <asm/byteorder.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "qlogicisp.h"
 
 /* Configuration section *****************************************************/
diff -Nru a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/sata_nv.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,353 @@
+/*
+ *  sata_nv.c - NVIDIA nForce SATA
+ *
+ *  Copyright 2004 NVIDIA Corp.  All rights reserved.
+ *  Copyright 2004 Andrew Chew
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME			"sata_nv"
+#define DRV_VERSION			"0.01"
+
+#define NV_PORTS			2
+#define NV_PIO_MASK			0x1f
+#define NV_UDMA_MASK			0x7f
+#define NV_PORT0_BMDMA_REG_OFFSET	0x00
+#define NV_PORT1_BMDMA_REG_OFFSET	0x08
+#define NV_PORT0_SCR_REG_OFFSET		0x00
+#define NV_PORT1_SCR_REG_OFFSET		0x40
+
+#define NV_INT_STATUS			0x10
+#define NV_INT_STATUS_PDEV_INT		0x01
+#define NV_INT_STATUS_PDEV_PM		0x02
+#define NV_INT_STATUS_PDEV_ADDED	0x04
+#define NV_INT_STATUS_PDEV_REMOVED	0x08
+#define NV_INT_STATUS_SDEV_INT		0x10
+#define NV_INT_STATUS_SDEV_PM		0x20
+#define NV_INT_STATUS_SDEV_ADDED	0x40
+#define NV_INT_STATUS_SDEV_REMOVED	0x80
+#define NV_INT_STATUS_PDEV_HOTPLUG	(NV_INT_STATUS_PDEV_ADDED | \
+					NV_INT_STATUS_PDEV_REMOVED)
+#define NV_INT_STATUS_SDEV_HOTPLUG	(NV_INT_STATUS_SDEV_ADDED | \
+					NV_INT_STATUS_SDEV_REMOVED)
+#define NV_INT_STATUS_HOTPLUG		(NV_INT_STATUS_PDEV_HOTPLUG | \
+					NV_INT_STATUS_SDEV_HOTPLUG)
+
+#define NV_INT_ENABLE			0x11
+#define NV_INT_ENABLE_PDEV_MASK		0x01
+#define NV_INT_ENABLE_PDEV_PM		0x02
+#define NV_INT_ENABLE_PDEV_ADDED	0x04
+#define NV_INT_ENABLE_PDEV_REMOVED	0x08
+#define NV_INT_ENABLE_SDEV_MASK		0x10
+#define NV_INT_ENABLE_SDEV_PM		0x20
+#define NV_INT_ENABLE_SDEV_ADDED	0x40
+#define NV_INT_ENABLE_SDEV_REMOVED	0x80
+#define NV_INT_ENABLE_PDEV_HOTPLUG	(NV_INT_ENABLE_PDEV_ADDED | \
+					NV_INT_ENABLE_PDEV_REMOVED)
+#define NV_INT_ENABLE_SDEV_HOTPLUG	(NV_INT_ENABLE_SDEV_ADDED | \
+					NV_INT_ENABLE_SDEV_REMOVED)
+#define NV_INT_ENABLE_HOTPLUG		(NV_INT_ENABLE_PDEV_HOTPLUG | \
+					NV_INT_ENABLE_SDEV_HOTPLUG)
+
+#define NV_INT_CONFIG			0x12
+#define NV_INT_CONFIG_METHD		0x01 // 0 = INT, 1 = SMI
+
+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 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);
+
+static struct pci_device_id nv_pci_tbl[] = {
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0, } /* terminate list */
+};
+
+static struct pci_driver nv_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= nv_pci_tbl,
+	.probe			= nv_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+static Scsi_Host_Template nv_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= ATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ATA_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations nv_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load_pio,
+	.tf_read		= ata_tf_read_pio,
+	.exec_command		= ata_exec_command_pio,
+	.check_status		= ata_check_status_pio,
+	.phy_reset		= sata_phy_reset,
+	.bmdma_setup		= ata_bmdma_setup_pio,
+	.bmdma_start		= ata_bmdma_start_pio,
+	.qc_prep		= ata_qc_prep,
+	.eng_timeout		= ata_eng_timeout,
+	.irq_handler		= nv_interrupt,
+	.scr_read		= nv_scr_read,
+	.scr_write		= nv_scr_write,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+	.host_stop		= nv_host_stop,
+};
+
+MODULE_AUTHOR("NVIDIA");
+MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
+
+irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	unsigned int i;
+	unsigned int handled = 0;
+	unsigned long flags;
+	u8 intr_status;
+	u8 intr_enable;
+
+	spin_lock_irqsave(&host_set->lock, flags);
+
+	for (i = 0; i < host_set->n_ports; i++) {
+		struct ata_port *ap;
+
+		ap = host_set->ports[i];
+		if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+			struct ata_queued_cmd *qc;
+
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+				handled += ata_host_intr(ap, qc);
+		}
+
+		intr_status = inb(ap->ioaddr.scr_addr + NV_INT_STATUS);
+		intr_enable = inb(ap->ioaddr.scr_addr + NV_INT_ENABLE);
+
+		// Clear interrupt status.
+		outb(0xff, ap->ioaddr.scr_addr + NV_INT_STATUS);
+
+		if (intr_status & NV_INT_STATUS_HOTPLUG) {
+			if (intr_status & NV_INT_STATUS_PDEV_ADDED) {
+				printk(KERN_WARNING "ata%u: "
+					"Primary device added\n", ap->id);
+			}
+
+			if (intr_status & NV_INT_STATUS_PDEV_REMOVED) {
+				printk(KERN_WARNING "ata%u: "
+					"Primary device removed\n", ap->id);
+			}
+
+			if (intr_status & NV_INT_STATUS_SDEV_ADDED) {
+				printk(KERN_WARNING "ata%u: "
+					"Secondary device added\n", ap->id);
+			}
+
+			if (intr_status & NV_INT_STATUS_SDEV_REMOVED) {
+				printk(KERN_WARNING "ata%u: "
+					"Secondary device removed\n", ap->id);
+			}
+		}
+	}
+
+	spin_unlock_irqrestore(&host_set->lock, flags);
+
+	return IRQ_RETVAL(handled);
+}
+
+static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	if (sc_reg > SCR_CONTROL)
+		return 0xffffffffU;
+
+	return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+	if (sc_reg > SCR_CONTROL)
+		return;
+
+	outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void nv_host_stop (struct ata_host_set *host_set)
+{
+	int i;
+
+	for (i=0; i<host_set->n_ports; i++) {
+		u8 intr_mask;
+
+		// Disable hotplug event interrupts.
+		intr_mask = inb(host_set->ports[i]->ioaddr.scr_addr +
+				NV_INT_ENABLE);
+		intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
+		outb(intr_mask, host_set->ports[i]->ioaddr.scr_addr +
+				NV_INT_ENABLE);
+	}
+}
+
+static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version = 0;
+	struct ata_probe_ent *probe_ent = NULL;
+	int i;
+	int rc;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (!probe_ent) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	probe_ent->pdev = pdev;
+	probe_ent->sht = &nv_sht;
+	probe_ent->host_flags = ATA_FLAG_SATA |
+				ATA_FLAG_SATA_RESET |
+				ATA_FLAG_SRST |
+				ATA_FLAG_NO_LEGACY;
+	probe_ent->port_ops = &nv_ops;
+	probe_ent->n_ports = NV_PORTS;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->pio_mask = NV_PIO_MASK;
+	probe_ent->udma_mask = NV_UDMA_MASK;
+
+	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+	ata_std_ports(&probe_ent->port[0]);
+	probe_ent->port[0].altstatus_addr =
+	probe_ent->port[0].ctl_addr =
+		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+	probe_ent->port[0].bmdma_addr =
+		pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET;
+	probe_ent->port[0].scr_addr =
+		pci_resource_start(pdev, 5) | NV_PORT0_SCR_REG_OFFSET;
+
+	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+	ata_std_ports(&probe_ent->port[1]);
+	probe_ent->port[1].altstatus_addr =
+	probe_ent->port[1].ctl_addr =
+		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+	probe_ent->port[1].bmdma_addr =
+		pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET;
+	probe_ent->port[1].scr_addr =
+		pci_resource_start(pdev, 5) | NV_PORT1_SCR_REG_OFFSET;
+
+	pci_set_master(pdev);
+
+	rc = ata_device_add(probe_ent);
+	if (rc != NV_PORTS)
+		goto err_out_regions;
+
+	// Enable hotplug event interrupts.
+	for (i=0; i<probe_ent->n_ports; i++) {
+		u8 intr_mask;
+
+		outb(NV_INT_STATUS_HOTPLUG, probe_ent->port[i].scr_addr +
+						NV_INT_STATUS);
+
+		intr_mask = inb(probe_ent->port[i].scr_addr + NV_INT_ENABLE);
+		intr_mask |= NV_INT_ENABLE_HOTPLUG;
+		outb(intr_mask, probe_ent->port[i].scr_addr + NV_INT_ENABLE);
+	}
+
+	kfree(probe_ent);
+
+	return 0;
+
+err_out_regions:
+	pci_release_regions(pdev);
+
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static int __init nv_init(void)
+{
+	return pci_module_init(&nv_pci_driver);
+}
+
+static void __exit nv_exit(void)
+{
+	pci_unregister_driver(&nv_pci_driver);
+}
+
+module_init(nv_init);
+module_exit(nv_exit);
diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/sata_promise.c	2004-06-23 19:04:27 -07:00
@@ -81,7 +81,7 @@
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
 static void pdc_phy_reset(struct ata_port *ap);
-static void pdc_fill_sg(struct ata_queued_cmd *qc);
+static void pdc_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static inline void pdc_dma_complete (struct ata_port *ap,
@@ -114,7 +114,7 @@
 	.phy_reset		= pdc_phy_reset,
 	.bmdma_setup            = pdc_dma_setup,
 	.bmdma_start            = pdc_dma_start,
-	.fill_sg		= pdc_fill_sg,
+	.qc_prep		= pdc_qc_prep,
 	.eng_timeout		= pdc_eng_timeout,
 	.irq_handler		= pdc_interrupt,
 	.scr_read		= pdc_sata_scr_read,
@@ -261,14 +261,14 @@
 	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static void pdc_fill_sg(struct ata_queued_cmd *qc)
+static void pdc_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct pdc_port_priv *pp = qc->ap->private_data;
 	unsigned int i;
 
 	VPRINTK("ENTER\n");
 
-	ata_fill_sg(qc);
+	ata_qc_prep(qc);
 
 	i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,  qc->dev->devno, pp->pkt);
 
diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/sata_sil.c	2004-06-23 19:04:25 -07:00
@@ -131,7 +131,7 @@
 	.post_set_mode		= sil_post_set_mode,
 	.bmdma_setup            = ata_bmdma_setup_mmio,
 	.bmdma_start            = ata_bmdma_start_mmio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
 	.eng_timeout		= ata_eng_timeout,
 	.irq_handler		= ata_interrupt,
 	.scr_read		= sil_scr_read,
@@ -302,6 +302,7 @@
 		       ap->id, dev->devno);
 		ap->host->max_sectors = 15;
 		ap->host->hostt->max_sectors = 15;
+		dev->flags |= ATA_DFLAG_LOCK_SECTORS;
 		return;
 	}
 
diff -Nru a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
--- a/drivers/scsi/sata_sis.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/sata_sis.c	2004-06-23 19:04:27 -07:00
@@ -100,7 +100,7 @@
 	.phy_reset		= sata_phy_reset,
 	.bmdma_setup            = ata_bmdma_setup_pio,
 	.bmdma_start            = ata_bmdma_start_pio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
 	.eng_timeout		= ata_eng_timeout,
 	.irq_handler		= ata_interrupt,
 	.scr_read		= sis_scr_read,
diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
--- a/drivers/scsi/sata_svw.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/sata_svw.c	2004-06-23 19:04:27 -07:00
@@ -233,7 +233,7 @@
 	.phy_reset		= sata_phy_reset,
 	.bmdma_setup            = ata_bmdma_setup_mmio,
 	.bmdma_start            = ata_bmdma_start_mmio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
 	.eng_timeout		= ata_eng_timeout,
 	.irq_handler		= ata_interrupt,
 	.scr_read		= k2_sata_scr_read,
diff -Nru a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
--- a/drivers/scsi/sata_sx4.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/sata_sx4.c	2004-06-23 19:04:25 -07:00
@@ -153,7 +153,7 @@
 static void pdc_20621_phy_reset (struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
-static void pdc20621_fill_sg(struct ata_queued_cmd *qc);
+static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc20621_host_stop(struct ata_host_set *host_set);
@@ -200,7 +200,7 @@
 	.phy_reset		= pdc_20621_phy_reset,
 	.bmdma_setup            = pdc20621_dma_setup,
 	.bmdma_start            = pdc20621_dma_start,
-	.fill_sg		= pdc20621_fill_sg,
+	.qc_prep		= pdc20621_qc_prep,
 	.eng_timeout		= pdc_eng_timeout,
 	.irq_handler		= pdc20621_interrupt,
 	.port_start		= pdc_port_start,
@@ -434,7 +434,7 @@
 		buf32[dw + 3]);
 }
 
-static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
+static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct scatterlist *sg = qc->sg;
 	struct ata_port *ap = qc->ap;
@@ -445,6 +445,9 @@
 	unsigned int portno = ap->port_no;
 	unsigned int i, last, idx, total_len = 0, sgt_len;
 	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
+
+	if (!(qc->flags & ATA_QCFLAG_SG))
+		return;
 
 	VPRINTK("ata%u: ENTER\n", ap->id);
 
diff -Nru a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
--- a/drivers/scsi/sata_via.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/sata_via.c	2004-06-23 19:04:25 -07:00
@@ -108,7 +108,7 @@
 
 	.bmdma_setup            = ata_bmdma_setup_pio,
 	.bmdma_start            = ata_bmdma_start_pio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
 	.eng_timeout		= ata_eng_timeout,
 
 	.irq_handler		= ata_interrupt,
diff -Nru a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
--- a/drivers/scsi/sata_vsc.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/sata_vsc.c	2004-06-23 19:04:27 -07:00
@@ -215,7 +215,7 @@
 	.phy_reset		= sata_phy_reset,
 	.bmdma_setup            = ata_bmdma_setup_mmio,
 	.bmdma_start            = ata_bmdma_start_mmio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
 	.eng_timeout		= ata_eng_timeout,
 	.irq_handler		= vsc_sata_interrupt,
 	.scr_read		= vsc_sata_scr_read,
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/scsi.h	2004-06-23 19:04:26 -07:00
@@ -11,6 +11,11 @@
  *       add scatter-gather, multiple outstanding request, and other
  *       enhancements.
  */
+/*
+ * NOTE:  this file only contains compatibility glue for old drivers.  All
+ * these wrappers will be removed sooner or later.  For new code please use
+ * the interfaces declared in the headers in include/scsi/
+ */
 
 #ifndef _SCSI_H
 #define _SCSI_H
@@ -18,6 +23,7 @@
 #include <linux/config.h>	    /* for CONFIG_SCSI_LOGGING */
 
 #include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_request.h>
@@ -34,12 +40,6 @@
 #define FALSE 0
 #endif
 
-#ifdef DEBUG
-#define SCSI_TIMEOUT (5*HZ)
-#else
-#define SCSI_TIMEOUT (2*HZ)
-#endif
-
 struct Scsi_Host;
 struct scsi_cmnd;
 struct scsi_device;
@@ -47,21 +47,6 @@
 struct scatterlist;
 
 /*
- * Prototypes for functions in constants.c
- * Some of these used to live in constants.h
- */
-extern void print_Scsi_Cmnd(struct scsi_cmnd *);
-extern void print_command(unsigned char *);
-extern void print_sense(const char *, struct scsi_cmnd *);
-extern void print_req_sense(const char *, struct scsi_request *);
-extern void print_driverbyte(int scsiresult);
-extern void print_hostbyte(int scsiresult);
-extern void print_status(unsigned char status);
-extern int print_msg(const unsigned char *);
-extern const char *scsi_sense_key_string(unsigned char);
-extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
-
-/*
  * Legacy dma direction interfaces.
  *
  * This assumes the pci/sbus dma mapping flags have the same numercial
@@ -75,6 +60,42 @@
 
 #define scsi_to_pci_dma_dir(scsi_dir)	((int)(scsi_dir))
 #define scsi_to_sbus_dma_dir(scsi_dir)	((int)(scsi_dir))
+
+/*
+ * Old names for debug prettyprinting functions.
+ */
+static inline void print_Scsi_Cmnd(struct scsi_cmnd *cmd)
+{
+	return scsi_print_command(cmd);
+}
+static inline void print_command(unsigned char *cdb)
+{
+	return __scsi_print_command(cdb);
+}
+static inline void print_sense(const char *devclass, struct scsi_cmnd *cmd)
+{
+	return scsi_print_sense(devclass, cmd);
+}
+static inline void print_req_sense(const char *devclass, struct scsi_request *req)
+{
+	return scsi_print_req_sense(devclass, req);
+}
+static inline void print_driverbyte(int scsiresult)
+{
+	return scsi_print_driverbyte(scsiresult);
+}
+static inline void print_hostbyte(int scsiresult)
+{
+	return scsi_print_hostbyte(scsiresult);
+}
+static inline void print_status(unsigned char status)
+{
+	return scsi_print_status(status);
+}
+static inline int print_msg(const unsigned char *msg)
+{
+	return scsi_print_msg(msg);
+}
 
 /*
  * This is the crap from the old error handling code.  We have it in a special
diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
--- a/drivers/scsi/scsi_debug.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/scsi_debug.c	2004-06-23 19:04:27 -07:00
@@ -1,4 +1,4 @@
-/* 
+/*
  *  linux/kernel/scsi_debug.c
  * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  *  Copyright (C) 1992  Eric Youngdale
@@ -7,9 +7,9 @@
  *  anything out of the ordinary is seen.
  * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  *
- *  This version is more generic, simulating a variable number of disk 
- *  (or disk like devices) sharing a common amount of RAM 
- *  
+ *  This version is more generic, simulating a variable number of disk
+ *  (or disk like devices) sharing a common amount of RAM
+ *
  *
  *  For documentation see http://www.torque.net/sg/sdebug25.html
  *
@@ -43,7 +43,7 @@
 
 #include <linux/blkdev.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
 
 #include <linux/stat.h>
@@ -55,7 +55,8 @@
 #include "scsi_logging.h"
 #include "scsi_debug.h"
 
-static const char * scsi_debug_version_str = "Version: 1.71 (20031007)";
+#define SCSI_DEBUG_VERSION "1.73"
+static const char * scsi_debug_version_date = "20040518";
 
 /* Additional Sense Code (ASC) used */
 #define NO_ADDED_SENSE 0x0
@@ -76,11 +77,13 @@
 /* With these defaults, this driver will make 1 host with 1 target
  * (id 0) containing 1 logical unit (lun 0). That is 1 device.
  */
+#define DEF_DELAY   1
 #define DEF_DEV_SIZE_MB   8
 #define DEF_EVERY_NTH   0
-#define DEF_DELAY   1
-#define DEF_SCSI_LEVEL   3
+#define DEF_NUM_PARTS   0
 #define DEF_OPTS   0
+#define DEF_SCSI_LEVEL   3
+#define DEF_PTYPE   0
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -101,19 +104,21 @@
  * or "peripheral device" addressing (value 0) */
 #define SAM2_LUN_ADDRESS_METHOD 0
 
+static int scsi_debug_add_host = DEF_NUM_HOST;
+static int scsi_debug_delay = DEF_DELAY;
 static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
-static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
-static int scsi_debug_opts = DEF_OPTS;
 static int scsi_debug_every_nth = DEF_EVERY_NTH;
-static int scsi_debug_cmnd_count = 0;
-static int scsi_debug_delay = DEF_DELAY;
 static int scsi_debug_max_luns = DEF_MAX_LUNS;
+static int scsi_debug_num_parts = DEF_NUM_PARTS;
+static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
+static int scsi_debug_opts = DEF_OPTS;
 static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
-static int scsi_debug_add_host = DEF_NUM_HOST;
+static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
+
+static int scsi_debug_cmnd_count = 0;
 
 #define DEV_READONLY(TGT)      (0)
 #define DEV_REMOVEABLE(TGT)    (0)
-#define PERIPH_DEVICE_TYPE(TGT) (TYPE_DISK);
 
 static unsigned long sdebug_store_size;	/* in bytes */
 static sector_t sdebug_capacity;	/* in sectors */
@@ -129,6 +134,8 @@
 #define SECT_SIZE (1 << POW2_SECT_SIZE)
 #define SECT_SIZE_PER(TGT) SECT_SIZE
 
+#define SDEBUG_MAX_PARTS 4
+
 #define SDEBUG_SENSE_LEN 32
 
 struct sdebug_dev_info {
@@ -215,7 +222,7 @@
 	.remove         = sdebug_driver_remove,
 };
 
-static const int check_condition_result = 
+static const int check_condition_result =
 		(DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
 /* function declarations */
@@ -224,7 +231,7 @@
 static int resp_mode_sense(unsigned char * cmd, int target,
 			   unsigned char * buff, int bufflen,
 			   struct sdebug_dev_info * devip);
-static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, 
+static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
 		     int num, struct sdebug_dev_info * devip);
 static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
 		      int num, struct sdebug_dev_info * devip);
@@ -232,14 +239,15 @@
 			    int bufflen, struct sdebug_dev_info * devip);
 static void timer_intr_handler(unsigned long);
 static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev);
-static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, 
+static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
 			    int asc, int asq, int inbandLen);
-static int check_reset(struct scsi_cmnd * SCpnt, 
+static int check_reset(struct scsi_cmnd * SCpnt,
 		       struct sdebug_dev_info * devip);
-static int schedule_resp(struct scsi_cmnd * cmnd, 
-			 struct sdebug_dev_info * devip, 
+static int schedule_resp(struct scsi_cmnd * cmnd,
+			 struct sdebug_dev_info * devip,
 			 done_funct_t done, int scsi_result, int delta_jiff);
-static void init_all_queued(void);
+static void __init sdebug_build_parts(unsigned char * ramp);
+static void __init init_all_queued(void);
 static void stop_all_queued(void);
 static int stop_queued_cmnd(struct scsi_cmnd * cmnd);
 static int inquiry_evpd_83(unsigned char * arr, int dev_id_num,
@@ -249,6 +257,8 @@
 
 static int sdebug_add_adapter(void);
 static void sdebug_remove_adapter(void);
+static void sdebug_max_tgts_luns(void);
+
 static struct device pseudo_primary;
 static struct bus_type pseudo_lld_bus;
 
@@ -257,7 +267,7 @@
 	if (NULL == sclp)
 		return NULL;
 	else if (sclp->page)
-		return (unsigned char *)page_address(sclp->page) + 
+		return (unsigned char *)page_address(sclp->page) +
 		       sclp->offset;
 	else
 		return NULL;
@@ -288,7 +298,7 @@
 		bufflen = sgpnt[0].length;
 		/* READ and WRITE process scatterlist themselves */
 	}
-	else 
+	else
 		buff = (unsigned char *) SCpnt->request_buffer;
 	if (NULL == buff) {
 		buff = spare_buff;	/* assume cmd moves no data */
@@ -304,11 +314,11 @@
         }
 
 	if (SCpnt->device->lun >= scsi_debug_max_luns)
-		return schedule_resp(SCpnt, NULL, done, 
+		return schedule_resp(SCpnt, NULL, done,
 				     DID_NO_CONNECT << 16, 0);
 	devip = devInfoReg(SCpnt->device);
 	if (NULL == devip)
-		return schedule_resp(SCpnt, NULL, done, 
+		return schedule_resp(SCpnt, NULL, done,
 				     DID_NO_CONNECT << 16, 0);
 
         if ((scsi_debug_every_nth > 0) &&
@@ -331,7 +341,7 @@
 		 * shouldn't need to call REQUEST_SENSE */
 		if (devip) {
 			sbuff = devip->sense_buff;
-			memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ? 
+			memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ?
 					     bufflen : SDEBUG_SENSE_LEN);
 			mk_sense_buffer(devip, 0, NO_ADDED_SENSE, 0, 7);
 		} else {
@@ -392,29 +402,29 @@
 			break;
 		upper_blk = 0;
 		if ((*cmd) == READ_16) {
-			upper_blk = cmd[5] + (cmd[4] << 8) + 
+			upper_blk = cmd[5] + (cmd[4] << 8) +
 				    (cmd[3] << 16) + (cmd[2] << 24);
-			block = cmd[9] + (cmd[8] << 8) + 
+			block = cmd[9] + (cmd[8] << 8) +
 				(cmd[7] << 16) + (cmd[6] << 24);
-			num = cmd[13] + (cmd[12] << 8) + 
+			num = cmd[13] + (cmd[12] << 8) +
 				(cmd[11] << 16) + (cmd[10] << 24);
 		} else if ((*cmd) == READ_12) {
-			block = cmd[5] + (cmd[4] << 8) + 
+			block = cmd[5] + (cmd[4] << 8) +
 				(cmd[3] << 16) + (cmd[2] << 24);
-			num = cmd[9] + (cmd[8] << 8) + 
+			num = cmd[9] + (cmd[8] << 8) +
 				(cmd[7] << 16) + (cmd[6] << 24);
 		} else if ((*cmd) == READ_10) {
-			block = cmd[5] + (cmd[4] << 8) + 
+			block = cmd[5] + (cmd[4] << 8) +
 				(cmd[3] << 16) + (cmd[2] << 24);
 			num = cmd[8] + (cmd[7] << 8);
 		} else {
-			block = cmd[3] + (cmd[2] << 8) + 
+			block = cmd[3] + (cmd[2] << 8) +
 				((cmd[1] & 0x1f) << 16);
 			num = cmd[4];
 		}
 		errsts = resp_read(SCpnt, upper_blk, block, num, devip);
 		if (inj_recovered && (0 == errsts)) {
-			mk_sense_buffer(devip, RECOVERED_ERROR, 
+			mk_sense_buffer(devip, RECOVERED_ERROR,
 					THRESHHOLD_EXCEEDED, 0, 18);
 			errsts = check_condition_result;
 		}
@@ -430,29 +440,29 @@
 			break;
 		upper_blk = 0;
 		if ((*cmd) == WRITE_16) {
-			upper_blk = cmd[5] + (cmd[4] << 8) + 
+			upper_blk = cmd[5] + (cmd[4] << 8) +
 				    (cmd[3] << 16) + (cmd[2] << 24);
-			block = cmd[9] + (cmd[8] << 8) + 
+			block = cmd[9] + (cmd[8] << 8) +
 				(cmd[7] << 16) + (cmd[6] << 24);
-			num = cmd[13] + (cmd[12] << 8) + 
+			num = cmd[13] + (cmd[12] << 8) +
 				(cmd[11] << 16) + (cmd[10] << 24);
 		} else if ((*cmd) == WRITE_12) {
-			block = cmd[5] + (cmd[4] << 8) + 
+			block = cmd[5] + (cmd[4] << 8) +
 				(cmd[3] << 16) + (cmd[2] << 24);
-			num = cmd[9] + (cmd[8] << 8) + 
+			num = cmd[9] + (cmd[8] << 8) +
 				(cmd[7] << 16) + (cmd[6] << 24);
 		} else if ((*cmd) == WRITE_10) {
-			block = cmd[5] + (cmd[4] << 8) + 
+			block = cmd[5] + (cmd[4] << 8) +
 				(cmd[3] << 16) + (cmd[2] << 24);
 			num = cmd[8] + (cmd[7] << 8);
 		} else {
-			block = cmd[3] + (cmd[2] << 8) + 
+			block = cmd[3] + (cmd[2] << 8) +
 				((cmd[1] & 0x1f) << 16);
 			num = cmd[4];
 		}
 		errsts = resp_write(SCpnt, upper_blk, block, num, devip);
 		if (inj_recovered && (0 == errsts)) {
-			mk_sense_buffer(devip, RECOVERED_ERROR, 
+			mk_sense_buffer(devip, RECOVERED_ERROR,
 					THRESHHOLD_EXCEEDED, 0, 18);
 			errsts = check_condition_result;
 		}
@@ -500,7 +510,7 @@
 static const char * product_id = "scsi_debug      ";
 static const char * product_rev = "0004";
 
-static int inquiry_evpd_83(unsigned char * arr, int dev_id_num, 
+static int inquiry_evpd_83(unsigned char * arr, int dev_id_num,
 			   const char * dev_id_str, int dev_id_str_len)
 {
 	int num;
@@ -537,7 +547,7 @@
 {
 	unsigned char pq_pdt;
 	unsigned char arr[SDEBUG_MAX_INQ_ARR_SZ];
-	int min_len = bufflen > SDEBUG_MAX_INQ_ARR_SZ ? 
+	int min_len = bufflen > SDEBUG_MAX_INQ_ARR_SZ ?
 			SDEBUG_MAX_INQ_ARR_SZ : bufflen;
 
 	if (bufflen < cmd[4])
@@ -545,7 +555,7 @@
 		       "< alloc_length=%d\n", bufflen, (int)cmd[4]);
 	memset(buff, 0, bufflen);
 	memset(arr, 0, SDEBUG_MAX_INQ_ARR_SZ);
-	pq_pdt = PERIPH_DEVICE_TYPE(target);
+	pq_pdt = (scsi_debug_ptype & 0x1f);
 	arr[0] = pq_pdt;
 	if (0x2 & cmd[1]) {  /* CMDDT bit set */
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
@@ -573,11 +583,11 @@
 						 dev_id_str, len);
 		} else {
 			/* Illegal request, invalid field in cdb */
-			mk_sense_buffer(devip, ILLEGAL_REQUEST, 
+			mk_sense_buffer(devip, ILLEGAL_REQUEST,
 					INVALID_FIELD_IN_CDB, 0, 18);
 			return check_condition_result;
 		}
-		memcpy(buff, arr, min_len); 
+		memcpy(buff, arr, min_len);
 		return 0;
 	}
 	/* drops through here for a standard inquiry */
@@ -592,11 +602,11 @@
 	return 0;
 }
 
-/* <<Following mode page info copied from ST318451LW>> */ 
+/* <<Following mode page info copied from ST318451LW>> */
 
 static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
 {	/* Read-Write Error Recovery page for mode_sense */
-	unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0, 
+	unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
 					5, 0, 0xff, 0xff};
 
 	memcpy(p, err_recov_pg, sizeof(err_recov_pg));
@@ -607,7 +617,7 @@
 
 static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target)
 { 	/* Disconnect-Reconnect page for mode_sense */
-	unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0, 
+	unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
 					 0, 0, 0, 0, 0, 0, 0, 0};
 
 	memcpy(p, disconnect_pg, sizeof(disconnect_pg));
@@ -636,7 +646,7 @@
 
 static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
 { 	/* Caching page for mode_sense */
-	unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, 
+	unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
 		0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,     0, 0, 0, 0};
 
 	memcpy(p, caching_pg, sizeof(caching_pg));
@@ -678,7 +688,7 @@
 	int alloc_len, msense_6, offset, len;
 	unsigned char * ap;
 	unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
-	int min_len = bufflen > SDEBUG_MAX_MSENSE_SZ ? 
+	int min_len = bufflen > SDEBUG_MAX_MSENSE_SZ ?
 			SDEBUG_MAX_MSENSE_SZ : bufflen;
 
 	SCSI_LOG_LLQUEUE(3, printk("Mode sense ...(%p %d)\n", buff, bufflen));
@@ -753,14 +763,14 @@
 		arr[0] = offset - 1;
 	else {
 		offset -= 2;
-		arr[0] = (offset >> 8) & 0xff; 
-		arr[1] = offset & 0xff; 
+		arr[0] = (offset >> 8) & 0xff;
+		arr[1] = offset & 0xff;
 	}
 	memcpy(buff, arr, min_len);
 	return 0;
 }
 
-static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, 
+static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
 		     int num, struct sdebug_dev_info * devip)
 {
         unsigned char *buff = (unsigned char *) SCpnt->request_buffer;
@@ -770,14 +780,14 @@
 	unsigned long iflags;
 
 	if (upper_blk || (block + num > sdebug_capacity)) {
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 
+		mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
 				0, 18);
 		return check_condition_result;
 	}
 	if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
-	    (block <= OPT_MEDIUM_ERR_ADDR) && 
+	    (block <= OPT_MEDIUM_ERR_ADDR) &&
 	    ((block + num) > OPT_MEDIUM_ERR_ADDR)) {
-		mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 
+		mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR,
 				0, 18);
 		/* claim unrecoverable read error */
 		return check_condition_result;
@@ -785,7 +795,7 @@
 	read_lock_irqsave(&atomic_rw, iflags);
         sgcount = 0;
 	nbytes = bufflen;
-	/* printk(KERN_INFO "scsi_debug_read: block=%d, tot_bufflen=%d\n", 
+	/* printk(KERN_INFO "scsi_debug_read: block=%d, tot_bufflen=%d\n",
 	       block, bufflen); */
 	if (SCpnt->use_sg) {
 		sgcount = 0;
@@ -857,7 +867,7 @@
 static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
 			    int bufflen, struct sdebug_dev_info * devip)
 {
-	unsigned int alloc_len; 
+	unsigned int alloc_len;
 	int lun_cnt, i, upper;
 	int select_report = (int)cmd[2];
 	struct scsi_lun *one_lun;
@@ -868,19 +878,19 @@
 			       	0, 18);
 		return check_condition_result;
 	}
-	if (bufflen > 8) { /* can produce response with up to 16k luns 
+	if (bufflen > 8) { /* can produce response with up to 16k luns
 			      (lun 0 to lun 16383) */
 		memset(buff, 0, bufflen);
 		lun_cnt = scsi_debug_max_luns;
 		buff[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff;
 		buff[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff;
-		lun_cnt = min((int)((bufflen - 8) / sizeof(struct scsi_lun)), 
+		lun_cnt = min((int)((bufflen - 8) / sizeof(struct scsi_lun)),
 			      lun_cnt);
 		one_lun = (struct scsi_lun *) &buff[8];
 		for (i = 0; i < lun_cnt; i++) {
 			upper = (i >> 8) & 0x3f;
 			if (upper)
-				one_lun[i].scsi_lun[0] = 
+				one_lun[i].scsi_lun[0] =
 				    (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
 			one_lun[i].scsi_lun[1] = i & 0xff;
 		}
@@ -926,7 +936,7 @@
 
 static int scsi_debug_slave_configure(struct scsi_device * sdp)
 {
-	struct sdebug_dev_info * devip; 
+	struct sdebug_dev_info * devip;
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
 		printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n",
@@ -936,14 +946,14 @@
 	devip = devInfoReg(sdp);
 	sdp->hostdata = devip;
 	if (sdp->host->cmd_per_lun)
-		scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, 
+		scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING,
 					sdp->host->cmd_per_lun);
 	return 0;
 }
 
 static void scsi_debug_slave_destroy(struct scsi_device * sdp)
 {
-	struct sdebug_dev_info * devip = 
+	struct sdebug_dev_info * devip =
 				(struct sdebug_dev_info *)sdp->hostdata;
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
@@ -980,6 +990,18 @@
 				open_devip = devip;
 		}
 	}
+	if (NULL == open_devip) { /* try and make a new one */
+		open_devip = kmalloc(sizeof(*open_devip),GFP_KERNEL);
+		if (NULL == open_devip) {
+			printk(KERN_ERR "%s: out of memory at line %d\n",
+				__FUNCTION__, __LINE__);
+			return NULL;
+		}
+		memset(open_devip, 0, sizeof(*open_devip));
+		open_devip->sdbg_host = sdbg_host;
+		list_add_tail(&open_devip->dev_list,
+		&sdbg_host->dev_info_list);
+	}
         if (open_devip) {
 		open_devip->channel = sdev->channel;
 		open_devip->target = sdev->id;
@@ -994,7 +1016,7 @@
         return NULL;
 }
 
-static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, 
+static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
 			    int asc, int asq, int inbandLen)
 {
 	unsigned char * sbuff;
@@ -1029,7 +1051,7 @@
 		printk(KERN_INFO "scsi_debug: biosparam\n");
 	buf = scsi_bios_ptable(bdev);
 	if (buf) {
-		res = scsi_partsize(buf, capacity, 
+		res = scsi_partsize(buf, capacity,
 				    &info[2], &info[0], &info[1]);
 		kfree(buf);
 		if (! res)
@@ -1138,7 +1160,7 @@
 }
 
 /* Initializes timers in queued array */
-static void init_all_queued(void)
+static void __init init_all_queued(void)
 {
 	unsigned long iflags;
 	int k;
@@ -1154,11 +1176,61 @@
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
-static int schedule_resp(struct scsi_cmnd * cmnd, 
+static void __init sdebug_build_parts(unsigned char * ramp)
+{
+	struct partition * pp;
+	int starts[SDEBUG_MAX_PARTS + 2];
+	int sectors_per_part, num_sectors, k;
+	int heads_by_sects, start_sec, end_sec;
+
+	/* assume partition table already zeroed */
+	if ((scsi_debug_num_parts < 1) || (sdebug_store_size < 1048576))
+		return;
+	if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
+		scsi_debug_num_parts = SDEBUG_MAX_PARTS;
+		printk(KERN_WARNING "scsi_debug:build_parts: reducing "
+				    "partitions to %d\n", SDEBUG_MAX_PARTS);
+	}
+	num_sectors = (int)(sdebug_store_size / SECT_SIZE);
+	sectors_per_part = (num_sectors - sdebug_sectors_per)
+			   / scsi_debug_num_parts;
+	heads_by_sects = sdebug_heads * sdebug_sectors_per;
+        starts[0] = sdebug_sectors_per;
+	for (k = 1; k < scsi_debug_num_parts; ++k)
+		starts[k] = ((k * sectors_per_part) / heads_by_sects)
+			    * heads_by_sects;
+	starts[scsi_debug_num_parts] = num_sectors;
+	starts[scsi_debug_num_parts + 1] = 0;
+
+	ramp[510] = 0x55;	/* magic partition markings */
+	ramp[511] = 0xAA;
+	pp = (struct partition *)(ramp + 0x1be);
+	for (k = 0; starts[k + 1]; ++k, ++pp) {
+		start_sec = starts[k];
+		end_sec = starts[k + 1] - 1;
+		pp->boot_ind = 0;
+
+		pp->cyl = start_sec / heads_by_sects;
+		pp->head = (start_sec - (pp->cyl * heads_by_sects))
+			   / sdebug_sectors_per;
+		pp->sector = (start_sec % sdebug_sectors_per) + 1;
+
+		pp->end_cyl = end_sec / heads_by_sects;
+		pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects))
+			       / sdebug_sectors_per;
+		pp->end_sector = (end_sec % sdebug_sectors_per) + 1;
+
+		pp->start_sect = start_sec;
+		pp->nr_sects = end_sec - start_sec + 1;
+		pp->sys_ind = 0x83;	/* plain Linux partition */
+	}
+}
+
+static int schedule_resp(struct scsi_cmnd * cmnd,
 			 struct sdebug_dev_info * devip,
 			 done_funct_t done, int scsi_result, int delta_jiff)
 {
-	int k, num; 
+	int k, num;
 
 	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) {
 		printk(KERN_INFO "scsi_debug: cmd ");
@@ -1176,7 +1248,7 @@
 	if (cmnd && devip) {
 		/* simulate autosense by this driver */
 		if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff))
-			memcpy(cmnd->sense_buffer, devip->sense_buff, 
+			memcpy(cmnd->sense_buffer, devip->sense_buff,
 			       (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ?
 			       SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE);
 	}
@@ -1219,38 +1291,43 @@
 
 /* Set 'perm' (4th argument) to 0 to disable module_param's definition
  * of sysfs parameters (which module_param doesn't yet support).
- * Sysfs parameters defined explicitly below. 
+ * Sysfs parameters defined explicitly below.
  */
-module_param_named(num_tgts, scsi_debug_num_tgts, int, 0);
-module_param_named(max_luns, scsi_debug_max_luns, int, 0);
-module_param_named(scsi_level, scsi_debug_scsi_level, int, 0);
+module_param_named(add_host, scsi_debug_add_host, int, 0); /* perm=0644 */
+module_param_named(delay, scsi_debug_delay, int, 0); /* perm=0644 */
 module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0);
-module_param_named(opts, scsi_debug_opts, int, 0); /* perm=0644 */
 module_param_named(every_nth, scsi_debug_every_nth, int, 0);
-module_param_named(delay, scsi_debug_delay, int, 0); /* perm=0644 */
-module_param_named(add_host, scsi_debug_add_host, int, 0); /* perm=0644 */
+module_param_named(max_luns, scsi_debug_max_luns, int, 0);
+module_param_named(num_parts, scsi_debug_num_parts, int, 0);
+module_param_named(num_tgts, scsi_debug_num_tgts, int, 0);
+module_param_named(opts, scsi_debug_opts, int, 0); /* perm=0644 */
+module_param_named(ptype, scsi_debug_ptype, int, 0);
+module_param_named(scsi_level, scsi_debug_scsi_level, int, 0);
 
 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
 MODULE_DESCRIPTION("SCSI debug adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(SCSI_DEBUG_VERSION);
 
-MODULE_PARM_DESC(num_tgts, "number of SCSI targets per host to simulate");
-MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate");
-MODULE_PARM_DESC(scsi_level, "SCSI level to simulate");
+MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
+MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
 MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs");
-MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->...");
 MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)");
-MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
-MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
+MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate");
+MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
+MODULE_PARM_DESC(num_tgts, "number of SCSI targets per host to simulate");
+MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->...");
+MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
+MODULE_PARM_DESC(scsi_level, "SCSI level to simulate");
 
 
 static char sdebug_info[256];
 
 static const char * scsi_debug_info(struct Scsi_Host * shp)
 {
-	sprintf(sdebug_info, "scsi_debug, %s, num_tgts=%d, "
-		"dev_size_mb=%d, opts=0x%x", scsi_debug_version_str,
-		scsi_debug_num_tgts, scsi_debug_dev_size_mb,
+	sprintf(sdebug_info, "scsi_debug, version %s [%s], "
+		"dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
+		scsi_debug_version_date, scsi_debug_dev_size_mb,
 		scsi_debug_opts);
 	return sdebug_info;
 }
@@ -1282,14 +1359,15 @@
 		return length;
 	}
 	begin = 0;
-	pos = len = sprintf(buffer, "scsi_debug adapter driver, %s\n"
+	pos = len = sprintf(buffer, "scsi_debug adapter driver, version "
+	    "%s [%s]\n"
 	    "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
 	    "every_nth=%d(curr:%d)\n"
 	    "delay=%d, max_luns=%d, scsi_level=%d\n"
 	    "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
-	    "number of aborts=%d, device_reset=%d, bus_resets=%d, " 
+	    "number of aborts=%d, device_reset=%d, bus_resets=%d, "
 	    "host_resets=%d\n",
-	    scsi_debug_version_str, scsi_debug_num_tgts, 
+	    SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts,
 	    scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth,
 	    scsi_debug_cmnd_count, scsi_debug_delay,
 	    scsi_debug_max_luns, scsi_debug_scsi_level,
@@ -1306,12 +1384,12 @@
 	return len;
 }
 
-static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf) 
+static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
 }
 
-static ssize_t sdebug_delay_store(struct device_driver * ddp, 
+static ssize_t sdebug_delay_store(struct device_driver * ddp,
 				  const char * buf, size_t count)
 {
         int delay;
@@ -1325,15 +1403,15 @@
 	}
 	return -EINVAL;
 }
-DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show, 
-	    sdebug_delay_store)
+DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show,
+	    sdebug_delay_store);
 
-static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf) 
+static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
 }
 
-static ssize_t sdebug_opts_store(struct device_driver * ddp, 
+static ssize_t sdebug_opts_store(struct device_driver * ddp,
 				 const char * buf, size_t count)
 {
         int opts;
@@ -1354,38 +1432,62 @@
 	scsi_debug_cmnd_count = 0;
 	return count;
 }
-DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show, 
-	    sdebug_opts_store)
+DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show,
+	    sdebug_opts_store);
+
+static ssize_t sdebug_ptype_show(struct device_driver * ddp, char * buf)
+{
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype);
+}
+static ssize_t sdebug_ptype_store(struct device_driver * ddp,
+				  const char * buf, size_t count)
+{
+        int n;
+
+	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+		scsi_debug_ptype = n;
+		return count;
+	}
+	return -EINVAL;
+}
+DRIVER_ATTR(ptype, S_IRUGO | S_IWUSR, sdebug_ptype_show, sdebug_ptype_store);
 
-static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf) 
+static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
 }
-static ssize_t sdebug_num_tgts_store(struct device_driver * ddp, 
+static ssize_t sdebug_num_tgts_store(struct device_driver * ddp,
 				     const char * buf, size_t count)
 {
         int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
 		scsi_debug_num_tgts = n;
+		sdebug_max_tgts_luns();
 		return count;
 	}
 	return -EINVAL;
 }
-DRIVER_ATTR(num_tgts, S_IRUGO | S_IWUSR, sdebug_num_tgts_show, 
-	    sdebug_num_tgts_store) 
+DRIVER_ATTR(num_tgts, S_IRUGO | S_IWUSR, sdebug_num_tgts_show,
+	    sdebug_num_tgts_store);
 
-static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) 
+static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
 }
-DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL) 
+DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL);
+
+static ssize_t sdebug_num_parts_show(struct device_driver * ddp, char * buf)
+{
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts);
+}
+DRIVER_ATTR(num_parts, S_IRUGO, sdebug_num_parts_show, NULL);
 
-static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf) 
+static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
 }
-static ssize_t sdebug_every_nth_store(struct device_driver * ddp, 
+static ssize_t sdebug_every_nth_store(struct device_driver * ddp,
 				      const char * buf, size_t count)
 {
         int nth;
@@ -1398,38 +1500,39 @@
 	return -EINVAL;
 }
 DRIVER_ATTR(every_nth, S_IRUGO | S_IWUSR, sdebug_every_nth_show,
-	    sdebug_every_nth_store) 
+	    sdebug_every_nth_store);
 
-static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) 
+static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
 }
-static ssize_t sdebug_max_luns_store(struct device_driver * ddp, 
+static ssize_t sdebug_max_luns_store(struct device_driver * ddp,
 				     const char * buf, size_t count)
 {
         int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
 		scsi_debug_max_luns = n;
+		sdebug_max_tgts_luns();
 		return count;
 	}
 	return -EINVAL;
 }
-DRIVER_ATTR(max_luns, S_IRUGO | S_IWUSR, sdebug_max_luns_show, 
-	    sdebug_max_luns_store) 
+DRIVER_ATTR(max_luns, S_IRUGO | S_IWUSR, sdebug_max_luns_show,
+	    sdebug_max_luns_store);
 
-static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) 
+static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
 }
-DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL) 
+DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL);
 
-static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) 
+static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
 }
 
-static ssize_t sdebug_add_host_store(struct device_driver * ddp, 
+static ssize_t sdebug_add_host_store(struct device_driver * ddp,
 				     const char * buf, size_t count)
 {
         int delta_hosts;
@@ -1459,30 +1562,34 @@
 	return count;
 }
 DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, 
-	    sdebug_add_host_store)
+	    sdebug_add_host_store);
 
 static void do_create_driverfs_files(void)
 {
+	driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host);
 	driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
-	driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
-	driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
 	driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
 	driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
 	driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
+	driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
+	driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
+	driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype);
+	driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
 	driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
-	driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host);
 }
 
 static void do_remove_driverfs_files(void)
 {
-	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host);
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
+	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts);
+	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ptype);
+	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
+	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
-	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
-	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts);
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay);
+	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host);
 }
 
 static int __init scsi_debug_init(void)
@@ -1491,23 +1598,25 @@
 	int host_to_add;
 	int k;
 
+	if (scsi_debug_dev_size_mb < 1)
+		scsi_debug_dev_size_mb = 1;  /* force minimum 1 MB ramdisk */
 	sdebug_store_size = (unsigned long)scsi_debug_dev_size_mb * 1048576;
 	sdebug_capacity = sdebug_store_size / SECT_SIZE;
 
 	/* play around with geometry, don't waste too much on track 0 */
 	sdebug_heads = 8;
 	sdebug_sectors_per = 32;
-	if (scsi_debug_dev_size_mb >= 16) 
+	if (scsi_debug_dev_size_mb >= 16)
 		sdebug_heads = 32;
 	else if (scsi_debug_dev_size_mb >= 256)
 		sdebug_heads = 64;
-	sdebug_cylinders_per = (unsigned long)sdebug_capacity / 
+	sdebug_cylinders_per = (unsigned long)sdebug_capacity /
 			       (sdebug_sectors_per * sdebug_heads);
-	if (sdebug_cylinders_per >= 1024) { 
+	if (sdebug_cylinders_per >= 1024) {
 		/* other LLDs do this; implies >= 1GB ram disk ... */
 		sdebug_heads = 255;
 		sdebug_sectors_per = 63;
-		sdebug_cylinders_per = (unsigned long)sdebug_capacity / 
+		sdebug_cylinders_per = (unsigned long)sdebug_capacity /
 			       (sdebug_sectors_per * sdebug_heads);
 	}
 
@@ -1518,6 +1627,8 @@
 		return -ENOMEM;
 	}
 	memset(fake_storep, 0, sz);
+	if (scsi_debug_num_parts > 0)
+		sdebug_build_parts(fake_storep);
 
 	init_all_queued();
 
@@ -1575,7 +1686,7 @@
 	.release	= pseudo_0_release,
 };
 
-static int pseudo_lld_bus_match(struct device *dev, 
+static int pseudo_lld_bus_match(struct device *dev,
                           struct device_driver *dev_driver)
 {
         return 1;
@@ -1736,4 +1847,22 @@
 
         scsi_host_put(sdbg_host->shost);
         return 0;
+}
+
+static void sdebug_max_tgts_luns(void)
+{
+	struct sdebug_host_info * sdbg_host;
+	struct Scsi_Host *hpnt;
+
+	spin_lock(&sdebug_host_list_lock);
+	list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
+		hpnt = sdbg_host->shost;
+		if ((hpnt->this_id >= 0) &&
+		    (scsi_debug_num_tgts > hpnt->this_id))
+			hpnt->max_id = scsi_debug_num_tgts + 1;
+		else
+			hpnt->max_id = scsi_debug_num_tgts;
+		hpnt->max_lun = scsi_debug_max_luns;
+	}
+	spin_unlock(&sdebug_host_list_lock);
 }
diff -Nru a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h
--- a/drivers/scsi/scsi_debug.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/scsi_debug.h	2004-06-23 19:04:27 -07:00
@@ -5,7 +5,7 @@
 static int scsi_debug_slave_alloc(struct scsi_device *);
 static int scsi_debug_slave_configure(struct scsi_device *);
 static void scsi_debug_slave_destroy(struct scsi_device *);
-static int scsi_debug_queuecommand(struct scsi_cmnd *, 
+static int scsi_debug_queuecommand(struct scsi_cmnd *,
 				   void (*done) (struct scsi_cmnd *));
 static int scsi_debug_ioctl(struct scsi_device *, int, void *);
 static int scsi_debug_biosparam(struct scsi_device *, struct block_device *,
@@ -17,9 +17,6 @@
 static int scsi_debug_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
 static const char * scsi_debug_info(struct Scsi_Host *);
 
-/*
- * This driver is written for the lk 2.5 series
- */
 #define SCSI_DEBUG_CANQUEUE  255 	/* needs to be >= 1 */
 
 #define SCSI_DEBUG_MAX_CMD_LEN 16
diff -Nru a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
--- a/drivers/scsi/scsi_devinfo.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/scsi_devinfo.c	2004-06-23 19:04:26 -07:00
@@ -9,7 +9,7 @@
 #include <scsi/scsi_devinfo.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "scsi_priv.h"
 
 /*
@@ -27,7 +27,7 @@
 static const char spaces[] = "                "; /* 16 of them */
 static unsigned scsi_default_dev_flags;
 static LIST_HEAD(scsi_dev_info_list);
-static __init char scsi_dev_flags[256];
+static __initdata char scsi_dev_flags[256];
 
 /*
  * scsi_static_device_list: deprecated list of devices that require
@@ -117,8 +117,10 @@
 	 */
 	{"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN},
 	{"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN},
-	{"BELKIN", "USB 2 HS-CF", "1.95",  BLIST_SPARSELUN},
+	{"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN},
+	{"BELKIN", "USB 2 HS-CF", "1.95",  BLIST_FORCELUN},
 	{"CANON", "IPUBJD", NULL, BLIST_SPARSELUN},
+	{"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN},
 	{"CMD", "CRA-7280", NULL, BLIST_SPARSELUN},	/* CMD RAID Controller */
 	{"CNSI", "G7324", NULL, BLIST_SPARSELUN},	/* Chaparral G7324 RAID */
 	{"CNSi", "G8324", NULL, BLIST_SPARSELUN},	/* Chaparral G8324 RAID */
@@ -139,6 +141,7 @@
 	{"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN},
 	{"EMULEX", "MD21/S2     ESDI", NULL, BLIST_SINGLELUN},
 	{"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN},
 	{"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN},
 	{"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN},
 	{"HITACHI", "DF400", "*", BLIST_SPARSELUN},
@@ -171,6 +174,7 @@
 	{"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
+	{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
 	{"SGI", "RAID3", "*", BLIST_SPARSELUN},
 	{"SGI", "RAID5", "*", BLIST_SPARSELUN},
 	{"SGI", "TP9100", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
@@ -182,6 +186,7 @@
 	{"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN},
 	{"TOSHIBA", "CDROM", NULL, BLIST_ISROM},
 	{"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM},
+	{"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN},
 	{"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN},
 	{"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN},
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/scsi_error.c	2004-06-23 19:04:25 -07:00
@@ -26,25 +26,20 @@
 #include <scsi/scsi_ioctl.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
-#ifdef DEBUG
-#define SENSE_TIMEOUT SCSI_TIMEOUT
-#else
-#define SENSE_TIMEOUT (10*HZ)
-#endif
-
-#define START_UNIT_TIMEOUT (30*HZ)
+#define SENSE_TIMEOUT		(10*HZ)
+#define START_UNIT_TIMEOUT	(30*HZ)
 
 /*
  * These should *probably* be handled by the host itself.
  * Since it is allowed to sleep, it probably should.
  */
-#define BUS_RESET_SETTLE_TIME   10*HZ
-#define HOST_RESET_SETTLE_TIME  10*HZ
+#define BUS_RESET_SETTLE_TIME   (10*HZ)
+#define HOST_RESET_SETTLE_TIME  (10*HZ)
 
 /* called with shost->host_lock held */
 void scsi_eh_wakeup(struct Scsi_Host *shost)
@@ -1026,7 +1021,8 @@
 	spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
 
 	if (rtn == SUCCESS) {
-		scsi_sleep(BUS_RESET_SETTLE_TIME);
+		if (!scmd->device->host->hostt->skip_settle_delay)
+			scsi_sleep(BUS_RESET_SETTLE_TIME);
 		spin_lock_irqsave(scmd->device->host->host_lock, flags);
 		scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
 		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
@@ -1057,7 +1053,8 @@
 	spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
 
 	if (rtn == SUCCESS) {
-		scsi_sleep(HOST_RESET_SETTLE_TIME);
+		if (!scmd->device->host->hostt->skip_settle_delay)
+			scsi_sleep(HOST_RESET_SETTLE_TIME);
 		spin_lock_irqsave(scmd->device->host->host_lock, flags);
 		scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
 		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
--- a/drivers/scsi/scsi_ioctl.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/scsi_ioctl.c	2004-06-23 19:04:28 -07:00
@@ -20,7 +20,7 @@
 
 #include <linux/blkdev.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 
 #include "scsi_logging.h"
@@ -446,20 +446,4 @@
 			return sdev->host->hostt->ioctl(sdev, cmd, arg);
 	}
 	return -EINVAL;
-}
-
-/*
- * Just like scsi_ioctl, only callable from kernel space with no 
- * fs segment fiddling.
- */
-
-int kernel_scsi_ioctl(struct scsi_device *sdev, int cmd, void *arg)
-{
-	mm_segment_t oldfs;
-	int tmp;
-	oldfs = get_fs();
-	set_fs(get_ds());
-	tmp = scsi_ioctl(sdev, cmd, arg);
-	set_fs(oldfs);
-	return tmp;
 }
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/scsi_lib.c	2004-06-23 19:04:27 -07:00
@@ -255,7 +255,6 @@
 	sreq->sr_request->rq_status = RQ_SCSI_BUSY;
 	scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done,
 			timeout, retries);
-	generic_unplug_device(sreq->sr_device->request_queue);
 	wait_for_completion(&wait);
 	sreq->sr_request->waiting = NULL;
 	if (sreq->sr_request->rq_status != RQ_SCSI_DONE)
diff -Nru a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c
--- a/drivers/scsi/scsi_module.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/scsi_module.c	2004-06-23 19:04:26 -07:00
@@ -12,7 +12,7 @@
 #include <linux/module.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 
 static int __init init_this_scsi_driver(void)
diff -Nru a/drivers/scsi/scsi_pc98.c b/drivers/scsi/scsi_pc98.c
--- a/drivers/scsi/scsi_pc98.c	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,69 +0,0 @@
-/*
- *  Copyright (C) 2003  Osamu Tomita <tomita@cinet.co.jp>
- *
- *  PC9801 BIOS geometry handling.
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/genhd.h>
-#include <linux/blkdev.h>
-#include <asm/pc9800.h>
-
-#include "scsi.h"
-#include "hosts.h"
-
-
-static int pc98_first_bios_param(struct scsi_device *sdev, int *ip)
-{
-	const u8 *p = (&__PC9800SCA(u8, PC9800SCA_SCSI_PARAMS) + sdev->id * 4);
-
-	ip[0] = p[1];   /* # of heads */
-	ip[1] = p[0];   /* # of sectors/track */
-	ip[2] = *(u16 *)&p[2] & 0x0fff; /* # of cylinders */
-	if (p[3] & (1 << 6)) { /* #-of-cylinders is 16-bit */
-		ip[2] |= (ip[0] & 0xf0) << 8;
-		ip[0] &= 0x0f;
-	}
-
-	return 0;
-}
-
-int pc98_bios_param(struct scsi_device *sdev, struct block_device *bdev,
-			sector_t capacity, int *ip)
-{
-	struct Scsi_Host *first_real = first_real_host();
-
-	/*
-	 * XXX
-	 * XXX This needs to become a sysfs attribute that's set
-	 * XXX by code that knows which host is the first one.
-	 * XXX
-	 * XXX Currently we support only one host on with a
-	 * XXX PC98ish HBA.
-	 * XXX
-	 */
-	if (1 || sdev->host == first_real && sdev->id < 7 &&
-	    __PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, sdev->id))
-	    	return pc98_first_bios_param(sdev, ip);
-
-	/* Assume PC-9801-92 compatible parameters for HAs without BIOS.  */
-	ip[0] = 8;
-	ip[1] = 32;
-	ip[2] = capacity / (8 * 32);
-	if (ip[2] > 65535) {    /* if capacity >= 8GB */
-		/* Recent on-board adapters seem to use this parameter. */
-		ip[1] = 128;
-		ip[2] = capacity / (8 * 128);
-		if (ip[2] > 65535) { /* if capacity >= 32GB  */
-			/* Clip the number of cylinders.  Currently
-			   this is the limit that we deal with.  */
-			ip[2] = 65535;
-		}
-	}
-
-	return 0;
-}
-
-EXPORT_SYMBOL(pc98_bios_param);
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/scsi_scan.c	2004-06-23 19:04:28 -07:00
@@ -45,6 +45,11 @@
 	" SCSI scanning, some SCSI devices might not be configured\n"
 
 /*
+ * Default timeout
+ */
+#define SCSI_TIMEOUT (2*HZ)
+
+/*
  * Prefix values for the SCSI id's (stored in driverfs name field)
  */
 #define SCSI_UID_SER_NUM 'S'
diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
--- a/drivers/scsi/scsi_syms.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/scsi_syms.c	2004-06-23 19:04:27 -07:00
@@ -46,15 +46,14 @@
 EXPORT_SYMBOL(scsi_partsize);
 EXPORT_SYMBOL(scsi_bios_ptable);
 EXPORT_SYMBOL(scsi_ioctl);
-EXPORT_SYMBOL(print_command);
-EXPORT_SYMBOL(print_sense);
-EXPORT_SYMBOL(print_req_sense);
-EXPORT_SYMBOL(print_msg);
-EXPORT_SYMBOL(print_status);
+EXPORT_SYMBOL(scsi_print_command);
+EXPORT_SYMBOL(__scsi_print_command);
+EXPORT_SYMBOL(scsi_print_sense);
+EXPORT_SYMBOL(scsi_print_req_sense);
+EXPORT_SYMBOL(scsi_print_msg);
+EXPORT_SYMBOL(scsi_print_status);
 EXPORT_SYMBOL(scsi_sense_key_string);
 EXPORT_SYMBOL(scsi_extd_sense_format);
-EXPORT_SYMBOL(kernel_scsi_ioctl);
-EXPORT_SYMBOL(print_Scsi_Cmnd);
 EXPORT_SYMBOL(scsi_block_when_processing_errors);
 EXPORT_SYMBOL(scsi_ioctl_send_command);
 EXPORT_SYMBOL(scsi_set_medium_removal);
diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/scsi_sysfs.c	2004-06-23 19:04:25 -07:00
@@ -99,7 +99,7 @@
  */
 #define shost_rd_attr2(name, field, format_string)			\
 	shost_show_function(name, field, format_string)			\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
 
 #define shost_rd_attr(field, format_string) \
 shost_rd_attr2(field, field, format_string)
@@ -228,8 +228,8 @@
  * read only field.
  */
 #define sdev_rd_attr(field, format_string)				\
-	sdev_show_function(field, format_string)				\
-static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL)
+	sdev_show_function(field, format_string)			\
+static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
 
 
 /*
@@ -247,7 +247,7 @@
 	snscanf (buf, 20, format_string, &sdev->field);			\
 	return count;							\
 }									\
-static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field)
+static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
 
 /* Currently we don't export bit fields, but we might in future,
  * so leave this code in */
@@ -272,7 +272,7 @@
 	}								\
 	return ret;							\
 }									\
-static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field)
+static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
 
 /*
  * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
@@ -320,7 +320,7 @@
 	sdev->timeout = timeout * HZ;
 	return count;
 }
-static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout)
+static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
 
 static ssize_t
 store_rescan_field (struct device *dev, const char *buf, size_t count) 
@@ -328,7 +328,7 @@
 	scsi_rescan_device(dev);
 	return count;
 }
-static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field)
+static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
 
 static ssize_t sdev_store_delete(struct device *dev, const char *buf,
 				 size_t count)
diff -Nru a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
--- a/drivers/scsi/scsi_transport_spi.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/scsi_transport_spi.c	2004-06-23 19:04:27 -07:00
@@ -152,7 +152,7 @@
 	spi_transport_store_function(field, format_string)		\
 static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR,			\
 			 show_spi_transport_##field,			\
-			 store_spi_transport_##field)
+			 store_spi_transport_##field);
 
 /* The Parallel SCSI Tranport Attributes: */
 spi_transport_rd_attr(offset, "%d\n");
@@ -173,7 +173,7 @@
 	spi_dv_device(sdev);
 	return count;
 }
-static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate)
+static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
 
 /* Translate the period into ns according to the current spec
  * for SDTR/PPR messages */
@@ -390,10 +390,11 @@
 {
 	struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
 	struct scsi_device *sdev = sreq->sr_device;
-	int period, prevperiod = 0; 
+	int period = 0, prevperiod = 0; 
 
 
 	for (;;) {
+		int newperiod;
 		if (compare_fn(sreq, buffer, ptr, DV_LOOPS))
 			/* Successful DV */
 			break;
@@ -401,7 +402,8 @@
 		/* OK, retrain, fallback */
 		if (i->f->get_period)
 			i->f->get_period(sdev);
-		period = spi_period(sdev);
+		newperiod = spi_period(sdev);
+		period = newperiod > period ? newperiod : period;
 		if (period < 0x0d)
 			period++;
 		else
diff -Nru a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c
--- a/drivers/scsi/scsicam.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/scsicam.c	2004-06-23 19:04:27 -07:00
@@ -19,7 +19,7 @@
 #include <linux/buffer_head.h>
 #include <asm/unaligned.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
 
 static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds,
diff -Nru a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c
--- a/drivers/scsi/scsiiom.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/scsiiom.c	2004-06-23 19:04:25 -07:00
@@ -12,7 +12,7 @@
 		pDCB->TagMask &= ~(1 << pSRB->TagNumber);   /* free tag mask */
 		pSRB->TagNumber = 255;
 	}
-};
+}
 
 
 static UCHAR
@@ -75,7 +75,7 @@
 		printk (KERN_WARNING "DC390: Out of tags for Dev. %02x %02x\n", pDCB->TargetID, pDCB->TargetLUN); 
 		return 1;
 		//goto no_tag;
-	};
+	}
 	DC390_write8 (ScsiFifo, SIMPLE_QUEUE_TAG);
 	pDCB->TagMask |= (1 << tag_no); pSRB->TagNumber = tag_no;
 	DC390_write8 (ScsiFifo, tag_no);
@@ -86,7 +86,7 @@
       {
 //      no_tag:
 	DEBUG1(printk (KERN_DEBUG "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", (disc_allowed?"":"o"), pSRB->pcmd->pid, pSRB));
-      };
+      }
 
     pSRB->SRBState = SRB_START_;
 
@@ -104,7 +104,7 @@
 	//pSRB->SRBState = SRB_MSGOUT_;
 	pSRB->SRBState |= DO_SYNC_NEGO;
 	cmd = SEL_W_ATN_STOP;
-      };
+      }
 
     /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */
     if (cmd != SEL_W_ATN_STOP)
@@ -125,7 +125,7 @@
 	    ptr = (PUCHAR) pSRB->pcmd->cmnd;
 	    for (i=0; i<pSRB->pcmd->cmd_len; i++)
 	      DC390_write8 (ScsiFifo, *(ptr++));
-	  };
+	  }
       }
     DEBUG0(if (pACB->pActiveDCB)	\
 	   printk (KERN_WARNING "DC390: ActiveDCB != 0\n"));
@@ -141,7 +141,7 @@
 	//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
 	pACB->SelLost++;
 	return 1;
-    };
+    }
     DC390_write8 (ScsiCmd, cmd);
     pACB->pActiveDCB = pDCB; pDCB->pActiveSRB = pSRB;
     pACB->Connected = 1;
@@ -176,7 +176,7 @@
     {
 	printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate);
 	return dstate;
-    };
+    }
   if (dstate & DMA_XFER_DONE)
     {
 	UINT residual, xferCnt; int ctr = 6000000;
@@ -253,7 +253,7 @@
       {
 	DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n"));
 	return IRQ_NONE;
-      };
+      }
 #else
     //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
     //dstatus = DC390_read8 (DMA_Status);
@@ -313,7 +313,7 @@
 	{
 		printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
 		goto unlock;
-	};
+	}
 	pSRB = pDCB->pActiveSRB;
 	if( pDCB->DCBFlag & ABORT_DEV_ )
 	  dc390_EnableMsgOut_Abort (pACB, pSRB);
@@ -549,7 +549,7 @@
   DC390_write8 (CtrlReg3, pDCB->CtrlR3);
   DC390_write8 (CtrlReg4, pDCB->CtrlR4);
   dc390_SetXferRate (pACB, pDCB);
-};
+}
 
 
 #ifdef DC390_DEBUG0
@@ -561,7 +561,7 @@
   for (i = 1; i < len; i++)
     printk (" %02x", MsgBuf[i]);
   printk ("\n");
-};
+}
 #endif
 
 #define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
@@ -671,11 +671,11 @@
 	{
 	  printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
 	  pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
-	};
+	}
       memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
       pSRB->MsgCnt = 5;
       DC390_ENABLE_MSGOUT;
-    };
+    }
 
   pSRB->SRBState &= ~DO_SYNC_NEGO;
   pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
@@ -713,7 +713,7 @@
     }
   
   dc390_reprog (pACB, pDCB);
-};
+}
 
 
 /* handle RESTORE_PTR */
@@ -761,7 +761,7 @@
     }
 
   pSRB->TotalXferredLen = pSRB->Saved_Ptr;
-};
+}
 
 
 /* According to the docs, the AM53C974 reads the message and 
@@ -789,7 +789,7 @@
 
 
 /* read and eval received messages */
-void
+static void
 dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
 {
     PDCB   pDCB = pACB->pActiveDCB;
@@ -832,7 +832,7 @@
 		  dc390_MsgIn_set_async (pACB, pSRB);
 		else
 		  dc390_MsgIn_set_sync (pACB, pSRB);
-	      };
+	      }
 	    
 	    // nothing has to be done
 	  case COMMAND_COMPLETE: break;
@@ -948,7 +948,7 @@
     dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
 }
 
-void
+static void
 dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
 {
     PDCB   pDCB;
@@ -989,7 +989,7 @@
     //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
 }
 
-void
+static void
 dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
 {
     UCHAR   bval, i, cnt;
@@ -1097,7 +1097,7 @@
 }
 
 
-void
+static void
 dc390_Disconnect( PACB pACB )
 {
     PDCB   pDCB;
@@ -1179,7 +1179,7 @@
 }
 
 
-void
+static void
 dc390_Reselect( PACB pACB )
 {
     PDCB   pDCB;
@@ -1276,7 +1276,7 @@
 	DCBDEBUG(printk (KERN_INFO "DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",\
 		pDCB->TargetID, pDCB->TargetLUN, (int)pDCB, pDCB->GoingSRBCnt));
 	return;
-     };
+     }
    pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN);
    
    // The first one
@@ -1302,8 +1302,7 @@
    if (pDCB == pACB->pDCBRunRobin) pACB->pDCBRunRobin = pDCB->pNextDCB;
    kfree (pDCB); 
    pACB->DCBCnt--;
-   /* pACB->DeviceCnt--; */
-};
+}
 
 
 static UCHAR __inline__
@@ -1314,7 +1313,7 @@
      if (memcmp (name, dc390_baddevname1[i], 28) == 0)
 	return 1;
    return 0;
-};
+}
    
 
 static void 
@@ -1336,7 +1335,7 @@
 	else
 	     pDCB->MaxCommand = 1;
      }
-};
+}
 
 
 static void 
@@ -1346,13 +1345,13 @@
    pDCB->DevType = bval1;
    /* if (bval1 == TYPE_DISK || bval1 == TYPE_MOD) */
 	dc390_disc_tagq_set (pDCB, ptr);
-};
+}
 
 
-void
+static void
 dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
 {
-    UCHAR  bval, status, i, DCB_removed;
+    UCHAR  bval, status, i;
     PSCSICMD pcmd;
     PSCSI_INQDATA  ptr;
     PSGL   ptr2;
@@ -1362,11 +1361,10 @@
     /* KG: Moved pci_unmap here */
     dc390_pci_unmap(pSRB);
 
-    DCB_removed = 0;
     status = pSRB->TargetStatus;
     ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
     if( pcmd->use_sg )
-	ptr = (PSCSI_INQDATA) sg_dma_address((PSGL) ptr);
+	ptr = (PSCSI_INQDATA) (page_address(((PSGL) ptr)->page) + ((PSGL) ptr)->offset);
 	
     DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\
 		pSRB, pcmd->pid));
@@ -1564,55 +1562,22 @@
 				   pcmd->sense_buffer[2], pcmd->sense_buffer[3]);
 	    else printk ("\n");
 #endif
-	    if( (host_byte(pcmd->result) != DID_OK && !(status_byte(pcmd->result) & CHECK_CONDITION) && !(status_byte(pcmd->result) & BUSY)) ||
-	       ((driver_byte(pcmd->result) & DRIVER_SENSE) && (pcmd->sense_buffer[0] & 0x70) == 0x70 &&
-		(pcmd->sense_buffer[2] & 0xf) == ILLEGAL_REQUEST) || host_byte(pcmd->result) & DID_ERROR )
-	    {
-	       /* device not present: remove */ 
-	       //dc390_Going_remove (pDCB, pSRB);
-	       dc390_remove_dev (pACB, pDCB); DCB_removed = 1;
-	       
-	       if( (pcmd->device->id == pACB->pScsiHost->max_id - 1) &&
-		  ((pcmd->device->lun == 0) || (pcmd->device->lun == pACB->pScsiHost->max_lun - 1)) )
-		 pACB->scan_devices = 0;
-	    }
-	    else
-	    {
-	        /* device present: add */
-		if( (pcmd->device->id == pACB->pScsiHost->max_id - 1) && 
-		    (pcmd->device->lun == pACB->pScsiHost->max_lun - 1) )
-		    pACB->scan_devices = END_SCAN ;
-	        /* pACB->DeviceCnt++; */ /* Dev is added on INQUIRY */
-	    }
 	}
     }
-   
-    //if( pSRB->pcmd->cmnd[0] == INQUIRY && 
-    //  (host_byte(pcmd->result) == DID_OK || status_byte(pcmd->result) & CHECK_CONDITION) )
+
     if( pcmd->cmnd[0] == INQUIRY && 
 	(pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) )
      {
-	if ((ptr->DevType & SCSI_DEVTYPE) == TYPE_NODEV && !DCB_removed)
-	  {
-	     //printk ("DC390: Type = nodev! (%02i-%i)\n", pcmd->target, pcmd->lun);
-	     /* device not present: remove */
-	     //dc390_Going_remove (pDCB, pSRB);
-	     dc390_remove_dev (pACB, pDCB); DCB_removed = 1;
-	  }
-	else
+	if ((ptr->DevType & SCSI_DEVTYPE) != TYPE_NODEV)
 	  {
 	     /* device found: add */ 
 	     dc390_add_dev (pACB, pDCB, ptr);
-	     if (pACB->scan_devices) pACB->DeviceCnt++;
 	  }
-	if( (pcmd->device->id == pACB->pScsiHost->max_id - 1) &&
-	    (pcmd->device->lun == pACB->pScsiHost->max_lun - 1) )
-	  pACB->scan_devices = 0;
-     };
+     }
 
     pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen;
 
-    if (!DCB_removed) dc390_Going_remove (pDCB, pSRB);
+    dc390_Going_remove (pDCB, pSRB);
     /* Add to free list */
     dc390_Free_insert (pACB, pSRB);
 
@@ -1625,7 +1590,7 @@
 
 
 /* Remove all SRBs from Going list and inform midlevel */
-void
+static void
 dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd )
 {
     PDCB   pDCB, pdcb;
@@ -1760,4 +1725,3 @@
     if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
 	DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
 }
-
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/sd.c	2004-06-23 19:04:28 -07:00
@@ -52,7 +52,7 @@
 #include <asm/uaccess.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include <scsi/scsi_driver.h>
 #include <scsi/scsi_ioctl.h>
@@ -763,11 +763,11 @@
 				good_bytes = 0;
 			break;
 
-		case RECOVERED_ERROR:
+		case RECOVERED_ERROR: /* an error occurred, but it recovered */
+		case NO_SENSE: /* LLDD got sense data */
 			/*
-			 * An error occurred, but it recovered.  Inform the
-			 * user, but make sure that it's not treated as a
-			 * hard error.
+			 * Inform the user, but make sure that it's not treated
+			 * as a hard error.
 			 */
 			print_sense("sd", SCpnt);
 			SCpnt->result = 0;
diff -Nru a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
--- a/drivers/scsi/seagate.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/seagate.c	2004-06-23 19:04:26 -07:00
@@ -103,7 +103,7 @@
 #include <asm/uaccess.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "seagate.h"
 
 #include <scsi/scsi_ioctl.h>
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/sg.c	2004-06-23 19:04:26 -07:00
@@ -42,7 +42,6 @@
 #include <linux/fcntl.h>
 #include <linux/init.h>
 #include <linux/poll.h>
-#include <linux/vmalloc.h>
 #include <linux/smp_lock.h>
 #include <linux/moduleparam.h>
 #include <linux/devfs_fs_kernel.h>
@@ -51,7 +50,7 @@
 
 #include <linux/blkdev.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsi_driver.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/sg.h>
@@ -60,7 +59,7 @@
 
 #ifdef CONFIG_SCSI_PROC_FS
 #include <linux/proc_fs.h>
-static char *sg_version_date = "20040513";
+static char *sg_version_date = "20040516";
 
 static int sg_proc_init(void);
 static void sg_proc_cleanup(void);
@@ -73,7 +72,7 @@
 #define SG_ALLOW_DIO_DEF 0
 #define SG_ALLOW_DIO_CODE /* compile out by commenting this define */
 
-#define SG_MAX_DEVS 8192
+#define SG_MAX_DEVS 32768
 
 /*
  * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d)
@@ -718,7 +717,6 @@
 		    (void *) SRpnt->sr_buffer, hp->dxfer_len,
 		    sg_cmd_done, timeout, SG_DEFAULT_RETRIES);
 	/* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */
-	generic_unplug_device(q);
 	return 0;
 }
 
@@ -1331,9 +1329,11 @@
 	void *old_sg_dev_arr = NULL;
 	int k, error;
 
-	sdp = vmalloc(sizeof(Sg_device));
-	if (!sdp)
+	sdp = kmalloc(sizeof(Sg_device), GFP_KERNEL);
+	if (!sdp) {
+		printk(KERN_WARNING "kmalloc Sg_device failure\n");
 		return -ENOMEM;
+	}
 
 	write_lock_irqsave(&sg_dev_arr_lock, iflags);
 	if (unlikely(sg_nr_dev >= sg_dev_max)) {	/* try to resize */
@@ -1341,7 +1341,7 @@
 		int tmp_dev_max = sg_nr_dev + SG_DEV_ARR_LUMP;
 		write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
 
-		tmp_da = vmalloc(tmp_dev_max * sizeof(Sg_device *));
+		tmp_da = kmalloc(tmp_dev_max * sizeof(Sg_device *), GFP_KERNEL);
 		if (unlikely(!tmp_da))
 			goto expand_failed;
 
@@ -1375,12 +1375,12 @@
 
  out:
 	if (error < 0)
-		vfree(sdp);
-	vfree(old_sg_dev_arr);
+		kfree(sdp);
+	kfree(old_sg_dev_arr);
 	return error;
 
  expand_failed:
-	printk(KERN_ERR "sg_alloc: device array cannot be resized\n");
+	printk(KERN_WARNING "sg_alloc: device array cannot be resized\n");
 	error = -ENOMEM;
 	goto out;
 
@@ -1404,20 +1404,26 @@
 	int error, k;
 
 	disk = alloc_disk(1);
-	if (!disk)
+	if (!disk) {
+		printk(KERN_WARNING "alloc_disk failed\n");
 		return -ENOMEM;
+	}
 	disk->major = SCSI_GENERIC_MAJOR;
 
 	error = -ENOMEM;
 	cdev = cdev_alloc();
-	if (!cdev)
+	if (!cdev) {
+		printk(KERN_WARNING "cdev_alloc failed\n");
 		goto out;
+	}
 	cdev->owner = THIS_MODULE;
 	cdev->ops = &sg_fops;
 
 	error = sg_alloc(disk, scsidp);
-	if (error < 0)
+	if (error < 0) {
+		printk(KERN_WARNING "sg_alloc failed\n");
 		goto out;
+	}
 	k = error;
 	sdp = sg_dev_arr[k];
 
@@ -1525,7 +1531,7 @@
 		put_disk(sdp->disk);
 		sdp->disk = NULL;
 		if (NULL == sdp->headfp)
-			vfree((char *) sdp);
+			kfree((char *) sdp);
 	}
 
 	if (delay)
@@ -1590,7 +1596,7 @@
 	unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
 				 SG_MAX_DEVS);
 	if (sg_dev_arr != NULL) {
-		vfree((char *) sg_dev_arr);
+		kfree((char *) sg_dev_arr);
 		sg_dev_arr = NULL;
 	}
 	sg_dev_max = 0;
@@ -2492,7 +2498,7 @@
 			}
 			if (k < maxd)
 				sg_dev_arr[k] = NULL;
-			vfree((char *) sdp);
+			kfree((char *) sdp);
 			res = 1;
 		}
 		write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
diff -Nru a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
--- a/drivers/scsi/sgiwd93.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/sgiwd93.c	2004-06-23 19:04:28 -07:00
@@ -31,7 +31,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "wd33c93.h"
 #include "sgiwd93.h"
 
diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
--- a/drivers/scsi/sim710.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/sim710.c	2004-06-23 19:04:28 -07:00
@@ -35,9 +35,8 @@
 #include <linux/mca.h>
 #include <linux/eisa.h>
 #include <linux/interrupt.h>
+#include <scsi/scsi_host.h>
 
-#include "scsi.h"
-#include "hosts.h"
 #include "53c700.h"
 
 
@@ -86,7 +85,7 @@
 }
 __setup("sim710=", param_setup);
 
-static Scsi_Host_Template sim710_driver_template = {
+static struct scsi_host_template sim710_driver_template = {
 	.name			= "LSI (Symbios) 710 MCA/EISA",
 	.proc_name		= "sim710",
 	.this_id		= 7,
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/sr.c	2004-06-23 19:04:29 -07:00
@@ -47,7 +47,7 @@
 #include <asm/uaccess.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include <scsi/scsi_driver.h>
 #include <scsi/scsi_ioctl.h>	/* For the door lock/unlock commands */
@@ -754,12 +754,11 @@
 static void get_capabilities(struct scsi_cd *cd)
 {
 	unsigned char *buffer;
-	int rc, n, mrw_write = 0, mrw = 1,ram_write=0;
 	struct scsi_mode_data data;
 	struct scsi_request *SRpnt;
 	unsigned char cmd[MAX_COMMAND_SIZE];
 	unsigned int the_result;
-	int retries;
+	int retries, rc, n;
 
 	static char *loadmech[] =
 	{
@@ -830,19 +829,6 @@
 		printk("%s: scsi-1 drive\n", cd->cdi.name);
 		return;
 	}
-
-	if (cdrom_is_mrw(&cd->cdi, &mrw_write)) {
-		mrw = 0;
-		cd->cdi.mask |= CDC_MRW;
-		cd->cdi.mask |= CDC_MRW_W;
-	}
-	if (!mrw_write)
-		cd->cdi.mask |= CDC_MRW_W;
-
-	if (cdrom_is_random_writable(&cd->cdi, &ram_write))
-		cd->cdi.mask |= CDC_RAM;
-	if (!ram_write)
-		cd->cdi.mask |= CDC_RAM;
 
 	n = data.header_length + data.block_descriptor_length;
 	cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
diff -Nru a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
--- a/drivers/scsi/sr_ioctl.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/sr_ioctl.c	2004-06-23 19:04:27 -07:00
@@ -11,7 +11,7 @@
 #include <asm/uaccess.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 
 #include "sr.h"
@@ -330,6 +330,9 @@
 	struct packet_command cgc;
 	int result;
 	unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
+
+	if (!buffer)
+		return -ENOMEM;
 
 	memset(&cgc, 0, sizeof(struct packet_command));
 	cgc.timeout = IOCTL_TIMEOUT;
diff -Nru a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
--- a/drivers/scsi/sr_vendor.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/sr_vendor.c	2004-06-23 19:04:26 -07:00
@@ -41,7 +41,7 @@
 
 #include <linux/blkdev.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 
 #include <linux/cdrom.h>
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/st.c	2004-06-23 19:04:27 -07:00
@@ -58,7 +58,7 @@
 
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include <scsi/scsi_driver.h>
 #include <scsi/scsi_ioctl.h>
diff -Nru a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
--- a/drivers/scsi/sun3_scsi.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/sun3_scsi.c	2004-06-23 19:04:25 -07:00
@@ -75,7 +75,7 @@
 #define REAL_DMA
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "sun3_scsi.h"
 #include "NCR5380.h"
 
diff -Nru a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
--- a/drivers/scsi/sun3_scsi_vme.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/sun3_scsi_vme.c	2004-06-23 19:04:29 -07:00
@@ -41,7 +41,7 @@
 #define REAL_DMA
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "sun3_scsi.h"
 #include "NCR5380.h"
 
diff -Nru a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
--- a/drivers/scsi/sun3x_esp.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/sun3x_esp.c	2004-06-23 19:04:27 -07:00
@@ -16,7 +16,7 @@
 #include <linux/interrupt.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "NCR53C9x.h"
 
 #include <asm/sun3x.h>
diff -Nru a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
--- a/drivers/scsi/sym53c416.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/scsi/sym53c416.c	2004-06-23 19:04:25 -07:00
@@ -43,7 +43,7 @@
 #include <linux/blkdev.h>
 #include <linux/isapnp.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "sym53c416.h"
 
 #define VERSION_STRING        "Version 1.0.0-ac"
@@ -622,12 +622,13 @@
 	int ints[2];
 
 	ints[0] = 1;
-	for(; *base; base++)
-	{
-		if(!check_region(*base, IO_RANGE) && sym53c416_test(*base))
-		{
-			ints[1] = *base;
-			sym53c416_setup(NULL, ints);
+	for(; *base; base++) {
+		if (request_region(*base, IO_RANGE, ID)) {
+			if (sym53c416_test(*base)) {
+				ints[1] = *base;
+				sym53c416_setup(NULL, ints);
+			}
+			release_region(*base, IO_RANGE);
 		}
 	}
 }
@@ -702,44 +703,42 @@
 	sym53c416_probe();
 
 	/* Now we register and set up each host adapter found... */
-	for(count = 0, i = 0; i < host_index; i++)
-	{
-		if(!sym53c416_test(hosts[i].base))
+	for(count = 0, i = 0; i < host_index; i++) {
+		if (!request_region(hosts[i].base, IO_RANGE, ID))
+			continue;
+		if (!sym53c416_test(hosts[i].base)) {
 			printk(KERN_WARNING "No sym53c416 found at address 0x%03x\n", hosts[i].base);
-		else
-		{
-			if(hosts[i].irq == 0)
-			/* We don't have an irq yet, so we should probe for one */
-				if((hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id)) == 0)
-					printk(KERN_WARNING "IRQ autoprobing failed for sym53c416 at address 0x%03x\n", hosts[i].base);
-			if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE))
-			{
-				shpnt = scsi_register(tpnt, 0);
-				if(shpnt==NULL)
-					continue;
-				spin_lock_irqsave(&sym53c416_lock, flags);
-				/* Request for specified IRQ */
-				if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, shpnt))
-				{
-					spin_unlock_irqrestore(&sym53c416_lock, flags);
-					printk(KERN_ERR "sym53c416: Unable to assign IRQ %d\n", hosts[i].irq);
-					scsi_unregister(shpnt);
-				}
-				else
-				{
-					/* Inform the kernel of our IO range */
-					request_region(hosts[i].base, IO_RANGE, ID);
-					shpnt->unique_id = hosts[i].base;
-					shpnt->io_port = hosts[i].base;
-					shpnt->n_io_port = IO_RANGE;
-					shpnt->irq = hosts[i].irq;
-					shpnt->this_id = hosts[i].scsi_id;
-					sym53c416_init(hosts[i].base, hosts[i].scsi_id);
-					count++;
-					spin_unlock_irqrestore(&sym53c416_lock, flags);
-				}
-			}
+			goto fail_release_region;
 		}
+
+		/* We don't have an irq yet, so we should probe for one */
+		if (!hosts[i].irq)
+			hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id);
+		if (!hosts[i].irq)
+			goto fail_release_region;
+	
+		shpnt = scsi_register(tpnt, 0);
+		if (!shpnt)
+			goto fail_release_region;
+		/* Request for specified IRQ */
+		if (request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, shpnt))
+			goto fail_free_host;
+
+		spin_lock_irqsave(&sym53c416_lock, flags);
+		shpnt->unique_id = hosts[i].base;
+		shpnt->io_port = hosts[i].base;
+		shpnt->n_io_port = IO_RANGE;
+		shpnt->irq = hosts[i].irq;
+		shpnt->this_id = hosts[i].scsi_id;
+		sym53c416_init(hosts[i].base, hosts[i].scsi_id);
+		count++;
+		spin_unlock_irqrestore(&sym53c416_lock, flags);
+		continue;
+
+ fail_free_host:
+		scsi_unregister(shpnt);
+ fail_release_region:
+		release_region(hosts[i].base, IO_RANGE);
 	}
 	return count;
 }
diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c
--- a/drivers/scsi/t128.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/t128.c	2004-06-23 19:04:28 -07:00
@@ -118,7 +118,7 @@
 #include <linux/delay.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "t128.h"
 #define AUTOPROBE_IRQ
 #include "NCR5380.h"
diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
--- a/drivers/scsi/tmscsim.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/tmscsim.c	2004-06-23 19:04:29 -07:00
@@ -172,6 +172,11 @@
  *	2.1b1 04/01/31	GL	(applied 05.04) Remove internal		*
  *				command-queuing.			*
  *	2.1b2 04/02/01	CH	(applied 05.04) Fix error-handling	*
+ *	2.1c  04/05/23  GL	Update to use the new pci_driver API,	*
+ *				some scsi EH updates, more cleanup.	*
+ *	2.1d  04/05/27	GL	Moved setting of scan_devices to	*
+ *				slave_alloc/_configure/_destroy, as	*
+ *				suggested by CH.			*
  ***********************************************************************/
 
 /* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */
@@ -239,7 +244,7 @@
 #include <linux/interrupt.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <linux/stat.h>
 #include <scsi/scsicam.h>
 
@@ -267,7 +272,6 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 
-#if defined(MODULE)
 static struct pci_device_id tmscsim_pci_tbl[] = {
 	{
 		.vendor		= PCI_VENDOR_ID_AMD,
@@ -278,8 +282,7 @@
 	{ }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
-#endif
-	
+
 #define USE_SPINLOCKS 1
 
 #define DC390_IFLAGS unsigned long iflags
@@ -342,6 +345,8 @@
 
 static int DC390_release(struct Scsi_Host *host);
 static int dc390_shutdown (struct Scsi_Host *host);
+static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start,
+			    off_t offset, int length, int inout);
 
 static PACB	dc390_pACB_start= NULL;
 static PACB	dc390_pACB_current = NULL;
@@ -351,16 +356,14 @@
 
 /* Startup values, to be overriden on the commandline */
 static int tmscsim[] = {-2, -2, -2, -2, -2, -2};
+static int tmscsim_paramnum = ARRAY_SIZE(tmscsim);
 
-#if defined(MODULE)
-MODULE_PARM(tmscsim, "1-6i");
+module_param_array(tmscsim, int, tmscsim_paramnum, 0);
 MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");
 MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
 MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
 MODULE_LICENSE("GPL");
-
 MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
-#endif
 
 static PVOID dc390_phase0[]={
        dc390_DataOut_0,
@@ -913,6 +916,14 @@
     }
 }
 
+static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length)
+{
+	memset(sg, 0, sizeof(struct scatterlist));
+	sg->page	= virt_to_page(addr);
+	sg->length	= length;
+	sg->offset	= (unsigned long)addr & ~PAGE_MASK;
+	return sg;
+}
 
 /* Create pci mapping */
 static int dc390_pci_map (PSRB pSRB)
@@ -921,40 +932,43 @@
 	Scsi_Cmnd *pcmd = pSRB->pcmd;
 	struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
 	dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp));
+
 	/* Map sense buffer */
 	if (pSRB->SRBFlag & AUTO_REQSENSE) {
-		sg_dma_address(&pSRB->Segmentx) = cmdp->saved_dma_handle = 
-			pci_map_page(pdev, virt_to_page(pcmd->sense_buffer),
-				     (unsigned long)pcmd->sense_buffer & ~PAGE_MASK, sizeof(pcmd->sense_buffer),
-				     DMA_FROM_DEVICE);
-		sg_dma_len(&pSRB->Segmentx) = sizeof(pcmd->sense_buffer);
-		pSRB->SGcount = 1;
-		pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
+		pSRB->pSegmentList	= dc390_sg_build_single(&pSRB->Segmentx, pcmd->sense_buffer, sizeof(pcmd->sense_buffer));
+		pSRB->SGcount		= pci_map_sg(pdev, pSRB->pSegmentList, 1,
+						     DMA_FROM_DEVICE);
+		cmdp->saved_dma_handle	= sg_dma_address(pSRB->pSegmentList);
+
+		/* TODO: error handling */
+		if (pSRB->SGcount != 1)
+			error = 1;
 		DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle));
-	/* Make SG list */	
+	/* Map SG list */
 	} else if (pcmd->use_sg) {
-		pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
-		pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList,
-					   pcmd->use_sg,
-					   scsi_to_pci_dma_dir(pcmd->sc_data_direction));
+		pSRB->pSegmentList	= (PSGL) pcmd->request_buffer;
+		pSRB->SGcount		= pci_map_sg(pdev, pSRB->pSegmentList, pcmd->use_sg,
+						     scsi_to_pci_dma_dir(pcmd->sc_data_direction));
 		/* TODO: error handling */
 		if (!pSRB->SGcount)
 			error = 1;
-		DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n", __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg));
+		DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
+			      __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg));
 	/* Map single segment */
 	} else if (pcmd->request_buffer && pcmd->request_bufflen) {
-		sg_dma_address(&pSRB->Segmentx) = cmdp->saved_dma_handle =
-			pci_map_page(pdev, virt_to_page(pcmd->request_buffer),
-				     (unsigned long)pcmd->request_buffer & ~PAGE_MASK,
-				     pcmd->request_bufflen, scsi_to_pci_dma_dir(pcmd->sc_data_direction));
+		pSRB->pSegmentList	= dc390_sg_build_single(&pSRB->Segmentx, pcmd->request_buffer, pcmd->request_bufflen);
+		pSRB->SGcount		= pci_map_sg(pdev, pSRB->pSegmentList, 1,
+						     scsi_to_pci_dma_dir(pcmd->sc_data_direction));
+		cmdp->saved_dma_handle	= sg_dma_address(pSRB->pSegmentList);
+
 		/* TODO: error handling */
-		sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen;
-		pSRB->SGcount = 1;
-		pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
+		if (pSRB->SGcount != 1)
+			error = 1;
 		DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle));
 	/* No mapping !? */	
     	} else
 		pSRB->SGcount = 0;
+
 	return error;
 }
 
@@ -963,21 +977,16 @@
 {
 	Scsi_Cmnd* pcmd = pSRB->pcmd;
 	struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
-	dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp));
+	DEBUG1(dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp)));
 
 	if (pSRB->SRBFlag) {
-		pci_unmap_page(pdev, cmdp->saved_dma_handle,
-			       sizeof(pcmd->sense_buffer), DMA_FROM_DEVICE);
+		pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
 		DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
 	} else if (pcmd->use_sg) {
-		pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg,
-			     scsi_to_pci_dma_dir(pcmd->sc_data_direction));
+		pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, scsi_to_pci_dma_dir(pcmd->sc_data_direction));
 		DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n", __FUNCTION__, pcmd->request_buffer, pcmd->use_sg));
 	} else if (pcmd->request_buffer && pcmd->request_bufflen) {
-		pci_unmap_page(pdev,
-			       cmdp->saved_dma_handle,
-			       pcmd->request_bufflen,
-			       scsi_to_pci_dma_dir(pcmd->sc_data_direction));
+		pci_unmap_sg(pdev, &pSRB->Segmentx, 1, scsi_to_pci_dma_dir(pcmd->sc_data_direction));
 		DEBUG1(printk("%s(): Unmapped request buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
 	}
 }
@@ -1031,15 +1040,15 @@
  * 2.0.x: always return 0
  * 2.1.x: old model: (use_new_eh_code == 0): like 2.0.x
  *	  TO BE DONE:
- *	  new model: return 0 if successful
- *	  	     return 1 if command cannot be queued (queue full)
+ *	  new model: return 0 if successful, or must not be re-queued
+ *		     return 1 if command cannot be queued (queue full)
  *		     command will be inserted in midlevel queue then ...
  *
  ***********************************************************************/
 
 static int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
 {
-    PDCB   pDCB;
+    PDCB   pDCB = (PDCB) cmd->device->hostdata;
     PSRB   pSRB;
     PACB   pACB = (PACB) cmd->device->host->hostdata;
 
@@ -1050,42 +1059,19 @@
     /* TODO: Change the policy: Always accept TEST_UNIT_READY or INQUIRY 
      * commands and alloc a DCB for the device if not yet there. DCB will
      * be removed in dc390_SRBdone if SEL_TIMEOUT */
-
-    if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) )
-	pACB->scan_devices = 0;
-
-    else if( (pACB->scan_devices) && (cmd->cmnd[0] == READ_6) )
-	pACB->scan_devices = 0;
-
-    if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY || cmd->cmnd[0] == INQUIRY) && 
-       !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun)) )
-    {
-        pACB->scan_devices = 1;
-
-	dc390_initDCB( pACB, &pDCB, cmd->device->id, cmd->device->lun );
-	if (!pDCB)
-	  {
-	    printk (KERN_ERR "DC390: kmalloc for DCB failed, target %02x lun %02x\n", 
-		    cmd->device->id, cmd->device->lun);
-	    goto fail;
-	  }
-            
-    }
-    else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun)) )
-    {
+    if (!(pACB->scan_devices) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun))) {
 	printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n",
 		cmd->device->id, cmd->device->lun); 
 	goto fail;
     }
-    else
-    {
-	pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun);
-	if (!pDCB)
-	 {  /* should never happen */
-	    printk (KERN_ERR "DC390: no DCB failed, target %02x lun %02x\n", 
-		    cmd->device->id, cmd->device->lun);
-	    goto fail;
-	 }
+
+    /* Should it be: BUG_ON(!pDCB); ? */
+
+    if (!pDCB)
+    {  /* should never happen */
+	printk (KERN_ERR "DC390: no DCB found, target %02x lun %02x\n", 
+		cmd->device->id, cmd->device->lun);
+	goto fail;
     }
 
     pACB->Cmds++;
@@ -1304,7 +1290,7 @@
 
 static int DC390_abort (Scsi_Cmnd *cmd)
 {
-    PDCB  pDCB;
+    PDCB  pDCB = (PDCB) cmd->device->hostdata;
     PSRB  pSRB, psrb;
     UINT  count, i;
     int   status;
@@ -1314,7 +1300,6 @@
     printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n",
 	    cmd->pid, cmd->device->id, cmd->device->lun);
 
-    pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun);
     if( !pDCB ) goto  NOT_RUN;
 
     /* Added 98/07/02 KG */
@@ -1561,15 +1546,16 @@
 {
     PEEprom	prom;
     UCHAR	index;
-    PDCB pDCB, pDCB2;
+    PDCB	pDCB, pDCB2 = 0;
 
     pDCB = kmalloc (sizeof(DC390_DCB), GFP_ATOMIC);
     DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n",	\
 		     id, lun, pDCB));
- 
+
     *ppDCB = pDCB;
-    if (!pDCB) return;
-    pDCB2 = 0;
+    if (!pDCB)
+	return;
+
     if( pACB->DCBCnt == 0 )
     {
 	pACB->pLinkDCB = pDCB;
@@ -1745,8 +1731,6 @@
     pACB->SRBCount = MAX_SRB_CNT;
     pACB->AdapterIndex = index;
     pACB->status = 0;
-    psh->this_id = dc390_eepromBuf[index][EE_ADAPT_SCSI_ID];
-    pACB->DeviceCnt = 0;
     pACB->DCBCnt = 0;
     pACB->TagMaxNum = 2 << dc390_eepromBuf[index][EE_TAG_CMD_NUM];
     pACB->ACBFlag = 0;
@@ -1856,7 +1840,7 @@
  *
  * Inputs : host - pointer to this host adapter's structure
  *	    io_port - IO ports mapped to this adapter
- *	    Irq - IRQ assigned to this adpater
+ *	    irq - IRQ assigned to this adpater
  *	    struct pci_dev - PCI access handle
  *	    index - Adapter index
  *
@@ -1865,10 +1849,8 @@
  * Note: written in capitals, because the locking is only done here,
  *	not in DC390_detect, called from outside 
  ***********************************************************************/
-
-static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, struct pci_dev *pdev, UCHAR index)
+static int __init dc390_init (PSH psh, unsigned long io_port, u8 irq, struct pci_dev *pdev, UCHAR index)
 {
-    PSH   psh;
     PACB  pACB;
 
     if (dc390_CheckEEpromCheckSum (PDEV, index))
@@ -1890,25 +1872,16 @@
 	dc390_check_for_safe_settings ();
 	dc390_EEprom_Override (index);
     }
-   
-    psh = scsi_register( psht, sizeof(DC390_ACB) );
-    if( !psh ) return( -1 );
-	
-    scsi_set_device(psh, &pdev->dev);
     pACB = (PACB) psh->hostdata;
 
     DEBUG0(printk(KERN_INFO "DC390: pSH = %8x, Index %02i\n", (UINT) psh, index));
 
-    dc390_initACB( psh, io_port, Irq, index );
+    dc390_initACB( psh, io_port, irq, index );
         
     PDEVSET;
 
-    if( !dc390_initAdapter( psh, io_port, Irq, index ) )
+    if( !dc390_initAdapter( psh, io_port, irq, index ) )
     {
-	DEBUG0(printk("DC390: pACB = %8x, pDCBmap = %8x, pSRB_array = %8x\n",\
-		      (UINT) pACB, (UINT) pACB->DCBmap, (UINT) pACB->SRB_array));
-	DEBUG0(printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",\
-		      sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) ));
         return (0);
     }
     else
@@ -1927,42 +1900,131 @@
 	PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));
 }
 
-int __init DC390_detect (Scsi_Host_Template *psht)
+/**
+ * dc390_slave_alloc - Called by the scsi mid layer to tell us about a new
+ * scsi device that we need to deal with.
+ *
+ * @scsi_device: The new scsi device that we need to handle.
+ */
+static int dc390_slave_alloc(struct scsi_device *scsi_device)
 {
-    struct pci_dev *pdev = NULL;
-    UCHAR   irq;
-    ULONG   io_port;
+	PDCB pDCB;
+	PACB pACB = (PACB) scsi_device->host->hostdata;
+	dc390_initDCB(pACB, &pDCB, scsi_device->id, scsi_device->lun);
+	if (pDCB != NULL) {
+		scsi_device->hostdata = pDCB;
+		pACB->scan_devices = 1;
+		return 0;
+	}
+	return -ENOMEM;
+}
 
-    dc390_pACB_start = NULL;
+/**
+ * dc390_slave_destroy - Called by the scsi mid layer to tell us about a
+ * device that is going away.
+ *
+ * @scsi_device: The scsi device that we need to remove.
+ */
+static void dc390_slave_destroy(struct scsi_device *scsi_device)
+{
+	PACB pACB = (PACB) scsi_device->host->hostdata;
+	PDCB pDCB = (PDCB) scsi_device->hostdata;
+	pACB->scan_devices = 0;
+	if (pDCB != NULL)
+		dc390_remove_dev(pACB, pDCB);
+	else
+		printk(KERN_ERR"%s() called for non-existing device!\n", __FUNCTION__);
+}
 
-    if ( PCI_PRESENT )
-	    while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974, pdev)))
-	{
-	    if (pci_enable_device (pdev))
-		continue;
+static int dc390_slave_configure(struct scsi_device *scsi_device)
+{
+	PACB pACB = (PACB) scsi_device->host->hostdata;
+	pACB->scan_devices = 0;
+	return 0;
+}
 
-	    if (pci_set_dma_mask(pdev, 0xffffffff)) {
-		    printk(KERN_ERR "DC390(%i): No suitable DMA available.\n", dc390_adapterCnt);
-		    continue;
-	    }
-	    PCI_GET_IO_AND_IRQ;
-	    DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq));
+static Scsi_Host_Template driver_template = {
+	.module			= THIS_MODULE,
+	.proc_name		= "tmscsim", 
+	.proc_info		= DC390_proc_info,
+	.name			= DC390_BANNER " V" DC390_VERSION,
+	.slave_alloc		= dc390_slave_alloc,
+	.slave_configure	= dc390_slave_configure,
+	.slave_destroy		= dc390_slave_destroy,
+	.queuecommand		= DC390_queue_command,
+	.eh_abort_handler	= DC390_abort,
+	.eh_bus_reset_handler	= DC390_reset,
+	.bios_param		= DC390_bios_param,
+	.can_queue		= 42,
+	.this_id		= 7,
+	.sg_tablesize		= SG_ALL,
+	.cmd_per_lun		= 16,
+	.use_clustering		= DISABLE_CLUSTERING,
+};
 
-	    if( !DC390_init(psht, io_port, irq, PDEV, dc390_adapterCnt))
-	    {
-		pci_set_master(pdev);
-		dc390_set_pci_cfg (PDEV);
-		dc390_adapterCnt++;
-	    }
+static int __devinit dc390_init_one(struct pci_dev *dev,
+				    const struct pci_device_id *id)
+{
+	struct Scsi_Host *scsi_host;
+	unsigned long io_port;
+	u8 irq;
+	PACB  pACB;
+	int ret = -ENOMEM;
+
+	if (pci_enable_device(dev))
+		return -ENODEV;
+
+	io_port = pci_resource_start(dev, 0);
+	irq = dev->irq;
+
+	/* allocate scsi host information (includes out adapter) */
+	scsi_host = scsi_host_alloc(&driver_template, sizeof(struct _ACB));
+	if (!scsi_host)
+		goto nomem;
+
+	pACB = (PACB) scsi_host->hostdata;
+
+	if (dc390_init(scsi_host, io_port, irq, dev, dc390_adapterCnt)) {
+		ret = -EBUSY;
+		goto busy;
 	}
-    else
-	printk (KERN_ERR "DC390: No PCI BIOS found!\n");
-   
-    if (dc390_adapterCnt)
-	psht->proc_name = "tmscsim";
 
-    printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt);
-    return( dc390_adapterCnt );
+	pci_set_master(dev);
+	dc390_set_pci_cfg(dev);
+	dc390_adapterCnt++;
+
+	/* get the scsi mid level to scan for new devices on the bus */
+	if (scsi_add_host(scsi_host, &dev->dev)) {
+		ret = -ENODEV;
+		goto nodev;
+	}
+	pci_set_drvdata(dev, scsi_host);
+	scsi_scan_host(scsi_host);
+
+	return 0;
+
+nodev:
+busy:
+	scsi_host_put(scsi_host);
+nomem:
+	pci_disable_device(dev);
+	return ret;
+}
+
+/**
+ * dc390_remove_one - Called to remove a single instance of the adapter.
+ *
+ * @dev: The PCI device to remove.
+ */
+static void __devexit dc390_remove_one(struct pci_dev *dev)
+{
+	struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
+
+	scsi_remove_host(scsi_host);
+	DC390_release(scsi_host);
+	pci_disable_device(dev);
+	scsi_host_put(scsi_host);
+	pci_set_drvdata(dev, NULL);
 }
 
 /********************************************************************
@@ -2035,7 +2097,7 @@
   SPRINTF("            Lost arbitrations %i, Sel. connected %i, Connected: %s\n", 
 	  pACB->SelLost, pACB->SelConn, pACB->Connected? "Yes": "No");
    
-  SPRINTF("Nr of attached devices: %i, Nr of DCBs: %i\n", pACB->DeviceCnt, pACB->DCBCnt);
+  SPRINTF("Nr of DCBs: %i\n", pACB->DCBCnt);
   SPRINTF("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n",
 	  pACB->DCBmap[0], pACB->DCBmap[1], pACB->DCBmap[2], pACB->DCBmap[3], 
 	  pACB->DCBmap[4], pACB->DCBmap[5], pACB->DCBmap[6], pACB->DCBmap[7]);
@@ -2122,7 +2184,7 @@
 static int dc390_shutdown (struct Scsi_Host *host)
 {
     UCHAR    bval;
-    PACB pACB = (PACB)(host->hostdata);
+    PACB pACB = (PACB) host->hostdata;
    
 /*  pACB->soft_reset(host); */
 
@@ -2142,7 +2204,7 @@
 static void dc390_freeDCBs (struct Scsi_Host *host)
 {
     PDCB pDCB, nDCB;
-    PACB pACB = (PACB)(host->hostdata);
+    PACB pACB = (PACB) host->hostdata;
     
     pDCB = pACB->pLinkDCB;
     if (!pDCB) return;
@@ -2161,7 +2223,7 @@
 static int DC390_release (struct Scsi_Host *host)
 {
     DC390_IFLAGS;
-    PACB pACB = (PACB)(host->hostdata);
+    PACB pACB = (PACB) host->hostdata;
 
     DC390_LOCK_IO(host);
 
@@ -2177,24 +2239,25 @@
     release_region(host->io_port,host->n_io_port);
     dc390_freeDCBs (host);
     DC390_UNLOCK_IO(host);
-    scsi_unregister(host);
     return( 1 );
 }
 
-static Scsi_Host_Template driver_template = {
-   .proc_name      = "tmscsim", 
-   .proc_info      = DC390_proc_info,
-   .name           = DC390_BANNER " V" DC390_VERSION,
-   .detect         = DC390_detect,
-   .release        = DC390_release,
-   .queuecommand   = DC390_queue_command,
-   .eh_abort_handler		= DC390_abort,
-   .eh_bus_reset_handler	= DC390_reset,
-   .bios_param     = DC390_bios_param,
-   .can_queue      = 42,
-   .this_id        = 7,
-   .sg_tablesize   = SG_ALL,
-   .cmd_per_lun    = 16,
-   .use_clustering = DISABLE_CLUSTERING,
+static struct pci_driver dc390_driver = {
+	.name           = "tmscsim",
+	.id_table       = tmscsim_pci_tbl,
+	.probe          = dc390_init_one,
+	.remove         = __devexit_p(dc390_remove_one),
 };
-#include "scsi_module.c"
+
+static int __init dc390_module_init(void)
+{
+	return pci_module_init(&dc390_driver);
+}
+
+static void __exit dc390_module_exit(void)
+{
+	pci_unregister_driver(&dc390_driver);
+}
+
+module_init(dc390_module_init);
+module_exit(dc390_module_exit);
diff -Nru a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
--- a/drivers/scsi/tmscsim.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/scsi/tmscsim.h	2004-06-23 19:04:28 -07:00
@@ -22,8 +22,6 @@
 
 #define SEL_TIMEOUT		153	/* 250 ms selection timeout (@ 40 MHz) */
 
-#define END_SCAN		2
-
 #define pci_dma_lo32(a)			(a & 0xffffffff)
 
 typedef u8		UCHAR;	/*  8 bits */
@@ -196,10 +194,8 @@
 
 UCHAR		SRBCount;
 UCHAR		AdapterIndex;	/*; nth Adapter this driver */
-UCHAR		DeviceCnt;
 UCHAR		DCBCnt;
 
-/* 0x10: */
 UCHAR		TagMaxNum;
 UCHAR		ACBFlag;
 UCHAR		Gmode2;
@@ -213,13 +209,11 @@
 PSRB		pFreeSRB;
 PSRB		pTmpSRB;
 
-/* 0x2c: */
 UCHAR		msgin123[4];
 UCHAR		DCBmap[MAX_SCSI_ID];
 UCHAR		Connected;
 UCHAR		pad;
 
-/* 0x30: */
 #if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0)
 spinlock_t	lock;
 #endif
@@ -230,20 +224,17 @@
 UCHAR		Ignore_IRQ;	/* Not used */
 
 PDEVDECL1;			/* Pointer to PCI cfg. space */
-/* 0x40/0x3c: */
+
 ULONG		Cmds;
 UINT		SelLost;
 UINT		SelConn;
 UINT		CmdInQ;
 UINT		CmdOutOfSRB;
 	
-/* 0x54/0x50: */
 struct timer_list	Waiting_Timer;
-/* 0x68/0x64: */
+
 DC390_SRB	TmpSRB;
-/* 0xcc/0xc8: */
 DC390_SRB	SRB_array[MAX_SRB_CNT]; 	/* 50 SRBs */
-/* 0xfa4/0xfa0: */
 };
 
 typedef  struct  _ACB	 DC390_ACB, *PACB;
diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
--- a/drivers/scsi/u14-34f.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/scsi/u14-34f.c	2004-06-23 19:04:26 -07:00
@@ -423,7 +423,7 @@
 #include <linux/spinlock.h>
 #include <scsi/scsicam.h>
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 
diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
--- a/drivers/scsi/ultrastor.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/ultrastor.c	2004-06-23 19:04:27 -07:00
@@ -145,7 +145,7 @@
 
 #define ULTRASTOR_PRIVATE	/* Get the private stuff from ultrastor.h */
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include "ultrastor.h"
 
 #define FALSE 0
diff -Nru a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
--- a/drivers/scsi/wd33c93.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/wd33c93.c	2004-06-23 19:04:27 -07:00
@@ -83,7 +83,7 @@
 #include <asm/irq.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "wd33c93.h"
 
diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
--- a/drivers/scsi/wd7000.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/scsi/wd7000.c	2004-06-23 19:04:29 -07:00
@@ -184,7 +184,7 @@
 #include <asm/io.h>
 
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
 
 
@@ -1605,6 +1605,7 @@
 	return 0;
 }
 
+#if 0
 /*
  *  I have absolutely NO idea how to do an abort with the WD7000...
  */
@@ -1619,7 +1620,7 @@
 	}
 	return FAILED;
 }
-
+#endif
 
 /*
  *  I also have no idea how to do a reset...
diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
--- a/drivers/scsi/zalon.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/scsi/zalon.c	2004-06-23 19:04:27 -07:00
@@ -24,7 +24,7 @@
 
 #include "../parisc/gsc.h"
 #include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
 
 #include "ncr53c8xx.h"
 
diff -Nru a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c
--- a/drivers/serial/8250_acpi.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/serial/8250_acpi.c	2004-06-23 19:04:28 -07:00
@@ -57,28 +57,18 @@
 static acpi_status acpi_serial_ext_irq(struct serial_struct *req,
 				       struct acpi_resource_ext_irq *ext_irq)
 {
-	if (ext_irq->number_of_interrupts > 0) {
-#ifdef CONFIG_IA64
-		req->irq = acpi_register_irq(ext_irq->interrupts[0],
-	                  ext_irq->active_high_low, ext_irq->edge_level);
-#else
-		req->irq = ext_irq->interrupts[0];
-#endif
-	}
+	if (ext_irq->number_of_interrupts > 0)
+		req->irq = acpi_register_gsi(ext_irq->interrupts[0],
+	                  ext_irq->edge_level, ext_irq->active_high_low);
 	return AE_OK;
 }
 
 static acpi_status acpi_serial_irq(struct serial_struct *req,
 				   struct acpi_resource_irq *irq)
 {
-	if (irq->number_of_interrupts > 0) {
-#ifdef CONFIG_IA64
-		req->irq = acpi_register_irq(irq->interrupts[0],
-	                  irq->active_high_low, irq->edge_level);
-#else
-		req->irq = irq->interrupts[0];
-#endif
-	}
+	if (irq->number_of_interrupts > 0)
+		req->irq = acpi_register_gsi(irq->interrupts[0],
+	                  irq->edge_level, irq->active_high_low);
 	return AE_OK;
 }
 
diff -Nru a/drivers/serial/8250_hcdp.c b/drivers/serial/8250_hcdp.c
--- a/drivers/serial/8250_hcdp.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/serial/8250_hcdp.c	2004-06-23 19:04:28 -07:00
@@ -183,16 +183,12 @@
 		}
 
 		if (HCDP_IRQ_SUPPORTED(hcdp_dev)) {
-#ifdef CONFIG_IA64
 			if (HCDP_PCI_UART(hcdp_dev))
-				port.irq = acpi_register_irq(gsi,
-					ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE);
+				port.irq = acpi_register_gsi(gsi,
+					ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
 			else
-				port.irq = acpi_register_irq(gsi,
-					ACPI_ACTIVE_HIGH, ACPI_EDGE_SENSITIVE);
-#else
-			port.irq = gsi;
-#endif
+				port.irq = acpi_register_gsi(gsi,
+					ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH);
 			port.flags |= UPF_AUTO_IRQ;
 
 			if (HCDP_PCI_UART(hcdp_dev))
diff -Nru a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
--- a/drivers/serial/8250_pnp.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/serial/8250_pnp.c	2004-06-23 19:04:25 -07:00
@@ -361,9 +361,6 @@
 			    ((port->min == 0x2f8) ||
 			     (port->min == 0x3f8) ||
 			     (port->min == 0x2e8) ||
-#ifdef CONFIG_X86_PC9800
-			     (port->min == 0x8b0) ||
-#endif
 			     (port->min == 0x3e8)))
 				return 1;
 	}
diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig
--- a/drivers/serial/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/serial/Kconfig	2004-06-23 19:04:28 -07:00
@@ -518,19 +518,6 @@
 	depends on V850E_UART
 	select SERIAL_CORE_CONSOLE
 
-config SERIAL98
-	tristate "PC-9800 8251-based primary serial port support"
-	depends on X86_PC9800
-	select SERIAL_CORE
-	help
-	  If you want to use standard primary serial ports on PC-9800, 
-	  say Y.  Otherwise, say N.
-
-config SERIAL98_CONSOLE
-        bool "Support for console on PC-9800 standard serial port"
-        depends on SERIAL98=y
-	select SERIAL_CORE_CONSOLE
-
 config SERIAL_SH_SCI
 	tristate "SH SCI(F) serial port support"
 	depends on SUPERH || H8300
@@ -615,6 +602,29 @@
 	  If you would like to be able to use the z85c30 serial port
 	  on your PowerMac as the console, you can do so by answering
 	  Y to this option.
+
+config SERIAL_LH7A40X
+	tristate "Sharp LH7A40X embedded UART support"
+	depends on ARM && ARCH_LH7A40X
+	select SERIAL_CORE
+	help
+	  This enables support for the three on-board UARTs of the
+	  Sharp LH7A40X series CPUs.  Choose Y or M.
+
+config SERIAL_LH7A40X_CONSOLE
+	bool "Support for connsole on Sharp LH7A40X serial port"
+	depends on SERIAL_LH7A40X=y
+	select SERIAL_CORE_CONSOLE
+	help
+	  Say Y here if you wish to use one of the serial ports as the
+	  system console--the system console is the device which
+	  receives all kernel messages and warnings and which allows
+	  logins in single user mode.
+
+	  Even if you say Y here, the currently visible framebuffer console
+	  (/dev/tty0) will still be used as the default system console, but
+	  you can alter that using a kernel command line, for example
+	  "console=ttyAM1".
 
 endmenu
 
diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile
--- a/drivers/serial/Makefile	2004-06-23 19:04:27 -07:00
+++ b/drivers/serial/Makefile	2004-06-23 19:04:27 -07:00
@@ -33,8 +33,8 @@
 obj-$(CONFIG_SERIAL_68360) += 68360serial.o
 obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o
 obj-$(CONFIG_V850E_UART) += v850e_uart.o
-obj-$(CONFIG_SERIAL98) += serial98.o
 obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
+obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
 obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o
 obj-$(CONFIG_SERIAL_DZ) += dz.o
 obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
diff -Nru a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
--- a/drivers/serial/amba-pl011.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/serial/amba-pl011.c	2004-06-23 19:04:29 -07:00
@@ -44,6 +44,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/hardware/amba.h>
+#include <asm/hardware/clock.h>
 
 #if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -68,6 +69,7 @@
  */
 struct uart_amba_port {
 	struct uart_port	port;
+	struct clk		*clk;
 	unsigned int		im;	/* interrupt mask */
 	unsigned int		old_status;
 };
@@ -352,11 +354,20 @@
 	int retval;
 
 	/*
+	 * Try to enable the clock producer.
+	 */
+	retval = clk_enable(uap->clk);
+	if (retval)
+		goto out;
+
+	uap->port.uartclk = clk_get_rate(uap->clk);
+
+	/*
 	 * Allocate the IRQ
 	 */
 	retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 	if (retval)
-		goto out;
+		goto clk_dis;
 
 	writew(UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
 	       uap->port.membase + UART011_IFLS);
@@ -391,6 +402,8 @@
 
 	return 0;
 
+ clk_dis:
+	clk_disable(uap->clk);
  out:
 	return retval;
 }
@@ -425,6 +438,11 @@
 	val = readw(uap->port.membase + UART011_LCRH);
 	val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
 	writew(val, uap->port.membase + UART011_LCRH);
+
+	/*
+	 * Shut down the clock producer
+	 */
+	clk_disable(uap->clk);
 }
 
 static void
@@ -594,38 +612,40 @@
 #ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE
 
 static inline void
-pl011_console_write_char(struct uart_port *port, char ch)
+pl011_console_write_char(struct uart_amba_port *uap, char ch)
 {
 	unsigned int status;
 
 	do {
-		status = readw(port->membase + UART01x_FR);
+		status = readw(uap->port.membase + UART01x_FR);
 	} while (status & UART01x_FR_TXFF);
-	writew(ch, port->membase + UART01x_DR);
+	writew(ch, uap->port.membase + UART01x_DR);
 }
 
 static void
 pl011_console_write(struct console *co, const char *s, unsigned int count)
 {
-	struct uart_port *port = &amba_ports[co->index]->port;
+	struct uart_amba_port *uap = amba_ports[co->index];
 	unsigned int status, old_cr, new_cr;
 	int i;
 
+	clk_enable(uap->clk);
+
 	/*
 	 *	First save the CR then disable the interrupts
 	 */
-	old_cr = readw(port->membase + UART011_CR);
+	old_cr = readw(uap->port.membase + UART011_CR);
 	new_cr = old_cr & ~UART011_CR_CTSEN;
 	new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-	writew(new_cr, port->membase + UART011_CR);
+	writew(new_cr, uap->port.membase + UART011_CR);
 
 	/*
 	 *	Now, do each character
 	 */
 	for (i = 0; i < count; i++) {
-		pl011_console_write_char(port, s[i]);
+		pl011_console_write_char(uap, s[i]);
 		if (s[i] == '\n')
-			pl011_console_write_char(port, '\r');
+			pl011_console_write_char(uap, '\r');
 	}
 
 	/*
@@ -633,19 +653,21 @@
 	 *	and restore the TCR
 	 */
 	do {
-		status = readw(port->membase + UART01x_FR);
+		status = readw(uap->port.membase + UART01x_FR);
 	} while (status & UART01x_FR_BUSY);
-	writew(old_cr, port->membase + UART011_CR);
+	writew(old_cr, uap->port.membase + UART011_CR);
+
+	clk_disable(uap->clk);
 }
 
 static void __init
-pl011_console_get_options(struct uart_port *port, int *baud,
+pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 			     int *parity, int *bits)
 {
-	if (readw(port->membase + UART011_CR) & UART01x_CR_UARTEN) {
+	if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
 
-		lcr_h = readw(port->membase + UART011_LCRH);
+		lcr_h = readw(uap->port.membase + UART011_LCRH);
 
 		*parity = 'n';
 		if (lcr_h & UART01x_LCRH_PEN) {
@@ -660,10 +682,10 @@
 		else
 			*bits = 8;
 
-		ibrd = readw(port->membase + UART011_IBRD);
-		fbrd = readw(port->membase + UART011_FBRD);
+		ibrd = readw(uap->port.membase + UART011_IBRD);
+		fbrd = readw(uap->port.membase + UART011_FBRD);
 
-		*baud = port->uartclk * 4 / (64 * ibrd + fbrd);
+		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 	}
 }
 
@@ -685,10 +707,12 @@
 		co->index = 0;
 	uap = amba_ports[co->index];
 
+	uap->port.uartclk = clk_get_rate(uap->clk);
+
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 	else
-		pl011_console_get_options(&uap->port, &baud, &parity, &bits);
+		pl011_console_get_options(uap, &baud, &parity, &bits);
 
 	return uart_set_options(&uap->port, co, baud, parity, bits, flow);
 }
@@ -747,16 +771,21 @@
 	}
 
 	memset(uap, 0, sizeof(struct uart_amba_port));
+	uap->clk = clk_get(&dev->dev, "UARTCLK");
+	if (IS_ERR(uap->clk)) {
+		ret = PTR_ERR(uap->clk);
+		goto unmap;
+	}
+
+	ret = clk_use(uap->clk);
+	if (ret)
+		goto putclk;
+
 	uap->port.dev = &dev->dev;
 	uap->port.mapbase = dev->res.start;
 	uap->port.membase = base;
 	uap->port.iotype = UPIO_MEM;
 	uap->port.irq = dev->irq[0];
-#if 0 /* FIXME */
-	uap->port.uartclk = 14745600;
-#else
-	uap->port.uartclk = 24000000;
-#endif
 	uap->port.fifosize = 16;
 	uap->port.ops = &amba_pl011_pops;
 	uap->port.flags = UPF_BOOT_AUTOCONF;
@@ -769,6 +798,10 @@
 	if (ret) {
 		amba_set_drvdata(dev, NULL);
 		amba_ports[i] = NULL;
+		clk_unuse(uap->clk);
+ putclk:
+		clk_put(uap->clk);
+ unmap:
 		iounmap(base);
  free:
 		kfree(uap);
@@ -791,6 +824,8 @@
 			amba_ports[i] = NULL;
 
 	iounmap(uap->port.membase);
+	clk_unuse(uap->clk);
+	clk_put(uap->clk);
 	kfree(uap);
 	return 0;
 }
diff -Nru a/drivers/serial/pxa.c b/drivers/serial/pxa.c
--- a/drivers/serial/pxa.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/serial/pxa.c	2004-06-23 19:04:28 -07:00
@@ -35,6 +35,7 @@
 #include <linux/circ_buf.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/hardware.h>
@@ -571,14 +572,9 @@
 	      unsigned int oldstate)
 {
 	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
-	if (state) {
-		/* sleep */
-		CKEN &= ~up->cken;
-	} else {
-		/* wake */
-		CKEN |= up->cken;
+	pxa_set_cken(up->cken, !state);
+	if (!state)
 		udelay(1);
-	}
 }
 
 static void serial_pxa_release_port(struct uart_port *port)
@@ -809,26 +805,76 @@
 	.cons		= PXA_CONSOLE,
 };
 
-static int __init serial_pxa_init(void)
+static int serial_pxa_suspend(struct device *_dev, u32 state, u32 level)
 {
-	int i, ret;
+        struct uart_pxa_port *sport = dev_get_drvdata(_dev);
 
-	ret = uart_register_driver(&serial_pxa_reg);
-	if (ret)
-		return ret;
+        if (sport && level == SUSPEND_DISABLE)
+                uart_suspend_port(&serial_pxa_reg, &sport->port);
+
+        return 0;
+}
+
+static int serial_pxa_resume(struct device *_dev, u32 level)
+{
+        struct uart_pxa_port *sport = dev_get_drvdata(_dev);
 
-	for (i = 0; i < ARRAY_SIZE(serial_pxa_ports); i++)
-		uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[i].port);
+        if (sport && level == RESUME_ENABLE)
+                uart_resume_port(&serial_pxa_reg, &sport->port);
 
+        return 0;
+}
+
+static int serial_pxa_probe(struct device *_dev)
+{
+	struct platform_device *dev = to_platform_device(_dev);
+
+	serial_pxa_ports[dev->id].port.dev = _dev;
+	uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[dev->id].port);
+	dev_set_drvdata(_dev, &serial_pxa_ports[dev->id]);
 	return 0;
 }
 
-static void __exit serial_pxa_exit(void)
+static int serial_pxa_remove(struct device *_dev)
 {
-	int i;
+	struct uart_pxa_port *sport = dev_get_drvdata(_dev);
+
+	dev_set_drvdata(_dev, NULL);
+
+	if (sport)
+		uart_remove_one_port(&serial_pxa_reg, &sport->port);
+
+	return 0;
+}
+
+static struct device_driver serial_pxa_driver = {
+        .name           = "pxa2xx-uart",
+        .bus            = &platform_bus_type,
+        .probe          = serial_pxa_probe,
+        .remove         = serial_pxa_remove,
+
+	.suspend	= serial_pxa_suspend,
+	.resume		= serial_pxa_resume,
+};
+
+int __init serial_pxa_init(void)
+{
+	int ret;
 
-	for (i = 0; i < ARRAY_SIZE(serial_pxa_ports); i++)
-		uart_remove_one_port(&serial_pxa_reg, &serial_pxa_ports[i].port);
+	ret = uart_register_driver(&serial_pxa_reg);
+	if (ret != 0)
+		return ret;
+
+	ret = driver_register(&serial_pxa_driver);
+	if (ret != 0)
+		uart_unregister_driver(&serial_pxa_reg);
+
+	return ret;
+}
+
+void __exit serial_pxa_exit(void)
+{
+        driver_unregister(&serial_pxa_driver);
 	uart_unregister_driver(&serial_pxa_reg);
 }
 
diff -Nru a/drivers/serial/serial98.c b/drivers/serial/serial98.c
--- a/drivers/serial/serial98.c	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,1120 +0,0 @@
-/*
- *  linux/drivers/serial/serial98.c
- *
- *  Driver for NEC PC-9801/PC-9821 standard serial ports
- *
- *  Based on drivers/serial/8250.c, by Russell King.
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- *  Copyright (C) 2002 Osamu Tomita <tomita@cinet.co.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.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/serial.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial_reg.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pc9800.h>
-#include <asm/pc9800_sca.h>
-
-#if defined(CONFIG_SERIAL98_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-
-#define SERIAL98_NR		1
-#define SERIAL98_ISR_PASS_LIMIT	256
-#define SERIAL98_EXT		0x434
-
-//#define RX_8251F		0x130	/* In: Receive buffer */
-//#define TX_8251F		0x130	/* Out: Transmit buffer */
-//#define LSR_8251F		0x132	/* In: Line Status Register */
-//#define MSR_8251F		0x134	/* In: Modem Status Register */
-#define IIR_8251F		0x136	/* In: Interrupt ID Register */
-#define FCR_8251F		0x138	/* I/O: FIFO Control Register */
-#define VFAST_8251F		0x13a	/* I/O: VFAST mode Register */
-
-#define CMD_8251F		0x32	/* Out: 8251 Command Resister */
-#define IER2_8251F		0x34	/* I/O: Interrupt Enable Register */
-#define IER1_8251F		0x35	/* I/O: Interrupt Enable Register */
-#define IER1_CTL		0x37	/* Out: Interrupt Enable Register */
-#define DIS_RXR_INT		0x00	/* disable RxRDY Interrupt */
-#define ENA_RXR_INT		0x01	/* enable RxRDY Interrupt */
-#define DIS_TXE_INT		0x02	/* disable TxEMPTY Interrupt */
-#define ENA_TXE_INT		0x03	/* enable TxEMPTY Interrupt */
-#define DIS_TXR_INT		0x04	/* disable TxRDY Interrupt */
-#define ENA_TXR_INT		0x05	/* enable TxRDY Interrupt */
-
-#define CMD_RESET		0x40	/* Reset Command */
-#define CMD_RTS			0x20	/* Set RTS line */
-#define CMD_CLR_ERR		0x10	/* Clear error flag */
-#define CMD_BREAK		0x08	/* Send Break */
-#define CMD_RXE			0x04	/* Enable receive */
-#define CMD_DTR			0x02	/* Set DTR line */
-#define CMD_TXE			0x01	/* Enable send */
-#define CMD_DUMMY		0x00	/* Dummy Command */
-
-#define VFAST_ENABLE		0x80	/* V.Fast mode Enable */
-
-/* Interrupt masks */
-#define INTR_8251_TXRE		0x04
-#define INTR_8251_TXEE		0x02
-#define INTR_8251_RXRE		0x01
-/* I/O Port */
-//#define PORT_8251_DATA	0
-//#define PORT_8251_CMD		2
-//#define PORT_8251_MOD		2
-//#define PORT_8251_STS		2
-/* status read */
-#define STAT_8251_TXRDY		0x01
-#define STAT_8251_RXRDY		0x02
-#define STAT_8251_TXEMP		0x04
-#define STAT_8251_PER		0x08
-#define STAT_8251_OER		0x10
-#define STAT_8251_FER		0x20
-#define STAT_8251_BRK		0x40
-#define STAT_8251_DSR		0x80
-#if 1
-#define STAT_8251F_TXEMP	0x01
-#define STAT_8251F_TXRDY	0x02
-#define STAT_8251F_RXRDY	0x04
-#define STAT_8251F_DSR		0x08
-#define STAT_8251F_OER		0x10
-#define STAT_8251F_PER		0x20
-#define STAT_8251F_FER		0x40
-#define STAT_8251F_BRK		0x80
-#else
-#define STAT_8251F_TXEMP	0x01
-#define STAT_8251F_TEMT		0x01
-#define STAT_8251F_TXRDY	0x02
-#define STAT_8251F_THRE		0x02
-#define STAT_8251F_RXRDY	0x04
-#define STAT_8251F_DSR		0x04
-#define STAT_8251F_PER		0x08
-#define STAT_8251F_OER		0x10
-#define STAT_8251F_FER		0x20
-#define STAT_8251F_BRK		0x40
-#endif
-
-/*
- * We wrap our port structure around the generic uart_port.
- */
-struct serial98_port {
-	struct uart_port	port;
-	unsigned int		type;
-	unsigned int		ext;
-	unsigned int		lsr_break_flag;
-	unsigned char		cmd;
-	unsigned char		mode;
-	unsigned char		msr;
-	unsigned char		ier;
-	unsigned char		rxchk;
-	unsigned char		txemp;
-	unsigned char		txrdy;
-	unsigned char		rxrdy;
-	unsigned char		brk;
-	unsigned char		fe;
-	unsigned char		oe;
-	unsigned char		pe;
-	unsigned char		dr;
-};
-
-#ifdef CONFIG_SERIAL98_CONSOLE
-static void
-serial98_console_write(struct console *co, const char *s, unsigned int count);
-static int __init serial98_console_setup(struct console *co, char *options);
-
-extern struct uart_driver serial98_reg;
-static struct console serial98_console = {
-	.name		= "ttyS",
-	.write		= serial98_console_write,
-	.device		= uart_console_device,
-	.setup		= serial98_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &serial98_reg,
-};
-
-#define SERIAL98_CONSOLE	&serial98_console
-#else
-#define SERIAL98_CONSOLE	NULL
-#endif
-
-static struct uart_driver serial98_reg = {
-	.owner			= THIS_MODULE,
-	.driver_name		= "serial98",
-	.dev_name		= "ttyS",
-	.major			= TTY_MAJOR,
-	.minor			= 64,
-	.nr			= SERIAL98_NR,
-	.cons			= SERIAL98_CONSOLE,
-};
-
-static int serial98_clk;
-static char type_str[48];
-
-#define PORT98 ((struct serial98_port *)port)
-#define PORT (PORT98->port)
-
-static void serial98_fifo_enable(struct uart_port *port, int enable)
-{
-	unsigned char fcr;
-
-	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
-		fcr = inb(FCR_8251F);
-		if (enable)
-			fcr |= UART_FCR_ENABLE_FIFO;
-		else
-			fcr &= ~UART_FCR_ENABLE_FIFO;
-		outb(fcr, FCR_8251F);
-	}
-
-	if (!enable)
-		return;
-
-	outb(0, 0x5f);	/* wait */
-	outb(0, 0x5f);
-	outb(0, 0x5f);
-	outb(0, 0x5f);
-}
-
-static void serial98_cmd_out(struct uart_port *port, unsigned char cmd)
-{
-	serial98_fifo_enable(port, 0);
-	outb(cmd, CMD_8251F);
-	serial98_fifo_enable(port, 1);
-}
-
-static void serial98_mode_set(struct uart_port *port)
-{
-	serial98_cmd_out(port, CMD_DUMMY);
-	serial98_cmd_out(port, CMD_DUMMY);
-	serial98_cmd_out(port, CMD_DUMMY);
-	serial98_cmd_out(port, CMD_RESET);
-	serial98_cmd_out(port, PORT98->mode);
-}
-
-static unsigned char serial98_msr_in(struct uart_port *port)
-{
-	unsigned long flags;
-	unsigned int ms, st;
-	unsigned int tmp;
-
-	spin_lock_irqsave(&PORT.lock, flags);
-	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
-		PORT98->msr = inb(PORT.iobase + 4);
-	} else {
-		ms = inb(0x33);
-		st = inb(0x32);
-		tmp = 0;
-		if(!(ms & 0x20))
-			tmp |= UART_MSR_DCD;
-		if(!(ms & 0x80)) {
-			tmp |= UART_MSR_RI;
-			PORT98->msr |= UART_MSR_RI;
-		}
-		if(!(ms & 0x40))
-			tmp |= UART_MSR_CTS;
-		if(st & 0x80)
-			tmp |= UART_MSR_DSR;
-		PORT98->msr = ((PORT98->msr ^ tmp) >> 4) | tmp;
-	}
-
-	spin_unlock_irqrestore(&PORT.lock, flags);
-	return PORT98->msr;
-}
-
-static void serial98_stop_tx(struct uart_port *port, unsigned int tty_stop)
-{
-	unsigned int ier = inb(IER1_8251F);
-
-	ier &= ~(INTR_8251_TXRE | INTR_8251_TXEE);
-	outb(ier, IER1_8251F);
-}
-
-static void serial98_start_tx(struct uart_port *port, unsigned int tty_start)
-{
-	unsigned int ier = inb(IER1_8251F);
-
-	ier |= INTR_8251_TXRE | INTR_8251_TXEE;
-	outb(ier, IER1_8251F);
-}
-
-static void serial98_stop_rx(struct uart_port *port)
-{
-	PORT.read_status_mask &= ~PORT98->dr;
-	outb(DIS_RXR_INT, IER1_CTL);
-}
-
-static void serial98_enable_ms(struct uart_port *port)
-{
-	outb(PORT98->ier | 0x80, IER2_8251F);
-}
-
-static void serial98_rx_chars(struct uart_port *port, int *status,
-				struct pt_regs *regs)
-{
-	struct tty_struct *tty = PORT.info->tty;
-	unsigned char ch;
-	int max_count = 256;
-
-	do {
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.work.func((void *)tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				return; // if TTY_DONT_FLIP is set
-		}
-		ch = inb(PORT.iobase);
-		*tty->flip.char_buf_ptr = ch;
-		*tty->flip.flag_buf_ptr = TTY_NORMAL;
-		PORT.icount.rx++;
-
-		if (unlikely(*status & (PORT98->brk | PORT98->pe |
-				       PORT98->fe | PORT98->oe))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & PORT98->brk) {
-				*status &= ~(PORT98->fe | PORT98->pe);
-				PORT.icount.brk++;
-				/*
-				 * We do the SysRQ and SAK checking
-				 * here because otherwise the break
-				 * may get masked by ignore_status_mask
-				 * or read_status_mask.
-				 */
-				if (uart_handle_break(&PORT))
-					goto ignore_char;
-			} else if (*status & PORT98->pe)
-				PORT.icount.parity++;
-			else if (*status & PORT98->fe)
-				PORT.icount.frame++;
-			if (*status & PORT98->oe)
-				PORT.icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ingored.
-			 */
-			*status &= PORT.read_status_mask;
-
-#ifdef CONFIG_SERIAL98_CONSOLE
-			if (PORT.line == PORT.cons->index) {
-				/* Recover the break flag from console xmit */
-				*status |= PORT98->lsr_break_flag;
-				PORT98->lsr_break_flag = 0;
-			}
-#endif
-			if (*status & PORT98->brk) {
-				*tty->flip.flag_buf_ptr = TTY_BREAK;
-			} else if (*status & PORT98->pe)
-				*tty->flip.flag_buf_ptr = TTY_PARITY;
-			else if (*status & PORT98->fe)
-				*tty->flip.flag_buf_ptr = TTY_FRAME;
-		}
-		if (uart_handle_sysrq_char(&PORT, ch, regs))
-			goto ignore_char;
-		if ((*status & PORT.ignore_status_mask) == 0) {
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
-		if ((*status & PORT98->oe) &&
-		    tty->flip.count < TTY_FLIPBUF_SIZE) {
-			/*
-			 * Overrun is special, since it's reported
-			 * immediately, and doesn't affect the current
-			 * character.
-			 */
-			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
-	ignore_char:
-		*status = inb(PORT.iobase + 2);
-	} while ((*status & PORT98->rxchk) && (max_count-- > 0));
-	tty_flip_buffer_push(tty);
-}
-
-static void serial98_tx_chars(struct uart_port *port)
-{
-	struct circ_buf *xmit = &PORT.info->xmit;
-	int count;
-
-	if (PORT.x_char) {
-		outb(PORT.x_char, PORT.iobase);
-		PORT.icount.tx++;
-		PORT.x_char = 0;
-		return;
-	}
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&PORT)) {
-		serial98_stop_tx(port, 0);
-		return;
-	}
-
-	count = PORT.fifosize;
-	do {
-		outb(xmit->buf[xmit->tail], PORT.iobase);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		PORT.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (--count > 0);
-
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&PORT);
-
-	if (uart_circ_empty(xmit))
-		serial98_stop_tx(&PORT, 0);
-}
-
-static void serial98_modem_status(struct uart_port *port)
-{
-	int status;
-
-	status = serial98_msr_in(port);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		PORT.icount.rng++;
-	if (status & UART_MSR_DDSR)
-		PORT.icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		uart_handle_dcd_change(&PORT, status & UART_MSR_DCD);
-	if (status & UART_MSR_DCTS)
-		uart_handle_cts_change(&PORT, status & UART_MSR_CTS);
-
-	wake_up_interruptible(&PORT.info->delta_msr_wait);
-}
-
-static void serial98_int(int irq, void *port, struct pt_regs *regs)
-{
-	unsigned int status;
-
-	spin_lock(&PORT.lock);
-	status = inb(PORT.iobase + 2);
-	if (status & PORT98->rxrdy) {
-		serial98_rx_chars(port, &status, regs);
-	}
-	serial98_modem_status(port);
-	if (status & PORT98->txrdy) {
-		serial98_tx_chars(port);
-	}
-	spin_unlock(&PORT.lock);
-}
-
-static unsigned int serial98_tx_empty(struct uart_port *port)
-{
-	unsigned long flags;
-	unsigned int ret = 0;
-
-	spin_lock_irqsave(&PORT.lock, flags);
-	if (inb(PORT.iobase + 2) & PORT98->txemp)
-			ret = TIOCSER_TEMT;
-
-	spin_unlock_irqrestore(&PORT.lock, flags);
-	return ret;
-}
-
-static unsigned int serial98_get_mctrl(struct uart_port *port)
-{
-	unsigned char status;
-	unsigned int ret = 0;
-
-	status = serial98_msr_in(port);
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void serial98_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-	PORT98->cmd &= 0xdd;
-	if (mctrl & TIOCM_RTS)
-		PORT98->cmd |= CMD_RTS;
-
-	if (mctrl & TIOCM_DTR)
-		PORT98->cmd |= CMD_DTR;
-
-	serial98_cmd_out(port, PORT98->cmd);
-}
-
-static void serial98_break_ctl(struct uart_port *port, int break_state)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&PORT.lock, flags);
-	if (break_state == -1)
-		PORT98->cmd |= CMD_BREAK;
-	else
-		PORT98->cmd &= ~CMD_BREAK;
-
-	serial98_cmd_out(port, PORT98->cmd);
-	spin_unlock_irqrestore(&PORT.lock, flags);
-}
-
-static int serial98_startup(struct uart_port *port)
-{
-	int retval;
-
-	if (PORT.type == PORT_8251_PC98) {
-		/* Wake up UART */
-		PORT98->mode = 0xfc;
-		serial98_mode_set(port);
-		outb(DIS_RXR_INT, IER1_CTL);
-		outb(DIS_TXE_INT, IER1_CTL);
-		outb(DIS_TXR_INT, IER1_CTL);
-		PORT98->mode = 0;
-		serial98_mode_set(port);
-	}
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reeanbled in set_termios())
-	 */
-	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
-		outb(UART_FCR_ENABLE_FIFO, FCR_8251F);
-		outb((UART_FCR_ENABLE_FIFO
-			| UART_FCR_CLEAR_RCVR
-			| UART_FCR_CLEAR_XMIT), FCR_8251F);
-		outb(0, FCR_8251F);
-	}
-
-	/* Clear the interrupt registers. */
-	inb(0x30);
-	inb(0x32);
-	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
-		inb(PORT.iobase);
-		inb(PORT.iobase + 2);
-		inb(PORT.iobase + 4);
-		inb(PORT.iobase + 6);
-	}
-
-	/* Allocate the IRQ */
-	retval = request_irq(PORT.irq, serial98_int, 0,
-				serial98_reg.driver_name, port);
-	if (retval)
-		return retval;
-
-	/*
-	 * Now, initialize the UART
-	 */
-	PORT98->mode = 0x4e;
-	serial98_mode_set(port);
-	PORT98->cmd = 0x15;
-	serial98_cmd_out(port, PORT98->cmd);
-	PORT98->cmd = 0x05;
-
-	/*
-	 * Finally, enable interrupts
-	 */
-	outb(0x00, IER2_8251F);
-	outb(ENA_RXR_INT, IER1_CTL);
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	inb(0x30);
-	inb(0x32);
-	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
-		inb(PORT.iobase);
-		inb(PORT.iobase + 2);
-		inb(PORT.iobase + 4);
-		inb(PORT.iobase + 6);
-	}
-
-	return 0;
-}
-
-static void serial98_shutdown(struct uart_port *port)
-{
-	unsigned long flags;
-
-	/*
-	 * disable all interrupts
-	 */
-	spin_lock_irqsave(&PORT.lock, flags);
-	if (PORT.type == PORT_VFAST_PC98)
-		outb(0, VFAST_8251F);		/* V.FAST mode off */
-
-	/* disnable all modem status interrupt */
-	outb(0x80, IER2_8251F);
-
-	/* disnable TX/RX interrupt */
-	outb(0x00, IER2_8251F);
-	outb(DIS_RXR_INT, IER1_CTL);
-	outb(DIS_TXE_INT, IER1_CTL);
-	outb(DIS_TXR_INT, IER1_CTL);
-	PORT98->ier = 0;
-
-	spin_unlock_irqrestore(&PORT.lock, flags);
-
-	/*
-	 * Free the interrupt
-	 */
-	free_irq(PORT.irq, port);
-
-	/* disable break condition and disable the port */
-	serial98_mode_set(port);
-
-	/* disable FIFO's */	
-	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
-		outb((UART_FCR_ENABLE_FIFO
-			| UART_FCR_CLEAR_RCVR
-			| UART_FCR_CLEAR_XMIT), FCR_8251F);
-		outb(0, FCR_8251F);
-	}
-
-	inb(PORT.iobase);
-}
-
-static void
-serial98_set_termios(struct uart_port *port, struct termios *termios,
-		       struct termios *old)
-{
-	unsigned char stopbit, cval, fcr = 0, ier = 0;
-	unsigned long flags;
-	unsigned int baud, quot;
-
-	stopbit = 0x80;
-	switch (termios->c_cflag & CSIZE) {
-		case CS5:
-			cval = 0x42;
-			stopbit = 0xc0;
-			break;
-		case CS6:
-			cval = 0x46;
-			break;
-		case CS7:
-			cval = 0x4a;
-			break;
-		default:
-		case CS8:
-			cval = 0x4e;
-			break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval ^= stopbit;
-	if (termios->c_cflag & PARENB)
-		cval |= 0x10;
-	if (!(termios->c_cflag & PARODD))
-		cval |= 0x20;
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
-	quot = uart_get_divisor(port, baud);
-
-	if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) {
-		if ((PORT.uartclk / quot) < (2400 * 16))
-			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
-		else
-			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
-	}
-
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&PORT.lock, flags);
-
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
-
-	PORT.read_status_mask = PORT98->oe | PORT98->txemp | PORT98->dr;
-	if (termios->c_iflag & INPCK)
-		PORT.read_status_mask |= PORT98->fe | PORT98->pe;
-
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		PORT.read_status_mask |= PORT98->brk;
-	/*
-	 * Characters to ignore
-	 */
-	PORT.ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		PORT.ignore_status_mask |= PORT98->fe | PORT98->pe;
-
-	if (termios->c_iflag & IGNBRK) {
-		PORT.ignore_status_mask |= PORT98->brk;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			PORT.ignore_status_mask |= PORT98->oe;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		PORT.ignore_status_mask |= PORT98->dr;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	if (PORT.flags & UPF_HARDPPS_CD)
-		ier |= 0x80;	/* enable modem status interrupt */
-	if (termios->c_cflag & CRTSCTS) {
-		ier |= 0x08;	/* enable CTS interrupt */
-		ier |= 0x80;	/* enable modem status interrupt */
-	}
-	if (!(termios->c_cflag & CLOCAL)) {
-		ier |= 0x20;	/* enable CD interrupt */
-		ier |= 0x80;	/* enable modem status interrupt */
-	}
-	PORT98->ier = ier;
-
-	PORT98->mode = cval;
-	serial98_mode_set(port);
-	if (PORT.type == PORT_VFAST_PC98 && quot <= 48) {
-		quot /= 4;
-		if (quot < 1)
-			quot = 1;
-		outb(quot | VFAST_ENABLE, VFAST_8251F);
-	} else {
-		quot /= 3;
-		if (quot < 1)
-			quot = 1;
-		if (PORT.type == PORT_VFAST_PC98)
-			outb(0, VFAST_8251F);		/* V.FAST mode off */
-		outb(0xb6, 0x77);
-		outb(quot & 0xff, 0x75);		/* LS of divisor */
-		outb(quot >> 8, 0x75);			/* MS of divisor */
-	}
-
-	if (fcr & UART_FCR_ENABLE_FIFO) {
-		outb(UART_FCR_ENABLE_FIFO, FCR_8251F);
-		outb(fcr, FCR_8251F);
-	}
-
-	/* enable RX/TX */
-	PORT98->cmd = 0x15;
-	serial98_cmd_out(port, PORT98->cmd);
-	PORT98->cmd = 0x05;
-	/* enable interrupts */
-	outb(0x00, IER2_8251F);
-	outb(ENA_RXR_INT, IER1_CTL);
-	spin_unlock_irqrestore(&PORT.lock, flags);
-}
-
-static const char *serial98_type(struct uart_port *port)
-{
-	char *p;
-
-	switch (PORT.type) {
-		case PORT_8251_PC98:
-			p = "PC98 onboard legacy 8251";
-			break;
-		case PORT_19K_PC98:
-			p =  "PC98 onboard max 19200bps";
-			break;
-		case PORT_FIFO_PC98:
-			p = "PC98 onboard with FIFO";
-			break;
-		case PORT_VFAST_PC98:
-			p = "PC98 onboard V.FAST";
-			break;
-		case PORT_PC9861:
-			p = "PC-9861K RS-232C ext. board";
-			break;
-		case PORT_PC9801_101:
-			p = "PC-9801-101 RS-232C ext. board";
-			break;
-		default:
-			return NULL;
-	}
-
-	sprintf(type_str, "%s  Clock %dMHz", p, serial98_clk);
-	return type_str;
-}
-
-/* Release the region(s) being used by 'port' */
-static void serial98_release_port(struct uart_port *port)
-{
-	switch (PORT.type) {
-		case PORT_VFAST_PC98:
-			release_region(PORT.iobase + 0xa, 1);
-		case PORT_FIFO_PC98:
-			release_region(PORT.iobase + 8, 1);
-			release_region(PORT.iobase + 6, 1);
-			release_region(PORT.iobase + 4, 1);
-			release_region(PORT.iobase + 2, 1);
-			release_region(PORT.iobase, 1);
-		case PORT_19K_PC98:
-			release_region(SERIAL98_EXT, 1);
-			release_region(0x34, 1);
-		case PORT_8251_PC98:
-			release_region(0x32, 1);
-			release_region(0x30, 1);
-	}
-}
-
-/* Request the region(s) being used by 'port' */
-#define REQ_REGION98(base) (request_region((base), 1, serial98_reg.driver_name))
-static int serial98_request_region(unsigned int type)
-{
-	if (!REQ_REGION98(0x30))
-		return -EBUSY;
-	if (REQ_REGION98(0x32)) {
-		if (type == PORT_8251_PC98)
-			return 0;
-		if (REQ_REGION98(0x34)) {
-			if (REQ_REGION98(SERIAL98_EXT)) {
-				unsigned long base;
-
-				if (type == PORT_19K_PC98)
-					return 0;
-				for (base = 0x130; base <= 0x138; base += 2) {
-					if (!REQ_REGION98(base)) {
-						base -= 2;
-						goto err;
-					}
-				}
-				if (type == PORT_FIFO_PC98)
-					return 0;
-				if (type == PORT_VFAST_PC98) {
-					if (REQ_REGION98(0x13a))
-						return 0;
-				}
-				err:
-				while (base >= 0x130) {
-					release_region(base, 1);
-					base -= 2;
-				}
-				release_region(SERIAL98_EXT, 1);
-			}
-			release_region(0x34, 1);
-		}
-		release_region(0x32, 1);
-	}
-	release_region(0x30, 1);
-	return -EBUSY;
-}
-
-static int serial98_request_port(struct uart_port *port)
-{
-	return serial98_request_region(PORT.type);
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void serial98_config_port(struct uart_port *port, int flags)
-{
-	if (flags & UART_CONFIG_TYPE)
-		PORT.type = PORT98->type;
-}
-
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int serial98_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-	switch (ser->type) {
-		case PORT_VFAST_PC98:
-		case PORT_FIFO_PC98:
-		case PORT_19K_PC98:
-		case PORT_8251_PC98:
-		/* not implemented yet
-		case PORT_PC9861:
-		case PORT_PC9801_101:
-		*/
-		case PORT_UNKNOWN:
-			break;
-		default:
-			return -EINVAL;
-	}
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
-		return -EINVAL;
-	if (ser->baud_base < 9600)
-		return -EINVAL;
-	return 0;
-}
-
-static struct uart_ops serial98_ops = {
-	.tx_empty	= serial98_tx_empty,
-	.set_mctrl	= serial98_set_mctrl,
-	.get_mctrl	= serial98_get_mctrl,
-	.stop_tx	= serial98_stop_tx,
-	.start_tx	= serial98_start_tx,
-	.stop_rx	= serial98_stop_rx,
-	.enable_ms	= serial98_enable_ms,
-	.break_ctl	= serial98_break_ctl,
-	.startup	= serial98_startup,
-	.shutdown	= serial98_shutdown,
-	.set_termios	= serial98_set_termios,
-	.type		= serial98_type,
-	.release_port	= serial98_release_port,
-	.request_port	= serial98_request_port,
-	.config_port	= serial98_config_port,
-	.verify_port	= serial98_verify_port,
-};
-
-static struct serial98_port serial98_ports[SERIAL98_NR] = {
-	{
-		.port =	{
-				.iobase		= 0x30,
-				.iotype		= SERIAL_IO_PORT,
-				.irq		= 4,
-				.fifosize	= 1,
-				.ops		= &serial98_ops,
-				.flags		= ASYNC_BOOT_AUTOCONF,
-				.line		= 0,
-			},
-		.rxchk = STAT_8251_RXRDY,
-		.txemp = STAT_8251_TXEMP,
-		.txrdy = STAT_8251_TXRDY,
-		.rxrdy = STAT_8251_RXRDY,
-		.brk = STAT_8251_BRK,
-		.fe = STAT_8251_FER,
-		.oe = STAT_8251_OER,
-		.pe = STAT_8251_PER,
-		.dr = STAT_8251_DSR,
-	},
-};
-
-#ifdef CONFIG_SERIAL98_CONSOLE
-
-#define BOTH_EMPTY (PORT98->txemp | PORT98->txrdy)
-
-/*
- *	Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_port *port)
-{
-	unsigned int status, tmout = 10000;
-
-	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
-		status = inb(PORT.iobase + 2);
-
-		if (status & PORT98->brk)
-			PORT98->lsr_break_flag = PORT98->brk;
-
-		if (--tmout == 0)
-			break;
-		udelay(1);
-	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
-	/* Wait up to 1s for flow control if necessary */
-	if (PORT.flags & UPF_CONS_FLOW) {
-		tmout = 1000000;
-		while (--tmout &&
-		       ((serial98_msr_in(port) & UART_MSR_CTS) == 0))
-			udelay(1);
-	}
-}
-
-/*
- *	Print a string to the serial port trying not to disturb
- *	any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- */
-static void
-serial98_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct uart_port *port = (struct uart_port *)&serial98_ports[co->index];
-	unsigned int ier1, ier2;
-	int i;
-
-	/*
-	 *	First save the UER then disable the interrupts
-	 */
-	ier1 = inb(IER1_8251F);
-	ier2 = inb(IER2_8251F);
-	/* disnable all modem status interrupt */
-	outb(0x80, IER2_8251F);
-
-	/* disnable TX/RX interrupt */
-	outb(0x00, IER2_8251F);
-	outb(DIS_RXR_INT, IER1_CTL);
-	outb(DIS_TXE_INT, IER1_CTL);
-	outb(DIS_TXR_INT, IER1_CTL);
-
-	/*
-	 *	Now, do each character
-	 */
-	for (i = 0; i < count; i++, s++) {
-		wait_for_xmitr(port);
-
-		/*
-		 *	Send the character out.
-		 *	If a LF, also do CR...
-		 */
-		outb(*s, PORT.iobase);
-		if (*s == 10) {
-			wait_for_xmitr(port);
-			outb(13, PORT.iobase);
-		}
-	}
-
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the IER
-	 */
-	wait_for_xmitr(port);
-
-	/* restore TX/RX interrupt */
-	outb(0x00, IER2_8251F);
-	if (ier1 & 0x01)
-		outb(ENA_RXR_INT, IER1_CTL);
-	if (ier1 & 0x02)
-		outb(ENA_TXE_INT, IER1_CTL);
-	if (ier1 & 0x04)
-		outb(ENA_TXR_INT, IER1_CTL);
-
-	/* restore modem status interrupt */
-	outb(ier2, IER2_8251F);
-}
-
-static int __init serial98_console_setup(struct console *co, char *options)
-{
-	struct uart_port *port;
-	int baud = 9600;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	/*
-	 * Check whether an invalid uart number has been specified, and
-	 * if so, search for the first available port that does have
-	 * console support.
-	 */
-	if (co->index >= SERIAL98_NR)
-		co->index = 0;
-	port = &serial98_ports[co->index].port;
-
-	/*
-	 * Temporary fix.
-	 */
-	spin_lock_init(&port->lock);
-
-	if (options)
-		uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-	return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-void __init serial98_console_init(void)
-{
-	register_console(&serial98_console);
-}
-
-#endif /* CONFIG_SERIAL98_CONSOLE */
-
-
-static int __init serial98_init(void)
-{
-	int ret;
-	unsigned char iir1, iir2;
-
-	if (PC9800_8MHz_P()) {
-		serial98_clk = 8;
-		serial98_ports[0].port.uartclk = 374400 * 16;
-	} else {
-		serial98_clk = 5;
-		serial98_ports[0].port.uartclk = 460800 * 16;
-	}
-
-	printk(KERN_INFO "serial98: PC-9801 standard serial port driver Version 0.1alpha\n");
-	serial98_ports[0].type = PORT_8251_PC98;
-	/* Check FIFO exist */
-	iir1 = inb(IIR_8251F);
-	iir2 = inb(IIR_8251F);
-	if ((iir1 & 0x40) != (iir2 & 0x40) && (iir1 & 0x20) == (iir2 & 0x20)) {
-		serial98_ports[0].port.iobase = 0x130;
-		serial98_ports[0].port.fifosize = 16;
-		serial98_ports[0].rxchk = STAT_8251F_DSR;
-		serial98_ports[0].txemp = STAT_8251F_TXEMP;
-		serial98_ports[0].txrdy = STAT_8251F_TXRDY;
-		serial98_ports[0].rxrdy = STAT_8251F_RXRDY;
-		serial98_ports[0].brk = STAT_8251F_BRK;
-		serial98_ports[0].fe = STAT_8251F_FER;
-		serial98_ports[0].oe = STAT_8251F_OER;
-		serial98_ports[0].pe = STAT_8251F_PER;
-		serial98_ports[0].dr = STAT_8251F_DSR;
-
-		if (*(unsigned char*)__va(PC9821SCA_RSFLAGS) & 0x10)
-			serial98_ports[0].type = PORT_VFAST_PC98;
-		else {
-			outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT);
-			serial98_ports[0].port.uartclk *= 4;
-			serial98_ports[0].type = PORT_FIFO_PC98;
-		}
-	} else if ((serial98_ports[0].ext = inb(SERIAL98_EXT)) != 0xff) {
-		outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT);
-		if (inb(SERIAL98_EXT) == (serial98_ports[0].ext | 0x40)) {
-			serial98_ports[0].port.uartclk *= 4;
-			serial98_ports[0].type = PORT_19K_PC98;
-		} else {
-			serial98_ops.enable_ms = NULL;
-			outb(serial98_ports[0].ext, SERIAL98_EXT);
-		}
-	}
-
-	if (serial98_request_region(serial98_ports[0].type))
-		return -EBUSY;
-
-	ret = uart_register_driver(&serial98_reg);
-	if (ret == 0) {
-		int i;
-
-		for (i = 0; i < SERIAL98_NR; i++) {
-			uart_add_one_port(&serial98_reg,
-					(struct uart_port *)&serial98_ports[i]);
-		}
-	}
-
-	return ret;
-}
-
-static void __exit serial98_exit(void)
-{
-	int i;
-
-	if (serial98_ports[0].type == PORT_19K_PC98
-			|| serial98_ports[0].type == PORT_FIFO_PC98)
-		outb(serial98_ports[0].ext, SERIAL98_EXT);
-
-	for (i = 0; i < SERIAL98_NR; i++) {
-		uart_remove_one_port(&serial98_reg,
-					(struct uart_port *)&serial98_ports[i]);
-	}
-
-	uart_unregister_driver(&serial98_reg);
-}
-
-module_init(serial98_init);
-module_exit(serial98_exit);
-
-MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
-MODULE_DESCRIPTION("PC-9801 standard serial port driver Version 0.1alpha");
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/serial/serial_lh7a40x.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,708 @@
+/* drivers/serial/serial_lh7a40x.c
+ *
+ *  Copyright (C) 2004 Coastal Environmental Systems
+ *
+ *  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.
+ *
+ */
+
+/* Driver for Sharp LH7A40X embedded serial ports
+ *
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *  Based on drivers/serial/amba.c, by Deep Blue Solutions Ltd.
+ *
+ *  ---
+ *
+ * This driver supports the embedded UARTs of the Sharp LH7A40X series
+ * CPUs.  While similar to the 16550 and other UART chips, there is
+ * nothing close to register compatibility.  Moreover, some of the
+ * modem control lines are not available, either in the chip or they
+ * are lacking in the board-level implementation.
+ *
+ * - Use of SIRDIS
+ *   For simplicity, we disable the IR functions of any UART whenever
+ *   we enable it.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#include <asm/arch/serial.h>
+
+#define DEV_MAJOR	204
+#define DEV_MINOR	16
+#define DEV_NR		3
+
+#define ISR_LOOP_LIMIT	256
+
+#define UR(p,o)	_UR ((p)->membase, o)
+#define _UR(b,o) (*((volatile unsigned int*)(((unsigned char*) b) + (o))))
+#define BIT_CLR(p,o,m)	UR(p,o) = UR(p,o) & (~(unsigned int)m)
+#define BIT_SET(p,o,m)	UR(p,o) = UR(p,o) | ( (unsigned int)m)
+
+#define UART_REG_SIZE	32
+
+#define UARTEN		(0x01)		/* UART enable */
+#define SIRDIS		(0x02)		/* Serial IR disable (UART1 only) */
+
+#define RxEmpty		(0x10)
+#define TxEmpty		(0x80)
+#define TxFull		(0x20)
+#define nRxRdy		RxEmpty
+#define nTxRdy		TxFull
+#define TxBusy		(0x08)
+
+#define RxBreak		(0x0800)
+#define RxOverrunError	(0x0400)
+#define RxParityError	(0x0200)
+#define RxFramingError	(0x0100)
+#define RxError     (RxBreak | RxOverrunError | RxParityError | RxFramingError)
+
+#define DCD		(0x04)
+#define DSR		(0x02)
+#define CTS		(0x01)
+
+#define RxInt		(0x01)
+#define TxInt		(0x02)
+#define ModemInt	(0x04)
+#define RxTimeoutInt	(0x08)
+
+#define MSEOI		(0x10)
+
+#define WLEN_8		(0x60)
+#define WLEN_7		(0x40)
+#define WLEN_6		(0x20)
+#define WLEN_5		(0x00)
+#define WLEN		(0x60)	/* Mask for all word-length bits */
+#define STP2		(0x08)
+#define PEN		(0x02)	/* Parity Enable */
+#define EPS		(0x04)	/* Even Parity Set */
+#define FEN		(0x10)	/* FIFO Enable */
+#define BRK		(0x01)	/* Send Break */
+
+
+struct uart_port_lh7a40x {
+	struct uart_port port;
+	unsigned int statusPrev; /* Most recently read modem status */
+};
+
+static void lh7a40xuart_stop_tx (struct uart_port* port, unsigned int tty_stop)
+{
+	BIT_CLR (port, UART_R_INTEN, TxInt);
+}
+
+static void lh7a40xuart_start_tx (struct uart_port* port,
+				  unsigned int tty_start)
+{
+	BIT_SET (port, UART_R_INTEN, TxInt);
+
+	/* *** FIXME: do I need to check for startup of the
+		      transmitter?  The old driver did, but AMBA
+		      doesn't . */
+}
+
+static void lh7a40xuart_stop_rx (struct uart_port* port)
+{
+	BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
+}
+
+static void lh7a40xuart_enable_ms (struct uart_port* port)
+{
+	BIT_SET (port, UART_R_INTEN, ModemInt);
+}
+
+static void
+#ifdef SUPPORT_SYSRQ
+lh7a40xuart_rx_chars (struct uart_port* port, struct pt_regs* regs)
+#else
+lh7a40xuart_rx_chars (struct uart_port* port)
+#endif
+{
+	struct tty_struct* tty = port->info->tty;
+	int cbRxMax = 256;	/* (Gross) limit on receive */
+	unsigned int data;	/* Received data and status */
+
+	while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+			tty->flip.work.func((void*)tty);
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
+				return;
+			}
+		}
+
+		data = UR (port, UART_R_DATA);
+
+		*tty->flip.char_buf_ptr = (unsigned char) data;
+		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		++port->icount.rx;
+
+		if (data & RxError) {	/* Quick check, short-circuit */
+			if (data & RxBreak) {
+				data &= ~(RxFramingError | RxParityError);
+				++port->icount.brk;
+				if (uart_handle_break (port))
+					continue;
+			}
+			else if (data & RxParityError)
+				++port->icount.parity;
+			else if (data & RxFramingError)
+				++port->icount.frame;
+			if (data & RxOverrunError)
+				++port->icount.overrun;
+
+				/* Mask by termios, leave Rx'd byte */
+			data &= port->read_status_mask | 0xff;
+
+			if (data & RxBreak)
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+			else if (data & RxParityError)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (data & RxFramingError)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+		}
+
+		if (uart_handle_sysrq_char (port, (unsigned char) data, regs))
+			continue;
+
+		if ((data & port->ignore_status_mask) == 0) {
+			++tty->flip.flag_buf_ptr;
+			++tty->flip.char_buf_ptr;
+			++tty->flip.count;
+		}
+		if ((data & RxOverrunError)
+		    && tty->flip.count < TTY_FLIPBUF_SIZE) {
+			/*
+			 * Overrun is special, since it's reported
+			 * immediately, and doesn't affect the current
+			 * character
+			 */
+			*tty->flip.char_buf_ptr++ = 0;
+			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+			++tty->flip.count;
+		}
+	}
+	tty_flip_buffer_push (tty);
+	return;
+}
+
+static void lh7a40xuart_tx_chars (struct uart_port* port)
+{
+	struct circ_buf* xmit = &port->info->xmit;
+	int cbTxMax = port->fifosize;
+
+	if (port->x_char) {
+		UR (port, UART_R_DATA) = port->x_char;
+		++port->icount.tx;
+		port->x_char = 0;
+		return;
+	}
+	if (uart_circ_empty (xmit) || uart_tx_stopped (port)) {
+		lh7a40xuart_stop_tx (port, 0);
+		return;
+	}
+
+	/* Unlike the AMBA UART, the lh7a40x UART does not guarantee
+	   that at least half of the FIFO is empty.  Instead, we check
+	   status for every character.  Using the AMBA method causes
+	   the transmitter to drop characters. */
+
+	do {
+		UR (port, UART_R_DATA) = xmit->buf[xmit->tail];
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		++port->icount.tx;
+		if (uart_circ_empty(xmit))
+			break;
+	} while (!(UR (port, UART_R_STATUS) & nTxRdy)
+		 && cbTxMax--);
+
+	if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
+		uart_write_wakeup (port);
+
+	if (uart_circ_empty (xmit))
+		lh7a40xuart_stop_tx (port, 0);
+}
+
+static void lh7a40xuart_modem_status (struct uart_port* port)
+{
+	unsigned int status = UR (port, UART_R_STATUS);
+	unsigned int delta
+		= status ^ ((struct uart_port_lh7a40x*) port)->statusPrev;
+
+	BIT_SET (port, UART_R_RAWISR, MSEOI); /* Clear modem status intr */
+
+	if (!delta)		/* Only happens if we missed 2 transitions */
+		return;
+
+	((struct uart_port_lh7a40x*) port)->statusPrev = status;
+
+	if (delta & DCD)
+		uart_handle_dcd_change (port, status & DCD);
+
+	if (delta & DSR)
+		++port->icount.dsr;
+
+	if (delta & CTS)
+		uart_handle_cts_change (port, status & CTS);
+
+	wake_up_interruptible (&port->info->delta_msr_wait);
+}
+
+static irqreturn_t lh7a40xuart_int (int irq, void* dev_id,
+				    struct pt_regs* regs)
+{
+	struct uart_port* port = dev_id;
+	unsigned int cLoopLimit = ISR_LOOP_LIMIT;
+	unsigned int isr = UR (port, UART_R_ISR);
+
+
+	do {
+		if (isr & (RxInt | RxTimeoutInt))
+#ifdef SUPPORT_SYSRQ
+			lh7a40xuart_rx_chars(port, regs);
+#else
+			lh7a40xuart_rx_chars(port);
+#endif
+		if (isr & ModemInt)
+			lh7a40xuart_modem_status (port);
+		if (isr & TxInt)
+			lh7a40xuart_tx_chars (port);
+
+		if (--cLoopLimit == 0)
+			break;
+
+		isr = UR (port, UART_R_ISR);
+	} while (isr & (RxInt | TxInt | RxTimeoutInt));
+
+	return IRQ_HANDLED;
+}
+
+static unsigned int lh7a40xuart_tx_empty (struct uart_port* port)
+{
+	return (UR (port, UART_R_STATUS) & TxEmpty) ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int lh7a40xuart_get_mctrl (struct uart_port* port)
+{
+	unsigned int result = 0;
+	unsigned int status = UR (port, UART_R_STATUS);
+
+	if (status & DCD)
+		result |= TIOCM_CAR;
+	if (status & DSR)
+		result |= TIOCM_DSR;
+	if (status & CTS)
+		result |= TIOCM_CTS;
+
+	return result;
+}
+
+static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl)
+{
+	/* None of the ports supports DTR. UART1 supports RTS through GPIO. */
+	/* Note, kernel appears to be setting DTR and RTS on console. */
+
+	/* *** FIXME: this deserves more work.  There's some work in
+               tracing all of the IO pins. */
+#if 0
+	if( port->mapbase == UART1_PHYS) {
+		gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS);
+
+		if (mctrl & TIOCM_RTS)
+			gpio->pbdr &= ~GPIOB_UART1_RTS;
+		else
+			gpio->pbdr |= GPIOB_UART1_RTS;
+	}
+#endif
+}
+
+static void lh7a40xuart_break_ctl (struct uart_port* port, int break_state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (break_state == -1)
+		BIT_SET (port, UART_R_FCON, BRK); /* Assert break */
+	else
+		BIT_CLR (port, UART_R_FCON, BRK); /* Deassert break */
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int lh7a40xuart_startup (struct uart_port* port)
+{
+	int retval;
+
+	retval = request_irq (port->irq, lh7a40xuart_int, 0,
+			      "serial_lh7a40x", port);
+	if (retval)
+		return retval;
+
+				/* Initial modem control-line settings */
+	((struct uart_port_lh7a40x*) port)->statusPrev
+		= UR (port, UART_R_STATUS);
+
+	/* There is presently no configuration option to enable IR.
+	   Thus, we always disable it. */
+
+	BIT_SET (port, UART_R_CON, UARTEN | SIRDIS);
+	BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
+
+	return 0;
+}
+
+static void lh7a40xuart_shutdown (struct uart_port* port)
+{
+	free_irq (port->irq, port);
+	BIT_CLR (port, UART_R_FCON, BRK | FEN);
+	BIT_CLR (port, UART_R_CON, UARTEN);
+}
+
+static void lh7a40xuart_set_termios (struct uart_port* port,
+				     struct termios* termios,
+				     struct termios* old)
+{
+	unsigned int con;
+	unsigned int inten;
+	unsigned int fcon;
+	unsigned long flags;
+	unsigned int baud;
+	unsigned int quot;
+
+	baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16);
+	quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		fcon = WLEN_5;
+		break;
+	case CS6:
+		fcon = WLEN_6;
+		break;
+	case CS7:
+		fcon = WLEN_7;
+		break;
+	case CS8:
+	default:
+		fcon = WLEN_8;
+		break;
+	}
+	if (termios->c_cflag & CSTOPB)
+		fcon |= STP2;
+	if (termios->c_cflag & PARENB) {
+		fcon |= PEN;
+		if (!(termios->c_cflag & PARODD))
+			fcon |= EPS;
+	}
+	if (port->fifosize > 1)
+		fcon |= FEN;
+
+	spin_lock_irqsave (&port->lock, flags);
+
+	uart_update_timeout (port, termios->c_cflag, baud);
+
+	port->read_status_mask = RxOverrunError;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= RxFramingError | RxParityError;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= RxBreak;
+
+		/* Figure mask for status we ignore */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= RxFramingError | RxParityError;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= RxBreak;
+		/* Ignore overrun when ignorning parity */
+		/* *** FIXME: is this in the right place? */
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= RxOverrunError;
+	}
+
+		/* Ignore all receive errors when receive disabled */
+	if ((termios->c_cflag & CREAD) == 0)
+		port->ignore_status_mask |= RxError;
+
+	con   = UR (port, UART_R_CON);
+	inten = (UR (port, UART_R_INTEN) & ~ModemInt);
+
+	if (UART_ENABLE_MS (port, termios->c_cflag))
+		inten |= ModemInt;
+
+	BIT_CLR (port, UART_R_CON, UARTEN);	/* Disable UART */
+	UR (port, UART_R_INTEN) = 0;		/* Disable interrupts */
+	UR (port, UART_R_BRCON) = quot - 1;	/* Set baud rate divisor */
+	UR (port, UART_R_FCON)  = fcon;		/* Set FIFO and frame ctrl */
+	UR (port, UART_R_INTEN) = inten;	/* Enable interrupts */
+	UR (port, UART_R_CON)   = con;		/* Restore UART mode */
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char* lh7a40xuart_type (struct uart_port* port)
+{
+	return port->type == PORT_LH7A40X ? "LH7A40X" : NULL;
+}
+
+static void lh7a40xuart_release_port (struct uart_port* port)
+{
+	release_mem_region (port->mapbase, UART_REG_SIZE);
+}
+
+static int lh7a40xuart_request_port (struct uart_port* port)
+{
+	return request_mem_region (port->mapbase, UART_REG_SIZE,
+				   "serial_lh7a40x") != NULL
+		? 0 : -EBUSY;
+}
+
+static void lh7a40xuart_config_port (struct uart_port* port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE) {
+		port->type = PORT_LH7A40X;
+		lh7a40xuart_request_port (port);
+	}
+}
+
+static int lh7a40xuart_verify_port (struct uart_port* port,
+				    struct serial_struct* ser)
+{
+	int ret = 0;
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
+		ret = -EINVAL;
+	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+		ret = -EINVAL;
+	if (ser->baud_base < 9600) /* *** FIXME: is this true? */
+		ret = -EINVAL;
+	return ret;
+}
+
+static struct uart_ops lh7a40x_uart_ops = {
+	.tx_empty	= lh7a40xuart_tx_empty,
+	.set_mctrl	= lh7a40xuart_set_mctrl,
+	.get_mctrl	= lh7a40xuart_get_mctrl,
+	.stop_tx	= lh7a40xuart_stop_tx,
+	.start_tx	= lh7a40xuart_start_tx,
+	.stop_rx	= lh7a40xuart_stop_rx,
+	.enable_ms	= lh7a40xuart_enable_ms,
+	.break_ctl	= lh7a40xuart_break_ctl,
+	.startup	= lh7a40xuart_startup,
+	.shutdown	= lh7a40xuart_shutdown,
+	.set_termios	= lh7a40xuart_set_termios,
+	.type		= lh7a40xuart_type,
+	.release_port	= lh7a40xuart_release_port,
+	.request_port	= lh7a40xuart_request_port,
+	.config_port	= lh7a40xuart_config_port,
+	.verify_port	= lh7a40xuart_verify_port,
+};
+
+static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
+	{
+		.port = {
+			.membase	= (void*) io_p2v (UART1_PHYS),
+			.mapbase	= UART1_PHYS,
+			.iotype		= SERIAL_IO_MEM,
+			.irq		= IRQ_UART1INTR,
+			.uartclk	= 14745600/2,
+			.fifosize	= 16,
+			.ops		= &lh7a40x_uart_ops,
+			.flags		= ASYNC_BOOT_AUTOCONF,
+			.line		= 0,
+		},
+	},
+	{
+		.port = {
+			.membase	= (void*) io_p2v (UART2_PHYS),
+			.mapbase	= UART2_PHYS,
+			.iotype		= SERIAL_IO_MEM,
+			.irq		= IRQ_UART2INTR,
+			.uartclk	= 14745600/2,
+			.fifosize	= 16,
+			.ops		= &lh7a40x_uart_ops,
+			.flags		= ASYNC_BOOT_AUTOCONF,
+			.line		= 1,
+		},
+	},
+	{
+		.port = {
+			.membase	= (void*) io_p2v (UART3_PHYS),
+			.mapbase	= UART3_PHYS,
+			.iotype		= SERIAL_IO_MEM,
+			.irq		= IRQ_UART3INTR,
+			.uartclk	= 14745600/2,
+			.fifosize	= 16,
+			.ops		= &lh7a40x_uart_ops,
+			.flags		= ASYNC_BOOT_AUTOCONF,
+			.line		= 2,
+		},
+	},
+};
+
+#ifndef CONFIG_SERIAL_LH7A40X_CONSOLE
+# define LH7A40X_CONSOLE NULL
+#else
+# define LH7A40X_CONSOLE &lh7a40x_console
+
+
+static void lh7a40xuart_console_write (struct console* co,
+				       const char* s,
+				       unsigned int count)
+{
+	struct uart_port* port = &lh7a40x_ports[co->index].port;
+	unsigned int con = UR (port, UART_R_CON);
+	unsigned int inten = UR (port, UART_R_INTEN);
+
+
+	UR (port, UART_R_INTEN) = 0;		/* Disable all interrupts */
+	BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */
+
+	for (; count-- > 0; ++s) {
+		while (UR (port, UART_R_STATUS) & nTxRdy)
+			;
+		UR (port, UART_R_DATA) = *s;
+		if (*s == '\n') {
+			while ((UR (port, UART_R_STATUS) & TxBusy))
+				;
+			UR (port, UART_R_DATA) = '\r';
+		}
+	}
+
+				/* Wait until all characters are sent */
+	while (UR (port, UART_R_STATUS) & TxBusy)
+		;
+
+				/* Restore control and interrupt mask */
+	UR (port, UART_R_CON) = con;
+	UR (port, UART_R_INTEN) = inten;
+}
+
+static void __init lh7a40xuart_console_get_options (struct uart_port* port,
+						    int* baud,
+						    int* parity,
+						    int* bits)
+{
+	if (UR (port, UART_R_CON) & UARTEN) {
+		unsigned int fcon = UR (port, UART_R_FCON);
+		unsigned int quot = UR (port, UART_R_BRCON) + 1;
+
+		switch (fcon & (PEN | EPS)) {
+		default:        *parity = 'n'; break;
+		case PEN:       *parity = 'o'; break;
+		case PEN | EPS: *parity = 'e'; break;
+		}
+
+		switch (fcon & WLEN) {
+		default:
+		case WLEN_8: *bits = 8; break;
+		case WLEN_7: *bits = 7; break;
+		case WLEN_6: *bits = 6; break;
+		case WLEN_5: *bits = 5; break;
+		}
+
+		*baud = port->uartclk/(16*quot);
+	}
+}
+
+static int __init lh7a40xuart_console_setup (struct console* co, char* options)
+{
+	struct uart_port* port;
+	int baud = 38400;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (co->index >= DEV_NR) /* Bounds check on device number */
+		co->index = 0;
+	port = &lh7a40x_ports[co->index].port;
+
+	if (options)
+		uart_parse_options (options, &baud, &parity, &bits, &flow);
+	else
+		lh7a40xuart_console_get_options (port, &baud, &parity, &bits);
+
+	return uart_set_options (port, co, baud, parity, bits, flow);
+}
+
+extern struct uart_driver lh7a40x_reg;
+static struct console lh7a40x_console = {
+	.name		= "ttyAM",
+	.write		= lh7a40xuart_console_write,
+	.device		= uart_console_device,
+	.setup		= lh7a40xuart_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &lh7a40x_reg,
+};
+
+static int __init lh7a40xuart_console_init(void)
+{
+	register_console (&lh7a40x_console);
+	return 0;
+}
+
+console_initcall (lh7a40xuart_console_init);
+
+#endif
+
+static struct uart_driver lh7a40x_reg = {
+	.owner			= THIS_MODULE,
+	.driver_name		= "ttyAM",
+	.dev_name		= "ttyAM",
+	.major			= DEV_MAJOR,
+	.minor			= DEV_MINOR,
+	.nr			= DEV_NR,
+	.cons			= LH7A40X_CONSOLE,
+};
+
+static int __init lh7a40xuart_init(void)
+{
+	int ret;
+
+	printk (KERN_INFO "serial: LH7A40X serial driver\n");
+
+	ret = uart_register_driver (&lh7a40x_reg);
+
+	if (ret == 0) {
+		int i;
+
+		for (i = 0; i < DEV_NR; i++)
+			uart_add_one_port (&lh7a40x_reg,
+					   &lh7a40x_ports[i].port);
+	}
+	return ret;
+}
+
+static void __exit lh7a40xuart_exit(void)
+{
+	int i;
+
+	for (i = 0; i < DEV_NR; i++)
+		uart_remove_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port);
+
+	uart_unregister_driver (&lh7a40x_reg);
+}
+
+module_init (lh7a40xuart_init);
+module_exit (lh7a40xuart_exit);
+
+MODULE_AUTHOR ("Marc Singer");
+MODULE_DESCRIPTION ("Sharp LH7A40X serial port driver");
+MODULE_LICENSE ("GPL");
diff -Nru a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
--- a/drivers/telephony/ixj.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/telephony/ixj.c	2004-06-23 19:04:25 -07:00
@@ -461,8 +461,8 @@
 static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf);
 static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr);
 static int ixj_init_tone(IXJ *j, IXJ_TONE * ti);
-static int ixj_build_cadence(IXJ *j, IXJ_CADENCE * cp);
-static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE * cp);
+static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp);
+static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp);
 /* Serial Control Interface funtions */
 static int SCI_Control(IXJ *j, int control);
 static int SCI_Prepare(IXJ *j);
@@ -2855,7 +2855,7 @@
 	}
 }
 
-static ssize_t ixj_read(struct file * file_p, char *buf, size_t length, loff_t * ppos)
+static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos)
 {
 	unsigned long i = *ppos;
 	IXJ * j = get_ixj(NUM(file_p->f_dentry->d_inode));
@@ -2910,7 +2910,7 @@
 	}
 }
 
-static ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length,
+static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t length,
 			  loff_t * ppos)
 {
 	int pre_retval;
@@ -2935,7 +2935,7 @@
 	return read_retval;
 }
 
-static ssize_t ixj_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos)
+static ssize_t ixj_write(struct file *file_p, const char __user *buf, size_t count, loff_t * ppos)
 {
 	unsigned long i = *ppos;
 	IXJ *j = file_p->private_data;
@@ -2989,7 +2989,7 @@
 	return min(count, j->write_buffer_size);
 }
 
-static ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos)
+static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf, size_t count, loff_t * ppos)
 {
 	int pre_retval;
 	ssize_t write_retval = 0;
@@ -5938,31 +5938,41 @@
 	ixj_WriteDSPCommand(0x3001, j);	/* Test External SRAM */
 }
 
-static int ixj_build_cadence(IXJ *j, IXJ_CADENCE * cp)
+static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp)
 {
-	IXJ_CADENCE *lcp;
+	ixj_cadence *lcp;
+	IXJ_CADENCE_ELEMENT __user *cep;
 	IXJ_CADENCE_ELEMENT *lcep;
 	IXJ_TONE ti;
+	int err;
 
-	lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
+	lcp = kmalloc(sizeof(ixj_cadence), GFP_KERNEL);
 	if (lcp == NULL)
 		return -ENOMEM;
-	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)) || (unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE_ELEMENT) )
-        {
-                kfree(lcp);
-                return -EFAULT;
-        }
+
+	err = -EFAULT;
+	if (copy_from_user(&lcp->elements_used,
+			   &cp->elements_used, sizeof(int)))
+		goto out;
+	if (copy_from_user(&lcp->termination,
+			   &cp->termination, sizeof(IXJ_CADENCE_TERM)))
+		goto out;
+	if (get_user(cep, &cp->ce))
+		goto out;
+
+	err = -EINVAL;
+	if ((unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE_ELEMENT))
+		goto out;
+
+	err = -ENOMEM;
 	lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL);
-	if (lcep == NULL) {
-		kfree(lcp);
-		return -ENOMEM;
-	}
-	if (copy_from_user(lcep, lcp->ce, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used))
-	{
-		kfree(lcep);
-		kfree(lcp);
-		return -EFAULT;
-	}
+	if (!lcep)
+		goto out;
+
+	err = -EFAULT;
+	if (copy_from_user(lcep, cep, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used))
+		goto out1;
+
 	if (j->cadence_t) {
 		kfree(j->cadence_t->ce);
 		kfree(j->cadence_t);
@@ -5982,9 +5992,14 @@
 	}
 	ixj_play_tone(j, lcp->ce[0].index);
 	return 1;
+out1:
+	kfree(lcep);
+out:
+	kfree(lcp);
+	return err;
 }
 
-static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE * cp)
+static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp)
 {
 	IXJ_FILTER_CADENCE *lcp;
 	lcp = kmalloc(sizeof(IXJ_FILTER_CADENCE), GFP_KERNEL);
@@ -5994,7 +6009,7 @@
 		}
 		return -ENOMEM;
         }
-	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE))) {
+	if (copy_from_user(lcp, cp, sizeof(IXJ_FILTER_CADENCE))) {
 		if(ixjdebug & 0x0001) {
 			printk(KERN_INFO "Could not copy cadence to kernel\n");
 		}
@@ -6206,6 +6221,7 @@
 	IXJ_TONE ti;
 	IXJ_FILTER jf;
 	IXJ_FILTER_RAW jfr;
+	void __user *argp = (void __user *)arg;
 
 	unsigned int raise, mant;
 	unsigned int minor = iminor(inode);
@@ -6251,7 +6267,7 @@
 		retval = j->serial;
 		break;
 	case IXJCTL_VERSION:
-		if (copy_to_user((char *) arg, ixj_c_revision, strlen(ixj_c_revision))) 
+		if (copy_to_user(argp, ixj_c_revision, strlen(ixj_c_revision))) 
 			retval = -EFAULT;
 		break;
 	case PHONE_RING_CADENCE:
@@ -6259,7 +6275,7 @@
 		break;
 	case IXJCTL_CIDCW:
 		if(arg) {
-			if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) {
+			if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) {
 				retval = -EFAULT;
 				break;
 			}
@@ -6274,7 +6290,7 @@
                 /* Fall through */
  	case PHONE_RING_START:
 		if(arg) {
-			if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) {
+			if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) {
 				retval = -EFAULT;
 				break;
 			}
@@ -6432,22 +6448,22 @@
 			samplerate = arg;
 		break;
 	case IXJCTL_DRYBUFFER_READ:
-		put_user(j->drybuffer, (unsigned long *) arg);
+		put_user(j->drybuffer, (unsigned long __user *) argp);
 		break;
 	case IXJCTL_DRYBUFFER_CLEAR:
 		j->drybuffer = 0;
 		break;
 	case IXJCTL_FRAMES_READ:
-		put_user(j->framesread, (unsigned long *) arg);
+		put_user(j->framesread, (unsigned long __user *) argp);
 		break;
 	case IXJCTL_FRAMES_WRITTEN:
-		put_user(j->frameswritten, (unsigned long *) arg);
+		put_user(j->frameswritten, (unsigned long __user *) argp);
 		break;
 	case IXJCTL_READ_WAIT:
-		put_user(j->read_wait, (unsigned long *) arg);
+		put_user(j->read_wait, (unsigned long __user *) argp);
 		break;
 	case IXJCTL_WRITE_WAIT:
-		put_user(j->write_wait, (unsigned long *) arg);
+		put_user(j->write_wait, (unsigned long __user *) argp);
 		break;
 	case PHONE_MAXRINGS:
 		j->maxrings = arg;
@@ -6573,7 +6589,7 @@
                         12, 10, 16, 9, 8, 48, 5,
                         40, 40, 80, 40, 40, 6
                 };
-                if(copy_from_user(&pd, (void *)arg, sizeof(pd))) {
+                if(copy_from_user(&pd, argp, sizeof(pd))) {
                         retval = -EFAULT;
 			break;
 		}
@@ -6590,7 +6606,7 @@
                         default:val=proto_size[pd.type]*3;break;
                 }
                 pd.buf_min=pd.buf_max=pd.buf_opt=val;
-                if(copy_to_user((void *)arg, &pd, sizeof(pd)))
+                if(copy_to_user(argp, &pd, sizeof(pd)))
                         retval = -EFAULT;
         	break;
         }
@@ -6644,7 +6660,7 @@
 		ixj_write_vmwi(j, arg);
 		break;
 	case IXJCTL_CID:
-		if (copy_to_user((char *) arg, &j->cid, sizeof(PHONE_CID))) 
+		if (copy_to_user(argp, &j->cid, sizeof(PHONE_CID))) 
 			retval = -EFAULT;
 		j->ex.bits.caller_id = 0;
 		break;
@@ -6666,13 +6682,13 @@
 		break;
 	case PHONE_CAPABILITIES_LIST:
 		add_caps(j);
-		if (copy_to_user((char *) arg, j->caplist, sizeof(struct phone_capability) * j->caps)) 
+		if (copy_to_user(argp, j->caplist, sizeof(struct phone_capability) * j->caps)) 
 			retval = -EFAULT;
 		break;
 	case PHONE_CAPABILITIES_CHECK:
 		{
 			struct phone_capability cap;
-			if (copy_from_user(&cap, (char *) arg, sizeof(cap))) 
+			if (copy_from_user(&cap, argp, sizeof(cap))) 
 				retval = -EFAULT;
 			else {
 				add_caps(j);
@@ -6688,12 +6704,12 @@
 		j->ex.bits.pstn_ring = 0;
 		break;
 	case IXJCTL_SET_FILTER:
-		if (copy_from_user(&jf, (char *) arg, sizeof(jf))) 
+		if (copy_from_user(&jf, argp, sizeof(jf))) 
 			retval = -EFAULT;
 		retval = ixj_init_filter(j, &jf);
 		break;
 	case IXJCTL_SET_FILTER_RAW:
-		if (copy_from_user(&jfr, (char *) arg, sizeof(jfr))) 
+		if (copy_from_user(&jfr, argp, sizeof(jfr))) 
 			retval = -EFAULT;
 		else
 			retval = ixj_init_filter_raw(j, &jfr);
@@ -6705,19 +6721,19 @@
 			retval = j->filter_hist[arg];
 		break;
 	case IXJCTL_INIT_TONE:
-		if (copy_from_user(&ti, (char *) arg, sizeof(ti)))
+		if (copy_from_user(&ti, argp, sizeof(ti)))
 			retval = -EFAULT;
 		else
 			retval = ixj_init_tone(j, &ti);
 		break;
 	case IXJCTL_TONE_CADENCE:
-		retval = ixj_build_cadence(j, (IXJ_CADENCE *) arg);
+		retval = ixj_build_cadence(j, argp);
 		break;
 	case IXJCTL_FILTER_CADENCE:
-		retval = ixj_build_filter_cadence(j, (IXJ_FILTER_CADENCE *) arg);
+		retval = ixj_build_filter_cadence(j, argp);
 		break;
 	case IXJCTL_SIGCTL:
-		if (copy_from_user(&j->sigdef, (char *)arg, sizeof(IXJ_SIGDEF))) {
+		if (copy_from_user(&j->sigdef, argp, sizeof(IXJ_SIGDEF))) {
 			retval = -EFAULT;
 			break;
 		}
diff -Nru a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h
--- a/drivers/telephony/ixj.h	2004-06-23 19:04:29 -07:00
+++ b/drivers/telephony/ixj.h	2004-06-23 19:04:29 -07:00
@@ -1167,6 +1167,12 @@
 ******************************************************************************/
 
 typedef struct {
+	int elements_used;
+	IXJ_CADENCE_TERM termination;
+	IXJ_CADENCE_ELEMENT *ce;
+} ixj_cadence;
+
+typedef struct {
 	struct phone_device p;
 	struct timer_list timer;
 	unsigned int board;
@@ -1220,8 +1226,8 @@
 	char tone_index;
 	char tone_state;
 	char maxrings;
-	IXJ_CADENCE *cadence_t;
-	IXJ_CADENCE *cadence_r;
+	ixj_cadence *cadence_t;
+	ixj_cadence *cadence_r;
 	int tone_cadence_state;
 	IXJ_CADENCE_F cadence_f[6];
 	DTMF dtmf;
diff -Nru a/drivers/usb/Kconfig b/drivers/usb/Kconfig
--- a/drivers/usb/Kconfig	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/Kconfig	2004-06-23 19:04:25 -07:00
@@ -7,7 +7,7 @@
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
 config USB
 	tristate "Support for Host-side USB"
-	depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610
+	depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_LH7A404
 	---help---
 	  Universal Serial Bus (USB) is a specification for a serial bus
 	  subsystem which offers higher speeds and more features than the
diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- a/drivers/usb/class/audio.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/class/audio.c	2004-06-23 19:04:28 -07:00
@@ -2008,6 +2008,7 @@
 {
 	struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;
 	int i, j, val;
+	int __user *user_arg = (int __user *)arg;
 
 	if (!ms->state->usbdev)
 		return -ENODEV;
@@ -2034,7 +2035,7 @@
 		return 0;
 	}
 	if (cmd == OSS_GETVERSION)
-		return put_user(SOUND_VERSION, (int *)arg);
+		return put_user(SOUND_VERSION, user_arg);
 	if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
 		return -EINVAL;
 	if (_IOC_DIR(cmd) == _IOC_READ) {
@@ -2043,27 +2044,27 @@
 			val = get_rec_src(ms);
 			if (val < 0)
 				return val;
-			return put_user(val, (int *)arg);
+			return put_user(val, user_arg);
 
 		case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
 			for (val = i = 0; i < ms->numch; i++)
 				val |= 1 << ms->ch[i].osschannel;
-			return put_user(val, (int *)arg);
+			return put_user(val, user_arg);
 
 		case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
 			for (val = i = 0; i < ms->numch; i++)
 				if (ms->ch[i].slctunitid)
 					val |= 1 << ms->ch[i].osschannel;
-			return put_user(val, (int *)arg);
+			return put_user(val, user_arg);
 
 		case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
 			for (val = i = 0; i < ms->numch; i++)
 				if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))
 					val |= 1 << ms->ch[i].osschannel;
-			return put_user(val, (int *)arg);
+			return put_user(val, user_arg);
 			
 		case SOUND_MIXER_CAPS:
-			return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
+			return put_user(SOUND_CAP_EXCL_INPUT, user_arg);
 
 		default:
 			i = _IOC_NR(cmd);
@@ -2071,7 +2072,7 @@
 				return -EINVAL;
 			for (j = 0; j < ms->numch; j++) {
 				if (ms->ch[j].osschannel == i) {
-					return put_user(ms->ch[j].value, (int *)arg);
+					return put_user(ms->ch[j].value, user_arg);
 				}
 			}
 			return -EINVAL;
@@ -2082,7 +2083,7 @@
 	ms->modcnt++;
 	switch (_IOC_NR(cmd)) {
 	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
-		if (get_user(val, (int *)arg))
+		if (get_user(val, user_arg))
 			return -EFAULT;
 		return set_rec_src(ms, val);
 
@@ -2093,11 +2094,11 @@
 		for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++);
 		if (j >= ms->numch)
 			return -EINVAL;
-		if (get_user(val, (int *)arg))
+		if (get_user(val, user_arg))
 			return -EFAULT;
 		if (wrmixer(ms, j, val))
 			return -EIO;
-		return put_user(ms->ch[j].value, (int *)arg);
+		return put_user(ms->ch[j].value, user_arg);
 	}
 }
 
@@ -2370,6 +2371,7 @@
 {
 	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
 	struct usb_audio_state *s = as->state;
+	int __user *user_arg = (int __user *)arg;
 	unsigned long flags;
 	audio_buf_info abinfo;
 	count_info cinfo;
@@ -2387,7 +2389,7 @@
 #endif
 	switch (cmd) {
 	case OSS_GETVERSION:
-		return put_user(SOUND_VERSION, (int *)arg);
+		return put_user(SOUND_VERSION, user_arg);
 
 	case SNDCTL_DSP_SYNC:
 		if (file->f_mode & FMODE_WRITE)
@@ -2399,7 +2401,7 @@
 
 	case SNDCTL_DSP_GETCAPS:
 		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | 
-				DSP_CAP_MMAP | DSP_CAP_BATCH, (int *)arg);
+				DSP_CAP_MMAP | DSP_CAP_BATCH, user_arg);
 
 	case SNDCTL_DSP_RESET:
 		if (file->f_mode & FMODE_WRITE) {
@@ -2413,7 +2415,7 @@
 		return 0;
 
 	case SNDCTL_DSP_SPEED:
-		if (get_user(val, (int *)arg))
+		if (get_user(val, user_arg))
 			return -EFAULT;
 		if (val >= 0) {
 			if (val < 4000)
@@ -2423,10 +2425,12 @@
 			if (set_format(as, file->f_mode, AFMT_QUERY, val))
 				return -EIO;
 		}
-		return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg);
+		return put_user((file->f_mode & FMODE_READ) ? 
+				as->usbin.dma.srate : as->usbout.dma.srate,
+				user_arg);
 
 	case SNDCTL_DSP_STEREO:
-		if (get_user(val, (int *)arg))
+		if (get_user(val, user_arg))
 			return -EFAULT;
 		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
 		if (val)
@@ -2438,7 +2442,7 @@
 		return 0;
 
 	case SNDCTL_DSP_CHANNELS:
-		if (get_user(val, (int *)arg))
+		if (get_user(val, user_arg))
 			return -EFAULT;
 		if (val != 0) {
 			val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
@@ -2450,14 +2454,14 @@
 				return -EIO;
 		}
 		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-		return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg);
+		return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg);
 
 	case SNDCTL_DSP_GETFMTS: /* Returns a mask */
 		return put_user(AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE |
-				AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, (int *)arg);
+				AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, user_arg);
 
 	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		if (get_user(val, (int *)arg))
+		if (get_user(val, user_arg))
 			return -EFAULT;
 		if (val != AFMT_QUERY) {
 			if (hweight32(val) != 1)
@@ -2471,7 +2475,7 @@
 				return -EIO;
 		}
 		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-		return put_user(val2 & ~AFMT_STEREO, (int *)arg);
+		return put_user(val2 & ~AFMT_STEREO, user_arg);
 
 	case SNDCTL_DSP_POST:
 		return 0;
@@ -2482,10 +2486,10 @@
 			val |= PCM_ENABLE_INPUT;
 		if (file->f_mode & FMODE_WRITE && as->usbout.flags & FLG_RUNNING) 
 			val |= PCM_ENABLE_OUTPUT;
-		return put_user(val, (int *)arg);
+		return put_user(val, user_arg);
 
 	case SNDCTL_DSP_SETTRIGGER:
-		if (get_user(val, (int *)arg))
+		if (get_user(val, user_arg))
 			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			if (val & PCM_ENABLE_INPUT) {
@@ -2543,7 +2547,7 @@
 		spin_lock_irqsave(&as->lock, flags);
 		val = as->usbout.dma.count;
 		spin_unlock_irqrestore(&as->lock, flags);
-		return put_user(val, (int *)arg);
+		return put_user(val, user_arg);
 
 	case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
@@ -2577,14 +2581,14 @@
 		if (file->f_mode & FMODE_WRITE) {
 			if ((val = prog_dmabuf_out(as)))
 				return val;
-			return put_user(as->usbout.dma.fragsize, (int *)arg);
+			return put_user(as->usbout.dma.fragsize, user_arg);
 		}
 		if ((val = prog_dmabuf_in(as)))
 			return val;
-		return put_user(as->usbin.dma.fragsize, (int *)arg);
+		return put_user(as->usbin.dma.fragsize, user_arg);
 
 	case SNDCTL_DSP_SETFRAGMENT:
-		if (get_user(val, (int *)arg))
+		if (get_user(val, user_arg))
 			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
 			as->usbin.dma.ossfragshift = val & 0xffff;
@@ -2612,7 +2616,7 @@
 		if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) ||
 		    (file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision))
 			return -EINVAL;
-		if (get_user(val, (int *)arg))
+		if (get_user(val, user_arg))
 			return -EFAULT;
 		if (val != 1 && val != 2 && val != 4)
 			return -EINVAL;
@@ -2623,15 +2627,17 @@
 		return 0;
 
 	case SOUND_PCM_READ_RATE:
-		return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg);
+		return put_user((file->f_mode & FMODE_READ) ? 
+				as->usbin.dma.srate : as->usbout.dma.srate,
+				user_arg);
 
 	case SOUND_PCM_READ_CHANNELS:
 		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-		return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg);
+		return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg);
 
 	case SOUND_PCM_READ_BITS:
 		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-		return put_user(AFMT_IS16BIT(val2) ? 16 : 8, (int *)arg);
+		return put_user(AFMT_IS16BIT(val2) ? 16 : 8, user_arg);
 
 	case SOUND_PCM_WRITE_FILTER:
 	case SNDCTL_DSP_SETSYNCRO:
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/class/cdc-acm.c	2004-06-23 19:04:27 -07:00
@@ -27,6 +27,7 @@
  *	v0.22 - probe only the control interface. if usbcore doesn't choose the
  *		config we want, sysadmin changes bConfigurationValue in sysfs.
  *	v0.23 - use softirq for rx processing, as needed by tty layer
+ *	v0.24 - change probe method to evaluate CDC union descriptor
  */
 
 /*
@@ -60,6 +61,8 @@
 #include <linux/usb.h>
 #include <asm/byteorder.h>
 
+#include "cdc-acm.h"
+
 /*
  * Version Information
  */
@@ -67,102 +70,12 @@
 #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
 
-/*
- * CMSPAR, some architectures can't have space and mark parity.
- */
-
-#ifndef CMSPAR
-#define CMSPAR			0
-#endif
-
-/*
- * Major and minor numbers.
- */
-
-#define ACM_TTY_MAJOR		166
-#define ACM_TTY_MINORS		32
-
-/*
- * Requests.
- */
-
-#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.
- */
-
-#define ACM_CTRL_DTR		0x01
-#define ACM_CTRL_RTS		0x02
-
-/*
- * Input control lines and line errors.
- */
-
-#define ACM_CTRL_DCD		0x01
-#define ACM_CTRL_DSR		0x02
-#define ACM_CTRL_BRK		0x04
-#define ACM_CTRL_RI		0x08
-
-#define ACM_CTRL_FRAMING	0x10
-#define ACM_CTRL_PARITY		0x20
-#define ACM_CTRL_OVERRUN	0x40
-
-/*
- * Line speed and caracter encoding.
- */
-
-struct acm_line {
-	__u32 speed;
-	__u8 stopbits;
-	__u8 parity;
-	__u8 databits;
-} __attribute__ ((packed));
-
-/*
- * Internal driver structures.
- */
-
-struct acm {
-	struct usb_device *dev;				/* the corresponding usb device */
-	struct usb_interface *control;			/* control interface */
-	struct usb_interface *data;			/* data interface */
-	struct tty_struct *tty;				/* the corresponding tty */
-	struct urb *ctrlurb, *readurb, *writeurb;	/* urbs */
-	struct acm_line line;				/* line coding (bits, stop, parity) */
-	struct work_struct work;			/* work queue entry for line discipline waking up */
-	struct tasklet_struct bh;			/* rx processing */
-	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
-	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
-	unsigned int writesize;				/* max packet size for the output bulk endpoint */
-	unsigned int used;				/* someone has this acm's device open */
-	unsigned int minor;				/* acm minor number */
-	unsigned char throttle;				/* throttled by tty layer */
-	unsigned char clocal;				/* termios CLOCAL */
-};
-
 static struct usb_driver acm_driver;
 static struct tty_driver *acm_tty_driver;
 static struct acm *acm_table[ACM_TTY_MINORS];
 
+static DECLARE_MUTEX(open_sem);
+
 #define ACM_READY(acm)	(acm && acm->dev && acm->used)
 
 /*
@@ -310,12 +223,14 @@
 	struct acm *acm = (struct acm *)urb->context;
 
 	if (!ACM_READY(acm))
-		return;
+		goto out;
 
 	if (urb->status)
 		dbg("nonzero write bulk status received: %d", urb->status);
 
 	schedule_work(&acm->work);
+out:
+	acm->ready_for_write = 1;
 }
 
 static void acm_softint(void *private)
@@ -346,22 +261,23 @@
 	tty->driver_data = acm;
 	acm->tty = tty;
 
-        lock_kernel();
+        down(&open_sem);
 
-	if (acm->used++) {
-                unlock_kernel();
-                return 0;
+	if (acm->used) {
+		goto done;
         }
 
-        unlock_kernel();
-
 	acm->ctrlurb->dev = acm->dev;
-	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL))
+	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
 		dbg("usb_submit_urb(ctrl irq) failed");
+		goto bail_out;
+	}
 
 	acm->readurb->dev = acm->dev;
-	if (usb_submit_urb(acm->readurb, GFP_KERNEL))
+	if (usb_submit_urb(acm->readurb, GFP_KERNEL)) {
 		dbg("usb_submit_urb(read bulk) failed");
+		goto bail_out_and_unlink;
+	}
 
 	acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
 
@@ -369,7 +285,16 @@
 	   otherwise it is scheduled, and with high data rates data can get lost. */
 	tty->low_latency = 1;
 
+done:
+	acm->used++;
+	up(&open_sem);
 	return 0;
+
+bail_out_and_unlink:
+	usb_unlink_urb(acm->ctrlurb);
+bail_out:
+	up(&open_sem);
+	return -EIO;
 }
 
 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
@@ -379,6 +304,7 @@
 	if (!acm || !acm->used)
 		return;
 
+	down(&open_sem);
 	if (!--acm->used) {
 		if (acm->dev) {
 			acm_set_control(acm, acm->ctrlout = 0);
@@ -394,6 +320,7 @@
 			kfree(acm);
 		}
 	}
+	up(&open_sem);
 }
 
 static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
@@ -403,7 +330,7 @@
 
 	if (!ACM_READY(acm))
 		return -EINVAL;
-	if (acm->writeurb->status == -EINPROGRESS)
+	if (!acm->ready_for_write)
 		return 0;
 	if (!count)
 		return 0;
@@ -419,10 +346,11 @@
 	acm->writeurb->transfer_buffer_length = count;
 	acm->writeurb->dev = acm->dev;
 
-	/* GFP_KERNEL probably works if from_user */
-	stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC);
+	acm->ready_for_write = 0;
+	stat = usb_submit_urb(acm->writeurb, GFP_NOIO);
 	if (stat < 0) {
 		dbg("usb_submit_urb(write bulk) failed");
+		acm->ready_for_write = 1;
 		return stat;
 	}
 
@@ -434,7 +362,7 @@
 	struct acm *acm = tty->driver_data;
 	if (!ACM_READY(acm))
 		return -EINVAL;
-	return acm->writeurb->status == -EINPROGRESS ? 0 : acm->writesize;
+	return !acm->ready_for_write ? 0 : acm->writesize;
 }
 
 static int acm_tty_chars_in_buffer(struct tty_struct *tty)
@@ -442,7 +370,7 @@
 	struct acm *acm = tty->driver_data;
 	if (!ACM_READY(acm))
 		return -EINVAL;
-	return acm->writeurb->status == -EINPROGRESS ? acm->writeurb->transfer_buffer_length : 0;
+	return !acm->ready_for_write ? acm->writeurb->transfer_buffer_length : 0;
 }
 
 static void acm_tty_throttle(struct tty_struct *tty)
@@ -567,77 +495,102 @@
  * USB probe and disconnect routines.
  */
 
-#define CHECK_XFERTYPE(descr, xfer_type) (((descr)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == xfer_type)
-			
 static int acm_probe (struct usb_interface *intf,
 		      const struct usb_device_id *id)
 {
-	struct usb_device *dev;
+	struct union_desc *union_header = NULL;
+	char *buffer = intf->altsetting->extra;
+	int buflen = intf->altsetting->extralen;
+	struct usb_interface *control_interface;
+	struct usb_interface *data_interface;
+	struct usb_endpoint_descriptor *epctrl;
+	struct usb_endpoint_descriptor *epread;
+	struct usb_endpoint_descriptor *epwrite;
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
 	struct acm *acm;
-	struct usb_host_config *cfacm;
-	struct usb_interface *data = NULL;
-	struct usb_host_interface *ifcom, *ifdata = NULL;
-	struct usb_endpoint_descriptor *epctrl = NULL;
-	struct usb_endpoint_descriptor *epread = NULL;
-	struct usb_endpoint_descriptor *epwrite = NULL;
-	int readsize, ctrlsize, minor, j;
-	unsigned char *buf;
-
-	dev = interface_to_usbdev (intf);
-
-	cfacm = dev->actconfig;
-
-	/* We know we're probe()d with the control interface. */
-	ifcom = intf->cur_altsetting;
-
-	/* ACM doesn't guarantee the data interface is
-	 * adjacent to the control interface, or that if one
-	 * is there it's not for call management ... so find
-	 * it
-	 */
-	for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
-		ifdata = cfacm->interface[j]->cur_altsetting;
-		data = cfacm->interface[j];
-
-		if (ifdata->desc.bInterfaceClass == USB_CLASS_CDC_DATA
-		    && ifdata->desc.bNumEndpoints == 2) {
-			
-			epctrl = &ifcom->endpoint[0].desc;
-			epread = &ifdata->endpoint[0].desc;
-			epwrite = &ifdata->endpoint[1].desc;
-
-			if ((epctrl->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN
-			    || !CHECK_XFERTYPE(epctrl,  USB_ENDPOINT_XFER_INT)
-			    || !CHECK_XFERTYPE(epread,  USB_ENDPOINT_XFER_BULK)
-			    || !CHECK_XFERTYPE(epwrite, USB_ENDPOINT_XFER_BULK)
-			    || ((epread->bEndpointAddress & USB_DIR_IN)
-			        ^ (epwrite->bEndpointAddress & USB_DIR_IN)) != USB_DIR_IN) {
-				/* not suitable */
-				goto next_interface;
-			}
-			
-			if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
-				/* descriptors are swapped */
-				epread = &ifdata->endpoint[1].desc;
-				epwrite = &ifdata->endpoint[0].desc;
-			}
-			dev_dbg(&intf->dev, "found data interface at %d\n", j);
-			break;
-		} else {
-next_interface:
-			ifdata = NULL;
-			data = NULL;
+	int minor;
+	int ctrlsize,readsize;
+	char *buf;
+
+	if (!buffer) {
+		err("Wierd descriptor references");
+		return -EINVAL;
+	}
+
+	while (buflen > 0) {
+		if (buffer [1] != USB_DT_CS_INTERFACE) {
+			err("skipping garbage");
+			goto next_desc;
 		}
+
+		switch (buffer [2]) {
+			case 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;
+				break;
+			default:
+				err("Ignoring extra header");
+				break;
+			}
+next_desc:
+		buflen -= buffer[0];
+		buffer += buffer[0];
 	}
 
-	/* there's been a problem */
-	if (!ifdata) {
-		dev_dbg(&intf->dev, "data interface not found\n");
+	if (!union_header) {
+		dev_dbg(&intf->dev,"No union descriptor, giving up\n");
 		return -ENODEV;
+	}
 
+	control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
+	data_interface = usb_ifnum_to_if(usb_dev, union_header->bSlaveInterface0);
+	if (!control_interface || !data_interface) {
+		dev_dbg(&intf->dev,"no interfaces\n");
+		return -ENODEV;
+	}
+
+	if (usb_interface_claimed(data_interface)) { /* valid in this context */
+		dev_dbg(&intf->dev,"The data interface isn't available\n");
+		return -EBUSY;
 	}
 
+	/*workaround for switched interfaces */
+	if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) {
+		if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) {
+			struct usb_interface *t;
+			dev_dbg(&intf->dev,"Your device has switched interfaces.\n");
+
+			t = control_interface;
+			control_interface = data_interface;
+			data_interface = t;
+		} else {
+			return -EINVAL;
+		}
+	}
+	if (data_interface->cur_altsetting->desc.bNumEndpoints < 2)
+		return -EINVAL;
+
+	epctrl = &control_interface->cur_altsetting->endpoint[0].desc;
+	epread = &data_interface->cur_altsetting->endpoint[0].desc;
+	epwrite = &data_interface->cur_altsetting->endpoint[1].desc;
+
+
+	/* workaround for switched endpoints */
+	if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
+		/* descriptors are swapped */
+		struct usb_endpoint_descriptor *t;
+		dev_dbg(&intf->dev,"The data interface has switched endpoints\n");
+		
+		t = epread;
+		epread = epwrite;
+		epwrite = t;
+	}
+	dbg("interfaces are valid");
 	for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
+
 	if (acm_table[minor]) {
 		err("no more free acm devices");
 		return -ENODEV;
@@ -647,20 +600,21 @@
 		dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n");
 		return -ENOMEM;
 	}
-	
 	memset(acm, 0, sizeof(struct acm));
 
 	ctrlsize = epctrl->wMaxPacketSize;
 	readsize = epread->wMaxPacketSize;
 	acm->writesize = epwrite->wMaxPacketSize;
-	acm->control = intf;
-	acm->data = data;
+	acm->control = control_interface;
+	acm->data = data_interface;
 	acm->minor = minor;
-	acm->dev = dev;
+	acm->dev = usb_dev;
 
 	acm->bh.func = acm_rx_tasklet;
 	acm->bh.data = (unsigned long) acm;
 	INIT_WORK(&acm->work, acm_softint, acm);
+	acm->ready_for_write = 1;
+
 
 	if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
 		dev_dbg(&intf->dev, "out of memory (buf kmalloc)\n");
@@ -693,29 +647,17 @@
 		return -ENOMEM;
 	}
 
-	usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
-		buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
+	usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
+			 buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
 
-	usb_fill_bulk_urb(acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
-		buf += ctrlsize, readsize, acm_read_bulk, acm);
+	usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
+			  buf += ctrlsize, readsize, acm_read_bulk, acm);
 	acm->readurb->transfer_flags |= URB_NO_FSBR;
 
-	usb_fill_bulk_urb(acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
-		buf += readsize, acm->writesize, acm_write_bulk, acm);
+	usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+			  buf += readsize, acm->writesize, acm_write_bulk, acm);
 	acm->writeurb->transfer_flags |= URB_NO_FSBR;
 
-	if ( (j = usb_driver_claim_interface(&acm_driver, data, acm)) != 0) {
-		err("claim failed");
-		usb_free_urb(acm->ctrlurb);
-		usb_free_urb(acm->readurb);
-		usb_free_urb(acm->writeurb);
-		kfree(acm);
-		kfree(buf);
-		return j;
-	} 
-
-	tty_register_device(acm_tty_driver, minor, &intf->dev);
-
 	dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
 
 	acm_set_control(acm, acm->ctrlout);
@@ -724,11 +666,14 @@
 	acm->line.databits = 8;
 	acm_set_line(acm, &acm->line);
 
+	usb_driver_claim_interface(&acm_driver, data_interface, acm);
+
+	tty_register_device(acm_tty_driver, minor, &intf->dev);
+
 	acm_table[minor] = acm;
 	usb_set_intfdata (intf, acm);
 	return 0;
 }
-#undef CHECK_XFERTYPE
 
 static void acm_disconnect(struct usb_interface *intf)
 {
@@ -745,6 +690,8 @@
 	usb_unlink_urb(acm->ctrlurb);
 	usb_unlink_urb(acm->readurb);
 	usb_unlink_urb(acm->writeurb);
+
+	flush_scheduled_work(); /* wait for acm_softint */
 
 	kfree(acm->ctrlurb->transfer_buffer);
 
diff -Nru a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/class/cdc-acm.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,115 @@
+/*
+ *
+ * Includes for cdc-acm.c
+ *
+ * Mainly take from usbnet's cdc-ether part
+ *
+ */
+
+/*
+ * CMSPAR, some architectures can't have space and mark parity.
+ */
+
+#ifndef CMSPAR
+#define CMSPAR			0
+#endif
+
+/*
+ * Major and minor numbers.
+ */
+
+#define ACM_TTY_MAJOR		166
+#define ACM_TTY_MINORS		32
+
+/*
+ * Requests.
+ */
+
+#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.
+ */
+
+#define ACM_CTRL_DTR		0x01
+#define ACM_CTRL_RTS		0x02
+
+/*
+ * Input control lines and line errors.
+ */
+
+#define ACM_CTRL_DCD		0x01
+#define ACM_CTRL_DSR		0x02
+#define ACM_CTRL_BRK		0x04
+#define ACM_CTRL_RI		0x08
+
+#define ACM_CTRL_FRAMING	0x10
+#define ACM_CTRL_PARITY		0x20
+#define ACM_CTRL_OVERRUN	0x40
+
+/*
+ * Line speed and caracter encoding.
+ */
+
+struct acm_line {
+	__u32 speed;
+	__u8 stopbits;
+	__u8 parity;
+	__u8 databits;
+} __attribute__ ((packed));
+
+/*
+ * Internal driver structures.
+ */
+
+struct acm {
+	struct usb_device *dev;				/* the corresponding usb device */
+	struct usb_interface *control;			/* control interface */
+	struct usb_interface *data;			/* data interface */
+	struct tty_struct *tty;				/* the corresponding tty */
+	struct urb *ctrlurb, *readurb, *writeurb;	/* urbs */
+	struct acm_line line;				/* line coding (bits, stop, parity) */
+	struct work_struct work;			/* work queue entry for line discipline waking up */
+	struct tasklet_struct bh;			/* rx processing */
+	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
+	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
+	unsigned int writesize;				/* max packet size for the output bulk endpoint */
+	unsigned int used;				/* someone has this acm's device open */
+	unsigned int minor;				/* acm minor number */
+	unsigned char throttle;				/* throttled by tty layer */
+	unsigned char clocal;				/* termios CLOCAL */
+	unsigned char ready_for_write;			/* write urb can be used */
+};
+
+/* "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));
+
+#define CDC_UNION_TYPE		0x06
+#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	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/class/usblp.c	2004-06-23 19:04:25 -07:00
@@ -75,6 +75,7 @@
 #define IOCNR_HP_SET_CHANNEL		4
 #define IOCNR_GET_BUS_ADDRESS		5
 #define IOCNR_GET_VID_PID		6
+#define IOCNR_SOFT_RESET		7
 /* Get device_id string: */
 #define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
 /* The following ioctls were added for http://hpoj.sourceforge.net: */
@@ -90,6 +91,8 @@
 #define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
 /* Get two-int array: [0]=vendor ID, [1]=product ID: */
 #define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
+/* Perform class specific soft reset */
+#define LPIOC_SOFT_RESET _IOC(_IOC_NONE, 'P', IOCNR_SOFT_RESET, 0);
 
 /*
  * A DEVICE_ID string may include the printer's serial number.
@@ -587,6 +590,13 @@
 					usblp->minor, twoints[0], twoints[1]);
 				break;
 
+			case IOCNR_SOFT_RESET:
+				if (_IOC_DIR(cmd) != _IOC_NONE) {
+					retval = -EINVAL;
+					goto done;
+				}
+				retval = usblp_reset(usblp);
+				break;
 			default:
 				retval = -ENOTTY;
 		}
@@ -761,6 +771,7 @@
 			usblp->minor, usblp->readurb->status);
 		usblp->readurb->dev = usblp->dev;
  		usblp->readcount = 0;
+		usblp->rcomplete = 0;
 		if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
 			dbg("error submitting urb");
 		count = -EIO;
diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
--- a/drivers/usb/core/devices.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/core/devices.c	2004-06-23 19:04:28 -07:00
@@ -589,6 +589,8 @@
 		bus = list_entry(buslist, struct usb_bus, bus_list);
 
 		/* recurse through all children of the root hub */
+		if (!bus->root_hub)
+			continue;
 		down(&bus->root_hub->serialize);
 		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
 		up(&bus->root_hub->serialize);
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/core/devio.c	2004-06-23 19:04:27 -07:00
@@ -290,8 +290,11 @@
 		spin_lock_irqsave(&ps->lock, flags);
 	}
 	spin_unlock_irqrestore(&ps->lock, flags);
-	while ((as = async_getcompleted(ps)))
+	as = async_getcompleted(ps);
+	while (as) {
 		free_async(as);
+		as = async_getcompleted(ps);
+	}
 }
 
 static void destroy_async_on_interface (struct dev_state *ps, unsigned int ifnum)
@@ -558,7 +561,7 @@
 			if (usbfs_snoop) {
 				dev_info(&dev->dev, "control read: data ");
 				for (j = 0; j < ctrl.wLength; ++j)
-					printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]);
+					printk ("%02x ", (unsigned char)(tbuf)[j]);
 				printk("\n");
 			}
 			if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) {
@@ -578,7 +581,7 @@
 		if (usbfs_snoop) {
 			dev_info(&dev->dev, "control write: data: ");
 			for (j = 0; j < ctrl.wLength; ++j)
-				printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]);
+				printk ("%02x ", (unsigned char)(tbuf)[j]);
 			printk("\n");
 		}
 		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
@@ -968,29 +971,27 @@
 static int processcompl(struct async *as)
 {
 	struct urb *urb = as->urb;
+	struct usbdevfs_urb __user *userurb = 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,
-		     &((struct usbdevfs_urb *)as->userurb)->status))
+	if (put_user(urb->status, &userurb->status))
 		return -EFAULT;
-	if (put_user(urb->actual_length,
-		     &((struct usbdevfs_urb *)as->userurb)->actual_length))
+	if (put_user(urb->actual_length, &userurb->actual_length))
 		return -EFAULT;
-	if (put_user(urb->error_count,
-		     &((struct usbdevfs_urb *)as->userurb)->error_count))
+	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,
-			     &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length))
+			     &userurb->iso_frame_desc[i].actual_length))
 			return -EFAULT;
 		if (put_user(urb->iso_frame_desc[i].status,
-			     &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status))
+			     &userurb->iso_frame_desc[i].status))
 			return -EFAULT;
 	}
 	return 0;
diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
--- a/drivers/usb/core/hcd-pci.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/core/hcd-pci.c	2004-06-23 19:04:27 -07:00
@@ -229,7 +229,6 @@
 void usb_hcd_pci_remove (struct pci_dev *dev)
 {
 	struct usb_hcd		*hcd;
-	struct usb_device	*hub;
 
 	hcd = pci_get_drvdata(dev);
 	if (!hcd)
@@ -239,12 +238,11 @@
 	if (in_interrupt ())
 		BUG ();
 
-	hub = hcd->self.root_hub;
 	if (HCD_IS_RUNNING (hcd->state))
 		hcd->state = USB_STATE_QUIESCING;
 
 	dev_dbg (hcd->self.controller, "roothub graceful disconnect\n");
-	usb_disconnect (&hub);
+	usb_disconnect (&hcd->self.root_hub);
 
 	hcd->driver->stop (hcd);
 	hcd_buffer_destroy (hcd);
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/core/hcd.c	2004-06-23 19:04:27 -07:00
@@ -764,8 +764,9 @@
  *
  * The USB host controller calls this function to register the root hub
  * properly with the USB subsystem.  It sets up the device properly in
- * the device model tree, and then calls usb_new_device() to register the
- * usb device.  It also assigns the root hub's USB address (always 1).
+ * the device tree and stores the root_hub pointer in the bus structure,
+ * then calls usb_new_device() to register the usb device.  It also
+ * assigns the root hub's USB address (always 1).
  */
 int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
 {
@@ -777,7 +778,10 @@
 	memset (&usb_dev->bus->devmap.devicemap, 0,
 			sizeof usb_dev->bus->devmap.devicemap);
 	set_bit (devnum, usb_dev->bus->devmap.devicemap);
-	usb_dev->state = USB_STATE_ADDRESS;
+	usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
+
+	down (&usb_bus_list_lock);
+	usb_dev->bus->root_hub = usb_dev;
 
 	usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64;
 	retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
@@ -787,14 +791,15 @@
 		return (retval < 0) ? retval : -EMSGSIZE;
 	}
 
-	(void) usb_get_dev (usb_dev);
 	down (&usb_dev->serialize);
 	retval = usb_new_device (usb_dev);
-	if (retval)
+	up (&usb_dev->serialize);
+	if (retval) {
+		usb_dev->bus->root_hub = NULL;
 		dev_err (parent_dev, "can't register root hub for %s, %d\n",
 				usb_dev->dev.bus_id, retval);
-	up (&usb_dev->serialize);
-	usb_put_dev (usb_dev);
+	}
+	up (&usb_bus_list_lock);
 	return retval;
 }
 EXPORT_SYMBOL (usb_register_root_hub);
@@ -1574,11 +1579,13 @@
 	unsigned		i;
 
 	/* hc's root hub is removed later removed in hcd->stop() */
-	hub->state = USB_STATE_NOTATTACHED;
+	down (&hub->serialize);
+	usb_set_device_state(hub, USB_STATE_NOTATTACHED);
 	for (i = 0; i < hub->maxchild; i++) {
 		if (hub->children [i])
 			usb_disconnect (&hub->children [i]);
 	}
+	up (&hub->serialize);
 }
 
 /**
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/core/hcd.h	2004-06-23 19:04:26 -07:00
@@ -244,17 +244,10 @@
 					struct usb_bus *, unsigned port);
 extern int usb_new_device(struct usb_device *dev);
 extern void usb_disconnect(struct usb_device **);
-extern void usb_choose_address(struct usb_device *dev);
-extern void usb_release_address(struct usb_device *dev);
 
-/* exported to hub driver ONLY to support usb_reset_device () */
 extern int usb_get_configuration(struct usb_device *dev);
 extern void usb_destroy_configuration(struct usb_device *dev);
 
-/* use these only before the device's address has been set */
-#define usb_snddefctrl(dev)		((PIPE_CONTROL << 30))
-#define usb_rcvdefctrl(dev)		((PIPE_CONTROL << 30) | USB_DIR_IN)
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -346,7 +339,8 @@
 extern int usb_register_root_hub (struct usb_device *usb_dev,
 		struct device *parent_dev);
 
-static inline int hcd_register_root (struct usb_hcd *hcd)
+static inline int hcd_register_root (struct usb_device *usb_dev,
+		struct usb_hcd *hcd)
 {
 	/* hcd->driver->start() reported can_wakeup, probably with
 	 * assistance from board's boot firmware.
@@ -356,8 +350,7 @@
 		dev_dbg (hcd->self.controller, "supports USB remote wakeup\n");
 	hcd->remote_wakeup = hcd->can_wakeup;
 
-	return usb_register_root_hub (
-		hcd_to_bus (hcd)->root_hub, hcd->self.controller);
+	return usb_register_root_hub (usb_dev, hcd->self.controller);
 }
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/core/hub.c	2004-06-23 19:04:26 -07:00
@@ -9,6 +9,11 @@
  */
 
 #include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -19,11 +24,6 @@
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/ioctl.h>
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
 #include <linux/suspend.h>
@@ -36,11 +36,13 @@
 #include "hcd.h"
 #include "hub.h"
 
+/* Protect all struct usb_device state members */
+static spinlock_t device_state_lock = SPIN_LOCK_UNLOCKED;
+
 /* Wakes up khubd */
 static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
 
 static LIST_HEAD(hub_event_list);	/* List of hubs needing servicing */
-static LIST_HEAD(hub_list);		/* List of all hubs (for cleanup) */
 
 static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
 static pid_t khubd_pid = 0;			/* PID of khubd */
@@ -229,6 +231,8 @@
 {
 	struct usb_hub *hub = (struct usb_hub *)urb->context;
 	int status;
+	int i;
+	unsigned long bits;
 
 	spin_lock(&hub_event_lock);
 	hub->urb_active = 0;
@@ -253,6 +257,11 @@
 	
 	/* let khubd handle things */
 	case 0:			/* we got data:  port status changed */
+		bits = 0;
+		for (i = 0; i < urb->actual_length; ++i)
+			bits |= ((unsigned long) ((*hub->buffer)[i]))
+					<< (i*8);
+		hub->event_bits[0] = bits;
 		break;
 	}
 
@@ -260,7 +269,7 @@
 
 	/* Something happened, let khubd figure it out */
 	if (list_empty(&hub->event_list)) {
-		list_add(&hub->event_list, &hub_event_list);
+		list_add_tail(&hub->event_list, &hub_event_list);
 		wake_up(&khubd_wait);
 	}
 
@@ -268,7 +277,7 @@
 	if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
 			/* ENODEV means we raced disconnect() */
 			&& status != -ENODEV)
-		dev_err (&hub->intf->dev, "resubmit --> %d\n", urb->status);
+		dev_err (&hub->intf->dev, "resubmit --> %d\n", status);
 	if (status == 0)
 		hub->urb_active = 1;
 done:
@@ -632,7 +641,6 @@
 {
 	struct usb_hub *hub = usb_get_intfdata (intf);
 	DECLARE_COMPLETION(urb_complete);
-	unsigned long flags;
 
 	if (!hub)
 		return;
@@ -641,17 +649,13 @@
 		highspeed_hubs--;
 
 	usb_set_intfdata (intf, NULL);
-	spin_lock_irqsave(&hub_event_lock, flags);
+	spin_lock_irq(&hub_event_lock);
 	hub->urb_complete = &urb_complete;
 
 	/* Delete it and then reset it */
 	list_del_init(&hub->event_list);
-	list_del_init(&hub->hub_list);
 
-	spin_unlock_irqrestore(&hub_event_lock, flags);
-
-	down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
-	up(&hub->khubd_sem);
+	spin_unlock_irq(&hub_event_lock);
 
 	/* assuming we used keventd, it must quiesce too */
 	if (hub->has_indicators)
@@ -695,7 +699,6 @@
 	struct usb_device *hdev;
 	struct usb_hub *hub;
 	struct device *hub_dev;
-	unsigned long flags;
 
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
@@ -711,23 +714,19 @@
 	}
 
 	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
-	if (desc->desc.bNumEndpoints != 1) {
+	if (desc->desc.bNumEndpoints != 1)
 		goto descriptor_error;
-	}
 
 	endpoint = &desc->endpoint[0].desc;
 
 	/* Output endpoint? Curiouser and curiouser.. */
-	if (!(endpoint->bEndpointAddress & USB_DIR_IN)) {
+	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
 		goto descriptor_error;
-	}
 
 	/* If it's not an interrupt endpoint, we'd better punt! */
 	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			!= USB_ENDPOINT_XFER_INT) {
+			!= USB_ENDPOINT_XFER_INT)
 		goto descriptor_error;
-		return -EIO;
-	}
 
 	/* We found a hub */
 	dev_info (hub_dev, "USB hub found\n");
@@ -742,15 +741,8 @@
 
 	INIT_LIST_HEAD(&hub->event_list);
 	hub->intf = intf;
-	init_MUTEX(&hub->khubd_sem);
 	INIT_WORK(&hub->leds, led_work, hub);
 
-	/* Record the new hub's existence */
-	spin_lock_irqsave(&hub_event_lock, flags);
-	INIT_LIST_HEAD(&hub->hub_list);
-	list_add(&hub->hub_list, &hub_list);
-	spin_unlock_irqrestore(&hub_event_lock, flags);
-
 	usb_set_intfdata (intf, hub);
 
 	if (hdev->speed == USB_SPEED_HIGH)
@@ -827,6 +819,7 @@
 	return 0;
 }
 
+/* FIXME!  This routine should be subsumed into hub_reset */
 static void hub_start_disconnect(struct usb_device *hdev)
 {
 	struct usb_device *parent = hdev->parent;
@@ -845,6 +838,289 @@
 	dev_err(&hdev->dev, "cannot disconnect hub!\n");
 }
 
+
+static void recursively_mark_NOTATTACHED(struct usb_device *udev)
+{
+	int i;
+
+	for (i = 0; i < udev->maxchild; ++i) {
+		if (udev->children[i])
+			recursively_mark_NOTATTACHED(udev->children[i]);
+	}
+	udev->state = USB_STATE_NOTATTACHED;
+}
+
+/**
+ * usb_set_device_state - change a device's current state (usbcore-internal)
+ * @udev: pointer to device whose state should be changed
+ * @new_state: new state value to be stored
+ *
+ * udev->state is _not_ protected by the udev->serialize semaphore.  This
+ * is so that devices can be marked as disconnected as soon as possible,
+ * without having to wait for the semaphore to be released.  Instead,
+ * changes to the state must be protected by the device_state_lock spinlock.
+ *
+ * Once a device has been added to the device tree, all changes to its state
+ * should be made using this routine.  The state should _not_ be set directly.
+ *
+ * If udev->state is already USB_STATE_NOTATTACHED then no change is made.
+ * Otherwise udev->state is set to new_state, and if new_state is
+ * USB_STATE_NOTATTACHED then all of udev's descendant's states are also set
+ * to USB_STATE_NOTATTACHED.
+ */
+void usb_set_device_state(struct usb_device *udev,
+		enum usb_device_state new_state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&device_state_lock, flags);
+	if (udev->state == USB_STATE_NOTATTACHED)
+		;	/* do nothing */
+	else if (new_state != USB_STATE_NOTATTACHED)
+		udev->state = new_state;
+	else
+		recursively_mark_NOTATTACHED(udev);
+	spin_unlock_irqrestore(&device_state_lock, flags);
+}
+
+
+static void choose_address(struct usb_device *udev)
+{
+	int		devnum;
+	struct usb_bus	*bus = udev->bus;
+
+	/* If khubd ever becomes multithreaded, this will need a lock */
+
+	/* Try to allocate the next devnum beginning at bus->devnum_next. */
+	devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
+			bus->devnum_next);
+	if (devnum >= 128)
+		devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);
+
+	bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
+
+	if (devnum < 128) {
+		set_bit(devnum, bus->devmap.devicemap);
+		udev->devnum = devnum;
+	}
+}
+
+static void release_address(struct usb_device *udev)
+{
+	if (udev->devnum > 0) {
+		clear_bit(udev->devnum, udev->bus->devmap.devicemap);
+		udev->devnum = -1;
+	}
+}
+
+/**
+ * usb_disconnect - disconnect a device (usbcore-internal)
+ * @pdev: pointer to device being disconnected
+ * Context: !in_interrupt ()
+ *
+ * Something got disconnected. Get rid of it, and all of its children.
+ * If *pdev is a normal device then the parent hub should be locked.
+ * If *pdev is a root hub then this routine will acquire the
+ * usb_bus_list_lock on behalf of the caller.
+ *
+ * Only hub drivers (including virtual root hub drivers for host
+ * controllers) should ever call this.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ */
+void usb_disconnect(struct usb_device **pdev)
+{
+	struct usb_device	*udev = *pdev;
+	int			i;
+
+	if (!udev) {
+		pr_debug ("%s nodev\n", __FUNCTION__);
+		return;
+	}
+
+	/* mark the device as inactive, so any further urb submissions for
+	 * this device will fail.
+	 */
+	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+
+	/* lock the bus list on behalf of HCDs unregistering their root hubs */
+	if (!udev->parent)
+		down(&usb_bus_list_lock);
+	down(&udev->serialize);
+
+	dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);
+
+	/* Free up all the children before we remove this device */
+	for (i = 0; i < USB_MAXCHILDREN; i++) {
+		if (udev->children[i])
+			usb_disconnect(&udev->children[i]);
+	}
+
+	/* deallocate hcd/hardware state ... nuking all pending urbs and
+	 * cleaning up all state associated with the current configuration
+	 */
+	usb_disable_device(udev, 0);
+
+	/* Free the device number, remove the /proc/bus/usb entry and
+	 * the sysfs attributes, and delete the parent's children[]
+	 * (or root_hub) pointer.
+	 */
+	dev_dbg (&udev->dev, "unregistering device\n");
+	release_address(udev);
+	usbfs_remove_device(udev);
+	usb_remove_sysfs_dev_files(udev);
+
+	/* Avoid races with recursively_mark_NOTATTACHED() */
+	spin_lock_irq(&device_state_lock);
+	*pdev = NULL;
+	spin_unlock_irq(&device_state_lock);
+
+	up(&udev->serialize);
+	if (!udev->parent)
+		up(&usb_bus_list_lock);
+
+	device_unregister(&udev->dev);
+}
+
+static int choose_configuration(struct usb_device *udev)
+{
+	int c, i;
+
+	/* NOTE: this should interact with hub power budgeting */
+
+	c = udev->config[0].desc.bConfigurationValue;
+	if (udev->descriptor.bNumConfigurations != 1) {
+		for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
+			struct usb_interface_descriptor	*desc;
+
+			/* heuristic:  Linux is more likely to have class
+			 * drivers, so avoid vendor-specific interfaces.
+			 */
+			desc = &udev->config[i].intf_cache[0]
+					->altsetting->desc;
+			if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
+				continue;
+			/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */
+			if (desc->bInterfaceClass == USB_CLASS_COMM
+					&& desc->bInterfaceSubClass == 2
+					&& desc->bInterfaceProtocol == 0xff)
+				continue;
+			c = udev->config[i].desc.bConfigurationValue;
+			break;
+		}
+		dev_info(&udev->dev,
+			"configuration #%d chosen from %d choices\n",
+			c, udev->descriptor.bNumConfigurations);
+	}
+	return c;
+}
+
+#ifdef DEBUG
+static void show_string(struct usb_device *udev, char *id, int index)
+{
+	char *buf;
+
+	if (!index)
+		return;
+	if (!(buf = kmalloc(256, GFP_KERNEL)))
+		return;
+	if (usb_string(udev, index, buf, 256) > 0)
+		dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, buf);
+	kfree(buf);
+}
+
+#else
+static inline void show_string(struct usb_device *udev, char *id, int index)
+{}
+#endif
+
+/*
+ * usb_new_device - perform initial device setup (usbcore-internal)
+ * @udev: newly addressed device (in ADDRESS state)
+ *
+ * This is called with devices which have been enumerated, but not yet
+ * configured.  The device descriptor is available, but not descriptors
+ * for any device configuration.  The caller must have locked udev and
+ * either the parent hub (if udev is a normal device) or else the
+ * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
+ * udev has already been installed, but udev is not yet visible through
+ * sysfs or other filesystem code.
+ *
+ * Returns 0 for success (device is configured and listed, with its
+ * interfaces, in sysfs); else a negative errno value.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Only the hub driver should ever call this; root hub registration
+ * uses it indirectly.
+ */
+int usb_new_device(struct usb_device *udev)
+{
+	int err;
+	int c;
+
+	err = usb_get_configuration(udev);
+	if (err < 0) {
+		dev_err(&udev->dev, "can't read configurations, error %d\n",
+			err);
+		goto fail;
+	}
+
+	/* 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);
+
+	/* put device-specific files into sysfs */
+	err = device_add (&udev->dev);
+	if (err) {
+		dev_err(&udev->dev, "can't device_add, error %d\n", err);
+		goto fail;
+	}
+	usb_create_sysfs_dev_files (udev);
+
+	/* choose and set the configuration. that registers the interfaces
+	 * with the driver core, and lets usb device drivers bind to them.
+	 */
+	c = choose_configuration(udev);
+	if (c < 0)
+		dev_warn(&udev->dev,
+				"can't choose an initial configuration\n");
+	else {
+		err = usb_set_configuration(udev, c);
+		if (err) {
+			dev_err(&udev->dev, "can't set config #%d, error %d\n",
+					c, err);
+			usb_remove_sysfs_dev_files(udev);
+			device_del(&udev->dev);
+			goto fail;
+		}
+	}
+
+	/* USB device state == configured ... usable */
+
+	/* add a /proc/bus/usb entry */
+	usbfs_add_device(udev);
+	return 0;
+
+fail:
+	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+	return err;
+}
+
+
 static int hub_port_status(struct usb_device *hdev, int port,
 			       u16 *status, u16 *change)
 {
@@ -934,16 +1210,20 @@
 
 	/* Reset the port */
 	for (i = 0; i < PORT_RESET_TRIES; i++) {
-		set_port_feature(hdev, port + 1, USB_PORT_FEAT_RESET);
+		status = set_port_feature(hdev, port + 1, USB_PORT_FEAT_RESET);
+		if (status)
+			dev_err(hub_dev, "cannot reset port %d (err = %d)\n",
+					port + 1, status);
+		else
+			status = hub_port_wait_reset(hdev, port, udev, delay);
 
 		/* return on disconnect or reset */
-		status = hub_port_wait_reset(hdev, port, udev, delay);
 		if (status == -ENOTCONN || status == 0) {
 			clear_port_feature(hdev,
 				port + 1, USB_PORT_FEAT_C_RESET);
-			udev->state = status
+			usb_set_device_state(udev, status
 					? USB_STATE_NOTATTACHED
-					: USB_STATE_DEFAULT;
+					: USB_STATE_DEFAULT);
 			return status;
 		}
 
@@ -964,6 +1244,9 @@
 {
 	int ret;
 
+	if (hdev->children[port])
+		usb_set_device_state(hdev->children[port],
+				USB_STATE_NOTATTACHED);
 	ret = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_ENABLE);
 	if (ret)
 		dev_err(hubdev(hdev), "cannot disable port %d (err = %d)\n",
@@ -975,57 +1258,62 @@
 /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
  *
  * Between connect detection and reset signaling there must be a delay
- * of 100ms at least for debounce and power-settling. The corresponding
+ * of 100ms at least for debounce and power-settling.  The corresponding
  * timer shall restart whenever the downstream port detects a disconnect.
  * 
- * Apparently there are some bluetooth and irda-dongles and a number
- * of low-speed devices which require longer delays of about 200-400ms.
+ * Apparently there are some bluetooth and irda-dongles and a number of
+ * low-speed devices for which this debounce period may last over a second.
  * Not covered by the spec - but easy to deal with.
  *
- * This implementation uses 400ms minimum debounce timeout and checks
- * every 25ms for transient disconnects to restart the delay.
+ * This implementation uses a 1500ms total debounce timeout; if the
+ * connection isn't stable by then it returns -ETIMEDOUT.  It checks
+ * every 25ms for transient disconnects.  When the port status has been
+ * unchanged for 100ms it returns the port status.
  */
 
-#define HUB_DEBOUNCE_TIMEOUT	400
-#define HUB_DEBOUNCE_STEP	 25
-#define HUB_DEBOUNCE_STABLE	  4
+#define HUB_DEBOUNCE_TIMEOUT	1500
+#define HUB_DEBOUNCE_STEP	  25
+#define HUB_DEBOUNCE_STABLE	 100
 
 static int hub_port_debounce(struct usb_device *hdev, int port)
 {
 	int ret;
-	int delay_time, stable_count;
+	int total_time, stable_time = 0;
 	u16 portchange, portstatus;
-	unsigned connection;
-
-	connection = 0;
-	stable_count = 0;
-	for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; delay_time += HUB_DEBOUNCE_STEP) {
-		msleep(HUB_DEBOUNCE_STEP);
+	unsigned connection = 0xffff;
 
+	for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
 		ret = hub_port_status(hdev, port, &portstatus, &portchange);
 		if (ret < 0)
 			return ret;
 
-		if ((portstatus & USB_PORT_STAT_CONNECTION) == connection) {
-			if (connection) {
-				if (++stable_count == HUB_DEBOUNCE_STABLE)
-					break;
-			}
+		if (!(portchange & USB_PORT_STAT_C_CONNECTION) &&
+		     (portstatus & USB_PORT_STAT_CONNECTION) == connection) {
+			stable_time += HUB_DEBOUNCE_STEP;
+			if (stable_time >= HUB_DEBOUNCE_STABLE)
+				break;
 		} else {
-			stable_count = 0;
+			stable_time = 0;
+			connection = portstatus & USB_PORT_STAT_CONNECTION;
 		}
-		connection = portstatus & USB_PORT_STAT_CONNECTION;
 
-		if ((portchange & USB_PORT_STAT_C_CONNECTION)) {
-			clear_port_feature(hdev, port+1, USB_PORT_FEAT_C_CONNECTION);
+		if (portchange & USB_PORT_STAT_C_CONNECTION) {
+			clear_port_feature(hdev, port+1,
+					USB_PORT_FEAT_C_CONNECTION);
 		}
+
+		if (total_time >= HUB_DEBOUNCE_TIMEOUT)
+			break;
+		msleep(HUB_DEBOUNCE_STEP);
 	}
 
 	dev_dbg (hubdev (hdev),
-		"debounce: port %d: delay %dms stable %d status 0x%x\n",
-		port + 1, delay_time, stable_count, portstatus);
+		"debounce: port %d: total %dms stable %dms status 0x%x\n",
+		port + 1, total_time, stable_time, portstatus);
 
-	return (portstatus & USB_PORT_STAT_CONNECTION) ? 0 : -ENOTCONN;
+	if (stable_time < HUB_DEBOUNCE_STABLE)
+		return -ETIMEDOUT;
+	return portstatus;
 }
 
 static int hub_set_address(struct usb_device *udev)
@@ -1037,11 +1325,11 @@
 	if (udev->state != USB_STATE_DEFAULT &&
 			udev->state != USB_STATE_ADDRESS)
 		return -EINVAL;
-	retval = usb_control_msg(udev, usb_snddefctrl(udev),
+	retval = usb_control_msg(udev, (PIPE_CONTROL << 30) /* Address 0 */,
 		USB_REQ_SET_ADDRESS, 0, udev->devnum, 0,
 		NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
 	if (retval == 0)
-		udev->state = USB_STATE_ADDRESS;
+		usb_set_device_state(udev, USB_STATE_ADDRESS);
 	return retval;
 }
 
@@ -1109,33 +1397,9 @@
 	udev->epmaxpacketin [0] = i;
 	udev->epmaxpacketout[0] = i;
  
-	/* set the address */
-	if (udev->devnum <= 0) {
-		usb_choose_address(udev);
-		if (udev->devnum <= 0)
-			goto fail;
-
-		/* Set up TT records, if needed  */
-		if (hdev->tt) {
-			udev->tt = hdev->tt;
-			udev->ttport = hdev->ttport;
-		} else if (udev->speed != USB_SPEED_HIGH
-				&& hdev->speed == USB_SPEED_HIGH) {
-			struct usb_hub	*hub;
- 
-			hub = usb_get_intfdata (hdev->actconfig
-							->interface[0]);
-			udev->tt = &hub->tt;
-			udev->ttport = port + 1;
-		}
-
-		/* force the right log message (below) at low speed */
-		oldspeed = USB_SPEED_UNKNOWN;
-	}
- 
 	dev_info (&udev->dev,
 			"%s %s speed USB device using address %d\n",
-			(oldspeed == USB_SPEED_UNKNOWN) ? "new" : "reset",
+			(udev->config) ? "reset" : "new",
 			({ char *speed; switch (udev->speed) {
 			case USB_SPEED_LOW:	speed = "low";	break;
 			case USB_SPEED_FULL:	speed = "full";	break;
@@ -1143,6 +1407,19 @@
 			default: 		speed = "?";	break;
 			}; speed;}),
 			udev->devnum);
+
+	/* Set up TT records, if needed  */
+	if (hdev->tt) {
+		udev->tt = hdev->tt;
+		udev->ttport = hdev->ttport;
+	} else if (udev->speed != USB_SPEED_HIGH
+			&& hdev->speed == USB_SPEED_HIGH) {
+		struct usb_hub *hub;
+
+		hub = usb_get_intfdata(hdev->actconfig->interface[0]);
+		udev->tt = &hub->tt;
+		udev->ttport = port + 1;
+	}
  
 	/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
 	 * Because device hardware and firmware is sometimes buggy in
@@ -1164,12 +1441,7 @@
 			dev_err(&udev->dev,
 				"device not accepting address %d, error %d\n",
 				udev->devnum, retval);
- fail:
-			hub_port_disable(hdev, port);
-			usb_release_address(udev);
-			usb_put_dev(udev);
-			up(&usb_address0_sem);
-			return retval;
+			goto fail;
 		}
  
 		/* cope with hardware quirkiness:
@@ -1192,7 +1464,8 @@
 	if (udev->speed == USB_SPEED_FULL
 			&& (udev->epmaxpacketin [0]
 				!= udev->descriptor.bMaxPacketSize0)) {
-		usb_disable_endpoint(udev, 0);
+		usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+		usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
 		usb_endpoint_running(udev, 0, 1);
 		usb_endpoint_running(udev, 0, 0);
 		udev->epmaxpacketin [0] = udev->descriptor.bMaxPacketSize0;
@@ -1208,11 +1481,11 @@
 		goto fail;
 	}
 
-	/* now dev is visible to other tasks */
-	hdev->children[port] = udev;
+	retval = 0;
 
+fail:
 	up(&usb_address0_sem);
-	return 0;
+	return retval;
 }
 
 static void
@@ -1271,7 +1544,14 @@
 	}
 	return remaining;
 }
- 
+
+/* Handle physical or logical connection change events.
+ * This routine is called when:
+ * 	a port connection-change occurs;
+ *	a port enable-change occurs (often caused by EMI);
+ *	usb_reset_device() encounters changed descriptors (as from
+ *		a firmware download)
+ */
 static void hub_port_connect_change(struct usb_hub *hub, int port,
 					u16 portstatus, u16 portchange)
 {
@@ -1282,9 +1562,6 @@
 	dev_dbg (hub_dev,
 		"port %d, status %04x, change %04x, %s\n",
 		port + 1, portstatus, portchange, portspeed (portstatus));
- 
-	/* Clear the connection change status */
-	clear_port_feature(hdev, port + 1, USB_PORT_FEAT_C_CONNECTION);
 
 	if (hub->has_indicators) {
 		set_port_led(hdev, port + 1, HUB_LED_AUTO);
@@ -1295,6 +1572,17 @@
 	if (hdev->children[port])
 		usb_disconnect(&hdev->children[port]);
 
+	if (portchange & USB_PORT_STAT_C_CONNECTION) {
+		status = hub_port_debounce(hdev, port);
+		if (status < 0) {
+			dev_err (hub_dev,
+				"connect-debounce failed, port %d disabled\n",
+				port+1);
+			goto done;
+		}
+		portstatus = status;
+	}
+
 	/* Return now if nothing is connected */
 	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
 
@@ -1308,13 +1596,6 @@
   			goto done;
 		return;
 	}
-  
-	if (hub_port_debounce(hdev, port)) {
-		dev_err (hub_dev,
-			"connect-debounce failed, port %d disabled\n",
-			port+1);
-		goto done;
-	}
 
 	for (i = 0; i < SET_CONFIG_TRIES; i++) {
 		struct usb_device *udev;
@@ -1328,21 +1609,26 @@
 				"couldn't allocate port %d usb_device\n", port+1);
 			goto done;
 		}
-		udev->state = USB_STATE_POWERED;
-	  
+
+		usb_set_device_state(udev, USB_STATE_POWERED);
+
 		/* hub can tell if it's lowspeed already:  D- pullup (not D+) */
 		if (portstatus & USB_PORT_STAT_LOW_SPEED)
 			udev->speed = USB_SPEED_LOW;
 		else
 			udev->speed = USB_SPEED_UNKNOWN;
+ 
+		/* set the address */
+		choose_address(udev);
+		if (udev->devnum <= 0) {
+			status = -ENOTCONN;	/* Don't retry */
+			goto loop;
+		}
 
-		/* reset, set address, get descriptor, add to hub's children */
-		down (&udev->serialize);
+		/* reset and get descriptor */
 		status = hub_port_init(hdev, udev, port);
-		if (status == -ENOTCONN)
-			break;
 		if (status < 0)
-			continue;
+			goto loop;
 
 		/* consecutive bus-powered hubs aren't reliable; they can
 		 * violate the voltage drop budget.  if the new child has
@@ -1358,7 +1644,7 @@
 					&devstat);
 			if (status < 0) {
 				dev_dbg(&udev->dev, "get status %d ?\n", status);
-				continue;
+				goto loop;
 			}
 			cpu_to_le16s(&devstat);
 			if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
@@ -1370,10 +1656,8 @@
 						INDICATOR_AMBER_BLINK;
 					schedule_work (&hub->leds);
 				}
-				hdev->children[port] = NULL;
-				usb_put_dev(udev);
-				hub_port_disable(hdev, port);
-				return;
+				status = -ENOTCONN;	/* Don't retry */
+				goto loop;
 			}
 		}
  
@@ -1383,13 +1667,37 @@
 				&& highspeed_hubs != 0)
 			check_highspeed (hub, udev, port);
 
+		/* Store the parent's children[] pointer.  At this point
+		 * udev becomes globally accessible, although presumably
+		 * no one will look at it until hdev is unlocked.
+		 */
+		down (&udev->serialize);
+		status = 0;
+
+		/* We mustn't add new devices if the parent hub has
+		 * been disconnected; we would race with the
+		 * recursively_mark_NOTATTACHED() routine.
+		 */
+		spin_lock_irq(&device_state_lock);
+		if (hdev->state == USB_STATE_NOTATTACHED)
+			status = -ENOTCONN;
+		else
+			hdev->children[port] = udev;
+		spin_unlock_irq(&device_state_lock);
+
 		/* Run it through the hoops (find a driver, etc) */
-		status = usb_new_device(udev);
-		if (status != 0) {
-			hdev->children[port] = NULL;
-			continue;
+		if (!status) {
+			status = usb_new_device(udev);
+			if (status) {
+				spin_lock_irq(&device_state_lock);
+				hdev->children[port] = NULL;
+				spin_unlock_irq(&device_state_lock);
+			}
 		}
+
 		up (&udev->serialize);
+		if (status)
+			goto loop;
 
 		status = hub_power_remaining(hub, hdev);
 		if (status)
@@ -1398,6 +1706,15 @@
 				2 * status);
 
 		return;
+
+loop:
+		hub_port_disable(hdev, port);
+		usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+		usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
+		release_address(udev);
+		usb_put_dev(udev);
+		if (status == -ENOTCONN)
+			break;
 	}
  
 done:
@@ -1406,7 +1723,6 @@
 
 static void hub_events(void)
 {
-	unsigned long flags;
 	struct list_head *tmp;
 	struct usb_device *hdev;
 	struct usb_hub *hub;
@@ -1416,6 +1732,7 @@
 	u16 portstatus;
 	u16 portchange;
 	int i, ret;
+	int connect_change;
 
 	/*
 	 *  We restart the list every time to avoid a deadlock with
@@ -1424,24 +1741,32 @@
 	 * Not the most efficient, but avoids deadlocks.
 	 */
 	while (1) {
-		spin_lock_irqsave(&hub_event_lock, flags);
 
-		if (list_empty(&hub_event_list))
+		/* Grab the first entry at the beginning of the list */
+		spin_lock_irq(&hub_event_lock);
+		if (list_empty(&hub_event_list)) {
+			spin_unlock_irq(&hub_event_lock);
 			break;
+		}
 
-		/* Grab the next entry from the beginning of the list */
 		tmp = hub_event_list.next;
+		list_del_init(tmp);
 
 		hub = list_entry(tmp, struct usb_hub, event_list);
 		hdev = interface_to_usbdev(hub->intf);
 		hub_dev = &hub->intf->dev;
 
-		list_del_init(tmp);
-
-		if (unlikely(down_trylock(&hub->khubd_sem)))
-			BUG();	/* never blocks, we were on list */
+		usb_get_dev(hdev);
+		spin_unlock_irq(&hub_event_lock);
 
-		spin_unlock_irqrestore(&hub_event_lock, flags);
+		/* Lock the device, then check to see if we were
+		 * disconnected while waiting for the lock to succeed. */
+		down(&hdev->serialize);
+		if (hdev->state != USB_STATE_CONFIGURED ||
+				!hdev->actconfig ||
+				hub != usb_get_intfdata(
+					hdev->actconfig->interface[0]))
+			goto loop;
 
 		if (hub->error) {
 			dev_dbg (hub_dev, "resetting for error %d\n",
@@ -1450,27 +1775,35 @@
 			if (hub_reset(hub)) {
 				dev_dbg (hub_dev,
 					"can't reset; disconnecting\n");
-				up(&hub->khubd_sem);
 				hub_start_disconnect(hdev);
-				continue;
+				goto loop;
 			}
 
 			hub->nerrors = 0;
 			hub->error = 0;
 		}
 
+		/* deal with port status changes */
 		for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
+			if (!test_and_clear_bit(i+1, hub->event_bits))
+				continue;
 			ret = hub_port_status(hdev, i, &portstatus, &portchange);
-			if (ret < 0) {
+			if (ret < 0)
 				continue;
-			}
+			connect_change = 0;
 
 			if (portchange & USB_PORT_STAT_C_CONNECTION) {
-				hub_port_connect_change(hub, i, portstatus, portchange);
-			} else if (portchange & USB_PORT_STAT_C_ENABLE) {
-				dev_dbg (hub_dev,
-					"port %d enable change, status %08x\n",
-					i + 1, portstatus);
+				clear_port_feature(hdev,
+					i + 1, USB_PORT_FEAT_C_CONNECTION);
+				connect_change = 1;
+			}
+
+			if (portchange & USB_PORT_STAT_C_ENABLE) {
+				if (!connect_change)
+					dev_dbg (hub_dev,
+						"port %d enable change, "
+						"status %08x\n",
+						i + 1, portstatus);
 				clear_port_feature(hdev,
 					i + 1, USB_PORT_FEAT_C_ENABLE);
 
@@ -1481,15 +1814,14 @@
 				 * Works at least with mouse driver. 
 				 */
 				if (!(portstatus & USB_PORT_STAT_ENABLE)
-				    && (portstatus & USB_PORT_STAT_CONNECTION)
-				    && (hdev->children[i])) {
+				    && !connect_change
+				    && hdev->children[i]) {
 					dev_err (hub_dev,
 					    "port %i "
 					    "disabled by hub (EMI?), "
 					    "re-enabling...",
 						i + 1);
-					hub_port_connect_change(hub,
-						i, portstatus, portchange);
+					connect_change = 1;
 				}
 			}
 
@@ -1517,10 +1849,16 @@
 				clear_port_feature(hdev,
 					i + 1, USB_PORT_FEAT_C_RESET);
 			}
+
+			if (connect_change)
+				hub_port_connect_change(hub, i,
+						portstatus, portchange);
 		} /* end for i */
 
 		/* deal with hub status changes */
-		if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)
+		if (test_and_clear_bit(0, hub->event_bits) == 0)
+			;	/* do nothing */
+		else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)
 			dev_err (hub_dev, "get_hub_status failed\n");
 		else {
 			if (hubchange & HUB_CHANGE_LOCAL_POWER) {
@@ -1534,10 +1872,12 @@
                         	hub_power_on(hub);
 			}
 		}
-		up(&hub->khubd_sem);
-        } /* end while (1) */
 
-	spin_unlock_irqrestore(&hub_event_lock, flags);
+loop:
+		up(&hdev->serialize);
+		usb_put_dev(hdev);
+
+        } /* end while (1) */
 }
 
 static int hub_thread(void *__unused)
@@ -1581,9 +1921,6 @@
 	.id_table =	hub_id_table,
 };
 
-/*
- * This should be a separate module.
- */
 int usb_hub_init(void)
 {
 	pid_t pid;
@@ -1726,7 +2063,7 @@
 			udev->actconfig->desc.bConfigurationValue, ret);
 		goto re_enumerate;
   	}
-	udev->state = USB_STATE_CONFIGURED;
+	usb_set_device_state(udev, USB_STATE_CONFIGURED);
 
 	for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 		struct usb_interface *intf = udev->actconfig->interface[i];
@@ -1752,7 +2089,7 @@
  
 re_enumerate:
 	/* FIXME make some task re-enumerate; don't just mark unusable */
-	udev->state = USB_STATE_NOTATTACHED;
+	hub_port_disable(parent, port);
 	return -ENODEV;
 }
 EXPORT_SYMBOL(__usb_reset_device);
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- a/drivers/usb/core/hub.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/core/hub.h	2004-06-23 19:04:25 -07:00
@@ -202,11 +202,13 @@
 	int			error;		/* last reported error */
 	int			nerrors;	/* track consecutive errors */
 
-	struct list_head	hub_list;	/* all hubs */
 	struct list_head	event_list;	/* hubs w/data or errs ready */
+	unsigned long		event_bits[1];	/* status change bitmask */
+#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
+#error event_bits[] is too short!
+#endif
 
 	struct usb_hub_descriptor *descriptor;	/* class descriptor */
-	struct semaphore	khubd_sem;
 	struct usb_tt		tt;		/* Transaction Translator */
 
 	u8			power_budget;	/* in 2mA units; or zero */
@@ -215,5 +217,16 @@
 	enum hub_led_mode	indicator[USB_MAXCHILDREN];
 	struct work_struct	leds;
 };
+
+/* use this for low-powered root hubs */
+static inline void
+hub_set_power_budget (struct usb_device *hubdev, unsigned mA)
+{
+	struct usb_hub	*hub;
+
+	hub = (struct usb_hub *)
+		usb_get_intfdata (hubdev->actconfig->interface[0]);
+	hub->power_budget = min(mA,(unsigned)500)/2;
+}
 
 #endif /* __LINUX_HUB_H */
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/core/message.c	2004-06-23 19:04:26 -07:00
@@ -566,22 +566,19 @@
  */
 int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
 {
-	int i = 5;
+	int i;
 	int result;
 	
 	memset(buf,0,size);	// Make sure we parse really received data
 
-	while (i--) {
+	for (i = 0; i < 3; ++i) {
 		/* retry on length 0 or stall; some devices are flakey */
-		if ((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)) > 0
-				|| result != -EPIPE)
+		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);
+		if (!(result == 0 || result == -EPIPE))
 			break;
-
-		dev_dbg (&dev->dev, "RETRY descriptor, result %d\n", result);
-		result = -ENOMSG;
 	}
 	return result;
 }
@@ -830,6 +827,7 @@
 			interface = dev->actconfig->interface[i];
 			dev_dbg (&dev->dev, "unregistering interface %s\n",
 				interface->dev.bus_id);
+			usb_remove_sysfs_intf_files(interface);
 			device_del (&interface->dev);
 		}
 
@@ -842,7 +840,7 @@
 		}
 		dev->actconfig = 0;
 		if (dev->state == USB_STATE_CONFIGURED)
-			dev->state = USB_STATE_ADDRESS;
+			usb_set_device_state(dev, USB_STATE_ADDRESS);
 	}
 }
 
@@ -1047,7 +1045,7 @@
 			config->desc.bConfigurationValue, 0,
 			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
 	if (retval < 0) {
-		dev->state = USB_STATE_ADDRESS;
+		usb_set_device_state(dev, USB_STATE_ADDRESS);
 		return retval;
 	}
 
@@ -1185,9 +1183,9 @@
 
 	dev->actconfig = cp;
 	if (!cp)
-		dev->state = USB_STATE_ADDRESS;
+		usb_set_device_state(dev, USB_STATE_ADDRESS);
 	else {
-		dev->state = USB_STATE_CONFIGURED;
+		usb_set_device_state(dev, USB_STATE_CONFIGURED);
 
 		/* Initialize the new interface structures and the
 		 * hc/hcd/usbcore interface/endpoint state.
@@ -1322,7 +1320,7 @@
 	 */
 
 	err = usb_get_string(dev, dev->string_langid, index, tbuf, 2);
-	if (err == -EPIPE) {
+	if (err == -EPIPE || err == 0) {
 		dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, 2);
 		err = usb_get_string(dev, dev->string_langid, index, tbuf, 2);
 	}
@@ -1331,7 +1329,7 @@
 	len=tbuf[0];	
 	
 	err = usb_get_string(dev, dev->string_langid, index, tbuf, len);
-	if (err == -EPIPE) {
+	if (err == -EPIPE || err == 0) {
 		dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, len);
 		err = usb_get_string(dev, dev->string_langid, index, tbuf, len);
 	}
diff -Nru a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
--- a/drivers/usb/core/sysfs.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/core/sysfs.c	2004-06-23 19:04:26 -07:00
@@ -2,8 +2,8 @@
  * drivers/usb/core/sysfs.c
  *
  * (C) Copyright 2002 David Brownell
- * (C) Copyright 2002 Greg Kroah-Hartman
- * (C) Copyright 2002 IBM Corp.
+ * (C) Copyright 2002,2004 Greg Kroah-Hartman
+ * (C) Copyright 2002,2004 IBM Corp.
  *
  * All of the sysfs file attributes for usb devices and interfaces.
  *
@@ -162,29 +162,35 @@
 usb_descriptor_attr (bDeviceProtocol, "%02x\n")
 usb_descriptor_attr (bNumConfigurations, "%d\n")
 
+static struct attribute *dev_attrs[] = {
+	/* current configuration's attributes */
+	&dev_attr_bNumInterfaces.attr,
+	&dev_attr_bConfigurationValue.attr,
+	&dev_attr_bmAttributes.attr,
+	&dev_attr_bMaxPower.attr,
+	/* device attributes */
+	&dev_attr_idVendor.attr,
+	&dev_attr_idProduct.attr,
+	&dev_attr_bcdDevice.attr,
+	&dev_attr_bDeviceClass.attr,
+	&dev_attr_bDeviceSubClass.attr,
+	&dev_attr_bDeviceProtocol.attr,
+	&dev_attr_bNumConfigurations.attr,
+	&dev_attr_speed.attr,
+	&dev_attr_devnum.attr,
+	&dev_attr_version.attr,
+	&dev_attr_maxchild.attr,
+	NULL,
+};
+static struct attribute_group dev_attr_grp = {
+	.attrs = dev_attrs,
+};
 
 void usb_create_sysfs_dev_files (struct usb_device *udev)
 {
 	struct device *dev = &udev->dev;
 
-	/* current configuration's attributes */
-	device_create_file (dev, &dev_attr_bNumInterfaces);
-	device_create_file (dev, &dev_attr_bConfigurationValue);
-	device_create_file (dev, &dev_attr_bmAttributes);
-	device_create_file (dev, &dev_attr_bMaxPower);
-
-	/* device attributes */
-	device_create_file (dev, &dev_attr_idVendor);
-	device_create_file (dev, &dev_attr_idProduct);
-	device_create_file (dev, &dev_attr_bcdDevice);
-	device_create_file (dev, &dev_attr_bDeviceClass);
-	device_create_file (dev, &dev_attr_bDeviceSubClass);
-	device_create_file (dev, &dev_attr_bDeviceProtocol);
-	device_create_file (dev, &dev_attr_bNumConfigurations);
-
-	/* speed varies depending on how you connect the device */
-	device_create_file (dev, &dev_attr_speed);
-	// FIXME iff there are other speed configs, show how many
+	sysfs_create_group(&dev->kobj, &dev_attr_grp);
 
 	if (udev->descriptor.iManufacturer)
 		device_create_file (dev, &dev_attr_manufacturer);
@@ -192,10 +198,20 @@
 		device_create_file (dev, &dev_attr_product);
 	if (udev->descriptor.iSerialNumber)
 		device_create_file (dev, &dev_attr_serial);
+}
+
+void usb_remove_sysfs_dev_files (struct usb_device *udev)
+{
+	struct device *dev = &udev->dev;
 
-	device_create_file (dev, &dev_attr_devnum);
-	device_create_file (dev, &dev_attr_version);
-	device_create_file (dev, &dev_attr_maxchild);
+	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
+
+	if (udev->descriptor.iManufacturer)
+		device_remove_file(dev, &dev_attr_manufacturer);
+	if (udev->descriptor.iProduct)
+		device_remove_file(dev, &dev_attr_product);
+	if (udev->descriptor.iSerialNumber)
+		device_remove_file(dev, &dev_attr_serial);
 }
 
 /* Interface fields */
@@ -217,13 +233,26 @@
 usb_intf_attr (bInterfaceProtocol, "%02x\n")
 usb_intf_attr (iInterface, "%02x\n")
 
+static struct attribute *intf_attrs[] = {
+	&dev_attr_bInterfaceNumber.attr,
+	&dev_attr_bAlternateSetting.attr,
+	&dev_attr_bNumEndpoints.attr,
+	&dev_attr_bInterfaceClass.attr,
+	&dev_attr_bInterfaceSubClass.attr,
+	&dev_attr_bInterfaceProtocol.attr,
+	&dev_attr_iInterface.attr,
+	NULL,
+};
+static struct attribute_group intf_attr_grp = {
+	.attrs = intf_attrs,
+};
+
 void usb_create_sysfs_intf_files (struct usb_interface *intf)
 {
-	device_create_file (&intf->dev, &dev_attr_bInterfaceNumber);
-	device_create_file (&intf->dev, &dev_attr_bAlternateSetting);
-	device_create_file (&intf->dev, &dev_attr_bNumEndpoints);
-	device_create_file (&intf->dev, &dev_attr_bInterfaceClass);
-	device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass);
-	device_create_file (&intf->dev, &dev_attr_bInterfaceProtocol);
-	device_create_file (&intf->dev, &dev_attr_iInterface);
+	sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+}
+
+void usb_remove_sysfs_intf_files (struct usb_interface *intf)
+{
+	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
 }
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/core/usb.c	2004-06-23 19:04:27 -07:00
@@ -883,6 +883,8 @@
 	     buslist != &usb_bus_list; 
 	     buslist = buslist->next) {
 		bus = container_of(buslist, struct usb_bus, bus_list);
+		if (!bus->root_hub)
+			continue;
 		dev = match_device(bus->root_hub, vendor_id, product_id);
 		if (dev)
 			goto exit;
@@ -942,235 +944,6 @@
 		size -= header->bLength;
 	}
 	return -1;
-}
-
-/**
- * usb_disconnect - disconnect a device (usbcore-internal)
- * @pdev: pointer to device being disconnected
- * Context: !in_interrupt ()
- *
- * Something got disconnected. Get rid of it, and all of its children.
- *
- * Only hub drivers (including virtual root hub drivers for host
- * controllers) should ever call this.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- */
-void usb_disconnect(struct usb_device **pdev)
-{
-	struct usb_device	*dev = *pdev;
-	struct usb_bus		*bus;
-	struct usb_operations	*ops;
-	int			i;
-
-	might_sleep ();
-
-	if (!dev) {
-		pr_debug ("%s nodev\n", __FUNCTION__);
-		return;
-	}
-	bus = dev->bus;
-	if (!bus) {
-		pr_debug ("%s nobus\n", __FUNCTION__);
-		return;
-	}
-	ops = bus->op;
-
-	*pdev = NULL;
-
-	/* mark the device as inactive, so any further urb submissions for
-	 * this device will fail.
-	 */
-	dev->state = USB_STATE_NOTATTACHED;
-	down(&dev->serialize);
-
-	dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum);
-
-	/* Free up all the children before we remove this device */
-	for (i = 0; i < USB_MAXCHILDREN; i++) {
-		struct usb_device **child = dev->children + i;
-		if (*child)
-			usb_disconnect(child);
-	}
-
-	/* deallocate hcd/hardware state ... nuking all pending urbs and
-	 * cleaning up all state associated with the current configuration
-	 */
-	usb_disable_device(dev, 0);
-
-	/* Free the device number and remove the /proc/bus/usb entry */
-	dev_dbg (&dev->dev, "unregistering device\n");
-	usb_release_address(dev);
-	usbfs_remove_device(dev);
-	up(&dev->serialize);
-	device_unregister(&dev->dev);
-}
-
-/**
- * usb_choose_address - pick device address (usbcore-internal)
- * @dev: newly detected device (in DEFAULT state)
- *
- * Picks a device address.  It's up to the hub (or root hub) driver
- * to handle and manage enumeration, starting from the DEFAULT state.
- * Only hub drivers (but not virtual root hub drivers for host
- * controllers) should ever call this.
- */
-void usb_choose_address(struct usb_device *dev)
-{
-	int devnum;
-	// FIXME needs locking for SMP!!
-	/* why? this is called only from the hub thread, 
-	 * which hopefully doesn't run on multiple CPU's simultaneously 8-)
-	 */
-
-	/* Try to allocate the next devnum beginning at bus->devnum_next. */
-	devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next);
-	if (devnum >= 128)
-		devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);
-
-	dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
-
-	if (devnum < 128) {
-		set_bit(devnum, dev->bus->devmap.devicemap);
-		dev->devnum = devnum;
-	}
-}
-
-/**
- * usb_release_address - deallocate device address (usbcore-internal)
- * @dev: newly removed device
- *
- * Removes and deallocates the address assigned to a device.
- * Only hub drivers (but not virtual root hub drivers for host
- * controllers) should ever call this.
- */
-void usb_release_address(struct usb_device *dev)
-{
-	if (dev->devnum > 0) {
-		clear_bit(dev->devnum, dev->bus->devmap.devicemap);
-		dev->devnum = -1;
-	}
-}
-
-
-static inline void usb_show_string(struct usb_device *dev, char *id, int index)
-{
-	char *buf;
-
-	if (!index)
-		return;
-	if (!(buf = kmalloc(256, GFP_KERNEL)))
-		return;
-	if (usb_string(dev, index, buf, 256) > 0)
-		dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf);
-	kfree(buf);
-}
-
-static int usb_choose_configuration(struct usb_device *dev)
-{
-	int c, i;
-
-	c = dev->config[0].desc.bConfigurationValue;
-	if (dev->descriptor.bNumConfigurations != 1) {
-		for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
-			struct usb_interface_descriptor	*desc;
-
-			/* heuristic:  Linux is more likely to have class
-			 * drivers, so avoid vendor-specific interfaces.
-			 */
-			desc = &dev->config[i].intf_cache[0]
-					->altsetting->desc;
-			if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
-				continue;
-			/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */
-			if (desc->bInterfaceClass == USB_CLASS_COMM
-					&& desc->bInterfaceSubClass == 2
-					&& desc->bInterfaceProtocol == 0xff)
-				continue;
-			c = dev->config[i].desc.bConfigurationValue;
-			break;
-		}
-		dev_info(&dev->dev,
-			"configuration #%d chosen from %d choices\n",
-			c, dev->descriptor.bNumConfigurations);
-	}
-	return c;
-}
-
-/*
- * usb_new_device - perform initial device setup (usbcore-internal)
- * @dev: newly addressed device (in ADDRESS state)
- *
- * This is called with devices which have been enumerated, but not yet
- * configured.  The device descriptor is available, but not descriptors
- * for any device configuration.  The caller owns dev->serialize, and
- * the device is not visible through sysfs or other filesystem code.
- *
- * Returns 0 for success (device is configured and listed, with its
- * interfaces, in sysfs); else a negative errno value.  On error, one
- * reference count to the device has been dropped.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Only the hub driver should ever call this; root hub registration
- * uses it only indirectly.
- */
-int usb_new_device(struct usb_device *dev)
-{
-	int err;
-	int c;
-
-	err = usb_get_configuration(dev);
-	if (err < 0) {
-		dev_err(&dev->dev, "can't read configurations, error %d\n",
-			err);
-		goto fail;
-	}
-
-	/* Tell the world! */
-	dev_dbg(&dev->dev, "new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
-		dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
-
-#ifdef DEBUG
-	if (dev->descriptor.iProduct)
-		usb_show_string(dev, "Product", dev->descriptor.iProduct);
-	if (dev->descriptor.iManufacturer)
-		usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
-	if (dev->descriptor.iSerialNumber)
-		usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
-#endif
-
-	/* put device-specific files into sysfs */
-	err = device_add (&dev->dev);
-	if (err) {
-		dev_err(&dev->dev, "can't device_add, error %d\n", err);
-		goto fail;
-	}
-	usb_create_sysfs_dev_files (dev);
-
-	/* choose and set the configuration. that registers the interfaces
-	 * with the driver core, and lets usb device drivers bind to them.
-	 * NOTE:  should interact with hub power budgeting.
-	 */
-	c = usb_choose_configuration(dev);
-	err = usb_set_configuration(dev, c);
-	if (err) {
-		dev_err(&dev->dev, "can't set config #%d, error %d\n", c, err);
-		device_del(&dev->dev);
-		goto fail;
-	}
-
-	/* USB device state == configured ... usable */
-
-	/* add a /proc/bus/usb entry */
-	usbfs_add_device(dev);
-
-	return 0;
-fail:
-	dev->state = USB_STATE_NOTATTACHED;
-	usb_release_address(dev);
-	usb_put_dev(dev);
-	return err;
 }
 
 /**
diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
--- a/drivers/usb/core/usb.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/core/usb.h	2004-06-23 19:04:25 -07:00
@@ -1,7 +1,9 @@
 /* Functions local to drivers/usb/core/ */
 
 extern void usb_create_sysfs_dev_files (struct usb_device *dev);
+extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
 extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
+extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
 extern int usb_probe_interface (struct device *dev);
 extern int usb_unbind_interface (struct device *dev);
 
@@ -18,6 +20,9 @@
 extern int usb_get_device_descriptor(struct usb_device *dev,
 		unsigned int size);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
+
+extern void usb_set_device_state(struct usb_device *udev,
+		enum usb_device_state new_state);
 
 /* for labeling diagnostics */
 extern const char *usbcore_name;
diff -Nru a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
--- a/drivers/usb/gadget/dummy_hcd.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/gadget/dummy_hcd.c	2004-06-23 19:04:25 -07:00
@@ -825,8 +825,7 @@
 	dum = container_of (hcd, struct dummy, hcd);
 	spin_lock_irqsave (&dum->lock, flags);
 
-	if (!dum->hdev)
-		dum->hdev = urb->dev->hcpriv;
+	dum->hdev = urb->dev->hcpriv;
 	urb->hcpriv = dum;
 	if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
 		urb->error_count = 1;		/* mark as a new urb */
@@ -994,10 +993,17 @@
 	return limit;
 }
 
+#define is_active(dum)	((dum->port_status & \
+		(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | \
+			USB_PORT_STAT_SUSPEND)) \
+		== (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
+
 static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
 {
 	int		i;
 
+	if (!is_active (dum))
+		return NULL;
 	if ((address & ~USB_DIR_IN) == 0)
 		return &dum->ep [0];
 	for (i = 1; i < DUMMY_ENDPOINTS; i++) {
@@ -1011,6 +1017,8 @@
 	return NULL;
 }
 
+#undef is_active
+
 #define Dev_Request	(USB_TYPE_STANDARD | USB_RECIP_DEVICE)
 #define Dev_InRequest	(Dev_Request | USB_DIR_IN)
 #define Intf_Request	(USB_TYPE_STANDARD | USB_RECIP_INTERFACE)
@@ -1152,11 +1160,6 @@
 			case USB_REQ_SET_ADDRESS:
 				if (setup.bRequestType != Dev_Request)
 					break;
-				if (dum->address != 0) {
-					maybe_set_status (urb, -ETIMEDOUT);
-					urb->actual_length = 0;
-					goto return_urb;
-				}
 				dum->address = setup.wValue;
 				maybe_set_status (urb, 0);
 				dev_dbg (hardware, "set_address = %d\n",
@@ -1404,9 +1407,8 @@
 			break;
 		case USB_PORT_FEAT_POWER:
 			dum->port_status = 0;
-			dum->address = 0;
-			dum->hdev = 0;
 			dum->resuming = 0;
+			stop_activity(dum, dum->driver);
 			break;
 		default:
 			dum->port_status &= ~(1 << wValue);
@@ -1657,7 +1659,7 @@
 	INIT_LIST_HEAD (&hcd->dev_list);
 	usb_register_bus (bus);
 
-	bus->root_hub = root = usb_alloc_dev (0, bus, 0);
+	root = usb_alloc_dev (0, bus, 0);
 	if (!root) {
 		retval = -ENOMEM;
 clean1:
@@ -1671,13 +1673,15 @@
 	root->speed = USB_SPEED_HIGH;
 
 	/* ...then configured, so khubd sees us. */
-	if ((retval = hcd_register_root (&dum->hcd)) != 0) {
-		bus->root_hub = 0;
+	if ((retval = hcd_register_root (root, &dum->hcd)) != 0) {
 		usb_put_dev (root);
 clean2:
 		dum->hcd.state = USB_STATE_QUIESCING;
 		goto clean1;
 	}
+
+	/* only show a low-power port: just 8mA */
+	hub_set_power_budget (root, 8);
 
 	dum->started = 1;
 
diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/gadget/ether.c	2004-06-23 19:04:28 -07:00
@@ -118,6 +118,7 @@
 	unsigned		zlp:1;
 	unsigned		cdc:1;
 	unsigned		rndis:1;
+	unsigned		suspended:1;
 	u16			cdc_filter;
 	unsigned long		todo;
 #define	WORK_RX_MEMORY		0
@@ -1345,24 +1346,23 @@
 
 static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
 {
-	struct eth_dev          *dev = ep->driver_data;
-	
 	if (req->status || req->actual != req->length)
 		DEBUG (dev, "rndis response complete --> %d, %d/%d\n",
 		       req->status, req->actual, req->length);
 
 	/* done sending after CDC_GET_ENCAPSULATED_RESPONSE */
-	rndis_free_response (dev->rndis_config, req->buf);
 }
 
 static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
 {
 	struct eth_dev          *dev = ep->driver_data;
+	int			status;
 	
 	/* received RNDIS command from CDC_SEND_ENCAPSULATED_COMMAND */
 	spin_lock(&dev->lock);
-	if (rndis_msg_parser (dev->rndis_config, (u8 *) req->buf))
-		ERROR(dev, "%s: rndis parse error\n", __FUNCTION__ );
+	status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
+	if (status < 0)
+		ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
 	spin_unlock(&dev->lock);
 }
 
@@ -1580,6 +1580,7 @@
 			if (buf) {
 				memcpy (req->buf, buf, value);
 				req->complete = rndis_response_complete;
+				rndis_free_response(dev->rndis_config, buf);
 			}
 			/* else stalls ... spec says to avoid that */
 		}
@@ -2064,6 +2065,16 @@
 	}
 }
 
+static void rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
+{
+	if (req->status || req->actual != req->length)
+		DEBUG (dev, "rndis control ack complete --> %d, %d/%d\n",
+		       req->status, req->actual, req->length);
+
+	usb_ep_free_buffer(ep, req->buf, req->dma, 8);
+	usb_ep_free_request(ep, req);
+}
+
 static int rndis_control_ack (struct net_device *net)
 {
 	struct eth_dev          *dev = (struct eth_dev *) net->priv;
@@ -2095,7 +2106,7 @@
 	 * CDC_NOTIFY_RESPONSE_AVAILABLE should work too
 	 */
 	resp->length = 8;
-	resp->complete = rndis_response_complete;
+	resp->complete = rndis_control_ack_complete;
 	
 	*((u32 *) resp->buf) = __constant_cpu_to_le32 (1);
 	*((u32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
@@ -2103,7 +2114,7 @@
 	length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
 	if (length < 0) {
 		resp->status = 0;
-		rndis_response_complete (dev->status_ep, resp);
+		rndis_control_ack_complete (dev->status_ep, resp);
 	}
 	
 	return 0;
@@ -2302,17 +2313,6 @@
 		UTS_SYSNAME " " UTS_RELEASE "/%s",
 		gadget->name);
 
-	/* CDC subset ... recognized by Linux since 2.4.10, but Windows
-	 * drivers aren't widely available.
-	 */
-	if (!cdc) {
-		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
-		device_desc.idVendor =
-			__constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
-		device_desc.idProduct =
-			__constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
-	}
-
 	/* If there's an RNDIS configuration, that's what Windows wants to
 	 * be using ... so use these product IDs here and in the "linux.inf"
 	 * needed to install MSFT drivers.  Current Linux kernels will use
@@ -2326,6 +2326,16 @@
 			__constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
 		snprintf (product_desc, sizeof product_desc,
 			"RNDIS/%s", driver_desc);
+
+	/* CDC subset ... recognized by Linux since 2.4.10, but Windows
+	 * drivers aren't widely available.
+	 */
+	} else if (!cdc) {
+		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+		device_desc.idVendor =
+			__constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
+		device_desc.idProduct =
+			__constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
 	}
 
 	/* support optional vendor/distro customization */
@@ -2554,6 +2564,26 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void
+eth_suspend (struct usb_gadget *gadget)
+{
+	struct eth_dev		*dev = get_gadget_data (gadget);
+
+	DEBUG (dev, "suspend\n");
+	dev->suspended = 1;
+}
+
+static void
+eth_resume (struct usb_gadget *gadget)
+{
+	struct eth_dev		*dev = get_gadget_data (gadget);
+
+	DEBUG (dev, "resume\n");
+	dev->suspended = 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
 static struct usb_gadget_driver eth_driver = {
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
@@ -2566,6 +2596,9 @@
 
 	.setup		= eth_setup,
 	.disconnect	= eth_disconnect,
+
+	.suspend	= eth_suspend,
+	.resume		= eth_resume,
 
 	.driver 	= {
 		.name		= (char *) shortname,
diff -Nru a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
--- a/drivers/usb/gadget/file_storage.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/gadget/file_storage.c	2004-06-23 19:04:28 -07:00
@@ -2501,7 +2501,7 @@
 		/* Store and send the Bulk-only CSW */
 		csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG);
 		csw->Tag = fsg->tag;
-		csw->Residue = fsg->residue;
+		csw->Residue = cpu_to_le32(fsg->residue);
 		csw->Status = status;
 
 		bh->inreq->length = USB_BULK_CS_WRAP_LEN;
@@ -2947,7 +2947,7 @@
 		fsg->data_dir = DATA_DIR_TO_HOST;
 	else
 		fsg->data_dir = DATA_DIR_FROM_HOST;
-	fsg->data_size = cbw->DataTransferLength;
+	fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
 	if (fsg->data_size == 0)
 		fsg->data_dir = DATA_DIR_NONE;
 	fsg->lun = cbw->Lun;
@@ -3834,6 +3834,7 @@
 	}
 
 	/* Find all the endpoints we will use */
+	usb_ep_autoconfig_reset(gadget);
 	ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc);
 	if (!ep)
 		goto autoconf_fail;
diff -Nru a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/ndis.h
--- a/drivers/usb/gadget/ndis.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/gadget/ndis.h	2004-06-23 19:04:27 -07:00
@@ -26,10 +26,40 @@
 #define NDIS_STATUS_MULTICAST_EXISTS      0xC001000A
 #define NDIS_STATUS_MULTICAST_NOT_FOUND   0xC001000B
 
+enum NDIS_DEVICE_POWER_STATE {
+	NdisDeviceStateUnspecified = 0,
+	NdisDeviceStateD0,
+	NdisDeviceStateD1,
+	NdisDeviceStateD2,
+	NdisDeviceStateD3,
+	NdisDeviceStateMaximum
+};
+
+struct NDIS_PM_WAKE_UP_CAPABILITIES {
+	enum NDIS_DEVICE_POWER_STATE  MinMagicPacketWakeUp;
+	enum NDIS_DEVICE_POWER_STATE  MinPatternWakeUp;
+	enum NDIS_DEVICE_POWER_STATE  MinLinkChangeWakeUp;
+};
+
 /* NDIS_PNP_CAPABILITIES.Flags constants */
 #define NDIS_DEVICE_WAKE_UP_ENABLE                0x00000001
 #define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE  0x00000002
 #define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE   0x00000004
+
+struct NDIS_PNP_CAPABILITIES {
+	u32					Flags;
+	struct NDIS_PM_WAKE_UP_CAPABILITIES	WakeUpCapabilities;
+};
+
+struct NDIS_PM_PACKET_PATTERN {
+	u32	Priority;
+	u32	Reserved;
+	u32	MaskSize;
+	u32	PatternOffset;
+	u32	PatternSize;
+	u32	PatternFlags;
+};
+
 
 /* Required Object IDs (OIDs) */
 #define OID_GEN_SUPPORTED_LIST            0x00010101
diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/gadget/net2280.c	2004-06-23 19:04:25 -07:00
@@ -1902,6 +1902,8 @@
 		, &dev->usb->stdrsp);
 	writel (  (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
 		| (1 << SELF_POWERED_USB_DEVICE)
+		/* erratum 0102 workaround */
+		| ((dev->chiprev == 0100) ? 0 : 1) << SUSPEND_IMMEDIATELY
 		| (1 << REMOTE_WAKEUP_SUPPORT)
 		| (1 << USB_DETECT_ENABLE)
 		| (1 << SELF_POWERED_STATUS)
@@ -1917,6 +1919,7 @@
 		| (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE)
 		| (1 << VBUS_INTERRUPT_ENABLE)
 		| (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE)
+		| (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE)
 		, &dev->regs->pciirqenb1);
 
 	/* don't leave any writes posted */
@@ -2513,19 +2516,24 @@
 			return;
 	}
 
-	/* NOTE: we don't actually suspend the hardware; that starts to
-	 * interact with PCI power management, and needs something like a
-	 * controller->suspend() call to clear SUSPEND_REQUEST_INTERRUPT.
-	 * we shouldn't see resume interrupts.
-	 * for rev 0100, this also avoids erratum 0102.
+	/* NOTE: chip stays in PCI D0 state for now, but it could
+	 * enter D1 to save more power
 	 */
 	tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
 	if (stat & tmp) {
-		if (dev->driver->suspend)
-			dev->driver->suspend (&dev->gadget);
+		writel (tmp, &dev->regs->irqstat1);
+		if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
+			if (dev->driver->suspend)
+				dev->driver->suspend (&dev->gadget);
+			/* we use SUSPEND_IMMEDIATELY */
+			stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
+		} else {
+			if (dev->driver->resume)
+				dev->driver->resume (&dev->gadget);
+			/* at high speed, note erratum 0133 */
+		}
 		stat &= ~tmp;
 	}
-	stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
 
 	/* clear any other status/irqs */
 	if (stat)
@@ -2533,6 +2541,7 @@
 
 	/* some status we can just ignore */
 	stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+			| (1 << SUSPEND_REQUEST_INTERRUPT)
 			| (1 << RESUME_INTERRUPT)
 			| (1 << SOF_INTERRUPT));
 	if (!stat)
diff -Nru a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
--- a/drivers/usb/gadget/pxa2xx_udc.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/gadget/pxa2xx_udc.c	2004-06-23 19:04:27 -07:00
@@ -1406,7 +1406,7 @@
 
 #ifdef	CONFIG_ARCH_PXA
         /* Disable clock for USB device */
-        CKEN &= ~CKEN11_USB;
+	pxa_set_cken(CKEN11_USB, 0);
 #endif
 
 	ep0_idle (dev);
@@ -1452,7 +1452,7 @@
 
 #ifdef	CONFIG_ARCH_PXA
         /* Enable clock for USB device */
-        CKEN |= CKEN11_USB;
+	pxa_set_cken(CKEN11_USB, 1);
 #endif
 
 	/* try to clear these bits before we enable the udc */
diff -Nru a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
--- a/drivers/usb/gadget/rndis.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/gadget/rndis.c	2004-06-23 19:04:25 -07:00
@@ -18,6 +18,9 @@
  * 
  * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
  * 		Fixed rndis_rm_hdr length bug.
+ *
+ * Copyright (C) 2004 by David Brownell
+ *		updates to merge with Linux 2.6, better match RNDIS spec
  */
 
 #include <linux/config.h>
@@ -35,28 +38,34 @@
 #include <asm/byteorder.h>
 #include <asm/system.h>
 
+
+#undef	RNDIS_PM
+#undef	VERBOSE
+
 #include "rndis.h"
 
 
 /* The driver for your USB chip needs to support ep0 OUT to work with
- * RNDIS, plus the same three descriptors as CDC Ethernet.
+ * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
  *
  * Windows hosts need an INF file like Documentation/usb/linux.inf
+ * and will be happier if you provide the host_addr module parameter.
  */
 
-#ifndef	__LITTLE_ENDIAN
-#warning this code is missing all cpu_to_leXX() calls ...
-#endif
-
 #if 0
-#define DEBUG if (rndis_debug) printk 
+#define DEBUG(str,args...) do { \
+	if (rndis_debug) \
+		printk(KERN_DEBUG str , ## args ); \
+	} while (0)
 static int rndis_debug = 0;
 
 module_param (rndis_debug, bool, 0);
 MODULE_PARM_DESC (rndis_debug, "enable debugging");
 
 #else
-#define DEBUG(str,args...) do{}while(0)
+
+#define rndis_debug		0
+#define DEBUG(str,args...)	do{}while(0)
 #endif
 
 #define RNDIS_MAX_CONFIGS	1
@@ -79,16 +88,14 @@
 
 static rndis_resp_t *rndis_add_response (int configNr, u32 length);
 
-/* FIXME OMITTED OIDs, that RNDIS-on-USB "must" support, include
- *  - power management (OID_PNP_CAPABILITIES, ...)
- *  - network wakeup (OID_PNP_ENABLE_WAKE_UP, ...)
- */
 
 /* NDIS Functions */
 static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
 {
 	int 			retval = -ENOTSUPP;
 	u32 			length = 0;
+	u32			*tmp;
+	int			i, count;
 	rndis_query_cmplt_type	*resp;
 
 	if (!r) return -ENOMEM;
@@ -97,11 +104,17 @@
 	if (!resp) return -ENOMEM;
 	
 	switch (OID) {
+
+	/* general oids (table 4-1) */
+
 	/* mandatory */
 	case OID_GEN_SUPPORTED_LIST:
 		DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
 		length = sizeof (oid_supported_list);
-		memcpy ((u8 *) resp + 24, oid_supported_list, length); 
+		count  = length / sizeof (u32);
+		tmp = (u32 *) ((u8 *)resp + 24);
+		for (i = 0; i < count; i++)
+			tmp[i] = cpu_to_le32 (oid_supported_list[i]);
 		retval = 0;
 		break;
 		
@@ -115,7 +128,7 @@
 		 * reddite ergo quae sunt Caesaris Caesari
 		 * et quae sunt Dei Deo!
 		 */
-		*((u32 *) resp + 6) = 0;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
@@ -123,7 +136,8 @@
 	case OID_GEN_MEDIA_SUPPORTED:
 		DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = rndis_per_dev_params [configNr].medium;
+		*((u32 *) resp + 6) = cpu_to_le32 (
+					rndis_per_dev_params [configNr].medium);
 		retval = 0;
 		break;
 		
@@ -132,24 +146,21 @@
 		DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
 		length = 4;
 		/* one medium, one transport... (maybe you do it better) */
-		*((u32 *) resp + 6) = rndis_per_dev_params [configNr].medium;
+		*((u32 *) resp + 6) = cpu_to_le32 (
+					rndis_per_dev_params [configNr].medium);
 		retval = 0;
 		break;
 		
-	case OID_GEN_MAXIMUM_LOOKAHEAD:
-		DEBUG("%s: OID_GEN_MAXIMUM_LOOKAHEAD\n", __FUNCTION__);
-		break;
-		
 	/* mandatory */
 	case OID_GEN_MAXIMUM_FRAME_SIZE:
 		DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = 4;
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr]
-						.dev->mtu;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr].dev->mtu);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -160,30 +171,20 @@
 		length = 4;
 		if (rndis_per_dev_params [configNr].media_state
 			== NDIS_MEDIA_STATE_DISCONNECTED)
-		    *((u32 *) resp + 6) = 0;
+		    *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		else
-		    *((u32 *) resp + 6) = rndis_per_dev_params [configNr].speed;
+		    *((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr].speed);
 		retval = 0;
 		break;
-		
-	case OID_GEN_TRANSMIT_BUFFER_SPACE:
-		DEBUG("%s: OID_GEN_TRANSMIT_BUFFER_SPACE\n", __FUNCTION__);
-		length = 4;
-		*((u32 *) resp + 6) = 0;
-		retval = 0;
-		break;
-		
-	case OID_GEN_RECEIVE_BUFFER_SPACE:
-		DEBUG("%s: OID_GEN_RECEIVE_BUFFER_SPACE\n", __FUNCTION__);
-		break;
-		
+
 	/* mandatory */
 	case OID_GEN_TRANSMIT_BLOCK_SIZE:
 		DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = 4;
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr]
-						.dev->mtu;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr].dev->mtu);
 			retval = 0;
 		}
 		break;
@@ -193,8 +194,8 @@
 		DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = 4;
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr]
-						.dev->mtu;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr].dev->mtu);
 			retval = 0;
 		}
 		break;
@@ -203,7 +204,8 @@
 	case OID_GEN_VENDOR_ID:
 		DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = rndis_per_dev_params [configNr].vendorID;
+		*((u32 *) resp + 6) = cpu_to_le32 (
+			rndis_per_dev_params [configNr].vendorID);
 		retval = 0;
 		break;
 		
@@ -216,129 +218,92 @@
 		retval = 0;
 		break;
 
+	case OID_GEN_VENDOR_DRIVER_VERSION:
+		DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
+		length = 4;
+		/* Created as LE */
+		*((u32 *) resp + 6) = rndis_driver_version;
+		retval = 0;
+		break;
+
 	/* mandatory */
 	case OID_GEN_CURRENT_PACKET_FILTER:
 		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = rndis_per_dev_params[configNr].filter;
+		*((u32 *) resp + 6) = cpu_to_le32 (
+					rndis_per_dev_params[configNr].filter);
 		retval = 0;
 		break;
-		
-	case OID_GEN_CURRENT_LOOKAHEAD:
-		DEBUG("%s: OID_GEN_CURRENT_LOOKAHEAD\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_DRIVER_VERSION:
-		DEBUG("%s: OID_GEN_DRIVER_VERSION\n", __FUNCTION__);
-		break;
-		
+
 	/* mandatory */
 	case OID_GEN_MAXIMUM_TOTAL_SIZE:
 		DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = RNDIS_MAX_TOTAL_SIZE;
-		retval = 0;
-		break;
-		
-	case OID_GEN_PROTOCOL_OPTIONS:
-		DEBUG("%s: OID_GEN_PROTOCOL_OPTIONS\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_MAC_OPTIONS:
-		DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
-		length = 4;
-		*((u32 *) resp + 6) = NDIS_MAC_OPTION_RECEIVE_SERIALIZED | 
-		    NDIS_MAC_OPTION_FULL_DUPLEX;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32(
+					RNDIS_MAX_TOTAL_SIZE);
 		retval = 0;
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_MEDIA_CONNECT_STATUS:
 		DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = rndis_per_dev_params [configNr]
-						.media_state;
+		*((u32 *) resp + 6) = cpu_to_le32 (
+					rndis_per_dev_params [configNr]
+						.media_state);
 		retval = 0;
 		break;
-		
-	case OID_GEN_MAXIMUM_SEND_PACKETS:
-		DEBUG("%s: OID_GEN_MAXIMUM_SEND_PACKETS\n", __FUNCTION__);
-		break;
-		
-	/* mandatory */
-	case OID_GEN_VENDOR_DRIVER_VERSION:
-		DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
-		length = 4;
-		*((u32 *) resp + 6) = rndis_driver_version;
-		retval = 0;
-		break;
-		
-	case OID_GEN_SUPPORTED_GUIDS:
-		DEBUG("%s: OID_GEN_SUPPORTED_GUIDS\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_NETWORK_LAYER_ADDRESSES:
-		DEBUG("%s: OID_GEN_NETWORK_LAYER_ADDRESSES\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_TRANSPORT_HEADER_OFFSET:
-		DEBUG("%s: OID_GEN_TRANSPORT_HEADER_OFFSET\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_MACHINE_NAME:
-		DEBUG("%s: OID_GEN_MACHINE_NAME\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_RNDIS_CONFIG_PARAMETER:
-		DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER\n", __FUNCTION__);
+
+	case OID_GEN_PHYSICAL_MEDIUM:
+		DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = 0;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
-		
-	case OID_GEN_VLAN_ID:
-		DEBUG("%s: OID_GEN_VLAN_ID\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_MEDIA_CAPABILITIES:
-		DEBUG("%s: OID_GEN_MEDIA_CAPABILITIES\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_PHYSICAL_MEDIUM:
-		DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
+
+	/* The RNDIS specification is incomplete/wrong.   Some versions
+	 * of MS-Windows expect OIDs that aren't specified there.  Other
+	 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
+	 */
+	case OID_GEN_MAC_OPTIONS:		/* from WinME */
+		DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = 0;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32(
+			  NDIS_MAC_OPTION_RECEIVE_SERIALIZED
+			| NDIS_MAC_OPTION_FULL_DUPLEX);
 		retval = 0;
 		break;
-		
+
+	/* statistics OIDs (table 4-2) */
+
 	/* mandatory */
 	case OID_GEN_XMIT_OK:
 		DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr]
-					.stats->tx_packets - 
+			*((u32 *) resp + 6) = cpu_to_le32 (
+			    rndis_per_dev_params [configNr].stats->tx_packets - 
 			    rndis_per_dev_params [configNr].stats->tx_errors -
-			    rndis_per_dev_params [configNr].stats->tx_dropped;
+			    rndis_per_dev_params [configNr].stats->tx_dropped);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_RCV_OK:
 		DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->rx_packets - 
+			*((u32 *) resp + 6) = cpu_to_le32 (
+			    rndis_per_dev_params [configNr].stats->rx_packets - 
 			    rndis_per_dev_params [configNr].stats->rx_errors -
-			    rndis_per_dev_params [configNr].stats->rx_dropped;
+			    rndis_per_dev_params [configNr].stats->rx_dropped);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -348,11 +313,12 @@
 		DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->tx_errors;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->tx_errors);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -361,11 +327,12 @@
 	case OID_GEN_RCV_ERROR:
 		DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->rx_errors;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_errors);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -374,15 +341,17 @@
 	case OID_GEN_RCV_NO_BUFFER:
 		DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->rx_dropped;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_dropped);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
-		
+
+#ifdef	RNDIS_OPTIONAL_STATS
 	case OID_GEN_DIRECTED_BYTES_XMIT:
 		DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
 		/* 
@@ -392,14 +361,17 @@
 		 */
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = (rndis_per_dev_params [configNr].
-					stats->tx_packets - 
-			    rndis_per_dev_params [configNr].stats->tx_errors -
-			    rndis_per_dev_params [configNr].stats->tx_dropped)
-					*123;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				(rndis_per_dev_params [configNr]
+					.stats->tx_packets - 
+				 rndis_per_dev_params [configNr]
+					 .stats->tx_errors -
+				 rndis_per_dev_params [configNr]
+					 .stats->tx_dropped)
+				* 123);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -409,14 +381,17 @@
 		/* dito */
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = (rndis_per_dev_params [configNr].
-					stats->tx_packets - 
-			    rndis_per_dev_params [configNr].stats->tx_errors -
-			    rndis_per_dev_params [configNr].stats->tx_dropped)
-			    		/123;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				(rndis_per_dev_params [configNr]
+					.stats->tx_packets - 
+				 rndis_per_dev_params [configNr]
+					 .stats->tx_errors -
+				 rndis_per_dev_params [configNr]
+					 .stats->tx_dropped)
+				/ 123);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -424,11 +399,12 @@
 	case OID_GEN_MULTICAST_BYTES_XMIT:
 		DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->multicast*1234;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->multicast*1234);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -436,11 +412,12 @@
 	case OID_GEN_MULTICAST_FRAMES_XMIT:
 		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->multicast;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->multicast);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -448,11 +425,12 @@
 	case OID_GEN_BROADCAST_BYTES_XMIT:
 		DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->tx_packets/42*255;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->tx_packets/42*255);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -460,35 +438,37 @@
 	case OID_GEN_BROADCAST_FRAMES_XMIT:
 		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->tx_packets/42;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->tx_packets/42);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
 		
 	case OID_GEN_DIRECTED_BYTES_RCV:
 		DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
-		*((u32 *) resp + 6) = 0;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
 	case OID_GEN_DIRECTED_FRAMES_RCV:
 		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
-		*((u32 *) resp + 6) = 0;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
 	case OID_GEN_MULTICAST_BYTES_RCV:
 		DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->multicast*1111;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->multicast * 1111);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -496,11 +476,12 @@
 	case OID_GEN_MULTICAST_FRAMES_RCV:
 		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->multicast;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->multicast);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -508,11 +489,12 @@
 	case OID_GEN_BROADCAST_BYTES_RCV:
 		DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->rx_packets/42*255;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_packets/42*255);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -520,11 +502,12 @@
 	case OID_GEN_BROADCAST_FRAMES_RCV:
 		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->rx_packets/42;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_packets/42);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -532,61 +515,25 @@
 	case OID_GEN_RCV_CRC_ERROR:
 		DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr].
-					stats->rx_crc_errors;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_crc_errors);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
 		
 	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
 		DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
-		*((u32 *) resp + 6) = 0;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
-		
-	case OID_GEN_GET_TIME_CAPS:
-		DEBUG("%s: OID_GEN_GET_TIME_CAPS\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_GET_NETCARD_TIME:
-		DEBUG("%s: OID_GEN_GET_NETCARD_TIME\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_NETCARD_LOAD:
-		DEBUG("%s: OID_GEN_NETCARD_LOAD\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_DEVICE_PROFILE:
-		DEBUG("%s: OID_GEN_DEVICE_PROFILE\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_INIT_TIME_MS:
-		DEBUG("%s: OID_GEN_INIT_TIME_MS\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_RESET_COUNTS:
-		DEBUG("%s: OID_GEN_RESET_COUNTS\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_MEDIA_SENSE_COUNTS:
-		DEBUG("%s: OID_GEN_MEDIA_SENSE_COUNTS\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_FRIENDLY_NAME:
-		DEBUG("%s: OID_GEN_FRIENDLY_NAME\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_MINIPORT_INFO:
-		DEBUG("%s: OID_GEN_MINIPORT_INFO\n", __FUNCTION__);
-		break;
-		
-	case OID_GEN_RESET_VERIFY_PARAMETERS:
-		DEBUG("%s: OID_GEN_RESET_VERIFY_PARAMETERS\n", __FUNCTION__);
-		break;
-		
+#endif	/* RNDIS_OPTIONAL_STATS */
+
+	/* ieee802.3 OIDs (table 4-3) */
+
 	/* mandatory */
 	case OID_802_3_PERMANENT_ADDRESS:
 		DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
@@ -597,7 +544,7 @@
 				length);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = 0;
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -619,7 +566,7 @@
 		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
 		length = 4;
 		/* Multicast base address only */
-		*((u32 *) resp + 6) = 0xE0000000;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
 		retval = 0;
 		break;
 		
@@ -628,22 +575,25 @@
 		DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
 		 length = 4;
 		/* Multicast base address only */
-		*((u32 *) resp + 6) = 1;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (1);
 		retval = 0;
 		break;
 		
 	case OID_802_3_MAC_OPTIONS:
 		DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
 		break;
-		
+
+	/* ieee802.3 statistics OIDs (table 4-4) */
+
 	/* mandatory */
 	case OID_802_3_RCV_ERROR_ALIGNMENT:
 		DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats)
 		{
 			length = 4;
-			*((u32 *) resp + 6) = rndis_per_dev_params [configNr]
-					.stats->rx_frame_errors;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_frame_errors);
 			retval = 0;
 		}
 		break;
@@ -652,7 +602,7 @@
 	case OID_802_3_XMIT_ONE_COLLISION:
 		DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = 0;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
@@ -660,10 +610,11 @@
 	case OID_802_3_XMIT_MORE_COLLISIONS:
 		DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = 0;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
+#ifdef	RNDIS_OPTIONAL_STATS
 	case OID_802_3_XMIT_DEFERRED:
 		DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
 		/* TODO */
@@ -698,14 +649,46 @@
 		DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
 		/* TODO */
 		break;		
-		
-	default: printk (KERN_ERR "%s: unknown OID 0x%08X\n", 
+#endif	/* RNDIS_OPTIONAL_STATS */
+
+#ifdef	RNDIS_PM
+	/* power management OIDs (table 4-5) */
+	case OID_PNP_CAPABILITIES:
+		DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
+
+		/* just PM, and remote wakeup on link status change
+		 * (not magic packet or pattern match)
+		 */
+		length = sizeof (struct NDIS_PNP_CAPABILITIES);
+		memset (resp, 0, length);
+		{
+			struct NDIS_PNP_CAPABILITIES *caps = (void *) resp;
+
+			caps->Flags = NDIS_DEVICE_WAKE_UP_ENABLE;
+			caps->WakeUpCapabilities.MinLinkChangeWakeUp 
+				 = NdisDeviceStateD3;
+
+			/* FIXME then use usb_gadget_wakeup(), and
+			 * set USB_CONFIG_ATT_WAKEUP in config desc
+			 */
+		}
+		retval = 0;
+		break;
+	case OID_PNP_QUERY_POWER:
+		DEBUG("%s: OID_PNP_QUERY_POWER\n", __FUNCTION__);
+		/* sure, handle any power state that maps to USB suspend */
+		retval = 0;
+		break;
+#endif
+
+	default:
+		printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", 
 			 __FUNCTION__, OID);
 	}
 	
-	resp->InformationBufferOffset = 16;
-	resp->InformationBufferLength = length;
-	resp->MessageLength = 24 + length;
+	resp->InformationBufferOffset = __constant_cpu_to_le32 (16);
+	resp->InformationBufferLength = cpu_to_le32 (length);
+	resp->MessageLength = cpu_to_le32 (24 + length);
 	r->length = 24 + length;
 	return retval;
 }
@@ -715,9 +698,7 @@
 {
 	rndis_set_cmplt_type		*resp;
 	int 				i, retval = -ENOTSUPP;
-	struct rndis_config_parameter	*param;
 	struct rndis_params		*params;
-	u8 *cp;
 
 	if (!r)
 		return -ENOMEM;
@@ -725,20 +706,37 @@
 	if (!resp)
 		return -ENOMEM;
 
-	cp = (u8 *)resp;
+	DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
+	for (i = 0; i < buf_len; i += 16) {
+		DEBUG ("%03d: "
+			" %02x %02x %02x %02x"
+			" %02x %02x %02x %02x"
+			" %02x %02x %02x %02x"
+			" %02x %02x %02x %02x"
+			"\n",
+			i,
+			buf[i], buf [i+1],
+				buf[i+2], buf[i+3],
+			buf[i+4], buf [i+5],
+				buf[i+6], buf[i+7],
+			buf[i+8], buf [i+9],
+				buf[i+10], buf[i+11],
+			buf[i+12], buf [i+13],
+				buf[i+14], buf[i+15]);
+	}
 
 	switch (OID) {
 	case OID_GEN_CURRENT_PACKET_FILTER:
 		params = &rndis_per_dev_params [configNr];
 		retval = 0;
 
-		/* FIXME use this NDIS_PACKET_TYPE_* bitflags to
+		/* FIXME use these NDIS_PACKET_TYPE_* bitflags to
 		 * filter packets in hard_start_xmit()
 		 * NDIS_PACKET_TYPE_x == CDC_PACKET_TYPE_x for x in:
 		 *	PROMISCUOUS, DIRECTED,
 		 *	MULTICAST, ALL_MULTICAST, BROADCAST
 		 */
-		params->filter = *(u32 *)buf;
+		params->filter = cpu_to_le32p((u32 *)buf);
 		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
 			__FUNCTION__, params->filter);
 
@@ -763,23 +761,40 @@
 		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
 		retval = 0;
 		break;
-		
+#if 0
 	case OID_GEN_RNDIS_CONFIG_PARAMETER:
-		DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER\n", __FUNCTION__);
+		{
+		struct rndis_config_parameter	*param;
 		param = (struct rndis_config_parameter *) buf;
-		if (param) {
-			for (i = 0; i < param->ParameterNameLength; i++) {
-				DEBUG ("%c", 
-				       *(buf + param->ParameterNameOffset + i));
-			}
-			DEBUG ("\n");
+		DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
+			__FUNCTION__,
+			min(cpu_to_le32(param->ParameterNameLength),80),
+			buf + param->ParameterNameOffset);
+		retval = 0;
 		}
-		
+		break;
+#endif
+
+#ifdef	RNDIS_PM
+	case OID_PNP_SET_POWER:
+		DEBUG ("OID_PNP_SET_POWER\n");
+		/* sure, handle any power state that maps to USB suspend */
 		retval = 0;
 		break;
-		
-	default: printk (KERN_ERR "%s: unknown OID 0x%08X\n", 
-			 __FUNCTION__, OID);
+
+	case OID_PNP_ENABLE_WAKE_UP:
+		/* always-connected ... */
+		DEBUG ("OID_PNP_ENABLE_WAKE_UP\n");
+		retval = 0;
+		break;
+
+	// no PM resume patterns supported (specified where?)
+	// so OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN always fails
+#endif
+
+	default:
+		printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", 
+			 __FUNCTION__, OID, buf_len);
 	}
 	
 	return retval;
@@ -804,22 +819,24 @@
 	
 	if (!resp) return -ENOMEM;
 	
-	resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
-	resp->MessageLength = 52;
-	resp->RequestID = buf->RequestID;
-	resp->Status = RNDIS_STATUS_SUCCESS;
-	resp->MajorVersion = RNDIS_MAJOR_VERSION;
-	resp->MinorVersion = RNDIS_MINOR_VERSION;
-	resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
-	resp->Medium = RNDIS_MEDIUM_802_3;
-	resp->MaxPacketsPerTransfer = 1;
-	resp->MaxTransferSize = rndis_per_dev_params [configNr].dev->mtu
+	resp->MessageType = __constant_cpu_to_le32 (
+			REMOTE_NDIS_INITIALIZE_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (52);
+	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	resp->MajorVersion = __constant_cpu_to_le32 (RNDIS_MAJOR_VERSION);
+	resp->MinorVersion = __constant_cpu_to_le32 (RNDIS_MINOR_VERSION);
+	resp->DeviceFlags = __constant_cpu_to_le32 (RNDIS_DF_CONNECTIONLESS);
+	resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3);
+	resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1);
+	resp->MaxTransferSize = cpu_to_le32 (
+		  rndis_per_dev_params [configNr].dev->mtu
 		+ sizeof (struct ethhdr)
 		+ sizeof (struct rndis_packet_msg_type)
-		+ 22;
-	resp->PacketAlignmentFactor = 0;
-	resp->AFListOffset = 0;
-	resp->AFListSize = 0;
+		+ 22);
+	resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0);
+	resp->AFListOffset = __constant_cpu_to_le32 (0);
+	resp->AFListSize = __constant_cpu_to_le32 (0);
 	
 	if (rndis_per_dev_params [configNr].ack)
 	    rndis_per_dev_params [configNr].ack (
@@ -833,7 +850,7 @@
 	rndis_query_cmplt_type *resp;
 	rndis_resp_t            *r;
 	
-	DEBUG("%s: OID = %08X\n", __FUNCTION__, buf->OID);
+	// DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
 	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
 	
 	/* 
@@ -847,17 +864,18 @@
 	
 	if (!resp) return -ENOMEM;
 	
-	resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
-	resp->MessageLength = 24;
-	resp->RequestID = buf->RequestID;
+	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (24);
+	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
 	
-	if (gen_ndis_query_resp (configNr, buf->OID, r)) {
+	if (gen_ndis_query_resp (configNr, cpu_to_le32 (buf->OID), r)) {
 		/* OID not supported */
-		resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
-		resp->InformationBufferLength = 0;
-		resp->InformationBufferOffset = 0;
+		resp->Status = __constant_cpu_to_le32 (
+				RNDIS_STATUS_NOT_SUPPORTED);
+		resp->InformationBufferLength = __constant_cpu_to_le32 (0);
+		resp->InformationBufferOffset = __constant_cpu_to_le32 (0);
 	} else
-		resp->Status = RNDIS_STATUS_SUCCESS;
+		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 	
 	if (rndis_per_dev_params [configNr].ack)
 	    rndis_per_dev_params [configNr].ack (
@@ -867,38 +885,42 @@
 
 static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
 {
+	u32			BufLength, BufOffset;
 	rndis_set_cmplt_type	*resp;
 	rndis_resp_t		*r;
-	int			i;
 	
 	r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
 	
 	if (!r) return -ENOMEM;
 	resp = (rndis_set_cmplt_type *) r->buf;
 	if (!resp) return -ENOMEM;
-	
-	DEBUG("%s: Length: %d\n", __FUNCTION__, buf->InformationBufferLength);
-	DEBUG("%s: Offset: %d\n", __FUNCTION__, buf->InformationBufferOffset);
+
+	BufLength = cpu_to_le32 (buf->InformationBufferLength);
+	BufOffset = cpu_to_le32 (buf->InformationBufferOffset);
+
+#ifdef	VERBOSE
+	DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
+	DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
 	DEBUG("%s: InfoBuffer: ", __FUNCTION__);
 	
-	for (i = 0; i < buf->InformationBufferLength; i++) {
-		DEBUG ("%02x ", *(((u8 *) buf) + i + 12 +
-		       buf->InformationBufferOffset));
+	for (i = 0; i < BufLength; i++) {
+		DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
 	}
 	
 	DEBUG ("\n");
+#endif
 	
-	resp->MessageType = REMOTE_NDIS_SET_CMPLT;
-	resp->MessageLength = 16;
-	resp->RequestID = buf->RequestID;
-	if (gen_ndis_set_resp (configNr, buf->OID, 
-			       ((u8 *) buf) + 28, 
-			       buf->InformationBufferLength, r))
-	    resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
-	else resp->Status = RNDIS_STATUS_SUCCESS;
+	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (16);
+	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+	if (gen_ndis_set_resp (configNr, cpu_to_le32 (buf->OID), 
+			       ((u8 *) buf) + 8 + BufOffset, BufLength, r))
+	    resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
+	else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 	
 	if (rndis_per_dev_params [configNr].ack)
-	    rndis_per_dev_params [configNr].ack (rndis_per_dev_params [configNr].dev);
+	    rndis_per_dev_params [configNr].ack (
+	    		rndis_per_dev_params [configNr].dev);
 	
 	return 0;
 }
@@ -914,10 +936,11 @@
 	resp = (rndis_reset_cmplt_type *) r->buf;
 	if (!resp) return -ENOMEM;
 	
-	resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
-	resp->MessageLength = 16;
-	resp->Status = RNDIS_STATUS_SUCCESS;
-	resp->AddressingReset = 1; /* resent information */
+	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (16);
+	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	/* resent information */
+	resp->AddressingReset = __constant_cpu_to_le32 (1);
 	
 	if (rndis_per_dev_params [configNr].ack)
 	    rndis_per_dev_params [configNr].ack (
@@ -938,10 +961,11 @@
 	resp = (rndis_keepalive_cmplt_type *) r->buf;
 	if (!resp) return -ENOMEM;
 		
-	resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
-	resp->MessageLength = 16;
-	resp->RequestID = buf->RequestID;
-	resp->Status = RNDIS_STATUS_SUCCESS;
+	resp->MessageType = __constant_cpu_to_le32 (
+			REMOTE_NDIS_KEEPALIVE_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (16);
+	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 	
 	if (rndis_per_dev_params [configNr].ack)
 	    rndis_per_dev_params [configNr].ack (
@@ -969,11 +993,12 @@
 	resp = (rndis_indicate_status_msg_type *) r->buf;
 	if (!resp) return -ENOMEM;
 	
-	resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG;
-	resp->MessageLength = 20;
-	resp->Status = status;
-	resp->StatusBufferLength = 0;
-	resp->StatusBufferOffset = 0;
+	resp->MessageType = __constant_cpu_to_le32 (
+			REMOTE_NDIS_INDICATE_STATUS_MSG);
+	resp->MessageLength = __constant_cpu_to_le32 (20);
+	resp->Status = cpu_to_le32 (status);
+	resp->StatusBufferLength = __constant_cpu_to_le32 (0);
+	resp->StatusBufferOffset = __constant_cpu_to_le32 (0);
 	
 	if (rndis_per_dev_params [configNr].ack) 
 	    rndis_per_dev_params [configNr].ack (
@@ -1014,8 +1039,8 @@
 		return -ENOMEM;
 	
 	tmp = (u32 *) buf; 
-	MsgType = *tmp;
-	MsgLength = *(tmp + 1);
+	MsgType   = cpu_to_le32p(tmp++);
+	MsgLength = cpu_to_le32p(tmp++);
 	
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return -ENOTSUPP;
@@ -1025,14 +1050,14 @@
 	switch (MsgType)
 	{
 	case REMOTE_NDIS_INITIALIZE_MSG:
-		DEBUG(KERN_INFO "%s: REMOTE_NDIS_INITIALIZE_MSG\n", 
+		DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", 
 			__FUNCTION__ );
 		params->state = RNDIS_INITIALIZED;
 		return  rndis_init_response (configNr,
 					     (rndis_init_msg_type *) buf);
 		
 	case REMOTE_NDIS_HALT_MSG:
-		DEBUG(KERN_INFO "%s: REMOTE_NDIS_HALT_MSG\n",
+		DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",
 			__FUNCTION__ );
 		params->state = RNDIS_UNINITIALIZED;
 		if (params->dev) {
@@ -1042,34 +1067,57 @@
 		return 0;
 		
 	case REMOTE_NDIS_QUERY_MSG:
-		DEBUG(KERN_INFO "%s: REMOTE_NDIS_QUERY_MSG\n", 
-			__FUNCTION__ );
 		return rndis_query_response (configNr, 
 					     (rndis_query_msg_type *) buf);
 		
 	case REMOTE_NDIS_SET_MSG:
-		DEBUG(KERN_INFO "%s: REMOTE_NDIS_SET_MSG\n", 
-			__FUNCTION__ );
 		return rndis_set_response (configNr, 
 					   (rndis_set_msg_type *) buf);
 		
 	case REMOTE_NDIS_RESET_MSG:
-		DEBUG(KERN_INFO "%s: REMOTE_NDIS_RESET_MSG\n", 
+		DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", 
 			__FUNCTION__ );
 		return rndis_reset_response (configNr,
 					     (rndis_reset_msg_type *) buf);
 
 	case REMOTE_NDIS_KEEPALIVE_MSG:
 		/* For USB: host does this every 5 seconds */
-		DEBUG(KERN_INFO "%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 
+#ifdef	VERBOSE
+		DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 
 			__FUNCTION__ );
+#endif
 		return rndis_keepalive_response (configNr,
 						 (rndis_keepalive_msg_type *) 
 						 buf);
 		
 	default: 
-		printk (KERN_ERR "%s: unknown RNDIS Message Type 0x%08X\n", 
-			__FUNCTION__ , MsgType);
+		/* At least Windows XP emits some undefined RNDIS messages.
+		 * In one case those messages seemed to relate to the host
+		 * suspending itself.
+		 */
+		printk (KERN_WARNING
+			"%s: unknown RNDIS message 0x%08X len %d\n", 
+			__FUNCTION__ , MsgType, MsgLength);
+		{
+			unsigned i;
+			for (i = 0; i < MsgLength; i += 16) {
+				DEBUG ("%03d: "
+					" %02x %02x %02x %02x"
+					" %02x %02x %02x %02x"
+					" %02x %02x %02x %02x"
+					" %02x %02x %02x %02x"
+					"\n",
+					i,
+					buf[i], buf [i+1],
+						buf[i+2], buf[i+3],
+					buf[i+4], buf [i+5],
+						buf[i+6], buf[i+7],
+					buf[i+8], buf [i+9],
+						buf[i+10], buf[i+11],
+					buf[i+12], buf [i+13],
+						buf[i+14], buf[i+15]);
+			}
+		}
 		break;
 	}
 	
@@ -1079,13 +1127,12 @@
 int rndis_register (int (* rndis_control_ack) (struct net_device *))
 {
 	u8 i;
-	DEBUG("%s: ", __FUNCTION__ );
 	
 	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
 		if (!rndis_per_dev_params [i].used) {
 			rndis_per_dev_params [i].used = 1;
 			rndis_per_dev_params [i].ack = rndis_control_ack;
-			DEBUG("configNr = %d\n", i);
+			DEBUG("%s: configNr = %d\n", __FUNCTION__, i);
 			return i;
 		}
 	}
@@ -1145,10 +1192,10 @@
 	if (!skb) return;
 	skb_push (skb, sizeof (struct rndis_packet_msg_type));
 	memset (skb->data, 0, sizeof (struct rndis_packet_msg_type));
-	*((u32 *) skb->data) = 1;
-	*((u32 *) skb->data + 1) = skb->len;
-	*((u32 *) skb->data + 2) = 36;
-	*((u32 *) skb->data + 3) = skb->len - 44;
+	*((u32 *) skb->data) = __constant_cpu_to_le32 (1);
+	*((u32 *) skb->data + 1) = cpu_to_le32(skb->len);
+	*((u32 *) skb->data + 2) = __constant_cpu_to_le32 (36);
+	*((u32 *) skb->data + 3) = cpu_to_le32(skb->len - 44);
 	
 	return;
 }
@@ -1208,14 +1255,16 @@
 
 int rndis_rm_hdr (u8 *buf, u32 *length)
 {
-	u32 i, messageLen, dataOffset;
+	u32 i, messageLen, dataOffset, *tmp;
 	
+	tmp = (u32 *) buf; 
+
 	if (!buf || !length) return -1;
-	if (*((u32 *) buf) != 1) return -1;
+	if (cpu_to_le32p(tmp++) != 1) return -1;
 	
-	messageLen = *((u32 *) buf + 1);
-	
-	dataOffset = *((u32 *) buf + 2) + 8;
+	messageLen = cpu_to_le32p(tmp++);
+	dataOffset = cpu_to_le32p(tmp++) + 8;
+
 	if (messageLen < dataOffset || messageLen > *length) return -1;
 	
 	for (i = dataOffset; i < messageLen; i++)
diff -Nru a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
--- a/drivers/usb/gadget/rndis.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/gadget/rndis.h	2004-06-23 19:04:26 -07:00
@@ -59,10 +59,18 @@
 
 #define RNDIS_MEDIUM_802_3		0x00000000U
 
+/* from drivers/net/sk98lin/h/skgepnmi.h */
+#define OID_PNP_CAPABILITIES			0xFD010100
+#define OID_PNP_SET_POWER			0xFD010101
+#define OID_PNP_QUERY_POWER			0xFD010102
+#define OID_PNP_ADD_WAKE_UP_PATTERN		0xFD010103
+#define OID_PNP_REMOVE_WAKE_UP_PATTERN		0xFD010104
+#define OID_PNP_ENABLE_WAKE_UP			0xFD010106
+
+
 /* supported OIDs */
 static const u32 oid_supported_list [] = 
 {
-	/* mandatory general */
 	/* the general stuff */
 	OID_GEN_SUPPORTED_LIST,
 	OID_GEN_HARDWARE_STATUS,
@@ -70,7 +78,6 @@
 	OID_GEN_MEDIA_IN_USE,
 	OID_GEN_MAXIMUM_FRAME_SIZE,
 	OID_GEN_LINK_SPEED,
-	OID_GEN_TRANSMIT_BUFFER_SPACE,
 	OID_GEN_TRANSMIT_BLOCK_SIZE,
 	OID_GEN_RECEIVE_BLOCK_SIZE,
 	OID_GEN_VENDOR_ID,
@@ -78,10 +85,11 @@
 	OID_GEN_VENDOR_DRIVER_VERSION,
 	OID_GEN_CURRENT_PACKET_FILTER,
 	OID_GEN_MAXIMUM_TOTAL_SIZE,
-	OID_GEN_MAC_OPTIONS,
 	OID_GEN_MEDIA_CONNECT_STATUS,
 	OID_GEN_PHYSICAL_MEDIUM,
+#if 0
 	OID_GEN_RNDIS_CONFIG_PARAMETER,
+#endif
 	
 	/* the statistical stuff */
 	OID_GEN_XMIT_OK,
@@ -89,6 +97,7 @@
 	OID_GEN_XMIT_ERROR,
 	OID_GEN_RCV_ERROR,
 	OID_GEN_RCV_NO_BUFFER,
+#ifdef	RNDIS_OPTIONAL_STATS
 	OID_GEN_DIRECTED_BYTES_XMIT,
 	OID_GEN_DIRECTED_FRAMES_XMIT,
 	OID_GEN_MULTICAST_BYTES_XMIT,
@@ -103,6 +112,7 @@
 	OID_GEN_BROADCAST_FRAMES_RCV,
 	OID_GEN_RCV_CRC_ERROR,
 	OID_GEN_TRANSMIT_QUEUE_LENGTH,
+#endif	/* RNDIS_OPTIONAL_STATS */
 
     	/* mandatory 802.3 */
 	/* the general stuff */
@@ -115,7 +125,30 @@
 	/* the statistical stuff */
 	OID_802_3_RCV_ERROR_ALIGNMENT,
 	OID_802_3_XMIT_ONE_COLLISION,
-	OID_802_3_XMIT_MORE_COLLISIONS
+	OID_802_3_XMIT_MORE_COLLISIONS,
+#ifdef	RNDIS_OPTIONAL_STATS
+	OID_802_3_XMIT_DEFERRED,
+	OID_802_3_XMIT_MAX_COLLISIONS,
+	OID_802_3_RCV_OVERRUN,
+	OID_802_3_XMIT_UNDERRUN,
+	OID_802_3_XMIT_HEARTBEAT_FAILURE,
+	OID_802_3_XMIT_TIMES_CRS_LOST,
+	OID_802_3_XMIT_LATE_COLLISIONS,
+#endif	/* RNDIS_OPTIONAL_STATS */
+
+#ifdef	RNDIS_PM
+	/* PM and wakeup are mandatory for USB: */
+
+	/* power management */
+	OID_PNP_CAPABILITIES,
+	OID_PNP_QUERY_POWER,
+	OID_PNP_SET_POWER,
+
+	/* wake up host */
+	OID_PNP_ENABLE_WAKE_UP,
+	OID_PNP_ADD_WAKE_UP_PATTERN,
+	OID_PNP_REMOVE_WAKE_UP_PATTERN,
+#endif
 };
 
 
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/host/ehci-hcd.c	2004-06-23 19:04:27 -07:00
@@ -290,16 +290,17 @@
 {
 	if (cap & (1 << 16)) {
 		int msec = 500;
+		struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller);
 
 		/* request handoff to OS */
-		cap &= 1 << 24;
-		pci_write_config_dword (to_pci_dev(ehci->hcd.self.controller), where, cap);
+		cap |= 1 << 24;
+		pci_write_config_dword(pdev, where, cap);
 
 		/* and wait a while for it to happen */
 		do {
 			msleep(10);
 			msec -= 10;
-			pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller), where, &cap);
+			pci_read_config_dword(pdev, where, &cap);
 		} while ((cap & (1 << 16)) && msec);
 		if (cap & (1 << 16)) {
 			ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",
@@ -520,7 +521,7 @@
 
 	/* wire up the root hub */
 	bus = hcd_to_bus (hcd);
-	bus->root_hub = udev = usb_alloc_dev (NULL, bus, 0);
+	udev = usb_alloc_dev (NULL, bus, 0);
 	if (!udev) {
 done2:
 		ehci_mem_cleanup (ehci);
@@ -553,11 +554,10 @@
 	 * and device drivers may start it running.
 	 */
 	udev->speed = USB_SPEED_HIGH;
-	if (hcd_register_root (hcd) != 0) {
+	if (hcd_register_root (udev, hcd) != 0) {
 		if (hcd->state == USB_STATE_RUNNING)
 			ehci_ready (ehci);
 		ehci_reset (ehci);
-		bus->root_hub = 0;
 		usb_put_dev (udev); 
 		retval = -ENODEV;
 		goto done2;
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/host/ehci-sched.c	2004-06-23 19:04:26 -07:00
@@ -483,7 +483,7 @@
 		qh->start = frame;
 
 		/* reset S-frame and (maybe) C-frame masks */
-		qh->hw_info2 &= ~0xffff;
+		qh->hw_info2 &= ~__constant_cpu_to_le32(0xffff);
 		qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask;
 	} else
 		dbg ("reused previous qh %p schedule", qh);
diff -Nru a/drivers/usb/host/hc_sl811_rh.c b/drivers/usb/host/hc_sl811_rh.c
--- a/drivers/usb/host/hc_sl811_rh.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/host/hc_sl811_rh.c	2004-06-23 19:04:27 -07:00
@@ -557,18 +557,24 @@
 static int rh_connect_rh (hci_t * hci)
 {
 	struct usb_device *usb_dev;
+	int retval;
 
 	hci->rh.devnum = 0;
 	usb_dev = usb_alloc_dev (NULL, hci->bus, 0);
 	if (!usb_dev)
 		return -ENOMEM;
 
-	hci->bus->root_hub = usb_dev;
 	usb_dev->devnum = 1;
 	usb_dev->bus->devnum_next = usb_dev->devnum + 1;
 	set_bit (usb_dev->devnum, usb_dev->bus->devmap.devicemap);
 
-	if (usb_new_device (usb_dev) != 0) {
+	down (&usb_bus_list_lock);
+	hci->bus->root_hub = usb_dev;
+	retval = usb_new_device (usb_dev);
+	if (retval != 0)
+		hci->bus->root_hub = NULL;
+	up (&usb_bus_list_lock);
+	if (retval != 0) {
 		usb_put_dev (usb_dev);
 		return -ENODEV;
 	}
diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/host/ohci-dbg.c	2004-06-23 19:04:28 -07:00
@@ -134,13 +134,13 @@
 	struct ohci_regs	*regs = controller->regs;
 	u32			temp;
 
-	temp = readl (&regs->revision) & 0xff;
+	temp = ohci_readl (&regs->revision) & 0xff;
 	ohci_dbg_sw (controller, next, size,
 		"OHCI %d.%d, %s legacy support registers\n",
 		0x03 & (temp >> 4), (temp & 0x0f),
 		(temp & 0x10) ? "with" : "NO");
 
-	temp = readl (&regs->control);
+	temp = ohci_readl (&regs->control);
 	ohci_dbg_sw (controller, next, size,
 		"control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
 		temp,
@@ -155,7 +155,7 @@
 		temp & OHCI_CTRL_CBSR
 		);
 
-	temp = readl (&regs->cmdstatus);
+	temp = ohci_readl (&regs->cmdstatus);
 	ohci_dbg_sw (controller, next, size,
 		"cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
 		(temp & OHCI_SOC) >> 16,
@@ -166,26 +166,26 @@
 		);
 
 	ohci_dump_intr_mask (controller, "intrstatus",
-			readl (&regs->intrstatus), next, size);
+			ohci_readl (&regs->intrstatus), next, size);
 	ohci_dump_intr_mask (controller, "intrenable",
-			readl (&regs->intrenable), next, size);
+			ohci_readl (&regs->intrenable), next, size);
 	// intrdisable always same as intrenable
 
 	maybe_print_eds (controller, "ed_periodcurrent",
-			readl (&regs->ed_periodcurrent), next, size);
+			ohci_readl (&regs->ed_periodcurrent), next, size);
 
 	maybe_print_eds (controller, "ed_controlhead",
-			readl (&regs->ed_controlhead), next, size);
+			ohci_readl (&regs->ed_controlhead), next, size);
 	maybe_print_eds (controller, "ed_controlcurrent",
-			readl (&regs->ed_controlcurrent), next, size);
+			ohci_readl (&regs->ed_controlcurrent), next, size);
 
 	maybe_print_eds (controller, "ed_bulkhead",
-			readl (&regs->ed_bulkhead), next, size);
+			ohci_readl (&regs->ed_bulkhead), next, size);
 	maybe_print_eds (controller, "ed_bulkcurrent",
-			readl (&regs->ed_bulkcurrent), next, size);
+			ohci_readl (&regs->ed_bulkcurrent), next, size);
 
 	maybe_print_eds (controller, "donehead",
-			readl (&regs->donehead), next, size);
+			ohci_readl (&regs->donehead), next, size);
 }
 
 #define dbg_port_sw(hc,num,value,next,size) \
@@ -637,7 +637,7 @@
 			"hcca frame 0x%04x\n", OHCI_FRAME_NO(ohci->hcca));
 
 	/* other registers mostly affect frame timings */
-	rdata = readl (&regs->fminterval);
+	rdata = ohci_readl (&regs->fminterval);
 	temp = scnprintf (next, size,
 			"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
 			rdata, (rdata >> 31) ? " FIT" : "",
@@ -645,20 +645,20 @@
 	size -= temp;
 	next += temp;
 
-	rdata = readl (&regs->fmremaining);
+	rdata = ohci_readl (&regs->fmremaining);
 	temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
 			rdata, (rdata >> 31) ? " FRT" : "",
 			rdata & 0x3fff);
 	size -= temp;
 	next += temp;
 
-	rdata = readl (&regs->periodicstart);
+	rdata = ohci_readl (&regs->periodicstart);
 	temp = scnprintf (next, size, "periodicstart 0x%04x\n",
 			rdata & 0x3fff);
 	size -= temp;
 	next += temp;
 
-	rdata = readl (&regs->lsthresh);
+	rdata = ohci_readl (&regs->lsthresh);
 	temp = scnprintf (next, size, "lsthresh 0x%04x\n",
 			rdata & 0x3fff);
 	size -= temp;
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/host/ohci-hcd.c	2004-06-23 19:04:25 -07:00
@@ -17,6 +17,7 @@
  *
  * History:
  * 
+ * 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer)
  * 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net)
  * 2003/02/24 show registers in sysfs (Kevin Brosius)
  *
@@ -393,7 +394,7 @@
 
 	/* boot firmware should have set this up (5.1.1.3.1) */
 	if (!ohci->fminterval) {
-		temp = readl (&ohci->regs->fminterval);
+		temp = ohci_readl (&ohci->regs->fminterval);
 		if (temp & 0x3fff0000)
 			ohci->fminterval = temp;
 		else
@@ -405,7 +406,7 @@
 	 * On PA-RISC, PDC can leave IR set incorrectly; ignore it there.
 	 */
 #ifndef __hppa__
-	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+	if (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
 		ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
 
 		/* this timeout is arbitrary.  we make it long, so systems
@@ -416,7 +417,7 @@
 
 		writel (OHCI_INTR_OC, &ohci->regs->intrenable);
 		writel (OHCI_OCR, &ohci->regs->cmdstatus);
-		while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+		while (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
 			msleep (10);
 			if (--temp == 0) {
 				ohci_err (ohci, "USB HC TakeOver failed!\n");
@@ -430,13 +431,13 @@
 	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
 
 	ohci_dbg (ohci, "reset, control = 0x%x\n",
-		readl (&ohci->regs->control));
+		  ohci_readl (&ohci->regs->control));
 
   	/* Reset USB (needed by some controllers); RemoteWakeupConnected
 	 * saved if boot firmware (BIOS/SMM/...) told us it's connected
 	 * (for OHCI integrated on mainboard, it normally is)
 	 */
-	ohci->hc_control = readl (&ohci->regs->control);
+	ohci->hc_control = ohci_readl (&ohci->regs->control);
 	ohci->hc_control &= OHCI_CTRL_RWC;	/* hcfs 0 = RESET */
 	if (ohci->hc_control)
 		ohci->hcd.can_wakeup = 1;
@@ -450,13 +451,13 @@
 				&ohci->regs->roothub.portstatus [temp]);
 	}
 	// flush those pci writes
-	(void) readl (&ohci->regs->control);
+	(void) ohci_readl (&ohci->regs->control);
 	msleep (50);
 
 	/* HC Reset requires max 10 us delay */
 	writel (OHCI_HCR,  &ohci->regs->cmdstatus);
 	temp = 30;	/* ... allow extra time */
-	while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+	while ((ohci_readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
 		if (--temp == 0) {
 			ohci_err (ohci, "USB HC reset timed out!\n");
 			return -1;
@@ -473,7 +474,7 @@
 	 */
 	writel (ohci->hc_control, &ohci->regs->control);
 	// flush those pci writes
-	(void) readl (&ohci->regs->control);
+	(void) ohci_readl (&ohci->regs->control);
 
 	return 0;
 }
@@ -505,8 +506,8 @@
 	/* some OHCI implementations are finicky about how they init.
 	 * bogus values here mean not even enumeration could work.
 	 */
-	if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
-			|| !readl (&ohci->regs->periodicstart)) {
+	if ((ohci_readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
+			|| !ohci_readl (&ohci->regs->periodicstart)) {
 		ohci_err (ohci, "init err\n");
 		return -EOVERFLOW;
 	}
@@ -548,7 +549,7 @@
 	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
 	writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b);
 	// flush those pci writes
-	(void) readl (&ohci->regs->control);
+	(void) ohci_readl (&ohci->regs->control);
 
 	// POTPGT delay is bits 24-31, in 2 ms units.
 	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
@@ -560,7 +561,7 @@
 	}
  
 	/* connect the virtual root hub */
-	bus->root_hub = udev = usb_alloc_dev (NULL, bus, 0);
+	udev = usb_alloc_dev (NULL, bus, 0);
 	ohci->hcd.state = USB_STATE_RUNNING;
 	if (!udev) {
 		disable (ohci);
@@ -570,9 +571,8 @@
 	}
 
 	udev->speed = USB_SPEED_FULL;
-	if (hcd_register_root (&ohci->hcd) != 0) {
+	if (hcd_register_root (udev, &ohci->hcd) != 0) {
 		usb_put_dev (udev);
-		bus->root_hub = NULL;
 		disable (ohci);
 		ohci->hc_control &= ~OHCI_CTRL_HCFS;
 		writel (ohci->hc_control, &ohci->regs->control);
@@ -592,19 +592,20 @@
 	struct ohci_regs	*regs = ohci->regs;
  	int			ints; 
 
-	/* we can eliminate a (slow) readl() if _only_ WDH caused this irq */
+	/* we can eliminate a (slow) ohci_readl()
+	   if _only_ WDH caused this irq */
 	if ((ohci->hcca->done_head != 0)
 			&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
 		ints =  OHCI_INTR_WDH;
 
 	/* cardbus/... hardware gone before remove() */
-	} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+	} else if ((ints = ohci_readl (&regs->intrstatus)) == ~(u32)0) {
 		disable (ohci);
 		ohci_dbg (ohci, "device removed!\n");
 		return IRQ_HANDLED;
 
 	/* interrupt for some other device? */
-	} else if ((ints &= readl (&regs->intrenable)) == 0) {
+	} else if ((ints &= ohci_readl (&regs->intrenable)) == 0) {
 		return IRQ_NONE;
 	} 
 
@@ -650,7 +651,7 @@
 		writel (ints, &regs->intrstatus);
 		writel (OHCI_INTR_MIE, &regs->intrenable);	
 		// flush those pci writes
-		(void) readl (&ohci->regs->control);
+		(void) ohci_readl (&ohci->regs->control);
 	}
 
 	return IRQ_HANDLED;
@@ -798,6 +799,14 @@
 #include "ohci-omap.c"
 #endif
 
-#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111) || defined(CONFIG_ARCH_OMAP))
+#ifdef CONFIG_ARCH_LH7A404
+#include "ohci-lh7a404.c"
+#endif
+
+#if !(defined(CONFIG_PCI) \
+      || defined(CONFIG_SA1111) \
+      || defined(CONFIG_ARCH_OMAP) \
+      || defined (CONFIG_ARCH_LH7A404) \
+	)
 #error "missing bus glue for ohci-hcd"
 #endif
diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
--- a/drivers/usb/host/ohci-hub.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/host/ohci-hub.c	2004-06-23 19:04:25 -07:00
@@ -20,20 +20,20 @@
  * till some bits (mostly reserved) are clear; ok for all revs.
  */
 #define read_roothub(hc, register, mask) ({ \
-	u32 temp = readl (&hc->regs->roothub.register); \
+	u32 temp = ohci_readl (&hc->regs->roothub.register); \
 	if (temp == -1) \
 		disable (hc); \
 	else if (hc->flags & OHCI_QUIRK_AMD756) \
 		while (temp & mask) \
-			temp = readl (&hc->regs->roothub.register); \
+			temp = ohci_readl (&hc->regs->roothub.register); \
 	temp; })
 
 static u32 roothub_a (struct ohci_hcd *hc)
 	{ return read_roothub (hc, a, 0xfc0fe000); }
 static inline u32 roothub_b (struct ohci_hcd *hc)
-	{ return readl (&hc->regs->roothub.b); }
+	{ return ohci_readl (&hc->regs->roothub.b); }
 static inline u32 roothub_status (struct ohci_hcd *hc)
-	{ return readl (&hc->regs->roothub.status); }
+	{ return ohci_readl (&hc->regs->roothub.status); }
 static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
 	{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
 
@@ -83,14 +83,14 @@
 
 	spin_lock_irq (&ohci->lock);
 
-	ohci->hc_control = readl (&ohci->regs->control);
+	ohci->hc_control = ohci_readl (&ohci->regs->control);
 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
 	case OHCI_USB_RESUME:
 		ohci_dbg (ohci, "resume/suspend?\n");
 		ohci->hc_control &= ~OHCI_CTRL_HCFS;
 		ohci->hc_control |= OHCI_USB_RESET;
 		writel (ohci->hc_control, &ohci->regs->control);
-		(void) readl (&ohci->regs->control);
+		(void) ohci_readl (&ohci->regs->control);
 		/* FALL THROUGH */
 	case OHCI_USB_RESET:
 		status = -EBUSY;
@@ -109,7 +109,7 @@
 
 		ohci->hc_control &= ~OHCI_SCHED_ENABLES;
 		writel (ohci->hc_control, &ohci->regs->control);
-		ohci->hc_control = readl (&ohci->regs->control);
+		ohci->hc_control = ohci_readl (&ohci->regs->control);
 		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
 
 		/* sched disables take effect on the next frame,
@@ -120,7 +120,7 @@
 		while (limit > 0) {
 			udelay (250);
 			limit =- 250;
-			if (readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
+			if (ohci_readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
 				break;
 		}
 		dl_done_list (ohci, 0);
@@ -128,7 +128,7 @@
 	}
 	dl_done_list (ohci, 0);
 	finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca), 0);
-	writel (readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
+	writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
 
 	/* maybe resume can wake root hub */
 	if (ohci->hcd.remote_wakeup)
@@ -140,7 +140,7 @@
 	ohci->hc_control &= ~OHCI_CTRL_HCFS;
 	ohci->hc_control |= OHCI_USB_SUSPEND;
 	writel (ohci->hc_control, &ohci->regs->control);
-	(void) readl (&ohci->regs->control);
+	(void) ohci_readl (&ohci->regs->control);
 
 	/* no resumes until devices finish suspending */
 	ohci->next_statechange = jiffies + msecs_to_jiffies (5);
@@ -179,13 +179,13 @@
 		return -EAGAIN;
 
 	spin_lock_irq (&ohci->lock);
-	ohci->hc_control = readl (&ohci->regs->control);
+	ohci->hc_control = ohci_readl (&ohci->regs->control);
 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
 	case OHCI_USB_SUSPEND:
 		ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
 		ohci->hc_control |= OHCI_USB_RESUME;
 		writel (ohci->hc_control, &ohci->regs->control);
-		(void) readl (&ohci->regs->control);
+		(void) ohci_readl (&ohci->regs->control);
 		ohci_dbg (ohci, "resume root hub\n");
 		break;
 	case OHCI_USB_RESUME:
@@ -210,7 +210,7 @@
 	temp = roothub_a (ohci) & RH_A_NDP;
 	enables = 0;
 	while (temp--) {
-		u32 stat = readl (&ohci->regs->roothub.portstatus [temp]);
+		u32 stat = ohci_readl (&ohci->regs->roothub.portstatus [temp]);
 
 		/* force global, not selective, resume */
 		if (!(stat & RH_PS_PSS))
@@ -222,7 +222,7 @@
 	ohci->hcd.state = USB_STATE_RESUMING;
 	mdelay (20 /* usb 11.5.1.10 */ + 15);
 
-	temp = readl (&ohci->regs->control);
+	temp = ohci_readl (&ohci->regs->control);
 	temp &= OHCI_CTRL_HCFS;
 	if (temp != OHCI_USB_RESUME) {
 		ohci_err (ohci, "controller won't resume\n");
@@ -243,11 +243,11 @@
 	writel (OHCI_INTR_INIT, &ohci->regs->intrenable);
 	if (ohci->ed_rm_list)
 		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-	writel (readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
+	writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
 
 	/* Then re-enable operations */
 	writel (OHCI_USB_OPER, &ohci->regs->control);
-	(void) readl (&ohci->regs->control);
+	(void) ohci_readl (&ohci->regs->control);
 	msleep (3);
 
 	temp = OHCI_CONTROL_INIT | OHCI_USB_OPER;
@@ -255,7 +255,7 @@
 		temp |= OHCI_CTRL_RWC;
 	ohci->hc_control = temp;
 	writel (temp, &ohci->regs->control);
-	(void) readl (&ohci->regs->control);
+	(void) ohci_readl (&ohci->regs->control);
 
 	/* TRSMRCY */
 	msleep (10);
@@ -290,7 +290,7 @@
 		writel (ohci->hc_control, &ohci->regs->control);
 		if (temp)
 			writel (status, &ohci->regs->cmdstatus);
-		(void) readl (&ohci->regs->control);
+		(void) ohci_readl (&ohci->regs->control);
 	}
 
 	ohci->hcd.state = USB_STATE_RUNNING;
@@ -332,7 +332,7 @@
 		if (!HCD_IS_RUNNING(ohci->hcd.state))
 			return -ESHUTDOWN;
 		ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
-			ports, readl (&ohci->regs->roothub.a) & RH_A_NDP);
+			ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP);
 		/* retry later; "should not happen" */
 		return 0;
 	}
@@ -496,7 +496,7 @@
 			goto error;
 		}
 		writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
-		// readl (&ohci->regs->roothub.portstatus [wIndex]);
+		// ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
 		break;
 	case GetHubDescriptor:
 		ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
@@ -541,7 +541,7 @@
 				&ohci->regs->roothub.portstatus [wIndex]);
 			break;
 		case USB_PORT_FEAT_RESET:
-			temp = readl (&ohci->regs->roothub.portstatus [wIndex]);
+			temp = ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
 			if (temp & RH_PS_CCS)
 				writel (RH_PS_PRS,
 				    &ohci->regs->roothub.portstatus [wIndex]);
diff -Nru a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/host/ohci-lh7a404.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,385 @@
+/*
+ * 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
+ *
+ * Bus Glue for Sharp LH7A404
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ * Based on fragments of previous driver by Rusell King et al.
+ *
+ * Modified for LH7A404 from ohci-sa1111.c
+ *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/hardware.h>
+
+
+extern int usb_disabled(void);
+
+/*-------------------------------------------------------------------------*/
+
+static void lh7a404_start_hc(struct platform_device *dev)
+{
+	printk(KERN_DEBUG __FILE__
+	       ": starting LH7A404 OHCI USB Controller\n");
+
+	/*
+	 * Now, carefully enable the USB clock, and take
+	 * the USB host controller out of reset.
+	 */
+	CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */
+	udelay(1000);
+	USBH_CMDSTATUS = OHCI_HCR;
+	
+	printk(KERN_DEBUG __FILE__
+		   ": Clock to USB host has been enabled \n");
+}
+
+static void lh7a404_stop_hc(struct platform_device *dev)
+{
+	printk(KERN_DEBUG __FILE__
+	       ": stopping LH7A404 OHCI USB Controller\n");
+
+	CSC_PWRCNT &= ~CSC_PWRCNT_USBH_EN; /* Disable clock */
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+
+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 */
+
+
+/**
+ * usb_hcd_lh7a404_probe - initialize LH7A404-based 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.
+ *
+ */
+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;
+
+	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;
+	}
+	
+
+	hcd = driver->hcd_alloc ();
+	if (hcd == NULL){
+		pr_debug ("hcd_alloc 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->driver = (struct hc_driver *) driver;
+	hcd->description = driver->description;
+	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 err1;
+	}
+
+	retval = request_irq (hcd->irq, usb_hcd_lh7a404_hcim_irq, SA_INTERRUPT,
+			      hcd->description, hcd);
+	if (retval != 0) {
+		pr_debug("request_irq failed");
+		retval = -EBUSY;
+		goto err2;
+	}
+
+	pr_debug ("%s (LH7A404) at 0x%p, irq %d",
+	     hcd->description, hcd->regs, hcd->irq);
+
+	usb_bus_init (&hcd->self);
+	hcd->self.op = &usb_hcd_operations;
+	hcd->self.hcpriv = (void *) hcd;
+	hcd->self.bus_name = "lh7a404";
+	hcd->product_desc = "LH7A404 OHCI";
+
+	INIT_LIST_HEAD (&hcd->dev_list);
+
+	usb_register_bus (&hcd->self);
+
+	if ((retval = driver->start (hcd)) < 0)
+	{
+		usb_hcd_lh7a404_remove(hcd, dev);
+		return retval;
+	}
+
+	*hcd_out = hcd;
+	return 0;
+
+ err2:
+	hcd_buffer_destroy (hcd);
+	if (hcd)
+		driver->hcd_free(hcd);
+ err1:
+	lh7a404_stop_hc(dev);
+	release_mem_region(dev->resource[0].start,
+				dev->resource[0].end
+			   - dev->resource[0].start + 1);
+	return retval;
+}
+
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_hcd_lh7a404_remove - shutdown processing for LH7A404-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_lh7a404_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+void usb_hcd_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev)
+{
+	void *base;
+
+	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);
+
+	base = hcd->regs;
+	hcd->driver->hcd_free (hcd);
+
+	lh7a404_stop_hc(dev);
+	release_mem_region(dev->resource[0].start,
+			   dev->resource[0].end
+			   - dev->resource[0].start + 1);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __devinit
+ohci_lh7a404_start (struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+	int		ret;
+
+	ohci_dbg (ohci, "ohci_lh7a404_start, ohci:%p", ohci);
+			
+	ohci->hcca = dma_alloc_coherent (hcd->self.controller,
+			sizeof *ohci->hcca, &ohci->hcca_dma, 0);
+	if (!ohci->hcca)
+		return -ENOMEM;
+
+	ohci_dbg (ohci, "ohci_lh7a404_start, ohci->hcca:%p",
+			ohci->hcca);
+
+	memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
+
+	if ((ret = ohci_mem_init (ohci)) < 0) {
+		ohci_stop (hcd);
+		return ret;
+	}
+	ohci->regs = hcd->regs;
+
+	if (hc_reset (ohci) < 0) {
+		ohci_stop (hcd);
+		return -ENODEV;
+	}
+
+	if (hc_start (ohci) < 0) {
+		err ("can't start %s", ohci->hcd.self.bus_name);
+		ohci_stop (hcd);
+		return -EBUSY;
+	}
+	create_debug_files (ohci);
+
+#ifdef	DEBUG
+	ohci_dump (ohci, 1);
+#endif /*DEBUG*/
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct hc_driver ohci_lh7a404_hc_driver = {
+	.description =		hcd_name,
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ohci_irq,
+	.flags =		HCD_USB11,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.start =		ohci_lh7a404_start,
+#ifdef	CONFIG_PM
+	/* suspend:		ohci_lh7a404_suspend,  -- tbd */
+	/* resume:		ohci_lh7a404_resume,   -- tbd */
+#endif /*CONFIG_PM*/
+	.stop =			ohci_stop,
+
+	/*
+	 * memory lifecycle (except per-request)
+	 */
+	.hcd_alloc =		ohci_hcd_alloc,
+	.hcd_free =		ohci_hcd_free,
+
+	/*
+	 * 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,
+};
+
+/*-------------------------------------------------------------------------*/
+
+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");
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, &hcd, pdev);
+
+	if (ret == 0)
+		dev_set_drvdata(dev, hcd);
+
+	return ret;
+}
+
+static int ohci_hcd_lh7a404_drv_remove(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	usb_hcd_lh7a404_remove(hcd, pdev);
+	dev_set_drvdata(dev, NULL);
+	return 0;
+}
+	/*TBD*/
+/*static int ohci_hcd_lh7a404_drv_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	return 0;
+}
+static int ohci_hcd_lh7a404_drv_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+
+	return 0;
+}
+*/
+
+static struct device_driver ohci_hcd_lh7a404_driver = {
+	.name		= "lh7a404-ohci",
+	.bus		= &platform_bus_type,
+	.probe		= ohci_hcd_lh7a404_drv_probe,
+	.remove		= ohci_hcd_lh7a404_drv_remove,
+	/*.suspend	= ohci_hcd_lh7a404_drv_suspend, */
+	/*.resume	= ohci_hcd_lh7a404_drv_resume, */
+};
+
+static int __init ohci_hcd_lh7a404_init (void)
+{
+	pr_debug (DRIVER_INFO " (LH7A404)");
+	pr_debug ("block sizes: ed %d td %d\n",
+		sizeof (struct ed), sizeof (struct td));
+
+	return driver_register(&ohci_hcd_lh7a404_driver);
+}
+
+static void __exit ohci_hcd_lh7a404_cleanup (void)
+{
+	driver_unregister(&ohci_hcd_lh7a404_driver);
+}
+
+module_init (ohci_hcd_lh7a404_init);
+module_exit (ohci_hcd_lh7a404_cleanup);
diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
--- a/drivers/usb/host/ohci-omap.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/host/ohci-omap.c	2004-06-23 19:04:27 -07:00
@@ -454,7 +454,6 @@
  */
 void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
 {
-	struct usb_device	*hub;
 	void *base;
 
 	info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
@@ -462,11 +461,10 @@
 	if (in_interrupt ())
 		BUG ();
 
-	hub = hcd->self.root_hub;
 	hcd->state = USB_STATE_QUIESCING;
 
 	dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
-	usb_disconnect (&hub);
+	usb_disconnect (&hcd->self.root_hub);
 
 	hcd->driver->stop (hcd);
 	hcd_buffer_destroy (hcd);
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/host/ohci-q.c	2004-06-23 19:04:28 -07:00
@@ -321,7 +321,7 @@
 			if (!ed->hwNextED) {
 				ohci->hc_control &= ~OHCI_CTRL_CLE;
 				writel (ohci->hc_control, &ohci->regs->control);
-				// a readl() later syncs CLE with the HC
+				// a ohci_readl() later syncs CLE with the HC
 			} else
 				writel (le32_to_cpup (&ed->hwNextED),
 					&ohci->regs->ed_controlhead);
@@ -345,7 +345,7 @@
 			if (!ed->hwNextED) {
 				ohci->hc_control &= ~OHCI_CTRL_BLE;
 				writel (ohci->hc_control, &ohci->regs->control);
-				// a readl() later syncs BLE with the HC
+				// a ohci_readl() later syncs BLE with the HC
 			} else
 				writel (le32_to_cpup (&ed->hwNextED),
 					&ohci->regs->ed_bulkhead);
@@ -481,7 +481,7 @@
 	writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
 	writel (OHCI_INTR_SF, &ohci->regs->intrenable);
 	// flush those writes, and get latest HCCA contents
-	(void) readl (&ohci->regs->control);
+	(void) ohci_readl (&ohci->regs->control);
 
 	/* SF interrupt might get delayed; record the frame counter value that
 	 * indicates when the HC isn't looking at it, so concurrent unlinks
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/host/ohci-sa1111.c	2004-06-23 19:04:27 -07:00
@@ -237,7 +237,6 @@
  */
 void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
 {
-	struct usb_device	*hub;
 	void *base;
 
 	info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
@@ -245,11 +244,10 @@
 	if (in_interrupt ())
 		BUG ();
 
-	hub = hcd->self.root_hub;
 	hcd->state = USB_STATE_QUIESCING;
 
 	dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
-	usb_disconnect (&hub);
+	usb_disconnect (&hcd->self.root_hub);
 
 	hcd->driver->stop (hcd);
 	hcd->state = USB_STATE_HALT;
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h	2004-06-23 19:04:29 -07:00
+++ b/drivers/usb/host/ohci.h	2004-06-23 19:04:29 -07:00
@@ -429,3 +429,22 @@
 #	define ohci_vdbg(ohci, fmt, args...) do { } while (0)
 #endif
 
+#ifdef CONFIG_ARCH_LH7A404
+	/* Marc Singer: at the time this code was written, the LH7A404
+	 * had a problem reading the USB host registers.  This
+	 * implementation of the ohci_readl function performs the read
+	 * twice as a work-around.
+	 */
+static inline unsigned int ohci_readl (void* regs)
+{
+	*(volatile unsigned int*) regs;
+	return *(volatile unsigned int*) regs;
+}
+#else
+	/* Standard version of ohci_readl uses standard, platform
+	 * specific implementation. */
+static inline unsigned int ohci_readl (void* regs)
+{
+	return readl (regs);
+}
+#endif
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/host/uhci-hcd.c	2004-06-23 19:04:28 -07:00
@@ -103,8 +103,8 @@
 static void hc_state_transitions(struct uhci_hcd *uhci);
 
 /* If a transfer is still active after this much time, turn off FSBR */
-#define IDLE_TIMEOUT	(HZ / 20)	/* 50 ms */
-#define FSBR_DELAY	(HZ / 20)	/* 50 ms */
+#define IDLE_TIMEOUT	msecs_to_jiffies(50)
+#define FSBR_DELAY	msecs_to_jiffies(50)
 
 /* When we timeout an idle transfer for FSBR, we'll switch it over to */
 /* depth first traversal. We'll do it in groups of this number of TD's */
@@ -1611,6 +1611,7 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	struct list_head list, *tmp, *head;
 	unsigned long flags;
+	int called_uhci_finish_completion = 0;
 
 	INIT_LIST_HEAD(&list);
 
@@ -1619,6 +1620,7 @@
 	    uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) {
 		uhci_remove_pending_urbps(uhci);
 		uhci_finish_completion(hcd, NULL);
+		called_uhci_finish_completion = 1;
 	}
 
 	head = &uhci->urb_list;
@@ -1646,6 +1648,10 @@
 	}
 	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
 
+	/* Wake up anyone waiting for an URB to complete */
+	if (called_uhci_finish_completion)
+		wake_up_all(&uhci->waitqh);
+
 	head = &list;
 	tmp = head->next;
 	while (tmp != head) {
@@ -1676,7 +1682,7 @@
 	init_timer(&uhci->stall_timer);
 	uhci->stall_timer.function = stall_callback;
 	uhci->stall_timer.data = (unsigned long)hcd;
-	uhci->stall_timer.expires = jiffies + (HZ / 10);
+	uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
 	add_timer(&uhci->stall_timer);
 
 	return 0;
@@ -1831,16 +1837,20 @@
 {
 	unsigned int io_addr = uhci->io_addr;
 
+	/* Turn off PIRQ, SMI, and all interrupts.  This also turns off
+	 * the BIOS's USB Legacy Support.
+	 */
+	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
+	outw(0, uhci->io_addr + USBINTR);
+
 	/* Global reset for 50ms */
 	uhci->state = UHCI_RESET;
 	outw(USBCMD_GRESET, io_addr + USBCMD);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((HZ*50+999) / 1000);
+	msleep(50);
 	outw(0, io_addr + USBCMD);
 
 	/* Another 10ms delay */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((HZ*10+999) / 1000);
+	msleep(10);
 	uhci->resume_detect = 0;
 }
 
@@ -1865,7 +1875,7 @@
 			/* Global resume for >= 20ms */
 			outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD);
 			uhci->state = UHCI_RESUMING_1;
-			uhci->state_end = jiffies + (20*HZ+999) / 1000;
+			uhci->state_end = jiffies + msecs_to_jiffies(20);
 			break;
 
 		case UHCI_RESUMING_1:		/* End global resume */
@@ -1990,7 +2000,9 @@
 		}
 	}
 
-	/* Turn on all interrupts */
+	/* Turn on PIRQ and all interrupts */
+	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+			USBLEGSUP_DEFAULT);
 	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
 		io_addr + USBINTR);
 
@@ -2054,15 +2066,10 @@
 
 	uhci->io_addr = (unsigned long) hcd->regs;
 
-	/* Turn off all interrupts */
-	outw(0, uhci->io_addr + USBINTR);
-
-	/* Maybe kick BIOS off this hardware.  Then reset, so we won't get
+	/* Kick BIOS off this hardware and reset, so we won't get
 	 * interrupts from any previous setup.
 	 */
 	reset_hc(uhci);
-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
-			USBLEGSUP_DEFAULT);
 	return 0;
 }
 
@@ -2178,7 +2185,7 @@
 
 	uhci->rh_numports = port;
 
-	hcd->self.root_hub = udev = usb_alloc_dev(NULL, &hcd->self, 0);
+	udev = usb_alloc_dev(NULL, &hcd->self, 0);
 	if (!udev) {
 		dev_err(uhci_dev(uhci), "unable to allocate root hub\n");
 		goto err_alloc_root_hub;
@@ -2260,7 +2267,7 @@
 
 	udev->speed = USB_SPEED_FULL;
 
-	if (usb_register_root_hub(udev, uhci_dev(uhci)) != 0) {
+	if (hcd_register_root(udev, &uhci->hcd) != 0) {
 		dev_err(uhci_dev(uhci), "unable to start root hub\n");
 		retval = -ENOMEM;
 		goto err_start_root_hub;
@@ -2288,7 +2295,6 @@
 
 err_alloc_term_td:
 	usb_put_dev(udev);
-	hcd->self.root_hub = NULL;
 
 err_alloc_root_hub:
 	dma_pool_destroy(uhci->qh_pool);
@@ -2369,14 +2375,18 @@
 		/*
 		 * Some systems don't maintain the UHCI register values
 		 * during a PM suspend/resume cycle, so reinitialize
-		 * the Frame Number, the Framelist Base Address, and the
-		 * Interrupt Enable registers.
+		 * the Frame Number, Framelist Base Address, Interrupt
+		 * Enable, and Legacy Support registers.
 		 */
+		pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+				0);
 		outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM);
 		outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
 		outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
 				USBINTR_SP, uhci->io_addr + USBINTR);
 		uhci->resume_detect = 1;
+		pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+				USBLEGSUP_DEFAULT);
 	} else {
 		reset_hc(uhci);
 		start_hc(uhci);
diff -Nru a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
--- a/drivers/usb/image/mdc800.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/image/mdc800.c	2004-06-23 19:04:27 -07:00
@@ -667,10 +667,10 @@
 /*
  * The Device read callback Function
  */
-static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, loff_t *pos)
+static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t len, loff_t *pos)
 {
 	size_t left=len, sts=len; /* single transfer size */
-	char* ptr=buf;
+	char __user *ptr = buf;
 	long timeout;
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -767,7 +767,7 @@
  * After this the driver initiates the request for the answer or
  * just waits until the camera becomes ready.
  */
-static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos)
+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);
diff -Nru a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
--- a/drivers/usb/input/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/input/Kconfig	2004-06-23 19:04:28 -07:00
@@ -219,14 +219,16 @@
 	  module will be called xpad.
 	  
 config USB_ATI_REMOTE
-	tristate "ATI USB RF remote control"
+	tristate "ATI / X10 USB RF remote control"
 	depends on USB && INPUT
 	---help---
-	  Say Y here if you want to use one of ATI's USB remote controls.
-	  These are RF remotes with USB receivers. They come with many of ATI's 
-	  All-In-Wonder video cards.  This driver provides mouse pointer, left
-          and right mouse buttons, and maps all the other remote buttons to
-	  keypress events.
+	  Say Y here if you want to use an ATI or X10 "Lola" USB remote control.
+	  These are RF remotes with USB receivers. 
+	  The ATI remote comes with many of ATI's All-In-Wonder video cards.
+	  The X10 "Lola" remote is available at:
+	     http://www.x10.com/products/lola_sg1.htm
+	  This driver provides mouse pointer, left and right mouse buttons, 
+	  and maps all the other remote buttons to keypress events.
 	  
 	  To compile this driver as a module, choose M here: the module will be
 	  called ati_remote.
diff -Nru a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
--- a/drivers/usb/input/ati_remote.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/input/ati_remote.c	2004-06-23 19:04:27 -07:00
@@ -16,6 +16,12 @@
  *
  *  Feb 2004: Torrey Hoffman <thoffman@arnor.net>
  *            Version 2.2.0
+ *  Jun 2004: Torrey Hoffman <thoffman@arnor.net>
+ *            Version 2.2.1
+ *            Added key repeat support contributed by:
+ *                Vincent Vanackere <vanackere@lif.univ-mrs.fr>
+ *            Added support for the "Lola" remote contributed by:
+ *                Seth Cohn <sethcohn@yahoo.com>
  *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
  *
@@ -41,6 +47,11 @@
  * "All-In-Wonder" video card packages.  The receiver self-identifies as a 
  * "USB Receiver" with manufacturer "X10 Wireless Technology Inc".
  *
+ * The "Lola" remote is available from X10.  See: 
+ *    http://www.x10.com/products/lola_sg1.htm
+ * The Lola is similar to the ATI remote but has no mouse support, and slightly
+ * different keys.
+ *
  * It is possible to use multiple receivers and remotes on multiple computers 
  * simultaneously by configuring them to use specific channels.
  * 
@@ -90,8 +101,9 @@
  
 #define ATI_REMOTE_VENDOR_ID 	0x0bc7
 #define ATI_REMOTE_PRODUCT_ID 	0x004
+#define LOLA_REMOTE_PRODUCT_ID 	0x002
 
-#define DRIVER_VERSION 	        "2.2.0"
+#define DRIVER_VERSION 	        "2.2.1"
 #define DRIVER_AUTHOR           "Torrey Hoffman <thoffman@arnor.net>"
 #define DRIVER_DESC             "ATI/X10 RF USB Remote Control"
 
@@ -113,6 +125,7 @@
  
 static struct usb_device_id ati_remote_table[] = {
 	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) },
 	{}	/* Terminating entry */
 };
 
@@ -134,10 +147,13 @@
 
 /* Duplicate event filtering time. 
  * Sequential, identical KIND_FILTERED inputs with less than
- * FILTER_TIME jiffies between them are dropped.  
- * (HZ >> 4) == 1/16th of a second and works well for me.
+ * FILTER_TIME jiffies between them are considered as repeat
+ * events. The hardware generates 5 events for the first keypress
+ * and we have to take this into account for an accurate repeat
+ * behaviour.
+ * (HZ / 20) == 50 ms and works well for me.
  */
-#define FILTER_TIME (HZ >> 4)
+#define FILTER_TIME (HZ / 20)
 
 static DECLARE_MUTEX(disconnect_sem);
 
@@ -161,6 +177,7 @@
 	unsigned char old_data[2];  /* Detect duplicate events */
 	unsigned long old_jiffies;
 	unsigned long acc_jiffies;  /* handle acceleration */
+	unsigned int repeat_count;
 	
 	char name[NAME_BUFSIZE];
 	char phys[NAME_BUFSIZE];
@@ -256,6 +273,12 @@
 	{KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1},    /* (>>) */
 	{KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1},       /* ([]) */ 
 	{KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1},      /* ('') */
+	{KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1},   /* (<-) */
+	{KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1},       /* (>+) */
+	{KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1},       /* PLAYING */
+	{KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1},       /* TOP */
+	{KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1},        /* END */
+	{KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1},     /* SELECT */	
 	
 	{KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0}
 };
@@ -483,9 +506,20 @@
 		if ((ati_remote->old_data[0] == data[1]) && 
 	 		(ati_remote->old_data[1] == data[2]) && 
 	 		((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) {
-			ati_remote->old_jiffies = jiffies;			
+			ati_remote->repeat_count++;
+		} 
+		else {
+			ati_remote->repeat_count = 0;
+		}
+		
+		ati_remote->old_data[0] = data[1];
+		ati_remote->old_data[1] = data[2];
+		ati_remote->old_jiffies = jiffies;
+
+		if ((ati_remote->repeat_count > 0)
+		    && (ati_remote->repeat_count < 5))
 			return;
-		}		
+		
 
 		input_regs(dev, regs);
 		input_event(dev, ati_remote_tbl[index].type,
@@ -494,9 +528,6 @@
 			ati_remote_tbl[index].code, 0);
 		input_sync(dev);
 
-		ati_remote->old_data[0] = data[1];
-		ati_remote->old_data[1] = data[2];
-		ati_remote->old_jiffies = jiffies;
 		return;
 	}			
 	
@@ -697,9 +728,9 @@
 
 	/* See if the offered device matches what we can accept */
 	if ((udev->descriptor.idVendor != ATI_REMOTE_VENDOR_ID) ||
-	    (udev->descriptor.idProduct != ATI_REMOTE_PRODUCT_ID)) {
+		( (udev->descriptor.idProduct != ATI_REMOTE_PRODUCT_ID) &&
+		  (udev->descriptor.idProduct != LOLA_REMOTE_PRODUCT_ID) ))
 		return -ENODEV;
-	}
 
 	/* Allocate and clear an ati_remote struct */
 	if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL)))
@@ -856,4 +887,3 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/input/hid-core.c	2004-06-23 19:04:27 -07:00
@@ -1324,12 +1324,14 @@
 	}
 
 	err = 0;
-	while ((ret = hid_wait_io(hid))) {
+	ret = hid_wait_io(hid);
+	while (ret) {
 		err |= ret;
 		if (test_bit(HID_CTRL_RUNNING, &hid->iofl))
 			usb_unlink_urb(hid->urbctrl);
 		if (test_bit(HID_OUT_RUNNING, &hid->iofl))
 			usb_unlink_urb(hid->urbout);
+		ret = hid_wait_io(hid);
 	}
 
 	if (err)
diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- a/drivers/usb/input/hiddev.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/input/hiddev.c	2004-06-23 19:04:26 -07:00
@@ -295,7 +295,7 @@
 /*
  * "write" file op
  */
-static ssize_t hiddev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos)
+static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
 {
 	return -EINVAL;
 }
@@ -303,7 +303,7 @@
 /*
  * "read" file op
  */
-static ssize_t hiddev_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
+static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct hiddev_list *list = file->private_data;
@@ -406,6 +406,7 @@
 	struct hiddev_devinfo dinfo;
 	struct hid_report *report;
 	struct hid_field *field;
+	void __user *user_arg = (void __user *)arg;
 	int i;
 
 	if (!hiddev->exist)
@@ -414,7 +415,7 @@
 	switch (cmd) {
 
 	case HIDIOCGVERSION:
-		return put_user(HID_VERSION, (int *) arg);
+		return put_user(HID_VERSION, (int __user *)arg);
 
 	case HIDIOCAPPLICATION:
 		if (arg < 0 || arg >= hid->maxapplication)
@@ -439,13 +440,13 @@
 		dinfo.product = dev->descriptor.idProduct;
 		dinfo.version = dev->descriptor.bcdDevice;
 		dinfo.num_applications = hid->maxapplication;
-		if (copy_to_user((void *) arg, &dinfo, sizeof(dinfo)))
+		if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
 			return -EFAULT;
 
 		return 0;
 
 	case HIDIOCGFLAG:
-		if (put_user(list->flags, (int *) arg))
+		if (put_user(list->flags, (int __user *)arg))
 			return -EFAULT;
 
 		return 0;
@@ -453,7 +454,7 @@
 	case HIDIOCSFLAG:
 		{
 			int newflags;
-			if (get_user(newflags, (int *) arg))
+			if (get_user(newflags, (int __user *)arg))
 				return -EFAULT;
 
 			if ((newflags & ~HIDDEV_FLAGS) != 0 ||
@@ -471,7 +472,7 @@
 			int idx, len;
 			char *buf;
 
-			if (get_user(idx, (int *) arg))
+			if (get_user(idx, (int __user *)arg))
 				return -EFAULT;
 
 			if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
@@ -482,7 +483,7 @@
 				return -EINVAL;
 			}
 
-			if (copy_to_user((void *) (arg+sizeof(int)), buf, len+1)) {
+			if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
 				kfree(buf);
 				return -EFAULT;
 			}
@@ -498,7 +499,7 @@
 		return 0;
 
 	case HIDIOCGREPORT:
-		if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
+		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
 			return -EFAULT;
 
 		if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
@@ -513,7 +514,7 @@
 		return 0;
 
 	case HIDIOCSREPORT:
-		if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
+		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
 			return -EFAULT;
 
 		if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
@@ -527,7 +528,7 @@
 		return 0;
 
 	case HIDIOCGREPORTINFO:
-		if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
+		if (copy_from_user(&rinfo, user_arg, sizeof(rinfo)))
 			return -EFAULT;
 
 		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
@@ -535,13 +536,13 @@
 
 		rinfo.num_fields = report->maxfield;
 
-		if (copy_to_user((void *) arg, &rinfo, sizeof(rinfo)))
+		if (copy_to_user(user_arg, &rinfo, sizeof(rinfo)))
 			return -EFAULT;
 
 		return 0;
 
 	case HIDIOCGFIELDINFO:
-		if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
+		if (copy_from_user(&finfo, user_arg, sizeof(finfo)))
 			return -EFAULT;
 		rinfo.report_type = finfo.report_type;
 		rinfo.report_id = finfo.report_id;
@@ -568,7 +569,7 @@
 		finfo.unit_exponent = field->unit_exponent;
 		finfo.unit = field->unit;
 
-		if (copy_to_user((void *) arg, &finfo, sizeof(finfo)))
+		if (copy_to_user(user_arg, &finfo, sizeof(finfo)))
 			return -EFAULT;
 
 		return 0;
@@ -578,7 +579,7 @@
 		if (!uref_multi)
 			return -ENOMEM;
 		uref = &uref_multi->uref;
-		if (copy_from_user(uref, (void *) arg, sizeof(*uref))) 
+		if (copy_from_user(uref, user_arg, sizeof(*uref))) 
 			goto fault;
 
 		rinfo.report_type = uref->report_type;
@@ -595,7 +596,7 @@
 
 		uref->usage_code = field->usage[uref->usage_index].hid;
 
-		if (copy_to_user((void *) arg, uref, sizeof(*uref)))
+		if (copy_to_user(user_arg, uref, sizeof(*uref)))
 			goto fault;
 
 		kfree(uref_multi);
@@ -611,11 +612,11 @@
 			return -ENOMEM;
 		uref = &uref_multi->uref;
 		if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
-			if (copy_from_user(uref_multi, (void *) arg, 
+			if (copy_from_user(uref_multi, user_arg, 
 					   sizeof(*uref_multi)))
 				goto fault;
 		} else {
-			if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
+			if (copy_from_user(uref, user_arg, sizeof(*uref)))
 				goto fault;
 		}
 
@@ -652,7 +653,7 @@
 		switch (cmd) {
 			case HIDIOCGUSAGE:
 				uref->value = field->value[uref->usage_index];
-				if (copy_to_user((void *) arg, uref, sizeof(*uref)))
+				if (copy_to_user(user_arg, uref, sizeof(*uref)))
 					goto fault;
 				goto goodreturn;
 
@@ -667,7 +668,7 @@
 				for (i = 0; i < uref_multi->num_values; i++)
 					uref_multi->values[i] = 
 					    field->value[uref->usage_index + i];
-				if (copy_to_user((void *) arg, uref_multi, 
+				if (copy_to_user(user_arg, uref_multi, 
 						 sizeof(*uref_multi)))
 					goto fault;
 				goto goodreturn;
@@ -689,7 +690,7 @@
 		return -EINVAL;
 
 	case HIDIOCGCOLLECTIONINFO:
-		if (copy_from_user(&cinfo, (void *) arg, sizeof(cinfo)))
+		if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
 			return -EFAULT;
 
 		if (cinfo.index >= hid->maxcollection)
@@ -699,7 +700,7 @@
 		cinfo.usage = hid->collection[cinfo.index].usage;
 		cinfo.level = hid->collection[cinfo.index].level;
 
-		if (copy_to_user((void *) arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user(user_arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
@@ -715,7 +716,7 @@
 			len = strlen(hid->name) + 1;
 			if (len > _IOC_SIZE(cmd))
 				 len = _IOC_SIZE(cmd);
-			return copy_to_user((char *) arg, hid->name, len) ?
+			return copy_to_user(user_arg, hid->name, len) ?
 				-EFAULT : len;
 		}
 
@@ -726,7 +727,7 @@
 			len = strlen(hid->phys) + 1;
 			if (len > _IOC_SIZE(cmd))
 				len = _IOC_SIZE(cmd);
-			return copy_to_user((char *) arg, hid->phys, len) ?
+			return copy_to_user(user_arg, hid->phys, len) ?
 				-EFAULT : len;
 		}
 	}
diff -Nru a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
--- a/drivers/usb/media/Kconfig	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/media/Kconfig	2004-06-23 19:04:25 -07:00
@@ -108,7 +108,7 @@
 
 config USB_PWC
 	tristate "USB Philips Cameras"
-	depends on USB && VIDEO_DEV
+	depends on USB && VIDEO_DEV && CONFIG_BROKEN
 	---help---
 	  Say Y or M here if you want to use one of these Philips & OEM
           webcams:
diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
--- a/drivers/usb/media/dabusb.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/media/dabusb.c	2004-06-23 19:04:27 -07:00
@@ -476,7 +476,7 @@
 	return 0;
 }
 
-static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t * ppos)
+static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos)
 {
 	pdabusb_t s = (pdabusb_t) file->private_data;
 	unsigned long flags;
@@ -670,7 +670,7 @@
 			break;
 		}
 
-		if (copy_from_user (pbulk, (void *) arg, sizeof (bulk_transfer_t))) {
+		if (copy_from_user (pbulk, (void __user *) arg, sizeof (bulk_transfer_t))) {
 			ret = -EFAULT;
 			kfree (pbulk);
 			break;
@@ -678,18 +678,18 @@
 
 		ret=dabusb_bulk (s, pbulk);
 		if(ret==0)
-			if (copy_to_user((void *)arg, pbulk,
+			if (copy_to_user((void __user *)arg, pbulk,
 					 sizeof(bulk_transfer_t)))
 				ret = -EFAULT;
 		kfree (pbulk);
 		break;
 
 	case IOCTL_DAB_OVERRUNS:
-		ret = put_user (s->overruns, (unsigned int *) arg);
+		ret = put_user (s->overruns, (unsigned int __user *) arg);
 		break;
 
 	case IOCTL_DAB_VERSION:
-		ret = put_user (version, (unsigned int *) arg);
+		ret = put_user (version, (unsigned int __user *) arg);
 		break;
 
 	default:
diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
--- a/drivers/usb/media/ov511.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/media/ov511.c	2004-06-23 19:04:26 -07:00
@@ -4593,7 +4593,7 @@
 }
 
 static ssize_t
-ov51x_v4l1_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
+ov51x_v4l1_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos)
 {
 	struct video_device *vdev = file->private_data;
 	int noblock = file->f_flags&O_NONBLOCK;
diff -Nru a/drivers/usb/media/ov511.h b/drivers/usb/media/ov511.h
--- a/drivers/usb/media/ov511.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/media/ov511.h	2004-06-23 19:04:26 -07:00
@@ -11,7 +11,7 @@
 #ifdef OV511_DEBUG
 	#define PDEBUG(level, fmt, args...) \
 		if (debug >= (level)) info("[%s:%d] " fmt, \
-		__PRETTY_FUNCTION__, __LINE__ , ## args)
+		__FUNCTION__, __LINE__ , ## args)
 #else
 	#define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
diff -Nru a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c
--- a/drivers/usb/media/pwc-if.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/media/pwc-if.c	2004-06-23 19:04:28 -07:00
@@ -129,7 +129,7 @@
 
 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,
+static ssize_t pwc_video_read(struct file *file, char __user *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,
@@ -1132,7 +1132,7 @@
                 device is tricky anyhow.
  */
 
-static ssize_t pwc_video_read(struct file *file, char *buf,
+static ssize_t pwc_video_read(struct file *file, char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	struct video_device *vdev = file->private_data;
diff -Nru a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
--- a/drivers/usb/media/se401.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/media/se401.c	2004-06-23 19:04:26 -07:00
@@ -1121,7 +1121,7 @@
 	return video_usercopy(inode, file, cmd, arg, se401_do_ioctl);
 }
 
-static ssize_t se401_read(struct file *file, char *buf,
+static ssize_t se401_read(struct file *file, char __user *buf,
 		     size_t count, loff_t *ppos)
 {
 	int realcount=count, ret=0;
diff -Nru a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
--- a/drivers/usb/media/stv680.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/media/stv680.c	2004-06-23 19:04:27 -07:00
@@ -1309,7 +1309,7 @@
 	return 0;
 }
 
-static ssize_t stv680_read (struct file *file, char *buf,
+static ssize_t stv680_read (struct file *file, char __user *buf,
 			size_t count, loff_t *ppos)
 {
 	struct video_device *dev = file->private_data;
diff -Nru a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
--- a/drivers/usb/media/usbvideo.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/usb/media/usbvideo.c	2004-06-23 19:04:29 -07:00
@@ -46,7 +46,7 @@
 			      unsigned int cmd, unsigned long arg);
 static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma);
 static int usbvideo_v4l_open(struct inode *inode, struct file *file);
-static ssize_t usbvideo_v4l_read(struct file *file, char *buf,
+static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
 			     size_t count, loff_t *ppos);
 static int usbvideo_v4l_close(struct inode *inode, struct file *file);
 
@@ -1587,7 +1587,7 @@
  * 20-Oct-2000 Created.
  * 01-Nov-2000 Added mutex (uvd->lock).
  */
-static ssize_t usbvideo_v4l_read(struct file *file, char *buf,
+static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
 		      size_t count, loff_t *ppos)
 {
 	struct uvd *uvd = file->private_data;
diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
--- a/drivers/usb/media/vicam.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/media/vicam.c	2004-06-23 19:04:26 -07:00
@@ -523,9 +523,9 @@
 }
 
 static int
-vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long ul_arg)
+vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg)
 {
-	void *arg = (void *)ul_arg;
+	void __user *user_arg = (void __user *)arg;
 	struct vicam_camera *cam = file->private_data;
 	int retval = 0;
 
@@ -549,7 +549,7 @@
 			b.minwidth = 320;	/* VIDEOSIZE_48_48 */
 			b.minheight = 240;
 
-			if (copy_to_user(arg, &b, sizeof (b)))
+			if (copy_to_user(user_arg, &b, sizeof(b)))
 				retval = -EFAULT;
 
 			break;
@@ -560,7 +560,7 @@
 			struct video_channel v;
 
 			DBG("VIDIOCGCHAN\n");
-			if (copy_from_user(&v, arg, sizeof (v))) {
+			if (copy_from_user(&v, user_arg, sizeof(v))) {
 				retval = -EFAULT;
 				break;
 			}
@@ -576,7 +576,7 @@
 			v.type = VIDEO_TYPE_CAMERA;
 			v.norm = 0;
 
-			if (copy_to_user(arg, &v, sizeof (v)))
+			if (copy_to_user(user_arg, &v, sizeof(v)))
 				retval = -EFAULT;
 			break;
 		}
@@ -585,7 +585,7 @@
 		{
 			int v;
 
-			if (copy_from_user(&v, arg, sizeof (v)))
+			if (copy_from_user(&v, user_arg, sizeof(v)))
 				retval = -EFAULT;
 			DBG("VIDIOCSCHAN %d\n", v);
 
@@ -604,8 +604,7 @@
 			vp.brightness = cam->gain << 8;
 			vp.depth = 24;
 			vp.palette = VIDEO_PALETTE_RGB24;
-			if (copy_to_user
-			    (arg, &vp, sizeof (struct video_picture)))
+			if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))
 				retval = -EFAULT;
 			break;
 		}
@@ -614,7 +613,7 @@
 		{
 			struct video_picture vp;
 			
-			if (copy_from_user(&vp, arg, sizeof(vp))) {
+			if (copy_from_user(&vp, user_arg, sizeof(vp))) {
 				retval = -EFAULT;
 				break;
 			}
@@ -646,8 +645,7 @@
 
 			DBG("VIDIOCGWIN\n");
 
-			if (copy_to_user
-			    ((void *) arg, (void *) &vw, sizeof (vw)))
+			if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))
 				retval = -EFAULT;
 
 			// I'm not sure what the deal with a capture window is, it is very poorly described
@@ -660,7 +658,7 @@
 
 			struct video_window vw;
 
-			if (copy_from_user(&vw, arg, sizeof(vw))) {
+			if (copy_from_user(&vw, user_arg, sizeof(vw))) {
 				retval = -EFAULT;
 				break;
 			}
@@ -687,8 +685,7 @@
 			for (i = 0; i < VICAM_FRAMES; i++)
 				vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
 
-			if (copy_to_user
-			    ((void *) arg, (void *) &vm, sizeof (vm)))
+			if (copy_to_user(user_arg, (void *)&vm, sizeof(vm)))
 				retval = -EFAULT;
 
 			break;
@@ -699,8 +696,7 @@
 			struct video_mmap vm;
 			// int video_size;
 
-			if (copy_from_user
-			    ((void *) &vm, (void *) arg, sizeof (vm))) {
+			if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {
 				retval = -EFAULT;
 				break;
 			}
@@ -723,7 +719,7 @@
 		{
 			int frame;
 
-			if (copy_from_user((void *) &frame, arg, sizeof (int))) {
+			if (copy_from_user((void *)&frame, user_arg, sizeof(int))) {
 				retval = -EFAULT;
 				break;
 			}
@@ -1003,7 +999,7 @@
 }
 
 static ssize_t
-vicam_read( struct file *file, char *buf, size_t count, loff_t *ppos )
+vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
 {
 	struct vicam_camera *cam = file->private_data;
 
diff -Nru a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
--- a/drivers/usb/media/w9968cf.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/media/w9968cf.c	2004-06-23 19:04:28 -07:00
@@ -388,7 +388,7 @@
 static struct file_operations w9968cf_fops;
 static int w9968cf_open(struct inode*, struct file*);
 static int w9968cf_release(struct inode*, struct file*);
-static ssize_t w9968cf_read(struct file*, char*, size_t, loff_t*);
+static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*);
 static int w9968cf_mmap(struct file*, struct vm_area_struct*);
 static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long);
 static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int, void*);
@@ -444,8 +444,8 @@
 /* High-level CMOS sensor control functions */
 static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val);
 static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val);
-static inline int w9968cf_sensor_cmd(struct w9968cf_device*, 
-                                     unsigned int cmd, void *arg);
+static int w9968cf_sensor_cmd(struct w9968cf_device*, 
+                              unsigned int cmd, void *arg);
 static int w9968cf_sensor_init(struct w9968cf_device*);
 static int w9968cf_sensor_update_settings(struct w9968cf_device*);
 static int w9968cf_sensor_get_picture(struct w9968cf_device*);
@@ -461,7 +461,7 @@
 static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture);
 static int w9968cf_set_window(struct w9968cf_device*, struct video_window);
 static inline u16 w9968cf_valid_palette(u16 palette);
-static inline u16 w9968cf_valid_depth(u16 palette);
+static u16 w9968cf_valid_depth(u16 palette);
 static inline u8 w9968cf_need_decompression(u16 palette);
 static int w9968cf_postprocess_frame(struct w9968cf_device*, 
                                      struct w9968cf_frame_t*);
@@ -1959,7 +1959,7 @@
   Return the depth corresponding to the given palette.
   Palette _must_ be supported !
   --------------------------------------------------------------------------*/
-static inline u16 w9968cf_valid_depth(u16 palette)
+static u16 w9968cf_valid_depth(u16 palette)
 {
 	u8 i=0;
 	while (w9968cf_formatlist[i].palette != palette)
@@ -2178,7 +2178,7 @@
 }
 
 
-static inline int
+static int
 w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg)
 {
 	struct i2c_client* c = cam->sensor_client;
@@ -2770,7 +2770,7 @@
 
 
 static ssize_t
-w9968cf_read(struct file* filp, char* buf, size_t count, loff_t* f_pos)
+w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
 {
 	struct w9968cf_device* cam;
 	struct w9968cf_frame_t* fr;
@@ -2915,6 +2915,7 @@
                   unsigned int cmd, void* arg)
 {
 	struct w9968cf_device* cam;
+	void __user *user_arg = (void __user *)arg;
 	const char* v4l1_ioctls[] = {
 		"?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", 
 		"GPICT", "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF",
@@ -2948,7 +2949,7 @@
 		cap.maxheight = (cam->upscaling && w9968cf_vppmod_present)
 		                ? W9968CF_MAX_HEIGHT : cam->maxheight;
 
-		if (copy_to_user(arg, &cap, sizeof(cap)))
+		if (copy_to_user(user_arg, &cap, sizeof(cap)))
 			return -EFAULT;
 
 		DBG(5, "VIDIOCGCAP successfully called.")
@@ -2958,7 +2959,7 @@
 	case VIDIOCGCHAN: /* get video channel informations */
 	{
 		struct video_channel chan;
-		if (copy_from_user(&chan, arg, sizeof(chan)))
+		if (copy_from_user(&chan, user_arg, sizeof(chan)))
 			return -EFAULT;
 
 		if (chan.channel != 0)
@@ -2970,7 +2971,7 @@
 		chan.type = VIDEO_TYPE_CAMERA;
 		chan.norm = VIDEO_MODE_AUTO;
 
-		if (copy_to_user(arg, &chan, sizeof(chan)))
+		if (copy_to_user(user_arg, &chan, sizeof(chan)))
 			return -EFAULT;
 
 		DBG(5, "VIDIOCGCHAN successfully called.")
@@ -2981,7 +2982,7 @@
 	{
 		struct video_channel chan;
 
-		if (copy_from_user(&chan, arg, sizeof(chan)))
+		if (copy_from_user(&chan, user_arg, sizeof(chan)))
 			return -EFAULT;
 
 		if (chan.channel != 0)
@@ -2996,7 +2997,7 @@
 		if (w9968cf_sensor_get_picture(cam))
 			return -EIO;
 
-		if (copy_to_user(arg, &cam->picture, sizeof(cam->picture)))
+		if (copy_to_user(user_arg, &cam->picture, sizeof(cam->picture)))
 			return -EFAULT;
 
 		DBG(5, "VIDIOCGPICT successfully called.")
@@ -3008,7 +3009,7 @@
 		struct video_picture pict;
 		int err = 0;
 
-		if (copy_from_user(&pict, arg, sizeof(pict)))
+		if (copy_from_user(&pict, user_arg, sizeof(pict)))
 			return -EFAULT;
 
 		if ( (cam->force_palette || !w9968cf_vppmod_present) 
@@ -3087,7 +3088,7 @@
 		struct video_window win;
 		int err = 0;
 
-		if (copy_from_user(&win, arg, sizeof(win)))
+		if (copy_from_user(&win, user_arg, sizeof(win)))
 			return -EFAULT;
 
 		DBG(6, "VIDIOCSWIN called: clipcount=%d, flags=%d, "
@@ -3141,7 +3142,7 @@
 
 	case VIDIOCGWIN: /* get current window properties */
 	{
-		if (copy_to_user(arg,&cam->window,sizeof(struct video_window)))
+		if (copy_to_user(user_arg, &cam->window, sizeof(struct video_window)))
 			return -EFAULT;
 
 		DBG(5, "VIDIOCGWIN successfully called.")
@@ -3159,7 +3160,7 @@
 			mbuf.offsets[i] = (unsigned long)cam->frame[i].buffer -
 			                  (unsigned long)cam->frame[0].buffer;
 
-		if (copy_to_user(arg, &mbuf, sizeof(mbuf)))
+		if (copy_to_user(user_arg, &mbuf, sizeof(mbuf)))
 			return -EFAULT;
 
 		DBG(5, "VIDIOCGMBUF successfully called.")
@@ -3172,7 +3173,7 @@
 		struct w9968cf_frame_t* fr;
 		int err = 0;
 
-		if (copy_from_user(&mmap, arg, sizeof(mmap)))
+		if (copy_from_user(&mmap, user_arg, sizeof(mmap)))
 			return -EFAULT;
 
 		DBG(6, "VIDIOCMCAPTURE called: frame #%d, format=%s, %dx%d",
@@ -3295,7 +3296,7 @@
 		struct w9968cf_frame_t* fr;
 		int err = 0;
 
-		if (copy_from_user(&f_num, arg, sizeof(f_num)))
+		if (copy_from_user(&f_num, user_arg, sizeof(f_num)))
 			return -EFAULT;
 
 		if (f_num >= cam->nbuffers) {
@@ -3348,7 +3349,7 @@
 			.teletext = VIDEO_NO_UNIT,
 		};
 
-		if (copy_to_user(arg, &unit, sizeof(unit)))
+		if (copy_to_user(user_arg, &unit, sizeof(unit)))
 			return -EFAULT;
 
 		DBG(5, "VIDIOCGUNIT successfully called.")
@@ -3360,7 +3361,7 @@
 
 	case VIDIOCGFBUF:
 	{
-		if (clear_user(arg, sizeof(struct video_buffer)))
+		if (clear_user(user_arg, sizeof(struct video_buffer)))
 			return -EFAULT;
 
 		DBG(5, "VIDIOCGFBUF successfully called.")
@@ -3370,7 +3371,7 @@
 	case VIDIOCGTUNER:
 	{
 		struct video_tuner tuner;
-		if (copy_from_user(&tuner, arg, sizeof(tuner)))
+		if (copy_from_user(&tuner, user_arg, sizeof(tuner)))
 			return -EFAULT;
 
 		if (tuner.tuner != 0)
@@ -3383,7 +3384,7 @@
 		tuner.mode = VIDEO_MODE_AUTO;
 		tuner.signal = 0xffff;
 
-		if (copy_to_user(arg, &tuner, sizeof(tuner)))
+		if (copy_to_user(user_arg, &tuner, sizeof(tuner)))
 			return -EFAULT;
 
 		DBG(5, "VIDIOCGTUNER successfully called.")
@@ -3393,7 +3394,7 @@
 	case VIDIOCSTUNER:
 	{
 		struct video_tuner tuner;
-		if (copy_from_user(&tuner, arg, sizeof(tuner)))
+		if (copy_from_user(&tuner, user_arg, sizeof(tuner)))
 			return -EFAULT;
 
 		if (tuner.tuner != 0)
diff -Nru a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h
--- a/drivers/usb/media/w9968cf.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/media/w9968cf.h	2004-06-23 19:04:25 -07:00
@@ -293,7 +293,7 @@
 		warn(fmt, ## args); \
 	else if ((level) >= 5) \
 		info("[%s:%d] " fmt, \
-		     __PRETTY_FUNCTION__, __LINE__ , ## args); \
+		     __FUNCTION__, __LINE__ , ## args); \
 } \
 }
 #else
diff -Nru a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
--- a/drivers/usb/misc/auerswald.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/misc/auerswald.c	2004-06-23 19:04:26 -07:00
@@ -1452,6 +1452,8 @@
         audevinfo_t devinfo;
         pauerswald_t cp = NULL;
 	unsigned int u;
+	unsigned int __user *user_arg = (unsigned int __user *)arg;
+
         dbg ("ioctl");
 
 	/* get the mutexes */
@@ -1483,14 +1485,14 @@
 		u   = ccp->auerdev
 		   && (ccp->scontext.id != AUH_UNASSIGNED)
 		   && !list_empty (&cp->bufctl.free_buff_list);
-	        ret = put_user (u, (unsigned int *) arg);
+	        ret = put_user (u, user_arg);
 		break;
 
 	/* return != 0 if connected to a service channel */
 	case IOCTL_AU_CONNECT:
 		dbg ("IOCTL_AU_CONNECT");
 		u = (ccp->scontext.id != AUH_UNASSIGNED);
-	        ret = put_user (u, (unsigned int *) arg);
+	        ret = put_user (u, user_arg);
 		break;
 
 	/* return != 0 if Receive Data available */
@@ -1511,14 +1513,14 @@
 				u = 1;
 			}
 		}
-	        ret = put_user (u, (unsigned int *) arg);
+	        ret = put_user (u, user_arg);
 		break;
 
 	/* return the max. buffer length for the device */
 	case IOCTL_AU_BUFLEN:
 		dbg ("IOCTL_AU_BUFLEN");
 		u = cp->maxControlLength;
-	        ret = put_user (u, (unsigned int *) arg);
+	        ret = put_user (u, user_arg);
 		break;
 
 	/* requesting a service channel */
@@ -1527,7 +1529,7 @@
                 /* requesting a service means: release the previous one first */
 		auerswald_removeservice (cp, &ccp->scontext);
 		/* get the channel number */
-		ret = get_user (u, (unsigned int *) arg);
+		ret = get_user (u, user_arg);
 		if (ret) {
 			break;
 		}
@@ -1564,7 +1566,7 @@
         case IOCTL_AU_SLEN:
 		dbg ("IOCTL_AU_SLEN");
 		u = AUSI_DLEN;
-	        ret = put_user (u, (unsigned int *) arg);
+	        ret = put_user (u, user_arg);
 		break;
 
 	default:
diff -Nru a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
--- a/drivers/usb/misc/legousbtower.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/misc/legousbtower.c	2004-06-23 19:04:26 -07:00
@@ -236,8 +236,8 @@
 
 
 /* local function prototypes */
-static ssize_t tower_read	(struct file *file, char *buffer, size_t count, loff_t *ppos);
-static ssize_t tower_write	(struct file *file, const char *buffer, size_t count, loff_t *ppos);
+static ssize_t tower_read	(struct file *file, char __user *buffer, size_t count, loff_t *ppos);
+static ssize_t tower_write	(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
 static inline void tower_delete (struct lego_usb_tower *dev);
 static int tower_open		(struct inode *inode, struct file *file);
 static int tower_release	(struct inode *inode, struct file *file);
@@ -560,7 +560,7 @@
 /**
  *	tower_read
  */
-static ssize_t tower_read (struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct lego_usb_tower *dev;
 	size_t bytes_to_read;
@@ -651,7 +651,7 @@
 /**
  *	tower_write
  */
-static ssize_t tower_write (struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static ssize_t tower_write (struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct lego_usb_tower *dev;
 	size_t bytes_to_write;
diff -Nru a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
--- a/drivers/usb/misc/phidgetservo.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/misc/phidgetservo.c	2004-06-23 19:04:27 -07:00
@@ -17,6 +17,10 @@
  *
  * CAUTION: Generally you should use 0 < degrees < 180 as anything else
  * is probably beyond the range of your servo and may damage it.
+ *
+ * Jun 16, 2004: Sean Young <sean@mess.org>
+ *  - cleanups
+ *  - was using memory after kfree()
  */
 
 #include <linux/config.h>
@@ -33,19 +37,36 @@
 #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
 #define DRIVER_DESC "USB PhidgetServo Driver"
 
-#define VENDOR_ID_GLAB			0x06c2
-#define DEVICE_ID_4MOTOR_SERVO_30	0x0038
-#define DEVICE_ID_1MOTOR_SERVO_30	0x0039
-
-#define VENDOR_ID_WISEGROUP		0x0925
-#define DEVICE_ID_1MOTOR_SERVO_20	0x8101
-#define DEVICE_ID_4MOTOR_SERVO_20	0x8104
+#define VENDOR_ID_GLAB				0x06c2
+#define DEVICE_ID_GLAB_PHIDGETSERVO_QUAD	0x0038
+#define DEVICE_ID_GLAB_PHIDGETSERVO_UNI		0x0039
+
+#define VENDOR_ID_WISEGROUP			0x0925
+#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD	0x8101
+#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI	0x8104
+
+#define SERVO_VERSION_30			0x01
+#define SERVO_COUNT_QUAD			0x02
 
 static struct usb_device_id id_table[] = {
-	{USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_4MOTOR_SERVO_30)},
-	{USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_1MOTOR_SERVO_30)},
-	{USB_DEVICE(VENDOR_ID_WISEGROUP, DEVICE_ID_4MOTOR_SERVO_20)},
-	{USB_DEVICE(VENDOR_ID_WISEGROUP, DEVICE_ID_1MOTOR_SERVO_20)},
+	{
+		USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_QUAD), 
+		.driver_info = SERVO_VERSION_30 | SERVO_COUNT_QUAD 
+	},
+	{
+		USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_UNI),
+		.driver_info = SERVO_VERSION_30 
+	},
+	{
+		USB_DEVICE(VENDOR_ID_WISEGROUP, 
+				VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD),
+		.driver_info = SERVO_COUNT_QUAD 
+	},
+	{
+		USB_DEVICE(VENDOR_ID_WISEGROUP, 
+				VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI),
+		.driver_info = 0
+	},
 	{}
 };
 
@@ -53,14 +74,13 @@
 
 struct phidget_servo {
 	struct usb_device *udev;
-	int version;
-	int quad_servo;
+	ulong type;
 	int pulse[4];
 	int degrees[4];
 	int minutes[4];
 };
 
-static void
+static int
 change_position_v30(struct phidget_servo *servo, int servo_no, int degrees, 
 								int minutes)
 {
@@ -71,7 +91,7 @@
 	if (!buffer) {
 		dev_err(&servo->udev->dev, "%s - out of memory\n",
 			__FUNCTION__);
-		return;
+		return -ENOMEM;
 	}
 
 	/*
@@ -124,12 +144,13 @@
 	retval = usb_control_msg(servo->udev,
 				 usb_sndctrlpipe(servo->udev, 0),
 				 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2 * HZ);
-	if (retval != 6)
-		dev_err(&servo->udev->dev, "retval = %d\n", retval);
+
 	kfree(buffer);
+
+	return retval;
 }
 
-static void
+static int
 change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
 								int minutes)
 {
@@ -140,7 +161,7 @@
 	if (!buffer) {
 		dev_err(&servo->udev->dev, "%s - out of memory\n",
 			__FUNCTION__);
-		return;
+		return -ENOMEM;
 	}
 
 	/*
@@ -171,16 +192,17 @@
 	retval = usb_control_msg(servo->udev,
 				 usb_sndctrlpipe(servo->udev, 0),
 				 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2 * HZ);
-	if (retval != 2)
-		dev_err(&servo->udev->dev, "retval = %d\n", retval);
+
 	kfree(buffer);
+
+	return retval;
 }
 
 #define show_set(value)	\
 static ssize_t set_servo##value (struct device *dev,			\
 					const char *buf, size_t count)	\
 {									\
-	int degrees, minutes;						\
+	int degrees, minutes, retval;					\
 	struct usb_interface *intf = to_usb_interface (dev);		\
 	struct phidget_servo *servo = usb_get_intfdata (intf);		\
 									\
@@ -195,12 +217,14 @@
 		return -EINVAL;						\
 	}								\
 									\
-	if (servo->version >= 3) 					\
-		change_position_v30 (servo, value, degrees, minutes);	\
+	if (servo->type & SERVO_VERSION_30)				\
+		retval = change_position_v30 (servo, value, degrees, 	\
+							minutes);	\
 	else 								\
-		change_position_v20 (servo, value, degrees, minutes);	\
+		retval = change_position_v20 (servo, value, degrees, 	\
+							minutes);	\
 									\
-	return count;							\
+	return retval < 0 ? retval : count;				\
 }									\
 									\
 static ssize_t show_servo##value (struct device *dev, char *buf) 	\
@@ -223,7 +247,7 @@
 servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
-	struct phidget_servo *dev = NULL;
+	struct phidget_servo *dev;
 
 	dev = kmalloc(sizeof (struct phidget_servo), GFP_KERNEL);
 	if (dev == NULL) {
@@ -233,37 +257,21 @@
 	memset(dev, 0x00, sizeof (*dev));
 
 	dev->udev = usb_get_dev(udev);
-	switch (udev->descriptor.idVendor) {
-	case VENDOR_ID_WISEGROUP:
-		dev->version = 2;
-		break;
-	case VENDOR_ID_GLAB:
-		dev->version = 3;
-		break;
-	}
-	switch (udev->descriptor.idProduct) {
-	case DEVICE_ID_4MOTOR_SERVO_20:
-	case DEVICE_ID_4MOTOR_SERVO_30:
-		dev->quad_servo = 1;
-		break;
-	case DEVICE_ID_1MOTOR_SERVO_20:
-	case DEVICE_ID_1MOTOR_SERVO_30:
-		dev->quad_servo = 0;
-		break;
-	}
-
+	dev->type = id->driver_info;
 	usb_set_intfdata(interface, dev);
 
 	device_create_file(&interface->dev, &dev_attr_servo0);
-	if (dev->quad_servo) {
+	if (dev->type & SERVO_COUNT_QUAD) {
 		device_create_file(&interface->dev, &dev_attr_servo1);
 		device_create_file(&interface->dev, &dev_attr_servo2);
 		device_create_file(&interface->dev, &dev_attr_servo3);
 	}
 
 	dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n",
-		 dev->quad_servo ? 4 : 1, dev->version);
-	if (dev->version == 2) 
+		dev->type & SERVO_COUNT_QUAD ? 4 : 1,
+		dev->type & SERVO_VERSION_30 ? 3 : 2);
+
+	if(!(dev->type & SERVO_VERSION_30))
 		dev_info(&interface->dev,
 			 "WARNING: v2.0 not tested! Please report if it works.\n");
 
@@ -279,7 +287,7 @@
 	usb_set_intfdata(interface, NULL);
 
 	device_remove_file(&interface->dev, &dev_attr_servo0);
-	if (dev->quad_servo) {
+	if (dev->type & SERVO_COUNT_QUAD) {
 		device_remove_file(&interface->dev, &dev_attr_servo1);
 		device_remove_file(&interface->dev, &dev_attr_servo2);
 		device_remove_file(&interface->dev, &dev_attr_servo3);
@@ -287,10 +295,11 @@
 
 	usb_put_dev(dev->udev);
 
-	kfree(dev);
-
 	dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n",
-		 dev->quad_servo ? 4 : 1, dev->version);
+		dev->type & SERVO_COUNT_QUAD ? 4 : 1,
+		dev->type & SERVO_VERSION_30 ? 3 : 2);
+
+	kfree(dev);
 }
 
 static struct usb_driver servo_driver = {
@@ -304,7 +313,7 @@
 static int __init
 phidget_servo_init(void)
 {
-	int retval = 0;
+	int retval;
 
 	retval = usb_register(&servo_driver);
 	if (retval)
diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
--- a/drivers/usb/misc/usbtest.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/misc/usbtest.c	2004-06-23 19:04:28 -07:00
@@ -459,8 +459,8 @@
  * or remote wakeup (which needs human interaction).
  */
 
-static int realworld = 1;
-MODULE_PARM (realworld, "i");
+static unsigned realworld = 1;
+module_param (realworld, uint, 0);
 MODULE_PARM_DESC (realworld, "clear to demand stricter ch9 compliance");
 
 static int get_altsetting (struct usbtest_dev *dev)
@@ -1808,17 +1808,17 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int force_interrupt = 0;
-MODULE_PARM (force_interrupt, "i");
+static unsigned force_interrupt = 0;
+module_param (force_interrupt, uint, 0);
 MODULE_PARM_DESC (force_interrupt, "0 = test default; else interrupt");
 
 #ifdef	GENERIC
-static int vendor;
-MODULE_PARM (vendor, "h");
+static unsigned short vendor;
+module_param(vendor, ushort, 0);
 MODULE_PARM_DESC (vendor, "vendor code (from usb-if)");
 
-static int product;
-MODULE_PARM (product, "h");
+static unsigned short product;
+module_param(product, ushort, 0);
 MODULE_PARM_DESC (product, "product code (from vendor)");
 #endif
 
diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
--- a/drivers/usb/net/pegasus.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/net/pegasus.h	2004-06-23 19:04:28 -07:00
@@ -121,6 +121,7 @@
 #define	VENDOR_ADMTEK		0x07a6
 #define	VENDOR_AEILAB		0x3334
 #define	VENDOR_ALLIEDTEL	0x07c9
+#define	VENDOR_ATEN		0x0557
 #define	VENDOR_BELKIN		0x050d
 #define	VENDOR_BILLIONTON	0x08dd
 #define	VENDOR_COMPAQ		0x049f
@@ -149,6 +150,8 @@
 #else	/* PEGASUS_DEV */
 
 PEGASUS_DEV( "3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "ATEN USB Ethernet UC-110T", VENDOR_ATEN, 0x2007,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x110c,
 		DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
--- a/drivers/usb/net/rtl8150.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/net/rtl8150.c	2004-06-23 19:04:27 -07:00
@@ -398,6 +398,21 @@
 	usb_unlink_urb(dev->ctrl_urb);
 }
 
+static inline struct sk_buff *pull_skb(rtl8150_t *dev)
+{
+	struct sk_buff *skb;
+	int i;
+
+	for (i = 0; i < RX_SKB_POOL_SIZE; i++) {
+		if (dev->rx_skb_pool[i]) {
+			skb = dev->rx_skb_pool[i];
+			dev->rx_skb_pool[i] = NULL;
+			return skb;
+		}
+	}
+	return NULL;
+}
+
 static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
 	rtl8150_t *dev;
@@ -601,21 +616,6 @@
 	for (i = 0; i < RX_SKB_POOL_SIZE; i++)
 		if (dev->rx_skb_pool[i])
 			dev_kfree_skb(dev->rx_skb_pool[i]);
-}
-
-static inline struct sk_buff *pull_skb(rtl8150_t *dev)
-{
-	struct sk_buff *skb;
-	int i;
-
-	for (i = 0; i < RX_SKB_POOL_SIZE; i++) {
-		if (dev->rx_skb_pool[i]) {
-			skb = dev->rx_skb_pool[i];
-			dev->rx_skb_pool[i] = NULL;
-			return skb;
-		}
-	}
-	return NULL;
 }
 
 static int enable_net_traffic(rtl8150_t * dev)
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/net/usbnet.c	2004-06-23 19:04:27 -07:00
@@ -104,6 +104,8 @@
  * 		disconnect; other cleanups. (db)  Flush net1080 fifos
  * 		after several sequential framing errors. (Johannes Erdfelt)
  * 22-aug-2003	AX8817X support (Dave Hollis).
+ * 14-jun-2004  Trivial patch for AX8817X based Buffalo LUA-U2-KTX in Japan
+ *		(Neil Bortnak)
  *
  *-------------------------------------------------------------------------*/
 
@@ -1157,6 +1159,7 @@
 
 	status = get_ethernet_addr (dev, info->ether);
 	if (status < 0) {
+		usb_set_intfdata(info->data, NULL);
 		usb_driver_release_interface (&usbnet_driver, info->data);
 		return status;
 	}
@@ -3203,6 +3206,10 @@
 }, {
 	// ATEN UC210T
 	USB_DEVICE (0x0557, 0x2009),
+	.driver_info =  (unsigned long) &ax8817x_info,
+}, {
+	// Buffalo LUA-U2-KTX
+	USB_DEVICE (0x0411, 0x003d),
 	.driver_info =  (unsigned long) &ax8817x_info,
 },
 #endif
diff -Nru a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
--- a/drivers/usb/serial/bus.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/usb/serial/bus.c	2004-06-23 19:04:29 -07:00
@@ -78,8 +78,8 @@
 	minor = port->number;
 	tty_register_device (usb_serial_tty_driver, minor, dev);
 	dev_info(&port->serial->dev->dev, 
-		 "%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)\n",
-		 driver->name, minor, minor);
+		 "%s converter now attached to ttyUSB%d\n",
+		 driver->name, minor);
 
 exit:
 	return retval;
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/serial/ftdi_sio.c	2004-06-23 19:04:28 -07:00
@@ -1022,7 +1022,7 @@
 }
 
 
-static int get_serial_info(struct usb_serial_port * port, struct serial_struct * retinfo)
+static int get_serial_info(struct usb_serial_port * port, struct serial_struct __user * retinfo)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	struct serial_struct tmp;
@@ -1039,7 +1039,7 @@
 } /* get_serial_info */
 
 
-static int set_serial_info(struct usb_serial_port * port, struct serial_struct * newinfo)
+static int set_serial_info(struct usb_serial_port * port, struct serial_struct __user * newinfo)
 { /* set_serial_info */
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	struct serial_struct new_serial;
@@ -1504,6 +1504,7 @@
 	if (status) {
 		err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
 		count = status;
+		kfree (buffer);
 	}
 
 	/* we are done with this urb, so let the host driver
@@ -2042,7 +2043,7 @@
 
 	case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
 		dbg("%s TIOCMBIS", __FUNCTION__);
- 	        if (get_user(mask, (unsigned long *) arg))
+ 	        if (get_user(mask, (unsigned long __user *) arg))
 			return -EFAULT;
   	        if (mask & TIOCM_DTR){
 			if ((ret = set_dtr(port, HIGH)) < 0) {
@@ -2061,7 +2062,7 @@
 
 	case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
 		dbg("%s TIOCMBIC", __FUNCTION__);
- 	        if (get_user(mask, (unsigned long *) arg))
+ 	        if (get_user(mask, (unsigned long __user *) arg))
 			return -EFAULT;
   	        if (mask & TIOCM_DTR){
 			if ((ret = set_dtr(port, LOW)) < 0){
@@ -2088,10 +2089,10 @@
 		 */
 
 	case TIOCGSERIAL: /* gets serial port data */
-		return get_serial_info(port, (struct serial_struct *) arg);
+		return get_serial_info(port, (struct serial_struct __user *) arg);
 
 	case TIOCSSERIAL: /* sets serial port data */
-		return set_serial_info(port, (struct serial_struct *) arg);
+		return set_serial_info(port, (struct serial_struct __user *) arg);
 
 	/*
 	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/serial/io_edgeport.c	2004-06-23 19:04:25 -07:00
@@ -1705,7 +1705,7 @@
  * 	    transmit holding register is empty.  This functionality
  * 	    allows an RS485 driver to be written in user space. 
  *****************************************************************************/
-static int get_lsr_info(struct edgeport_port *edge_port, unsigned int *value)
+static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *value)
 {
 	unsigned int result = 0;
 
@@ -1720,7 +1720,7 @@
 	return 0;
 }
 
-static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int *value)
+static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int __user *value)
 {
 	unsigned int result = 0;
 	struct tty_struct *tty = edge_port->port->tty;
@@ -1790,7 +1790,7 @@
 	return result;
 }
 
-static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct * retinfo)
+static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo)
 {
 	struct serial_struct tmp;
 
@@ -1812,7 +1812,6 @@
 //	tmp.hub6		= state->hub6;
 //	tmp.io_type		= state->io_type;
 
-
 	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
 		return -EFAULT;
 	return 0;
@@ -1838,17 +1837,17 @@
 		// return number of bytes available
 		case TIOCINQ:
 			dbg("%s (%d) TIOCINQ", __FUNCTION__,  port->number);
-			return get_number_bytes_avail(edge_port, (unsigned int *) arg);
+			return get_number_bytes_avail(edge_port, (unsigned int __user *) arg);
 			break;
 
 		case TIOCSERGETLSR:
 			dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__,  port->number);
-			return get_lsr_info(edge_port, (unsigned int *) arg);
+			return get_lsr_info(edge_port, (unsigned int __user *) arg);
 			return 0;
 
 		case TIOCGSERIAL:
 			dbg("%s (%d) TIOCGSERIAL", __FUNCTION__,  port->number);
-			return get_serial_info(edge_port, (struct serial_struct *) arg);
+			return get_serial_info(edge_port, (struct serial_struct __user *) arg);
 
 		case TIOCSSERIAL:
 			dbg("%s (%d) TIOCSSERIAL", __FUNCTION__,  port->number);
@@ -1893,7 +1892,7 @@
 			icount.buf_overrun = cnow.buf_overrun;
 
 			dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,  port->number, icount.rx, icount.tx );
-			if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+			if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
 				return -EFAULT;
 			return 0;
 	}
diff -Nru a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
--- a/drivers/usb/serial/io_ti.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/serial/io_ti.c	2004-06-23 19:04:28 -07:00
@@ -2428,7 +2428,7 @@
 	return result;
 }
 
-static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct * retinfo)
+static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct __user *retinfo)
 {
 	struct serial_struct tmp;
 
@@ -2477,7 +2477,7 @@
 
 		case TIOCGSERIAL:
 			dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
-			return get_serial_info(edge_port, (struct serial_struct *) arg);
+			return get_serial_info(edge_port, (struct serial_struct __user *) arg);
 			break;
 
 		case TIOCSSERIAL:
@@ -2510,7 +2510,7 @@
 		case TIOCGICOUNT:
 			dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
 			     port->number, edge_port->icount.rx, edge_port->icount.tx);
-			if (copy_to_user((void *)arg, &edge_port->icount, sizeof(edge_port->icount)))
+			if (copy_to_user((void __user *)arg, &edge_port->icount, sizeof(edge_port->icount)))
 				return -EFAULT;
 			return 0;
 	}
diff -Nru a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
--- a/drivers/usb/serial/kl5kusb105.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/serial/kl5kusb105.c	2004-06-23 19:04:27 -07:00
@@ -926,6 +926,7 @@
 			   unsigned int cmd, unsigned long arg)
 {
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
+	void __user *user_arg = (void __user *)arg;
 	
 	dbg("%scmd=0x%x", __FUNCTION__, cmd);
 
@@ -948,13 +949,12 @@
 
 	     dbg("%s - TCGETS data faked/incomplete", __FUNCTION__);
 
-	     retval = verify_area(VERIFY_WRITE, (void *)arg,
+	     retval = verify_area(VERIFY_WRITE, user_arg,
 				  sizeof(struct termios));
-
 	     if (retval)
-			 return(retval);
+			 return retval;
 
-	     if (kernel_termios_to_user_termios((struct termios *)arg,  
+	     if (kernel_termios_to_user_termios((struct termios __user *)arg,
 						&priv->termios))
 		     return -EFAULT;
 	     return(0);
@@ -965,14 +965,13 @@
 
 		dbg("%s - TCSETS not handled", __FUNCTION__);
 
-		retval = verify_area(VERIFY_READ, (void *)arg,
+		retval = verify_area(VERIFY_READ, user_arg,
 				     sizeof(struct termios));
-
 		if (retval)
-			    return(retval);
+			    return retval;
 
 		if (user_termios_to_kernel_termios(&priv->termios,
-						  (struct termios *)arg))
+						  (struct termios __user *)arg))
 			return -EFAULT;
 		klsi_105_set_termios(port, &priv->termios);
 		return(0);
diff -Nru a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
--- a/drivers/usb/serial/kobil_sct.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/serial/kobil_sct.c	2004-06-23 19:04:28 -07:00
@@ -643,6 +643,7 @@
 	unsigned char *transfer_buffer;
 	int transfer_buffer_length = 8;
 	char *settings;
+	void __user *user_arg = (void __user *)arg;
 
 	priv = usb_get_serial_port_data(port);
 	if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
@@ -652,12 +653,12 @@
 
 	switch (cmd) {
 	case TCGETS:   // 0x5401
-		result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct termios));
+		result = verify_area(VERIFY_WRITE, user_arg, sizeof(struct termios));
 		if (result) {
 			dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number);
 			return(result);
 		}
-		if (kernel_termios_to_user_termios((struct termios *)arg,
+		if (kernel_termios_to_user_termios((struct termios __user *)arg,
 						   &priv->internal_termios))
 			return -EFAULT;
 		return 0;
@@ -667,13 +668,13 @@
 			dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number);
 			return -ENOTTY;
 		}
-		result = verify_area(VERIFY_READ, (void *)arg, sizeof(struct termios));
+		result = verify_area(VERIFY_READ, user_arg, sizeof(struct termios));
 		if (result) {
 			dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number);
 			return result;
 		}
 		if (user_termios_to_kernel_termios(&priv->internal_termios,
-						   (struct termios *)arg))
+						   (struct termios __user *)arg))
 			return -EFAULT;
 		
 		settings = (unsigned char *) kmalloc(50, GFP_KERNEL);  
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/serial/visor.c	2004-06-23 19:04:26 -07:00
@@ -247,6 +247,8 @@
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID),
+		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ },					/* optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -290,6 +292,7 @@
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
 	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
+	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) },
 	{ },					/* optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -515,6 +518,7 @@
 		dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n",
 			__FUNCTION__, status);
 		count = status;
+		kfree (buffer);
 	} else {
 		bytes_out += count;
 	}
@@ -795,7 +799,7 @@
 		dev_err(dev, "%s - error %d getting connection info\n",
 			__FUNCTION__, retval);
 	else
-		usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer);
+		usb_serial_debug_data (__FILE__, __FUNCTION__, retval, transfer_buffer);
 
 	kfree (transfer_buffer);
 	return 0;
@@ -881,18 +885,19 @@
 
 	/* Only do this endpoint hack for the Handspring devices with
 	 * interrupt in endpoints, which for now are the Treo devices. */
-	if ((serial->dev->descriptor.idVendor != HANDSPRING_VENDOR_ID) ||
+	if (!((serial->dev->descriptor.idVendor == HANDSPRING_VENDOR_ID) ||
+	      (serial->dev->descriptor.idVendor == KYOCERA_VENDOR_ID)) ||
 	    (serial->num_interrupt_in == 0))
 		return 0;
 
 	dbg("%s", __FUNCTION__);
 
 	/*
-	* It appears that Treos want to use the 1st interrupt endpoint to
-	* communicate with the 2nd bulk out endpoint, so let's swap the 1st
-	* and 2nd bulk in and interrupt endpoints.  Note that swapping the
-	* bulk out endpoints would break lots of apps that want to communicate
-	* on the second port.
+	* It appears that Treos and Kyoceras want to use the 
+	* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, 
+	* so let's swap the 1st and 2nd bulk in and interrupt endpoints.  
+	* Note that swapping the bulk out endpoints would break lots of 
+	* apps that want to communicate on the second port.
 	*/
 #define COPY_PORT(dest, src)						\
 	dest->read_urb = src->read_urb;					\
diff -Nru a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
--- a/drivers/usb/serial/visor.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/serial/visor.h	2004-06-23 19:04:28 -07:00
@@ -55,6 +55,9 @@
 #define ACEECA_VENDOR_ID		0x4766
 #define ACEECA_MEZ1000_ID		0x0001
 
+#define KYOCERA_VENDOR_ID		0x0C88
+#define KYOCERA_7135_ID			0x0021 
+
 /****************************************************************************
  * Handspring Visor Vendor specific request codes (bRequest values)
  * A big thank you to Handspring for providing the following information.
diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
--- a/drivers/usb/serial/whiteheat.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/serial/whiteheat.c	2004-06-23 19:04:26 -07:00
@@ -835,6 +835,7 @@
 static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
 {
 	struct serial_struct serstruct;
+	void __user *user_arg = (void __user *)arg;
 
 	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
 
@@ -851,13 +852,13 @@
 			serstruct.close_delay = CLOSING_DELAY;
 			serstruct.closing_wait = CLOSING_DELAY;
 
-			if (copy_to_user((void *)arg, &serstruct, sizeof(serstruct)))
+			if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
 				return -EFAULT;
 
 			break;
 
 		case TIOCSSERIAL:
-			if (copy_from_user(&serstruct, (void *)arg, sizeof(serstruct)))
+			if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
 				return -EFAULT;
 
 			/*
diff -Nru a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
--- a/drivers/usb/storage/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/storage/Kconfig	2004-06-23 19:04:28 -07:00
@@ -23,6 +23,28 @@
 	  Say Y here in order to have the USB Mass Storage code generate
 	  verbose debugging messages.
 
+config USB_STORAGE_RW_DETECT
+	bool "USB Mass Storage Write-Protected Media Detection (EXPERIMENTAL)"
+	depends on USB_STORAGE && EXPERIMENTAL
+	help
+	  Say Y here in order to have the USB Mass Storage code indicate to
+	  the SCSI layer that using MODE SENSE(6) and MODE SENSE(10) to
+	  determine if the media is write-protected is a good thing to do.
+
+	  Many devices have historically had trouble with these commands,
+	  hence the default 2.6.x behavior has been to suppress their use.
+	  2.4.x used these commands with (at best) mixed results, often
+	  crashing the firmware of the device.  However, the SCSI layer now
+	  issues these commands in a manner more consistent with other
+	  "popular" OSes, in an attempt to improve compatibility.
+
+	  Saying Y here allows these commands to be sent to a USB device.
+	  If you find a device this doesn't work for, switch to N and let
+	  us know at usb-storage@lists.one-eyed-alien.net
+
+	  If you say N here, the kernel will assume that all disk-like USB
+	  devices are write-enabled.
+
 config USB_STORAGE_DATAFAB
 	bool "Datafab Compact Flash Reader support (EXPERIMENTAL)"
 	depends on USB_STORAGE && EXPERIMENTAL
diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
--- a/drivers/usb/storage/jumpshot.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/usb/storage/jumpshot.c	2004-06-23 19:04:25 -07:00
@@ -471,7 +471,7 @@
 
 		// build the reply
 		//
-		((u32 *) ptr)[0] = cpu_to_be32(info->sectors);
+		((u32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
 		((u32 *) ptr)[1] = cpu_to_be32(info->ssize);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
 
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/storage/scsiglue.c	2004-06-23 19:04:27 -07:00
@@ -48,13 +48,13 @@
 #include "usb.h"
 #include "debug.h"
 #include "transport.h"
+#include "protocol.h"
 
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <scsi/scsi_devinfo.h>
 #include <scsi/scsi_host.h>
 
-
 /***********************************************************************
  * Host functions 
  ***********************************************************************/
@@ -68,10 +68,13 @@
 {
 	/*
 	 * Set default bflags. These can be overridden for individual
-	 * models and vendors via the scsi devinfo mechanism.
+	 * models and vendors via the scsi devinfo mechanism.  The only
+	 * flag we need is to force 36-byte INQUIRYs; we don't use any
+	 * of the extra data and many devices choke if asked for more or
+	 * less than 36 bytes.
 	 */
-	sdev->sdev_bflags = (BLIST_MS_SKIP_PAGE_08 | BLIST_MS_SKIP_PAGE_3F |
-			     BLIST_USE_10_BYTE_MS);
+	sdev->sdev_bflags = BLIST_INQUIRY_36;
+
 	return 0;
 }
 
@@ -95,11 +98,48 @@
 	 * reduce the maximum transfer size to 64 KB = 128 sectors. */
 
 #define USB_VENDOR_ID_GENESYS	0x05e3		// Needs a standard location
+
 	if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS &&
-			us->pusb_dev->speed == USB_SPEED_HIGH)
+			us->pusb_dev->speed == USB_SPEED_HIGH &&
+			sdev->request_queue->max_sectors > 128)
 		blk_queue_max_sectors(sdev->request_queue, 128);
 
-	/* this is to satisify the compiler, tho I don't think the 
+	/* We can't put these settings in slave_alloc() because that gets
+	 * called before the device type is known.  Consequently these
+	 * settings can't be overridden via the scsi devinfo mechanism. */
+	if (sdev->type == TYPE_DISK) {
+
+		/* Disk-type devices use MODE SENSE(6) if the protocol
+		 * (SubClass) is Transparent SCSI, otherwise they use
+		 * MODE SENSE(10). */
+		if (us->subclass != US_SC_SCSI)
+			sdev->use_10_for_ms = 1;
+
+		/* Many disks only accept MODE SENSE transfer lengths of
+		 * 192 bytes (that's what Windows uses). */
+		sdev->use_192_bytes_for_3f = 1;
+
+		/* A number of devices have problems with MODE SENSE for
+		 * page x08, so we will skip it. */
+		sdev->skip_ms_page_8 = 1;
+
+#ifndef CONFIG_USB_STORAGE_RW_DETECT
+		/* Some devices may not like MODE SENSE with page=0x3f.
+		 * Now that we're using 192-byte transfers this may no
+		 * longer be a problem.  So this will be a configuration
+		 * option. */
+		sdev->skip_ms_page_3f = 1;
+#endif
+
+	} else {
+
+		/* Non-disk-type devices don't need to blacklist any pages
+		 * or to force 192-byte transfer lengths for MODE SENSE.
+		 * But they do need to use MODE SENSE(10). */
+		sdev->use_10_for_ms = 1;
+	}
+
+	/* this is to satisfy the compiler, tho I don't think the 
 	 * return code is ever checked anywhere. */
 	return 0;
 }
@@ -408,6 +448,9 @@
 
 	/* emulated HBA */
 	.emulated =			TRUE,
+
+	/* we do our own delay after a device or bus reset */
+	.skip_settle_delay =		1,
 
 	/* sysfs device attributes */
 	.sdev_attrs =			sysfs_device_attr_list,
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/storage/transport.c	2004-06-23 19:04:26 -07:00
@@ -908,26 +908,29 @@
 				 USB_RECIP_INTERFACE,
 				 0, us->ifnum, us->iobuf, 1, HZ);
 
+	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
+		  result, us->iobuf[0]);
+
+	/* if we have a successful request, return the result */
+	if (result == 1)
+		return us->iobuf[0];
+
 	/* 
 	 * Some devices (i.e. Iomega Zip100) need this -- apparently
 	 * the bulk pipes get STALLed when the GetMaxLUN request is
 	 * processed.   This is, in theory, harmless to all other devices
 	 * (regardless of if they stall or not).
 	 */
-	if (result < 0) {
+	if (result == -EPIPE) {
 		usb_stor_clear_halt(us, us->recv_bulk_pipe);
 		usb_stor_clear_halt(us, us->send_bulk_pipe);
+		/* return the default -- no LUNs */
+		return 0;
 	}
 
-	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
-		  result, us->iobuf[0]);
-
-	/* if we have a successful request, return the result */
-	if (result == 1)
-		return us->iobuf[0];
-
-	/* return the default -- no LUNs */
-	return 0;
+	/* An answer or a STALL are the only valid responses.  If we get
+	 * something else, return an indication of error */
+	return -1;
 }
 
 int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
@@ -1110,10 +1113,11 @@
 		goto Done;
 	}
 
-	/* long wait for reset, so unlock to allow disconnects */
-	up(&us->dev_semaphore);
-	msleep(6000);
-	down(&us->dev_semaphore);
+ 	/* Give the device some time to recover from the reset,
+ 	 * but don't delay disconnect processing. */
+ 	wait_event_interruptible_timeout(us->dev_reset_wait,
+ 			test_bit(US_FLIDX_DISCONNECTING, &us->flags),
+ 			HZ*6);
 	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
 		US_DEBUGP("Reset interrupted by disconnect\n");
 		goto Done;
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/usb/storage/unusual_devs.h	2004-06-23 19:04:28 -07:00
@@ -207,7 +207,7 @@
 UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0205, 
 		"Shuttle",
 		"eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_CB, NULL, 
+		US_SC_SCSI, US_PR_DEVICE, NULL, 
 		US_FL_SINGLE_LUN), 
 
 UNUSUAL_DEV(  0x04e6, 0x0007, 0x0100, 0x0200, 
@@ -359,13 +359,19 @@
 UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
 		"Fujifilm",
 		"Digital Camera EX-20 DSC",
-		US_SC_8070, US_PR_CBI, NULL, 0 ),
+		US_SC_8070, US_PR_DEVICE, NULL, 0 ),
 
 UNUSUAL_DEV(  0x059f, 0xa601, 0x0200, 0x0200, 
 		"LaCie",
 		"USB Hard Disk",
 		US_SC_RBC, US_PR_CB, NULL, 0 ), 
 
+/* Submitted by Jol Bourquard <numlock@freesurf.ch> */
+UNUSUAL_DEV(  0x05ab, 0x0060, 0x1104, 0x1110,
+		"In-System",
+		"PyroGate External CD-ROM Enclosure (FCD-523)",
+		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+
 #ifdef CONFIG_USB_STORAGE_ISD200
 UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
 		"In-System",
@@ -396,8 +402,8 @@
 UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
 		"Lexar",
 		"Jumpshot USB CF Reader",
-		US_SC_DEVICE, US_PR_JUMPSHOT, NULL,
-		US_FL_MODE_XLATE ),
+		US_SC_SCSI, US_PR_JUMPSHOT, NULL,
+		US_FL_NEED_OVERRIDE | US_FL_MODE_XLATE ),
 #endif
 
 /* Reported by Blake Matheny <bmatheny@purdue.edu> */
@@ -628,19 +634,13 @@
  * - Some cameras with idProduct=0x1001 and bcdDevice=0x1000 have
  *   bInterfaceProtocol=0x00 (US_PR_CBI) while others have 0x01 (US_PR_CB).
  *   So don't remove the US_PR_CB override!
+ * - Cameras with bcdDevice=0x9009 require the US_SC_8070 override.
  */
-UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
+UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
 		"Casio",
 		"QV DigitalCamera",
-		US_SC_DEVICE, US_PR_CB, NULL,
+		US_SC_8070, US_PR_CB, NULL,
 		US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
-
-/* Later Casio cameras apparently tell the truth */
-UNUSUAL_DEV( 0x07cf, 0x1001, 0x9010, 0x9999,
-		"Casio",
-		"QV DigitalCamera",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_INQUIRY ),
 
 /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
 UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/usb/storage/usb.c	2004-06-23 19:04:26 -07:00
@@ -266,6 +266,7 @@
 static int usb_stor_control_thread(void * __us)
 {
 	struct us_data *us = (struct us_data *)__us;
+	struct Scsi_Host *host = us->host;
 
 	lock_kernel();
 
@@ -283,19 +284,21 @@
 	complete(&(us->notify));
 
 	for(;;) {
-		struct Scsi_Host *host;
 		US_DEBUGP("*** thread sleeping.\n");
 		if(down_interruptible(&us->sema))
 			break;
 			
 		US_DEBUGP("*** thread awakened.\n");
 
+		/* lock the device pointers */
+		down(&(us->dev_semaphore));
+
 		/* if us->srb is NULL, we are being asked to exit */
 		if (us->srb == NULL) {
 			US_DEBUGP("-- exit command received\n");
+			up(&(us->dev_semaphore));
 			break;
 		}
-		host = us->srb->device->host;
 
 		/* lock access to the state */
 		scsi_lock(host);
@@ -306,23 +309,20 @@
 			goto SkipForAbort;
 		}
 
-		/* set the state and release the lock */
-		us->sm_state = US_STATE_RUNNING;
-		scsi_unlock(host);
-
-		/* lock the device pointers */
-		down(&(us->dev_semaphore));
-
 		/* don't do anything if we are disconnecting */
 		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
 			US_DEBUGP("No command during disconnect\n");
-			us->srb->result = DID_BAD_TARGET << 16;
+			goto SkipForDisconnect;
 		}
 
+		/* set the state and release the lock */
+		us->sm_state = US_STATE_RUNNING;
+		scsi_unlock(host);
+
 		/* reject the command if the direction indicator 
 		 * is UNKNOWN
 		 */
-		else if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
+		if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
 			US_DEBUGP("UNKNOWN data direction\n");
 			us->srb->result = DID_ERROR << 16;
 		}
@@ -362,9 +362,6 @@
 			us->proto_handler(us->srb, us);
 		}
 
-		/* unlock the device pointers */
-		up(&(us->dev_semaphore));
-
 		/* lock access to the state */
 		scsi_lock(host);
 
@@ -374,7 +371,7 @@
 				   us->srb->result);
 			us->srb->scsi_done(us->srb);
 		} else {
-			SkipForAbort:
+SkipForAbort:
 			US_DEBUGP("scsi command aborted\n");
 		}
 
@@ -387,9 +384,13 @@
 			complete(&(us->notify));
 
 		/* empty the queue, reset the state, and release the lock */
+SkipForDisconnect:
 		us->srb = NULL;
 		us->sm_state = US_STATE_IDLE;
 		scsi_unlock(host);
+
+		/* unlock the device pointers */
+		up(&(us->dev_semaphore));
 	} /* for (;;) */
 
 	/* notify the exit routine that we're actually exiting now 
@@ -423,10 +424,8 @@
 	us->pusb_intf = intf;
 	us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
 
-	/* Store our private data in the interface and increment the
-	 * device's reference count */
+	/* Store our private data in the interface */
 	usb_set_intfdata(intf, us);
-	usb_get_dev(us->pusb_dev);
 
 	/* Allocate the device-related DMA-mapped buffers */
 	us->cr = usb_buffer_alloc(us->pusb_dev, sizeof(*us->cr),
@@ -754,8 +753,14 @@
 	down(&us->dev_semaphore);
 
 	/* For bulk-only devices, determine the max LUN value */
-	if (us->protocol == US_PR_BULK)
-		us->max_lun = usb_stor_Bulk_max_lun(us);
+	if (us->protocol == US_PR_BULK) {
+		p = usb_stor_Bulk_max_lun(us);
+		if (p < 0) {
+			up(&us->dev_semaphore);
+			return p;
+		}
+		us->max_lun = p;
+	}
 
 	/* Just before we start our control thread, initialize
 	 * the device if it needs initialization */
@@ -764,19 +769,6 @@
 
 	up(&us->dev_semaphore);
 
-	/* Start up our control thread */
-	us->sm_state = US_STATE_IDLE;
-	p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
-	if (p < 0) {
-		printk(KERN_WARNING USB_STORAGE 
-		       "Unable to start control thread\n");
-		return p;
-	}
-	us->pid = p;
-
-	/* Wait for the thread to start */
-	wait_for_completion(&(us->notify));
-
 	/*
 	 * Since this is a new device, we need to register a SCSI
 	 * host definition with the higher SCSI layers.
@@ -784,69 +776,61 @@
 	us->host = scsi_host_alloc(&usb_stor_host_template, sizeof(us));
 	if (!us->host) {
 		printk(KERN_WARNING USB_STORAGE
-			"Unable to register the scsi host\n");
+			"Unable to allocate the scsi host\n");
 		return -EBUSY;
 	}
 
 	/* Set the hostdata to prepare for scanning */
 	us->host->hostdata[0] = (unsigned long) us;
 
-	return 0;
-}
-
-/* Dissociate from the USB device */
-static void dissociate_dev(struct us_data *us)
-{
-	US_DEBUGP("-- %s\n", __FUNCTION__);
-	down(&us->dev_semaphore);
-
-	/* Free the device-related DMA-mapped buffers */
-	if (us->cr) {
-		usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
-				us->cr_dma);
-		us->cr = NULL;
-	}
-	if (us->iobuf) {
-		usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf,
-				us->iobuf_dma);
-		us->iobuf = NULL;
+	/* Start up our control thread */
+	us->sm_state = US_STATE_IDLE;
+	p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
+	if (p < 0) {
+		printk(KERN_WARNING USB_STORAGE 
+		       "Unable to start control thread\n");
+		return p;
 	}
+	us->pid = p;
 
-	/* Remove our private data from the interface and decrement the
-	 * device's reference count */
-	usb_set_intfdata(us->pusb_intf, NULL);
-	usb_put_dev(us->pusb_dev);
+	/* Wait for the thread to start */
+	wait_for_completion(&(us->notify));
 
-	us->pusb_dev = NULL;
-	us->pusb_intf = NULL;
-	up(&us->dev_semaphore);
+	return 0;
 }
 
-/* Release all our static and dynamic resources */
+/* Release all our dynamic resources */
 void usb_stor_release_resources(struct us_data *us)
 {
-	/*
-	 * The host must already have been removed
-	 * and dissociate_dev() must have been called.
-	 */
-
-	/* Finish the SCSI host removal sequence */
-	if (us->host) {
-		us->host->hostdata[0] = 0;
-		scsi_host_put(us->host);
-	}
+	US_DEBUGP("-- %s\n", __FUNCTION__);
 
-	/* Kill the control thread
-	 *
-	 * Enqueue the command, wake up the thread, and wait for 
-	 * notification that it has exited.
+	/* Kill the control thread.  The SCSI host must already have been
+	 * removed so it won't try to queue any more commands.
 	 */
 	if (us->pid) {
+
+		/* Wait for the thread to be idle */
+		down(&us->dev_semaphore);
 		US_DEBUGP("-- sending exit command to thread\n");
 		BUG_ON(us->sm_state != US_STATE_IDLE);
+
+		/* If the SCSI midlayer queued a final command just before
+		 * scsi_remove_host() was called, us->srb might not be
+		 * NULL.  We can overwrite it safely, because the midlayer
+		 * will not wait for the command to finish.  Also the
+		 * control thread will already have been awakened.
+		 * That's okay, an extra up() on us->sema won't hurt.
+		 *
+		 * Enqueue the command, wake up the thread, and wait for 
+		 * notification that it has exited.
+		 */
+		scsi_lock(us->host);
 		us->srb = NULL;
-		up(&(us->sema));
-		wait_for_completion(&(us->notify));
+		scsi_unlock(us->host);
+		up(&us->dev_semaphore);
+
+		up(&us->sema);
+		wait_for_completion(&us->notify);
 	}
 
 	/* Call the destructor routine, if it exists */
@@ -855,15 +839,36 @@
 		us->extra_destructor(us->extra);
 	}
 
+	/* Finish the host removal sequence */
+	if (us->host)
+		scsi_host_put(us->host);
+
 	/* Free the extra data and the URB */
 	if (us->extra)
 		kfree(us->extra);
 	if (us->current_urb)
 		usb_free_urb(us->current_urb);
 
+}
+
+/* Dissociate from the USB device */
+static void dissociate_dev(struct us_data *us)
+{
+	US_DEBUGP("-- %s\n", __FUNCTION__);
+
+	/* Free the device-related DMA-mapped buffers */
+	if (us->cr)
+		usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
+				us->cr_dma);
+	if (us->iobuf)
+		usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf,
+				us->iobuf_dma);
+
+	/* Remove our private data from the interface */
+	usb_set_intfdata(us->pusb_intf, NULL);
+
 	/* Free the structure itself */
 	kfree(us);
-	US_DEBUGP("-- %s finished\n", __FUNCTION__);
 }
 
 /* Probe to see if we can drive a newly-connected USB device */
@@ -889,6 +894,7 @@
 	init_MUTEX(&(us->dev_semaphore));
 	init_MUTEX_LOCKED(&(us->sema));
 	init_completion(&(us->notify));
+	init_waitqueue_head(&us->dev_reset_wait);
 
 	/* Associate the us_data structure with the USB device */
 	result = associate_dev(us, intf);
@@ -959,8 +965,8 @@
 	/* We come here if there are any problems */
 BadDevice:
 	US_DEBUGP("storage_probe() failed\n");
-	dissociate_dev(us);
 	usb_stor_release_resources(us);
+	dissociate_dev(us);
 	return result;
 }
 
@@ -971,20 +977,20 @@
 
 	US_DEBUGP("storage_disconnect() called\n");
 
-	/* Prevent new USB transfers and stop the current command */
+	/* Prevent new USB transfers, stop the current command, and
+	 * interrupt a device-reset delay */
 	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
 	usb_stor_stop_transport(us);
+	wake_up(&us->dev_reset_wait);
 
-	/* Dissociate from the USB device */
-	dissociate_dev(us);
-
+	/* Wait for the current command to finish, then remove the host */
+	down(&us->dev_semaphore);
+	up(&us->dev_semaphore);
 	scsi_remove_host(us->host);
 
-	/* TODO: somehow, wait for the device to
-	 * be 'idle' (tasklet completion) */
-
-	/* Release all our other resources */
+	/* Wait for everything to become idle and release all our resources */
 	usb_stor_release_resources(us);
+	dissociate_dev(us);
 }
 
 /***********************************************************************
@@ -1017,47 +1023,6 @@
 	 */
 	US_DEBUGP("-- calling usb_deregister()\n");
 	usb_deregister(&usb_storage_driver) ;
-
-#if 0
-	/* While there are still virtual hosts, unregister them
-	 * Note that it's important to do this completely before removing
-	 * the structures because of possible races with the /proc
-	 * interface
-	 */
-	for (next = us_list; next; next = next->next) {
-		US_DEBUGP("-- calling scsi_unregister_host()\n");
-		scsi_unregister_host(&usb_stor_host_template);
-	}
-
-	/* While there are still structures, free them.  Note that we are
-	 * now race-free, since these structures can no longer be accessed
-	 * from either the SCSI command layer or the /proc interface
-	 */
-	while (us_list) {
-		/* keep track of where the next one is */
-		next = us_list->next;
-
-		/* If there's extra data in the us_data structure then
-		 * free that first */
-		if (us_list->extra) {
-			/* call the destructor routine, if it exists */
-			if (us_list->extra_destructor) {
-				US_DEBUGP("-- calling extra_destructor()\n");
-				us_list->extra_destructor(us_list->extra);
-			}
-
-			/* destroy the extra data */
-			US_DEBUGP("-- freeing the data structure\n");
-			kfree(us_list->extra);
-		}
-
-		/* free the structure itself */
-		kfree (us_list);
-
-		/* advance the list pointer */
-		us_list = next;
-	}
-#endif
 }
 
 module_init(usb_stor_init);
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/usb/storage/usb.h	2004-06-23 19:04:27 -07:00
@@ -158,9 +158,10 @@
 	dma_addr_t		cr_dma;		 /* buffer DMA addresses */
 	dma_addr_t		iobuf_dma;
 
-	/* mutual exclusion structures */
+	/* mutual exclusion and synchronization structures */
 	struct semaphore	sema;		 /* to sleep thread on   */
-	struct completion	notify;		 /* thread begin/end	    */
+	struct completion	notify;		 /* thread begin/end	 */
+	wait_queue_head_t	dev_reset_wait;  /* wait during reset    */
 
 	/* subdriver information */
 	void			*extra;		 /* Any extra data          */
diff -Nru a/drivers/video/Kconfig b/drivers/video/Kconfig
--- a/drivers/video/Kconfig	2004-06-23 19:04:25 -07:00
+++ b/drivers/video/Kconfig	2004-06-23 19:04:25 -07:00
@@ -432,6 +432,11 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called rivafb.
 
+config FB_RIVA_I2C
+       bool "Enable DDC Support"
+       depends on FB_RIVA && I2C
+       help
+
 config FB_I810
 	tristate "Intel 810/815 support (EXPERIMENTAL)"
 	depends on FB && AGP && AGP_INTEL && EXPERIMENTAL && PCI	
diff -Nru a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
--- a/drivers/video/aty/radeon_accel.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/aty/radeon_accel.c	2004-06-23 19:04:27 -07:00
@@ -38,8 +38,8 @@
 		return;
 	}
 
-	vxres = info->var.xres;
-	vyres = info->var.yres;
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
 
 	memcpy(&modded, region, sizeof(struct fb_fillrect));
 
@@ -104,8 +104,8 @@
 		return;
 	}
 
-	vxres = info->var.xres;
-	vyres = info->var.yres;
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
 
 	if(!modded.width || !modded.height ||
 	   modded.sx >= vxres || modded.sy >= vyres ||
diff -Nru a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
--- a/drivers/video/aty/radeon_base.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/aty/radeon_base.c	2004-06-23 19:04:26 -07:00
@@ -858,6 +858,7 @@
         if (rinfo->asleep)
         	return 0;
 
+	radeon_fifo_wait(2);
         OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
 			     * var->bits_per_pixel / 8) & ~7);
         return 0;
@@ -882,11 +883,12 @@
 			if (!rinfo->is_mobility)
 				return -EINVAL;
 
-			rc = get_user(value, (__u32*)arg);
+			rc = get_user(value, (__u32 __user *)arg);
 
 			if (rc)
 				return rc;
 
+			radeon_fifo_wait(2);
 			if (value & 0x01) {
 				tmp = INREG(LVDS_GEN_CNTL);
 
@@ -926,7 +928,7 @@
 			if (CRTC_CRT_ON & tmp)
 				value |= 0x02;
 
-			return put_user(value, (__u32*)arg);
+			return put_user(value, (__u32 __user *)arg);
 		default:
 			return -EINVAL;
 	}
@@ -963,6 +965,7 @@
                         break;
         }
 
+	radeon_fifo_wait(1);
 	switch (rinfo->mon1_type) {
 		case MT_LCD:
 			OUTREG(LVDS_GEN_CNTL, val2);
@@ -1021,6 +1024,7 @@
         if (!rinfo->asleep) {
         	u32 dac_cntl2, vclk_cntl = 0;
         	
+		radeon_fifo_wait(9);
 		if (rinfo->is_mobility) {
 			vclk_cntl = INPLL(VCLK_ECP_CNTL);
 			OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
@@ -1112,6 +1116,8 @@
 {
 	int i;
 
+	radeon_fifo_wait(20);
+
 	/* Workaround from XFree */
 	if (rinfo->is_mobility) {
 	        /* A temporal workaround for the occational blanking on certain laptop panels. 
@@ -1198,6 +1204,8 @@
 {
 	struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
 
+	radeon_fifo_wait(3);
+
 	OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
 	if (rinfo->pending_pixclks_cntl) {
 		OUTPLL(PIXCLKS_CNTL, rinfo->pending_pixclks_cntl);
@@ -1222,6 +1230,7 @@
 
 	radeon_screen_blank(rinfo, VESA_POWERDOWN);
 
+	radeon_fifo_wait(31);
 	for (i=0; i<10; i++)
 		OUTREG(common_regs[i].reg, common_regs[i].val);
 
@@ -1249,6 +1258,7 @@
 	radeon_write_pll_regs(rinfo, mode);
 
 	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
+		radeon_fifo_wait(10);
 		OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
 		OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
 		OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
@@ -1288,6 +1298,7 @@
 
 	radeon_screen_blank(rinfo, VESA_NO_BLANKING);
 
+	radeon_fifo_wait(2);
 	OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
 	
 	return;
@@ -1696,7 +1707,7 @@
 
 
 
-static ssize_t radeonfb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+static ssize_t radeonfb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
 	struct inode *inode = file->f_dentry->d_inode;
@@ -1723,7 +1734,7 @@
 	return count;
 }
 
-static ssize_t radeonfb_write(struct file *file, const char *buf, size_t count,
+static ssize_t radeonfb_write(struct file *file, const char __user *buf, size_t count,
 			      loff_t *ppos)
 {
 	unsigned long p = *ppos;
@@ -1864,6 +1875,7 @@
 	del_timer_sync(&rinfo->lvds_timer);
 
 	lvds_gen_cntl |= (LVDS_BL_MOD_EN | LVDS_BLON);
+	radeon_fifo_wait(3);
 	if (on && (level > BACKLIGHT_OFF)) {
 		lvds_gen_cntl |= LVDS_DIGON;
 		if (!(lvds_gen_cntl & LVDS_ON)) {
@@ -2136,6 +2148,7 @@
           u32 tom = INREG(NB_TOM);
           tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
  
+ 		radeon_fifo_wait(6);
           OUTREG(MC_FB_LOCATION, tom);
           OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
           OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
@@ -2255,9 +2268,17 @@
 
 	/*
 	 * Map the BIOS ROM if any and retreive PLL parameters from
-	 * either BIOS or Open Firmware
+	 * the BIOS. We skip that on mobility chips as the real panel
+	 * values we need aren't in the ROM but in the BIOS image in
+	 * memory. This is definitely not the best meacnism though,
+	 * we really need the arch code to tell us which is the "primary"
+	 * video adapter to use the memory image (or better, the arch
+	 * should provide us a copy of the BIOS image to shield us from
+	 * archs who would store that elsewhere and/or could initialize
+	 * more than one adapter during boot).
 	 */
-	radeon_map_ROM(rinfo, pdev);
+	if (!rinfo->is_mobility)
+		radeon_map_ROM(rinfo, pdev);
 
 	/*
 	 * On x86, the primary display on laptop may have it's BIOS
@@ -2269,6 +2290,12 @@
 	if (rinfo->bios_seg == NULL)
 		radeon_find_mem_vbios(rinfo);
 #endif /* __i386__ */
+
+	/* If both above failed, try the BIOS ROM again for mobility
+	 * chips
+	 */
+	if (rinfo->bios_seg == NULL && rinfo->is_mobility)
+		radeon_map_ROM(rinfo, pdev);
 
 	/* Get informations about the board's PLL */
 	radeon_get_pllinfo(rinfo);
diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
--- a/drivers/video/console/fbcon.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/console/fbcon.c	2004-06-23 19:04:27 -07:00
@@ -601,8 +601,9 @@
 	int display_fg = (*default_mode)->vc_num;
 	int logo = 1, rows, cols, charcnt = 256;
 	unsigned short *save = NULL, *r, *q;
+	int cap = info->flags;
 
-	if (vc->vc_num != display_fg || (info->flags & FBINFO_FLAG_MODULE) ||
+	if (vc->vc_num != display_fg || (info->flags & FBINFO_MODULE) ||
 	    (info->fix.type == FB_TYPE_TEXT))
 		logo = 0;
 
@@ -635,10 +636,10 @@
 	rows = info->var.yres / vc->vc_font.height;
 	vc_resize(vc->vc_num, cols, rows);
 
-	if (info->var.accel_flags)
-		p->scrollmode = SCROLL_YNOMOVE;
-	else
-		p->scrollmode = SCROLL_YREDRAW;
+	if ((cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED))
+		p->scrollmode = SCROLL_ACCEL;
+	else /* default to something safe */
+		p->scrollmode = SCROLL_REDRAW;
 
 	/*
 	 *  ++guenther: console.c:vc_allocate() relies on initializing
@@ -1245,7 +1246,7 @@
 {
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
-	int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL);
+	int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
 
 	if (!info->fbops->fb_blank && console_blanked)
 		return 0;
@@ -1269,15 +1270,15 @@
 			fbcon_softback_note(vc, t, count);
 		if (logo_shown >= 0)
 			goto redraw_up;
-		switch (p->scrollmode & __SCROLL_YMASK) {
-		case __SCROLL_YMOVE:
+		switch (p->scrollmode) {
+		case SCROLL_ACCEL:
 			accel_bmove(vc, info, t + count, 0, t, 0,
 					 b - t - count, vc->vc_cols);
 			accel_clear(vc, info, b - count, 0, count,
 					 vc->vc_cols);
 			break;
 
-		case __SCROLL_YWRAP:
+		case SCROLL_WRAP:
 			if (b - t - count > 3 * vc->vc_rows >> 2) {
 				if (t > 0)
 					fbcon_bmove(vc, 0, 0, count, 0, t,
@@ -1287,15 +1288,15 @@
 					fbcon_bmove(vc, b - count, 0, b, 0,
 						    vc->vc_rows - b,
 						    vc->vc_cols);
-			} else if (p->scrollmode & __SCROLL_YPANREDRAW)
-				goto redraw_up;
-			else
+			} else if (info->flags & FBINFO_READS_FAST)
 				fbcon_bmove(vc, t + count, 0, t, 0,
 					    b - t - count, vc->vc_cols);
+			else
+				goto redraw_up;
 			fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
 			break;
 
-		case __SCROLL_YPAN:
+		case SCROLL_PAN:
 			if ((p->yscroll + count <=
 			     2 * (p->vrows - vc->vc_rows))
 			    && ((!scroll_partial && (b - t == vc->vc_rows))
@@ -1310,15 +1311,15 @@
 					fbcon_bmove(vc, b - count, 0, b, 0,
 						    vc->vc_rows - b,
 						    vc->vc_cols);
-			} else if (p->scrollmode & __SCROLL_YPANREDRAW)
-				goto redraw_up;
-			else
+			} else if (info->flags & FBINFO_READS_FAST)
 				fbcon_bmove(vc, t + count, 0, t, 0,
 					    b - t - count, vc->vc_cols);
+			else
+				goto redraw_up;
 			fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
 			break;
 
-		case __SCROLL_YREDRAW:
+		case SCROLL_REDRAW:
 		      redraw_up:
 			fbcon_redraw(vc, p, t, b - t - count,
 				     count * vc->vc_cols);
@@ -1336,14 +1337,14 @@
 	case SM_DOWN:
 		if (count > vc->vc_rows)	/* Maximum realistic size */
 			count = vc->vc_rows;
-		switch (p->scrollmode & __SCROLL_YMASK) {
-		case __SCROLL_YMOVE:
+		switch (p->scrollmode) {
+		case SCROLL_ACCEL:
 			accel_bmove(vc, info, t, 0, t + count, 0,
 					 b - t - count, vc->vc_cols);
 			accel_clear(vc, info, t, 0, count, vc->vc_cols);
 			break;
 
-		case __SCROLL_YWRAP:
+		case SCROLL_WRAP:
 			if (b - t - count > 3 * vc->vc_rows >> 2) {
 				if (vc->vc_rows - b > 0)
 					fbcon_bmove(vc, b, 0, b - count, 0,
@@ -1353,15 +1354,15 @@
 				if (t > 0)
 					fbcon_bmove(vc, count, 0, 0, 0, t,
 						    vc->vc_cols);
-			} else if (p->scrollmode & __SCROLL_YPANREDRAW)
-				goto redraw_down;
-			else
+			} else if (info->flags & FBINFO_READS_FAST)
 				fbcon_bmove(vc, t, 0, t + count, 0,
 					    b - t - count, vc->vc_cols);
+			else
+				goto redraw_down;
 			fbcon_clear(vc, t, 0, count, vc->vc_cols);
 			break;
 
-		case __SCROLL_YPAN:
+		case SCROLL_PAN:
 			if ((count - p->yscroll <= p->vrows - vc->vc_rows)
 			    && ((!scroll_partial && (b - t == vc->vc_rows))
 				|| (scroll_partial
@@ -1375,15 +1376,15 @@
 				if (t > 0)
 					fbcon_bmove(vc, count, 0, 0, 0, t,
 						    vc->vc_cols);
-			} else if (p->scrollmode & __SCROLL_YPANREDRAW)
-				goto redraw_down;
-			else
+			} else if (info->flags & FBINFO_READS_FAST)
 				fbcon_bmove(vc, t, 0, t + count, 0,
 					    b - t - count, vc->vc_cols);
+			else
+				goto redraw_down;
 			fbcon_clear(vc, t, 0, count, vc->vc_cols);
 			break;
 
-		case __SCROLL_YREDRAW:
+		case SCROLL_REDRAW:
 		      redraw_down:
 			fbcon_redraw(vc, p, b - 1, b - t - count,
 				     -count * vc->vc_cols);
@@ -1467,21 +1468,27 @@
 
 static __inline__ void updatescrollmode(struct display *p, struct fb_info *info, struct vc_data *vc)
 {
-	int m;
-
-	if (p->scrollmode & __SCROLL_YFIXED)
-		return;
-	if (divides(info->fix.ywrapstep, vc->vc_font.height) &&
-	    divides(vc->vc_font.height, info->var.yres_virtual))
-		m = __SCROLL_YWRAP;
-	else if (divides(info->fix.ypanstep, vc->vc_font.height) &&
-		 info->var.yres_virtual >= info->var.yres + vc->vc_font.height)
-		m = __SCROLL_YPAN;
-	else if (p->scrollmode & __SCROLL_YNOMOVE)
-		m = __SCROLL_YREDRAW;
-	else
-		m = __SCROLL_YMOVE;
-	p->scrollmode = (p->scrollmode & ~__SCROLL_YMASK) | m;
+	int cap = info->flags;
+	int good_pan = (cap & FBINFO_HWACCEL_YPAN)
+		 && divides(info->fix.ypanstep, vc->vc_font.height)
+		 && info->var.yres_virtual >= 2*info->var.yres;
+	int good_wrap = (cap & FBINFO_HWACCEL_YWRAP)
+		 && divides(info->fix.ywrapstep, vc->vc_font.height)
+		 && divides(vc->vc_font.height, info->var.yres_virtual);
+	int reading_fast = cap & FBINFO_READS_FAST;
+	int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED);
+
+	if (good_wrap || good_pan) {
+		if (reading_fast || fast_copyarea)
+			p->scrollmode = good_wrap ? SCROLL_WRAP : SCROLL_PAN;
+		else
+			p->scrollmode = SCROLL_REDRAW;
+	} else {
+		if (reading_fast || fast_copyarea)
+			p->scrollmode = SCROLL_ACCEL;
+		else
+			p->scrollmode = SCROLL_REDRAW;
+	}
 }
 
 static int fbcon_resize(struct vc_data *vc, unsigned int width, 
@@ -1505,9 +1512,10 @@
 		if (!info->fbops->fb_set_par)
 			return -EINVAL;
 
-		sprintf(mode, "%dx%d", var.xres, var.yres);
-		err = fb_find_mode(&var, info, mode, NULL, 0, NULL,
-					info->var.bits_per_pixel);
+		snprintf(mode, 40, "%ix%i", var.xres, var.yres);
+		err = fb_find_mode(&var, info, mode, info->monspecs.modedb,
+				   info->monspecs.modedb_len, NULL,
+				   info->var.bits_per_pixel);
 		if (!err || width > var.xres/fw || height > var.yres/fh)
 			return -EINVAL;
 		DPRINTK("resize now %ix%i\n", var.xres, var.yres);
@@ -1555,12 +1563,12 @@
 	}
 	if (info)
 		info->var.yoffset = p->yscroll = 0;
-        fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
-	switch (p->scrollmode & __SCROLL_YMASK) {
-	case __SCROLL_YWRAP:
+ 	fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
+	switch (p->scrollmode) {
+	case SCROLL_WRAP:
 		scrollback_phys_max = p->vrows - vc->vc_rows;
 		break;
-	case __SCROLL_YPAN:
+	case SCROLL_PAN:
 		scrollback_phys_max = p->vrows - 2 * vc->vc_rows;
 		if (scrollback_phys_max < 0)
 			scrollback_phys_max = 0;
@@ -2133,11 +2141,11 @@
 
 	offset = p->yscroll - scrollback_current;
 	limit = p->vrows;
-	switch (p->scrollmode && __SCROLL_YMASK) {
-	case __SCROLL_YWRAP:
+	switch (p->scrollmode) {
+	case SCROLL_WRAP:
 		info->var.vmode |= FB_VMODE_YWRAP;
 		break;
-	case __SCROLL_YPAN:
+	case SCROLL_PAN:
 		limit -= vc->vc_rows;
 		info->var.vmode &= ~FB_VMODE_YWRAP;
 		break;
diff -Nru a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
--- a/drivers/video/console/fbcon.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/video/console/fbcon.h	2004-06-23 19:04:28 -07:00
@@ -67,40 +67,27 @@
      *  Scroll Method
      */
      
-/* Internal flags */
-#define __SCROLL_YPAN		0x001
-#define __SCROLL_YWRAP		0x002
-#define __SCROLL_YMOVE		0x003
-#define __SCROLL_YREDRAW	0x004
-#define __SCROLL_YMASK		0x00f
-#define __SCROLL_YFIXED		0x010
-#define __SCROLL_YNOMOVE	0x020
-#define __SCROLL_YPANREDRAW	0x040
-#define __SCROLL_YNOPARTIAL	0x080
-
-/* Only these should be used by the drivers */
-/* Which one should you use? If you have a fast card and slow bus,
-   then probably just 0 to indicate fbcon should choose between
-   YWRAP/YPAN+MOVE/YMOVE. On the other side, if you have a fast bus
-   and even better if your card can do fonting (1->8/32bit painting),
-   you should consider either SCROLL_YREDRAW (if your card is
-   able to do neither YPAN/YWRAP), or SCROLL_YNOMOVE.
-   The best is to test it with some real life scrolling (usually, not
-   all lines on the screen are filled completely with non-space characters,
-   and REDRAW performs much better on such lines, so don't cat a file
-   with every line covering all screen columns, it would not be the right
-   benchmark).
+/* There are several methods fbcon can use to move text around the screen:
+ *
+ * + use the hardware engine to move the text
+ *    (hw-accelerated copyarea() and fillrect())
+ * + use hardware-supported panning on a large virtual screen
+ * + amifb can not only pan, but also wrap the display by N lines
+ *    (i.e. visible line i = physical line (i+N) % yres).
+ * + read what's already rendered on the screen and
+ *     write it in a different place (this is cfb_copyarea())
+ * + re-render the text to the screen
+ *
+ * Whether to use wrapping or panning can only be figured out at
+ * runtime (when we know whether our font height is a multiple
+ * of the pan/wrap step)
+ *
  */
-#define SCROLL_YREDRAW		(__SCROLL_YFIXED|__SCROLL_YREDRAW)
-#define SCROLL_YNOMOVE		(__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW)
 
-/* SCROLL_YNOPARTIAL, used in combination with the above, is for video
-   cards which can not handle using panning to scroll a portion of the
-   screen without excessive flicker.  Panning will only be used for
-   whole screens.
- */
-/* Namespace consistency */
-#define SCROLL_YNOPARTIAL	__SCROLL_YNOPARTIAL
+#define SCROLL_ACCEL	0x001
+#define SCROLL_PAN	0x002
+#define SCROLL_WRAP	0x003
+#define SCROLL_REDRAW	0x004
 
 extern int fb_console_init(void);
 
diff -Nru a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
--- a/drivers/video/console/sticore.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/console/sticore.c	2004-06-23 19:04:26 -07:00
@@ -22,7 +22,6 @@
 #include <linux/pci.h>
 #include <linux/font.h>
 
-#include <asm/pgalloc.h>
 #include <asm/hardware.h>
 #include <asm/parisc-device.h>
 #include <asm/cacheflush.h>
diff -Nru a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
--- a/drivers/video/console/vgacon.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/console/vgacon.c	2004-06-23 19:04:26 -07:00
@@ -963,6 +963,8 @@
 		p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
 		    lines * c->vc_size_row;
 		st = (c->vc_origin - vga_vram_base - ul + we) % we;
+		if (st < 2 * margin)
+			margin = 0;
 		if (p < margin)
 			p = 0;
 		if (p > st - margin)
diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c
--- a/drivers/video/fbmem.c	2004-06-23 19:04:24 -07:00
+++ b/drivers/video/fbmem.c	2004-06-23 19:04:24 -07:00
@@ -172,6 +172,7 @@
 extern int kyrofb_setup(char*);
 extern int mc68x328fb_init(void);
 extern int mc68x328fb_setup(char *);
+extern int asiliantfb_init(void);
 
 static struct {
 	const char *name;
@@ -385,6 +386,9 @@
 #ifdef CONFIG_FB_68328
 	{ "68328fb", mc68x328fb_init, mc68x328fb_setup },
 #endif
+#ifdef CONFIG_FB_ASILIANT
+	{ "asiliantfb", asiliantfb_init, NULL },
+#endif
 
 	/*
 	 * Generic drivers that don't use resource management (yet)
@@ -802,7 +806,7 @@
 }
 
 static ssize_t
-fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
 	struct inode *inode = file->f_dentry->d_inode;
@@ -839,7 +843,7 @@
 }
 
 static ssize_t
-fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
 	struct inode *inode = file->f_dentry->d_inode;
@@ -916,26 +920,30 @@
 	
 	if (cursor.set & FB_CUR_SETSHAPE) {
 		int size = ((cursor.image.width + 7) >> 3) * cursor.image.height;		
+		char *data, *mask;
+
 		if ((cursor.image.height != info->cursor.image.height) ||
 		    (cursor.image.width != info->cursor.image.width))
 			cursor.set |= FB_CUR_SETSIZE;
 		
-		cursor.image.data = kmalloc(size, GFP_KERNEL);
-		if (!cursor.image.data)
+		data = kmalloc(size, GFP_KERNEL);
+		if (!data)
 			return -ENOMEM;
 		
-		cursor.mask = kmalloc(size, GFP_KERNEL);
-		if (!cursor.mask) {
-			kfree(cursor.image.data);
+		mask = kmalloc(size, GFP_KERNEL);
+		if (!mask) {
+			kfree(data);
 			return -ENOMEM;
 		}
 		
-		if (copy_from_user(cursor.image.data, sprite->image.data, size) ||
-		    copy_from_user(cursor.mask, sprite->mask, size)) { 
-			kfree(cursor.image.data);
-			kfree(cursor.mask);
+		if (copy_from_user(data, sprite->image.data, size) ||
+		    copy_from_user(mask, sprite->mask, size)) {
+			kfree(data);
+			kfree(mask);
 			return -EFAULT;
 		}
+		cursor.image.data = data;
+		cursor.mask = mask;
 	}
 	info->cursor.set = cursor.set;
 	info->cursor.rop = cursor.rop;
diff -Nru a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
--- a/drivers/video/imsttfb.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/imsttfb.c	2004-06-23 19:04:27 -07:00
@@ -1267,48 +1267,49 @@
 	      u_long arg, struct fb_info *info)
 {
 	struct imstt_par *par = (struct imstt_par *) info->par;
+	void __user *argp = (void __user *)arg;
 	__u32 reg[2];
 	__u8 idx[2];
 
 	switch (cmd) {
 		case FBIMSTT_SETREG:
-			if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
+			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
 			write_reg_le32(par->dc_regs, reg[0], reg[1]);
 			return 0;
 		case FBIMSTT_GETREG:
-			if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
+			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
 			reg[1] = read_reg_le32(par->dc_regs, reg[0]);
-			if (copy_to_user((void *)(arg + 4), &reg[1], 4))
+			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
 				return -EFAULT;
 			return 0;
 		case FBIMSTT_SETCMAPREG:
-			if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
+			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
 			write_reg_le32(((u_int *)par->cmap_regs), reg[0], reg[1]);
 			return 0;
 		case FBIMSTT_GETCMAPREG:
-			if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
+			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
 			reg[1] = read_reg_le32(((u_int *)par->cmap_regs), reg[0]);
-			if (copy_to_user((void *)(arg + 4), &reg[1], 4))
+			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
 				return -EFAULT;
 			return 0;
 		case FBIMSTT_SETIDXREG:
-			if (copy_from_user(idx, (void *)arg, 2))
+			if (copy_from_user(idx, argp, 2))
 				return -EFAULT;
 			par->cmap_regs[PIDXHI] = 0;		eieio();
 			par->cmap_regs[PIDXLO] = idx[0];	eieio();
 			par->cmap_regs[PIDXDATA] = idx[1];	eieio();
 			return 0;
 		case FBIMSTT_GETIDXREG:
-			if (copy_from_user(idx, (void *)arg, 1))
+			if (copy_from_user(idx, argp, 1))
 				return -EFAULT;
 			par->cmap_regs[PIDXHI] = 0;		eieio();
 			par->cmap_regs[PIDXLO] = idx[0];	eieio();
 			idx[1] = par->cmap_regs[PIDXDATA];
-			if (copy_to_user((void *)(arg + 1), &idx[1], 1))
+			if (copy_to_user((void __user *)(arg + 1), &idx[1], 1))
 				return -EFAULT;
 			return 0;
 		default:
diff -Nru a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
--- a/drivers/video/kyro/fbdev.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/video/kyro/fbdev.c	2004-06-23 19:04:25 -07:00
@@ -592,11 +592,11 @@
 {
 	overlay_create ol_create;
 	overlay_viewport_set ol_viewport_set;
+	void __user *argp = (void __user *)arg;
 
 	switch (cmd) {
 	case KYRO_IOCTL_OVERLAY_CREATE:
-		copy_from_user((void *) &ol_create, (void *) arg,
-			       sizeof(overlay_create));
+		copy_from_user(&ol_create, argp, sizeof(overlay_create));
 
 		if (kyro_dev_overlay_create(ol_create.ulWidth,
 					    ol_create.ulHeight, 0) < 0) {
@@ -606,7 +606,7 @@
 		}
 		break;
 	case KYRO_IOCTL_OVERLAY_VIEWPORT_SET:
-		copy_from_user((void *) &ol_viewport_set, (void *) arg,
+		copy_from_user(&ol_viewport_set, argp,
 			       sizeof(overlay_viewport_set));
 
 		if (kyro_dev_overlay_viewport_set(ol_viewport_set.xOrgin,
@@ -627,13 +627,13 @@
 		}
 		break;
 	case KYRO_IOCTL_UVSTRIDE:
-		copy_to_user((void *)arg, (void *)&deviceInfo.ulOverlayUVStride, sizeof(unsigned long));
+		copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long));
 		break;
 	case KYRO_IOCTL_STRIDE:
-		copy_to_user((void *)arg, (void *)&deviceInfo.ulOverlayStride, sizeof(unsigned long));
+		copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long));
 		break;
 	case KYRO_IOCTL_OVERLAY_OFFSET:
-		copy_to_user((void *)arg, (void *)&deviceInfo.ulOverlayOffset, sizeof(unsigned long));
+		copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long));
 		break;
 	}
 
diff -Nru a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
--- a/drivers/video/matrox/matroxfb_base.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/matrox/matroxfb_base.c	2004-06-23 19:04:27 -07:00
@@ -874,6 +874,7 @@
 			  unsigned int cmd, unsigned long arg,
 			  struct fb_info *info)
 {
+	void __user *argp = (void __user *)arg;
 	MINFO_FROM_INFO(info);
 	
 	DBG(__FUNCTION__)
@@ -891,7 +892,7 @@
 				err = matroxfb_get_vblank(PMINFO &vblank);
 				if (err)
 					return err;
-				if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank)))
+				if (copy_to_user(argp, &vblank, sizeof(vblank)))
 					return -EFAULT;
 				return 0;
 			}
@@ -899,7 +900,7 @@
 			{
 				u_int32_t crt;
 
-				if (get_user(crt, (u_int32_t *)arg))
+				if (get_user(crt, (u_int32_t __user *)arg))
 					return -EFAULT;
 
 				return matroxfb_wait_for_sync(PMINFO crt);
@@ -910,7 +911,7 @@
 				struct matrox_altout *oproc;
 				int val;
 
-				if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom)))
+				if (copy_from_user(&mom, argp, sizeof(mom)))
 					return -EFAULT;
 				if (mom.output >= MATROXFB_MAX_OUTPUTS)
 					return -ENXIO;
@@ -960,7 +961,7 @@
 				struct matrox_altout *oproc;
 				int val;
 
-				if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom)))
+				if (copy_from_user(&mom, argp, sizeof(mom)))
 					return -EFAULT;
 				if (mom.output >= MATROXFB_MAX_OUTPUTS)
 					return -ENXIO;
@@ -975,7 +976,7 @@
 				up_read(&ACCESS_FBINFO(altout.lock));
 				if (val)
 					return val;
-				if (copy_to_user((struct matroxioc_output_mode*)arg, &mom, sizeof(mom)))
+				if (copy_to_user(argp, &mom, sizeof(mom)))
 					return -EFAULT;
 				return 0;
 			}
@@ -985,7 +986,7 @@
 				int i;
 				int changes;
 
-				if (copy_from_user(&tmp, (u_int32_t*)arg, sizeof(tmp)))
+				if (copy_from_user(&tmp, argp, sizeof(tmp)))
 					return -EFAULT;
 				for (i = 0; i < 32; i++) {
 					if (tmp & (1 << i)) {
@@ -1040,7 +1041,7 @@
 						conn |= 1 << i;
 					}
 				}
-				if (put_user(conn, (u_int32_t*)arg))
+				if (put_user(conn, (u_int32_t __user *)arg))
 					return -EFAULT;
 				return 0;
 			}
@@ -1065,7 +1066,7 @@
 					if (conn & MATROXFB_OUTPUT_CONN_SECONDARY)
 						conn &= ~MATROXFB_OUTPUT_CONN_DFP;
 				}
-				if (put_user(conn, (u_int32_t*)arg))
+				if (put_user(conn, (u_int32_t __user *)arg))
 					return -EFAULT;
 				return 0;
 			}
@@ -1079,7 +1080,7 @@
 						conn |= 1 << i;
 					}
 				}
-				if (put_user(conn, (u_int32_t*)arg))
+				if (put_user(conn, (u_int32_t __user *)arg))
 					return -EFAULT;
 				return 0;
 			}
@@ -1093,7 +1094,7 @@
 				sprintf(r.bus_info, "PCI:%s", pci_name(ACCESS_FBINFO(pcidev)));
 				r.version = KERNEL_VERSION(1,0,0);
 				r.capabilities = V4L2_CAP_VIDEO_OUTPUT;
-				if (copy_to_user((void*)arg, &r, sizeof(r)))
+				if (copy_to_user(argp, &r, sizeof(r)))
 					return -EFAULT;
 				return 0;
 				
@@ -1103,7 +1104,7 @@
 				struct v4l2_queryctrl qctrl;
 				int err;
 
-				if (copy_from_user(&qctrl, (struct v4l2_queryctrl*)arg, sizeof(qctrl)))
+				if (copy_from_user(&qctrl, argp, sizeof(qctrl)))
 					return -EFAULT;
 
 				down_read(&ACCESS_FBINFO(altout).lock);
@@ -1116,7 +1117,7 @@
 				}
 				up_read(&ACCESS_FBINFO(altout).lock);
 				if (err >= 0 &&
-				    copy_to_user((struct v4l2_queryctrl*)arg, &qctrl, sizeof(qctrl)))
+				    copy_to_user(argp, &qctrl, sizeof(qctrl)))
 					return -EFAULT;
 				return err;
 			}
@@ -1125,7 +1126,7 @@
 				struct v4l2_control ctrl;
 				int err;
 
-				if (copy_from_user(&ctrl, (struct v4l2_control*)arg, sizeof(ctrl)))
+				if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
 					return -EFAULT;
 
 				down_read(&ACCESS_FBINFO(altout).lock);
@@ -1138,7 +1139,7 @@
 				}
 				up_read(&ACCESS_FBINFO(altout).lock);
 				if (err >= 0 &&
-				    copy_to_user((struct v4l2_control*)arg, &ctrl, sizeof(ctrl)))
+				    copy_to_user(argp, &ctrl, sizeof(ctrl)))
 					return -EFAULT;
 				return err;
 			}
@@ -1147,7 +1148,7 @@
 				struct v4l2_control ctrl;
 				int err;
 
-				if (copy_from_user(&ctrl, (struct v4l2_control*)arg, sizeof(ctrl)))
+				if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
 					return -EFAULT;
 
 				down_read(&ACCESS_FBINFO(altout).lock);
diff -Nru a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
--- a/drivers/video/matrox/matroxfb_crtc2.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/video/matrox/matroxfb_crtc2.c	2004-06-23 19:04:28 -07:00
@@ -437,7 +437,7 @@
 				err = matroxfb_dh_get_vblank(m2info, &vblank);
 				if (err)
 					return err;
-				if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank)))
+				if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
 					return -EFAULT;
 				return 0;
 			}
@@ -445,7 +445,7 @@
 			{
 				u_int32_t crt;
 
-				if (get_user(crt, (u_int32_t *)arg))
+				if (get_user(crt, (u_int32_t __user *)arg))
 					return -EFAULT;
 
 				if (crt != 0)
@@ -464,7 +464,7 @@
 				int out;
 				int changes;
 
-				if (get_user(tmp, (u_int32_t*)arg))
+				if (get_user(tmp, (u_int32_t __user *)arg))
 					return -EFAULT;
 				for (out = 0; out < 32; out++) {
 					if (tmp & (1 << out)) {
@@ -514,7 +514,7 @@
 						conn |= 1 << out;
 					}
 				}
-				if (put_user(conn, (u_int32_t*)arg))
+				if (put_user(conn, (u_int32_t __user *)arg))
 					return -EFAULT;
 				return 0;
 			}
@@ -539,7 +539,7 @@
 						tmp = 0;
 					}
 				}
-				if (put_user(tmp, (u_int32_t*)arg))
+				if (put_user(tmp, (u_int32_t __user *)arg))
 					return -EFAULT;
 				return 0;
 			}
diff -Nru a/drivers/video/modedb.c b/drivers/video/modedb.c
--- a/drivers/video/modedb.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/modedb.c	2004-06-23 19:04:26 -07:00
@@ -490,6 +490,7 @@
 	int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
 	unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
 	int yres_specified = 0;
+	u32 best = -1, diff = -1;
 
 	for (i = namelen-1; i >= 0; i--) {
 	    switch (name[i]) {
@@ -529,14 +530,30 @@
 	}
 done:
 	for (i = refresh_specified; i >= 0; i--) {
-	    DPRINTK("Trying specified video mode%s\n",
-		    i ? "" : " (ignoring refresh rate)");
+	    DPRINTK("Trying specified video mode%s %ix%i\n",
+		    i ? "" : " (ignoring refresh rate)", xres, yres);
 	    for (j = 0; j < dbsize; j++)
 		if ((name_matches(db[j], name, namelen) ||
 		     (res_specified && res_matches(db[j], xres, yres))) &&
 		    (!i || db[j].refresh == refresh) &&
 		    !fb_try_mode(var, info, &db[j], bpp))
 		    return 2-i;
+	}
+	DPRINTK("Trying best-fit modes\n");
+	for (i = 0; i < dbsize; i++) {
+	    if (xres <= db[i].xres && yres <= db[i].yres) {
+		DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
+		if (!fb_try_mode(var, info, &db[i], bpp)) {
+		    if (diff > (db[i].xres - xres) + (db[i].yres - yres)) {
+			diff = (db[i].xres - xres) + (db[i].yres - yres);
+			best = i;
+		    }
+		}
+	    }
+	}
+	if (best != -1) {
+	    fb_try_mode(var, info, &db[best], bpp);
+	    return 5;
 	}
     }
 
diff -Nru a/drivers/video/pxafb.c b/drivers/video/pxafb.c
--- a/drivers/video/pxafb.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/pxafb.c	2004-06-23 19:04:26 -07:00
@@ -42,7 +42,6 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/mach-types.h>
 #include <asm/uaccess.h>
 #include <asm/arch/bitfield.h>
 #include <asm/arch/pxafb.h>
@@ -109,10 +108,13 @@
 	u_int val, ret = 1;
 
 	if (regno < fbi->palette_size) {
-		val  = ((red   >>  0) & 0xf800);
-		val |= ((green >>  5) & 0x07e0);
-		val |= ((blue  >> 11) & 0x001f);
-
+		if (fbi->fb.var.grayscale) {
+			val = ((blue >> 8) & 0x00ff);
+		} else {
+			val  = ((red   >>  0) & 0xf800);
+			val |= ((green >>  5) & 0x07e0);
+			val |= ((blue  >> 11) & 0x001f);
+		}
 		fbi->palette_cpu[regno] = val;
 		ret = 0;
 	}
@@ -150,7 +152,7 @@
 	switch (fbi->fb.fix.visual) {
 	case FB_VISUAL_TRUECOLOR:
 		/*
-		 * 12 or 16-bit True Colour.  We encode the RGB value
+		 * 16-bit True Colour.  We encode the RGB value
 		 * according to the RGB bitfield information.
 		 */
 		if (regno < 16) {
@@ -242,7 +244,7 @@
 	 * The pixel packing format is described on page 7-11 of the
 	 * PXA2XX Developer's Manual.
          */
-	if ( var->bits_per_pixel == 16 ) {
+	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;
@@ -297,7 +299,10 @@
 
 	fbi->fb.fix.line_length = var->xres_virtual *
 				  var->bits_per_pixel / 8;
-	fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
+	if (var->bits_per_pixel == 16)
+		fbi->palette_size = 0;
+	else
+		fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;
 
 	palette_mem_size = fbi->palette_size * sizeof(u16);
 
@@ -311,6 +316,11 @@
 	 */
 	pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
 
+	if (fbi->fb.var.bits_per_pixel == 16)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+	else
+		fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
+
 	pxafb_activate_var(var, fbi);
 
 	return 0;
@@ -349,7 +359,7 @@
 /*
  * pxafb_blank():
  *	Blank the display by setting all palette values to zero.  Note, the
- * 	12 and 16 bpp modes don't really use the palette, so this will not
+ * 	16 bpp mode does not really use the palette, so this will not
  *      blank the display in all modes.
  */
 static int pxafb_blank(int blank, struct fb_info *info)
@@ -514,7 +524,7 @@
 	 * the YRES parameter.
 	 */
 	lines_per_panel = var->yres;
-	if (fbi->lccr0 & LCCR0_SDS)
+	if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual)
 		lines_per_panel /= 2;
 
 	new_regs.lccr2 =
@@ -566,20 +576,16 @@
 	fbi->dmadesc_palette_cpu->fidr  = 0;
 	fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
 
-	if( var->bits_per_pixel < 12)
-	{
-		/* assume any mode with <12 bpp is palette driven */
-		fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
-		fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma;
-		fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */
-	}
-	else
-	{
+	if (var->bits_per_pixel == 16) {
 		/* palette shouldn't be loaded in true-color mode */
 		fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
 		fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
 		/* init it to something, even though we won't be using it */
 		fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_palette_dma;
+	} else {
+		fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
+		fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma;
+		fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */
 	}
 
 #if 0
@@ -696,7 +702,7 @@
 	}
 
 	else {
-	        printk( KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n");
+	        printk(KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n");
         }
 }
 
@@ -1010,7 +1016,7 @@
 	struct pxafb_mach_info *inf = dev->platform_data;
 
 	/* Alloc the pxafb_info and pseudo_palette in one step */
-	fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 17, GFP_KERNEL);
+	fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
 	if (!fbi)
 		return NULL;
 
@@ -1123,11 +1129,11 @@
 				res_specified = 1;
 			}
 		done:
-			if ( res_specified ) {
-				dev_info(dev, "overriding resolution: %dx%x\n", xres, yres);
+			if (res_specified) {
+				dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
 				inf->xres = xres; inf->yres = yres;
 			}
-			if ( bpp_specified )
+			if (bpp_specified)
 				switch (bpp) {
 				case 1:
 				case 2:
@@ -1142,7 +1148,7 @@
 				}
                 } else if (!strncmp(this_opt, "pixclock:", 9)) {
                         inf->pixclock = simple_strtoul(this_opt+9, NULL, 0);
-			dev_info(dev, "override pixclock: %u\n", inf->pixclock);
+			dev_info(dev, "override pixclock: %ld\n", inf->pixclock);
                 } else if (!strncmp(this_opt, "left:", 5)) {
                         inf->left_margin = simple_strtoul(this_opt+5, NULL, 0);
 			dev_info(dev, "override left: %u\n", inf->left_margin);
@@ -1162,7 +1168,7 @@
                         inf->vsync_len = simple_strtoul(this_opt+9, NULL, 0);
 			dev_info(dev, "override vsynclen: %u\n", inf->vsync_len);
                 } else if (!strncmp(this_opt, "hsync:", 6)) {
-                        if ( simple_strtoul(this_opt+6, NULL, 0) == 0 ) {
+                        if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
 				dev_info(dev, "override hsync: Active Low\n");
 				inf->sync &= ~FB_SYNC_HOR_HIGH_ACT;
 			} else {
@@ -1170,7 +1176,7 @@
 				inf->sync |= FB_SYNC_HOR_HIGH_ACT;
 			}
                 } else if (!strncmp(this_opt, "vsync:", 6)) {
-                        if ( simple_strtoul(this_opt+6, NULL, 0) == 0 ) {
+                        if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
 				dev_info(dev, "override vsync: Active Low\n");
 				inf->sync &= ~FB_SYNC_VERT_HIGH_ACT;
 			} else {
@@ -1178,7 +1184,7 @@
 				inf->sync |= FB_SYNC_VERT_HIGH_ACT;
 			}
                 } else if (!strncmp(this_opt, "dpc:", 4)) {
-                        if ( simple_strtoul(this_opt+4, NULL, 0) == 0 ) {
+                        if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
 				dev_info(dev, "override double pixel clock: false\n");
 				inf->lccr3 &= ~LCCR3_DPC;
 			} else {
@@ -1186,20 +1192,20 @@
 				inf->lccr3 |= LCCR3_DPC;
 			}
                 } else if (!strncmp(this_opt, "outputen:", 9)) {
-                        if ( simple_strtoul(this_opt+9, NULL, 0) == 0 ) {
+                        if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
 				dev_info(dev, "override output enable: active low\n");
-				inf->lccr3 = ( inf->lccr3 & ~LCCR3_OEP ) | LCCR3_OutEnL;
+				inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
 			} else {
 				dev_info(dev, "override output enable: active high\n");
-				inf->lccr3 = ( inf->lccr3 & ~LCCR3_OEP ) | LCCR3_OutEnH;
+				inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
 			}
                 } else if (!strncmp(this_opt, "pixclockpol:", 12)) {
-                        if ( simple_strtoul(this_opt+12, NULL, 0) == 0 ) {
+                        if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
 				dev_info(dev, "override pixel clock polarity: falling edge\n");
-				inf->lccr3 = ( inf->lccr3 & ~LCCR3_PCP ) | LCCR3_PixFlEdg;
+				inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
 			} else {
 				dev_info(dev, "override pixel clock polarity: rising edge\n");
-				inf->lccr3 = ( inf->lccr3 & ~LCCR3_PCP ) | LCCR3_PixRsEdg;
+				inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
 			}
                 } else if (!strncmp(this_opt, "color", 5)) {
 			inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
@@ -1231,7 +1237,6 @@
 {
 	struct pxafb_info *fbi;
 	struct pxafb_mach_info *inf;
-	unsigned long flags;
 	int ret;
 
 	dev_dbg(dev, "pxafb_probe\n");
@@ -1244,7 +1249,7 @@
 
 #ifdef CONFIG_FB_PXA_PARAMETERS
 	ret = pxafb_parse_options(dev, g_options);
-	if ( ret < 0 )
+	if (ret < 0)
 		goto failed;
 #endif
 
@@ -1252,23 +1257,23 @@
         /* Check for various illegal bit-combinations. Currently only
 	 * a warning is given. */
 
-        if ( inf->lccr0 & LCCR0_INVALID_CONFIG_MASK )
+        if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
                 dev_warn(dev, "machine LCCR0 setting contains illegal bits: %08x\n",
                         inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
-        if ( inf->lccr3 & LCCR3_INVALID_CONFIG_MASK )
+        if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
                 dev_warn(dev, "machine LCCR3 setting contains illegal bits: %08x\n",
                         inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
-        if ( inf->lccr0 & LCCR0_DPD &&
-             ( ( inf->lccr0 & LCCR0_PAS ) != LCCR0_Pas ||
-               ( inf->lccr0 & LCCR0_SDS ) != LCCR0_Sngl ||
-               ( inf->lccr0 & LCCR0_CMS ) != LCCR0_Mono ) )
+        if (inf->lccr0 & LCCR0_DPD &&
+	    ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
+	     (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
+	     (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))
                 dev_warn(dev, "Double Pixel Data (DPD) mode is only valid in passive mono"
 			 " single panel mode\n");
-        if ( (inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
-             ( inf->lccr0 & LCCR0_SDS ) == LCCR0_Dual )
+        if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
+	    (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
                 dev_warn(dev, "Dual panel only valid in passive mode\n");
-        if ( (inf->lccr0 & LCCR0_PAS ) == LCCR0_Pas &&
-             (inf->upper_margin || inf->lower_margin) )
+        if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
+             (inf->upper_margin || inf->lower_margin))
                 dev_warn(dev, "Upper and lower margins must be 0 in passive mode\n");
 #endif
 
@@ -1295,9 +1300,7 @@
 		goto failed;
 	}
 	/* enable LCD controller clock */
-	local_irq_save(flags);
-	CKEN |= CKEN16_LCD;
-	local_irq_restore(flags);
+	pxa_set_cken(CKEN16_LCD, 1);
 
 	ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi);
 	if (ret) {
diff -Nru a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
--- a/drivers/video/radeonfb.c	2004-06-23 19:04:28 -07:00
+++ b/drivers/video/radeonfb.c	2004-06-23 19:04:28 -07:00
@@ -1544,7 +1544,7 @@
 					break;
 			}
 
-			rc = get_user(value, (__u32*)arg);
+			rc = get_user(value, (__u32 __user *)arg);
 
 			if (rc)
 				return rc;
@@ -1598,7 +1598,7 @@
 			if (CRTC_CRT_ON & tmp)
 				value |= 0x02;
 
-			return put_user(value, (__u32*)arg);
+			return put_user(value, (__u32 __user *)arg);
 		default:
 			return -EINVAL;
 	}
diff -Nru a/drivers/video/riva/Makefile b/drivers/video/riva/Makefile
--- a/drivers/video/riva/Makefile	2004-06-23 19:04:25 -07:00
+++ b/drivers/video/riva/Makefile	2004-06-23 19:04:25 -07:00
@@ -2,6 +2,10 @@
 # Makefile for the Riva framebuffer driver
 #
 
-obj-$(CONFIG_FB_RIVA) += rivafb.o
+obj-$(CONFIG_FB_RIVA)     += rivafb.o
 
-rivafb-objs := fbdev.o riva_hw.o nv_driver.o
+rivafb-objs               := fbdev.o riva_hw.o nv_driver.o
+
+ifdef CONFIG_FB_RIVA_I2C
+	rivafb-objs       += rivafb-i2c.o
+endif
diff -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
--- a/drivers/video/riva/fbdev.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/riva/fbdev.c	2004-06-23 19:04:27 -07:00
@@ -296,9 +296,8 @@
 static int nomtrr __initdata = 0;
 #endif
 
-#ifndef MODULE
 static char *mode_option __initdata = NULL;
-#endif
+static int  strictmode       = 0;
 
 static struct fb_fix_screeninfo rivafb_fix = {
 	.id		= "nVidia",
@@ -493,54 +492,30 @@
  * rivafb_cursor()
  */
 static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8,
-				     u8 *mask8, u16 bg, u16 fg, u32 w, u32 h)
+				     u16 bg, u16 fg, u32 w, u32 h)
 {
 	int i, j, k = 0;
-	u32 b, m, tmp;
+	u32 b, tmp;
 	u32 *data = (u32 *)data8;
-	u32 *mask = (u32 *)mask8;
 
 	for (i = 0; i < h; i++) {
 		b = *data++;
-		m = *mask++;
 		reverse_order(&b);
 		
 		for (j = 0; j < w/2; j++) {
 			tmp = 0;
 #if defined (__BIG_ENDIAN)
-			if (m & (1 << 31)) {
-				fg |= 1 << 15;
-				bg |= 1 << 15;
-			}
 			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
 			b <<= 1;
-			m <<= 1;
-
-			if (m & (1 << 31)) {
-				fg |= 1 << 15;
-				bg |= 1 << 15;
-			}
 			tmp |= (b & (1 << 31)) ? fg : bg;
 			b <<= 1;
-			m <<= 1;
 #else
-			if (m & 1) {
-				fg |= 1 << 15;
-				bg |= 1 << 15;
-			}
 			tmp = (b & 1) ? fg : bg;
 			b >>= 1;
-			m >>= 1;
-			
-			if (m & 1) {
-				fg |= 1 << 15;
-				bg |= 1 << 15;
-			}
 			tmp |= (b & 1) ? fg << 16 : bg << 16;
 			b >>= 1;
-			m >>= 1;
 #endif
-			writel(tmp, par->riva.CURSOR + k++);
+			writel(tmp, &par->riva.CURSOR[k++]);
 		}
 		k += (MAX_CURS - w)/2;
 	}
@@ -833,6 +808,24 @@
 	rivafb_blank(0, info);
 }
 
+static void riva_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;
+}
+
 /**
  * rivafb_do_maximize - 
  * @info: pointer to fb_info object containing info for current riva board
@@ -872,7 +865,7 @@
 		       "using maximum available virtual resolution\n");
 		for (i = 0; modes[i].xres != -1; i++) {
 			if (modes[i].xres * nom / den * modes[i].yres <
-			    info->fix.smem_len / 2)
+			    info->fix.smem_len)
 				break;
 		}
 		if (modes[i].xres == -1) {
@@ -927,35 +920,47 @@
 		       "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
 		return -EINVAL;
 	}
+	if (var->xres_virtual > 0x7fff)
+	    var->xres_virtual = 0x7fff;
+	if (var->yres_virtual > 0x7fff)
+	    var->yres_virtual = 0x7fff;
 	return 0;
 }
 
+static void
+riva_set_pattern(struct riva_par *par, int clr0, int clr1, int pat0, int pat1)
+{
+	RIVA_FIFO_FREE(par->riva, Patt, 4);
+	par->riva.Patt->Color0        = clr0;
+	par->riva.Patt->Color1        = clr1;
+	par->riva.Patt->Monochrome[0] = pat0;
+	par->riva.Patt->Monochrome[1] = pat1;
+}
+
 /* acceleration routines */
 inline void wait_for_idle(struct riva_par *par)
 {
 	while (par->riva.Busy(&par->riva));
 }
 
-/* set copy ROP, no mask */
-static void riva_setup_ROP(struct riva_par *par)
+/*
+ * Set ROP.  Translate X rop into ROP3.  Internal routine.
+ */
+static void
+riva_set_rop_solid(struct riva_par *par, int rop)
 {
-	RIVA_FIFO_FREE(par->riva, Patt, 5);
-	par->riva.Patt->Shape = 0;
-	par->riva.Patt->Color0 = 0xffffffff;
-	par->riva.Patt->Color1 = 0xffffffff;
-	par->riva.Patt->Monochrome[0] = 0xffffffff;
-	par->riva.Patt->Monochrome[1] = 0xffffffff;
+	riva_set_pattern(par, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+        RIVA_FIFO_FREE(par->riva, Rop, 1);
+        par->riva.Rop->Rop3 = rop;
 
-	RIVA_FIFO_FREE(par->riva, Rop, 1);
-	par->riva.Rop->Rop3 = 0xCC;
 }
 
 void riva_setup_accel(struct riva_par *par)
 {
 	RIVA_FIFO_FREE(par->riva, Clip, 2);
 	par->riva.Clip->TopLeft     = 0x0;
-	par->riva.Clip->WidthHeight = 0x80008000;
-	riva_setup_ROP(par);
+	par->riva.Clip->WidthHeight = 0x7fff7fff;
+	riva_set_rop_solid(par, 0xcc);
 	wait_for_idle(par);
 }
 
@@ -1043,7 +1048,9 @@
 
 static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct fb_monspecs *specs = &info->monspecs;
 	int nom, den;		/* translating from pixels->bytes */
+	int mode_valid = 0;
 	
 	switch (var->bits_per_pixel) {
 	case 1 ... 8:
@@ -1094,6 +1101,73 @@
 		return -EINVAL;
 	}
 
+	if (!strictmode) {
+		if (!fb_validate_mode(var, info))
+			mode_valid = 1;
+	}
+
+	/* find best mode from modedb */
+	if (!mode_valid && specs->modedb_len) {
+		int i, best, best_refresh, best_x, best_y, diff_x, diff_y;
+
+		best_refresh = best = best_x = best_y = 0;
+		diff_x = diff_y = -1;
+
+		for (i = 0; i < specs->modedb_len; i++) {
+			if (var->xres <= specs->modedb[i].xres &&
+			    !(specs->modedb[i].flag & FB_MODE_IS_CALCULATED) &&
+			    specs->modedb[i].xres - var->xres < diff_x) {
+				best_x = specs->modedb[i].xres;
+				diff_x = best_x - var->xres;
+			}
+			if (!diff_x) break;
+		}
+
+		if (diff_x != -1) {
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (best_x == specs->modedb[i].xres &&
+				    var->yres <= specs->modedb[i].yres &&
+				    !(specs->modedb[i].flag &
+				      FB_MODE_IS_CALCULATED) &&
+				    specs->modedb[i].yres-var->yres < diff_y) {
+					best_y = specs->modedb[i].yres;
+					diff_y = best_y - var->yres;
+				}
+				if (!diff_y) break;
+			}
+		}
+
+		if (diff_y != -1) {
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (best_x == specs->modedb[i].xres &&
+				    best_y == specs->modedb[i].yres &&
+				    !(specs->modedb[i].flag &
+				      FB_MODE_IS_CALCULATED) &&
+				    specs->modedb[i].refresh > best_refresh) {
+					best_refresh=specs->modedb[i].refresh;
+					best = i;
+				}
+			}
+		}
+
+		if (best_refresh) {
+			riva_update_var(var, &specs->modedb[best]);
+			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 && info->monspecs.modedb_len)
+		return -EINVAL;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual <= var->yres)
+		var->yres_virtual = -1;
 	if (rivafb_do_maximize(info, var, nom, den) < 0)
 		return -EINVAL;
 
@@ -1329,8 +1403,7 @@
 		break;
 	}
 
-	RIVA_FIFO_FREE(par->riva, Rop, 1);
-	par->riva.Rop->Rop3 = rop;
+	riva_set_rop_solid(par, rop);
 
 	RIVA_FIFO_FREE(par->riva, Bitmap, 1);
 	par->riva.Bitmap->Color1A = color;
@@ -1338,10 +1411,12 @@
 	RIVA_FIFO_FREE(par->riva, Bitmap, 2);
 	par->riva.Bitmap->UnclippedRectangle[0].TopLeft =
 			(rect->dx << 16) | rect->dy;
+	mb();
 	par->riva.Bitmap->UnclippedRectangle[0].WidthHeight =
 			(rect->width << 16) | rect->height;
-	RIVA_FIFO_FREE(par->riva, Rop, 1);
-	par->riva.Rop->Rop3 = 0xCC;	// back to COPY
+	mb();
+	riva_set_rop_solid(par, 0xcc);
+
 }
 
 /**
@@ -1362,8 +1437,9 @@
 	RIVA_FIFO_FREE(par->riva, Blt, 3);
 	par->riva.Blt->TopLeftSrc  = (region->sy << 16) | region->sx;
 	par->riva.Blt->TopLeftDst  = (region->dy << 16) | region->dx;
+	mb();
 	par->riva.Blt->WidthHeight = (region->height << 16) | region->width;
-	wait_for_idle(par);
+	mb();
 }
 
 static inline void convert_bgcolor_16(u32 *col)
@@ -1372,6 +1448,7 @@
 		| ((*col & 0x000003E0) << 6)
 		| ((*col & 0x0000001F) << 3)
 		|	   0xFF000000;
+	mb();
 }
 
 /**
@@ -1478,7 +1555,6 @@
 {
 	struct riva_par *par = (struct riva_par *) info->par;
 	u8 data[MAX_CURS * MAX_CURS/8];
-	u8 mask[MAX_CURS * MAX_CURS/8];
 	u16 fg, bg;
 	int i;
 
@@ -1508,7 +1584,7 @@
 		info->cursor.image.fg_color = cursor->image.fg_color;
 	}
 
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) {
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETCUR)) {
 		u32 bg_idx = info->cursor.image.bg_color;
 		u32 fg_idx = info->cursor.image.fg_color;
 		u32 s_pitch = (info->cursor.image.width+7) >> 3;
@@ -1517,34 +1593,35 @@
 		u8 *msk = (u8 *) info->cursor.mask;
 		u8 src[64];	
 		
+		info->cursor.image.data = cursor->image.data;
 		switch (info->cursor.rop) {
 		case ROP_XOR:
-			for (i = 0; i < s_pitch * info->cursor.image.height; i++)
-					src[i] = dat[i] ^ msk[i];
+			for (i = 0; i < s_pitch * info->cursor.image.height;
+			     i++)
+				src[i] = dat[i] ^ msk[i];
 			break;
 		case ROP_COPY:
 		default:
-			for (i = 0; i < s_pitch * info->cursor.image.height; i++)
-				
-					src[i] = dat[i] & msk[i];
+			for (i = 0; i < s_pitch * info->cursor.image.height;
+			     i++)
+				src[i] = dat[i] & msk[i];
 			break;
 		}
 		
-		fb_move_buf_aligned(info, &info->sprite, data, d_pitch, src, s_pitch, info->cursor.image.height);
-
-		fb_move_buf_aligned(info, &info->sprite, mask, d_pitch, msk, s_pitch, info->cursor.image.height);
+		fb_move_buf_aligned(info, &info->sprite, data, d_pitch, src,
+				    s_pitch, info->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);
+		     ((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);
+		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
 
 		par->riva.LockUnlock(&par->riva, 0);
 
-		rivafb_load_cursor_image(par, data, mask, bg, fg,
+		rivafb_load_cursor_image(par, data, bg, fg,
 					 info->cursor.image.width, 
 					 info->cursor.image.height);
 	}
@@ -1586,24 +1663,19 @@
 
 static int __devinit riva_set_fbinfo(struct fb_info *info)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
 	unsigned int cmap_len;
 
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT
+		    | FBINFO_HWACCEL_XPAN
+		    | FBINFO_HWACCEL_YPAN
+		    | FBINFO_HWACCEL_COPYAREA
+		    | FBINFO_HWACCEL_FILLRECT
+		    | FBINFO_HWACCEL_IMAGEBLIT;
 	info->var = rivafb_default_var;
-	info->fix = rivafb_fix;
-	info->fbops = &riva_fb_ops;
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
 	info->pseudo_palette = pseudo_palette;
 
-#ifndef MODULE
-	if (mode_option)
-		fb_find_mode(&info->var, info, mode_option,
-			     NULL, 0, NULL, 8);
-#endif
-	if (par->use_default_var)
-		/* We will use the modified default var */
-		info->var = rivafb_default_var;
-
 	cmap_len = riva_get_cmap_len(&info->var);
 	fb_alloc_cmap(&info->cmap, cmap_len, 0);	
 
@@ -1611,7 +1683,8 @@
 	info->pixmap.buf_align = 4;
 	info->pixmap.scan_align = 4;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-	return 0;
+	info->var.yres_virtual = -1;
+	return (rivafb_check_var(&info->var, info));
 }
 
 #ifdef CONFIG_PPC_OF
@@ -1645,77 +1718,35 @@
 }
 #endif /* CONFIG_PPC_OF */
 
-static int riva_dfp_parse_EDID(struct riva_par *par)
+static void riva_update_default_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	unsigned char *block = par->EDID;
-
-	if (!block)
-		return 0;
+	struct fb_monspecs *specs = &info->monspecs;
+	struct fb_videomode modedb;
 
-	/* jump to detailed timing block section */
-	block += 54;
-
-	par->clock = (block[0] + (block[1] << 8));
-	par->panel_xres = (block[2] + ((block[4] & 0xf0) << 4));
-	par->hblank = (block[3] + ((block[4] & 0x0f) << 8));
-	par->panel_yres = (block[5] + ((block[7] & 0xf0) << 4));
-	par->vblank = (block[6] + ((block[7] & 0x0f) << 8));
-	par->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2));
-	par->hSync_width = (block[9] + ((block[11] & 0x30) << 4));
-	par->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2));
-	par->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4));
-	par->interlaced = ((block[17] & 0x80) >> 7);
-	par->synct = ((block[17] & 0x18) >> 3);
-	par->misc = ((block[17] & 0x06) >> 1);
-	par->hAct_high = par->vAct_high = 0;
-	if (par->synct == 3) {
-		if (par->misc & 2)
-			par->hAct_high = 1;
-		if (par->misc & 1)
-			par->vAct_high = 1;
+	/* respect mode options */
+	if (mode_option) {
+		fb_find_mode(var, info, mode_option,
+			     specs->modedb, specs->modedb_len,
+			     NULL, 8);
+	} else if (specs->modedb != NULL) {
+		/* get preferred timing */
+		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];
+		}
+		var->bits_per_pixel = 8;
+		riva_update_var(var, &modedb);
 	}
-
-	printk(KERN_INFO PFX
-			"detected DFP panel size from EDID: %dx%d\n", 
-			par->panel_xres, par->panel_yres);
-	par->got_dfpinfo = 1;
-	return 1;
-}
-
-static void riva_update_default_var(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &rivafb_default_var;
-	struct riva_par *par = (struct riva_par *) info->par;
-
-        var->xres = par->panel_xres;
-        var->yres = par->panel_yres;
-        var->xres_virtual = par->panel_xres;
-        var->yres_virtual = par->panel_yres;
-        var->xoffset = var->yoffset = 0;
-        var->bits_per_pixel = 8;
-        var->pixclock = 100000000 / par->clock;
-        var->left_margin = (par->hblank - par->hOver_plus - par->hSync_width);
-        var->right_margin = par->hOver_plus;
-        var->upper_margin = (par->vblank - par->vOver_plus - par->vSync_width);
-        var->lower_margin = par->vOver_plus;
-        var->hsync_len = par->hSync_width;
-        var->vsync_len = par->vSync_width;
-        var->sync = 0;
-
-        if (par->synct == 3) {
-                if (par->hAct_high)
-                        var->sync |= FB_SYNC_HOR_HIGH_ACT;
-                if (par->vAct_high)
-                        var->sync |= FB_SYNC_VERT_HIGH_ACT;
-        }
- 
-        var->vmode = 0;
-        if (par->interlaced)
-                var->vmode |= FB_VMODE_INTERLACED;
-
 	var->accel_flags |= FB_ACCELF_TEXT;
-        
-        par->use_default_var = 1;
 }
 
 
@@ -1726,19 +1757,27 @@
 		printk("rivafb: could not retrieve EDID from OF\n");
 #else
 	/* XXX use other methods later */
+#ifdef CONFIG_FB_RIVA_I2C
+	struct riva_par *par = (struct riva_par *) info->par;
+
+	riva_create_i2c_busses(par);
+	riva_probe_i2c_connector(par, 1, &par->EDID);
+	riva_delete_i2c_busses(par);
+#endif
 #endif
 }
 
 
-static void riva_get_dfpinfo(struct fb_info *info)
+static void riva_get_edidinfo(struct fb_info *info)
 {
+	struct fb_var_screeninfo *var = &rivafb_default_var;
 	struct riva_par *par = (struct riva_par *) info->par;
 
-	if (riva_dfp_parse_EDID(par))
-		riva_update_default_var(info);
+	fb_edid_to_monspecs(par->EDID, &info->monspecs);
+	riva_update_default_var(var, info);
 
 	/* if user specified flatpanel, we respect that */
-	if (par->got_dfpinfo == 1)
+	if (info->monspecs.input & FB_DISP_DDI)
 		par->FlatPanel = 1;
 }
 
@@ -1768,6 +1807,7 @@
 
 	memset(info, 0, sizeof(struct fb_info));
 	memset(default_par, 0, sizeof(struct riva_par));
+	default_par->pdev = pd;
 
 	info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL);
 	if (info->pixmap.addr == NULL)
@@ -1815,10 +1855,6 @@
 
 	info->par = default_par;
 
-	riva_get_EDID(info, pd);
-
-	riva_get_dfpinfo(info);
-
 	switch (default_par->riva.Architecture) {
 	case NV_ARCH_03:
 		/* Riva128's PRAMIN is in the "framebuffer" space
@@ -1883,6 +1919,11 @@
 	}
 #endif /* CONFIG_MTRR */
 
+	info->fbops = &riva_fb_ops;
+	info->fix = rivafb_fix;
+	riva_get_EDID(info, pd);
+	riva_get_edidinfo(info);
+
 	if (riva_set_fbinfo(info) < 0) {
 		printk(KERN_ERR PFX "error setting initial video mode\n");
 		goto err_out_iounmap_fb;
@@ -1991,6 +2032,8 @@
 		} else if (!strncmp(this_opt, "nomtrr", 6)) {
 			nomtrr = 1;
 #endif
+		} else if (!strncmp(this_opt, "strictmode", 10)) {
+			strictmode = 1;
 		} else
 			mode_option = this_opt;
 	}
@@ -2039,6 +2082,8 @@
 #ifdef CONFIG_MTRR
 MODULE_PARM(nomtrr, "i");
 MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
+MODULE_PARM(strictmode, "i");
+MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
 #endif
 #endif /* MODULE */
 
diff -Nru a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/riva/rivafb-i2c.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,209 @@
+/*
+ * linux/drivers/video/riva/fbdev-i2c.c - nVidia i2c
+ *
+ * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on radeonfb-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 "rivafb.h"
+#include "../edid.h"
+
+#define RIVA_DDC 	0x50
+
+static void riva_gpio_setscl(void* data, int state)
+{
+	struct riva_i2c_chan 	*chan = (struct riva_i2c_chan *)data;
+	struct riva_par 	*par = chan->par;
+	u32			val;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+	val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0;
+
+	if (state)
+		val |= 0x20;
+	else
+		val &= ~0x20;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+	VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1);
+}
+
+static void riva_gpio_setsda(void* data, int state)
+{
+	struct riva_i2c_chan 	*chan = (struct riva_i2c_chan *)data;
+	struct riva_par 	*par = chan->par;
+	u32			val;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+	val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0;
+
+	if (state)
+		val |= 0x10;
+	else
+		val &= ~0x10;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+	VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1);
+}
+
+static int riva_gpio_getscl(void* data)
+{
+	struct riva_i2c_chan 	*chan = (struct riva_i2c_chan *)data;
+	struct riva_par 	*par = chan->par;
+	u32			val = 0;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base);
+	if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x04)
+		val = 1;
+
+	val = VGA_RD08(par->riva.PCIO, 0x3d5);
+
+	return val;
+}
+
+static int riva_gpio_getsda(void* data)
+{
+	struct riva_i2c_chan 	*chan = (struct riva_i2c_chan *)data;
+	struct riva_par 	*par = chan->par;
+	u32			val = 0;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base);
+	if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x08)
+		val = 1;
+
+	return val;
+}
+
+#define I2C_ALGO_RIVA   0x0e0000
+static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name)
+{
+	int rc;
+
+	strcpy(chan->adapter.name, name);
+	chan->adapter.owner		= THIS_MODULE;
+	chan->adapter.id		= I2C_ALGO_RIVA;
+	chan->adapter.algo_data		= &chan->algo;
+	chan->adapter.dev.parent	= &chan->par->pdev->dev;
+	chan->algo.setsda		= riva_gpio_setsda;
+	chan->algo.setscl		= riva_gpio_setscl;
+	chan->algo.getsda		= riva_gpio_getsda;
+	chan->algo.getscl		= riva_gpio_getscl;
+	chan->algo.udelay		= 40;
+	chan->algo.timeout		= 20;
+	chan->algo.data 		= chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	/* Raise SCL and SDA */
+	riva_gpio_setsda(chan, 1);
+	riva_gpio_setscl(chan, 1);
+	udelay(20);
+
+	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);
+	return rc;
+}
+
+void riva_create_i2c_busses(struct riva_par *par)
+{
+	par->chan[0].par	= par;
+	par->chan[1].par	= par;
+	par->chan[2].par        = par;
+
+	switch (par->riva.Architecture) {
+#if 0		/* no support yet for other nVidia chipsets */
+		par->chan[2].ddc_base   = 0x50;
+		riva_setup_i2c_bus(&par->chan[2], "BUS2");
+#endif
+	case NV_ARCH_10:
+	case NV_ARCH_20:
+	case NV_ARCH_04:
+		par->chan[1].ddc_base	= 0x36;
+		riva_setup_i2c_bus(&par->chan[1], "BUS1");
+	case NV_ARCH_03:
+		par->chan[0].ddc_base	= 0x3e;
+		riva_setup_i2c_bus(&par->chan[0], "BUS0");
+	}
+}
+
+void riva_delete_i2c_busses(struct riva_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;
+
+}
+
+static u8 *riva_do_probe_i2c_edid(struct riva_i2c_chan *chan)
+{
+	u8 start = 0x0;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= RIVA_DDC,
+			.len	= 1,
+			.buf	= &start,
+		}, {
+			.addr	= RIVA_DDC,
+			.flags	= I2C_M_RD,
+			.len	= EDID_LENGTH,
+		},
+	};
+	u8 *buf;
+
+	buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!buf) {
+		dev_warn(&chan->par->pdev->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->pdev->dev, "Unable to read EDID block.\n");
+	kfree(buf);
+	return NULL;
+}
+
+int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid)
+{
+	u8 *edid = NULL;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		/* Do the real work */
+		edid = riva_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/riva/rivafb.h b/drivers/video/riva/rivafb.h
--- a/drivers/video/riva/rivafb.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/riva/rivafb.h	2004-06-23 19:04:26 -07:00
@@ -4,6 +4,10 @@
 #include <linux/config.h>
 #include <linux/fb.h>
 #include <video/vga.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+
 #include "riva_hw.h"
 
 /* GGI compatibility macros */
@@ -12,6 +16,12 @@
 #define NUM_GRC_REGS		0x09
 #define NUM_ATC_REGS		0x15
 
+/* I2C */
+#define DDC_SCL_READ_MASK       (1 << 2)
+#define DDC_SCL_WRITE_MASK      (1 << 5)
+#define DDC_SDA_READ_MASK       (1 << 3)
+#define DDC_SDA_WRITE_MASK      (1 << 4)
+
 /* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
  * From KGI originally. */
 struct riva_regs {
@@ -23,6 +33,15 @@
 	RIVA_HW_STATE ext;
 };
 
+struct riva_par;
+
+struct riva_i2c_chan {
+	struct riva_par *par;
+	unsigned long   ddc_base;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+};
+
 struct riva_par {
 	RIVA_HW_INST riva;	/* interface to riva_hw.c */
 
@@ -36,26 +55,22 @@
 	u32 cursor_data[32 * 32/4];
 	int cursor_reset;
 	unsigned char *EDID;
-
-	int panel_xres, panel_yres;
-	int hOver_plus, hSync_width, hblank;
-	int vOver_plus, vSync_width, vblank;
-	int hAct_high, vAct_high, interlaced;
-	int synct, misc, clock;
-
-	int use_default_var;
-	int got_dfpinfo;
 	unsigned int Chipset;
 	int forceCRTC;
 	Bool SecondCRTC;
 	int FlatPanel;
+	struct pci_dev *pdev;
 #ifdef CONFIG_MTRR
 	struct { int vram; int vram_valid; } mtrr;
 #endif
+	struct riva_i2c_chan chan[3];
 };
 
 void riva_common_setup(struct riva_par *);
 unsigned long riva_get_memlen(struct riva_par *);
 unsigned long riva_get_maxdclk(struct riva_par *);
+void riva_delete_i2c_busses(struct riva_par *par);
+void riva_create_i2c_busses(struct riva_par *par);
+int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid);
 
 #endif /* __RIVAFB_H */
diff -Nru a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
--- a/drivers/video/sa1100fb.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/sa1100fb.c	2004-06-23 19:04:26 -07:00
@@ -328,17 +328,17 @@
 
 #ifdef CONFIG_SA1100_COLLIE
 static struct sa1100fb_mach_info collie_info __initdata = {
-	pixclock:	171521,		bpp:		16,
-	xres:		320,		yres:		240,
+	.pixclock	= 171521,	.bpp		= 16,
+	.xres		= 320,		.yres		= 240,
 
-	hsync_len:	5,		vsync_len:	1,
-	left_margin:	11,		upper_margin:	2,
-	right_margin:	30,		lower_margin:	0,
+	.hsync_len	= 5,		.vsync_len	= 1,
+	.left_margin	= 11,		.upper_margin	= 2,
+	.right_margin	= 30,		.lower_margin	= 0,
 
-	sync:		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 
-	lccr0:		LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-	lccr3:		LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
 };
 #endif
 
diff -Nru a/drivers/video/sis/300vtbl.h b/drivers/video/sis/300vtbl.h
--- a/drivers/video/sis/300vtbl.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/video/sis/300vtbl.h	2004-06-23 19:04:25 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Register settings for SiS 300 series
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -52,20 +50,7 @@
  *
  */
 
-typedef struct _SiS300_StStruct
-{
-	UCHAR St_ModeID;
-	USHORT St_ModeFlag;
-	UCHAR St_StTableIndex;
-	UCHAR St_CRT2CRTC;
-	UCHAR St_ResInfo;
-	UCHAR VB_StTVFlickerIndex;
-	UCHAR VB_StTVEdgeIndex;
-	UCHAR VB_StTVYFilterIndex;
-	UCHAR St_PDC;
-} SiS300_StStruct;
-
-static const SiS300_StStruct  SiS300_SModeIDTable[] =
+static const SiS_StStruct  SiS300_SModeIDTable[] =
 {
 	{0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00, 0},
 	{0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00, 0},
@@ -89,206 +74,168 @@
 	{0xff,     0,   0,   0,   0,   0,   0,   0, 0}
 };
 
-typedef struct _SiS300_ExtStruct
+static const SiS_ExtStruct  SiS300_EModeIDTable[] =
 {
-	UCHAR  Ext_ModeID;
-	USHORT Ext_ModeFlag;
-	UCHAR  Ext_ModeOffset;
-	USHORT Ext_VESAID;
-	UCHAR  Ext_RESINFO;
-	UCHAR  VB_ExtTVFlickerIndex;
-	UCHAR  VB_ExtTVEdgeIndex;
-	UCHAR  VB_ExtTVYFilterIndex;
-	UCHAR  VB_ExtTVYFilterIndexROM661;
-	UCHAR  REFindex;
-} SiS300_ExtStruct;
-
-static const SiS300_ExtStruct  SiS300_EModeIDTable[] =
-{
-	{0x6a,0x2212,0x04,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x? */
-	{0x2e,0x0a1b,0x03,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x2f,0x021b,0x03,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x8 */
-	{0x30,0x2a1b,0x04,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},
-	{0x31,0x0a1b,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x8 */
-	{0x32,0x2a1b,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x8 */
-	{0x33,0x0a1d,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x16 */
-	{0x34,0x2a1d,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x16 */
-	{0x35,0x0a1f,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x32 */
-	{0x36,0x2a1f,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x32 */
-	{0x37,0x0212,0x05,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x? */
-	{0x38,0x0a1b,0x05,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x8 */
-	{0x3a,0x0e3b,0x06,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},  /* 1280x1024x8 */
-	{0x3c,0x063b,0x07,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x3d,0x067d,0x07,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x40,0x921c,0x00,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x15 */
-	{0x41,0x921d,0x00,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x16 */
-	{0x43,0x0a1c,0x03,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x44,0x0a1d,0x03,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x46,0x2a1c,0x04,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x15 */
-	{0x47,0x2a1d,0x04,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x16 */
-	{0x49,0x0a3c,0x05,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4a,0x0a3d,0x05,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4c,0x0e7c,0x06,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x06,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x50,0x921b,0x00,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x8  */
-	{0x51,0xb21b,0x01,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x8  */
-	{0x52,0x921b,0x02,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x8  */
-	{0x56,0x921d,0x00,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x16 */
-	{0x57,0xb21d,0x01,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x16 */
-	{0x58,0x921d,0x02,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x16 */
-	{0x59,0x921b,0x00,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x8  */
-	{0x5c,0x921f,0x02,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x32 */
-	{0x5d,0x021d,0x03,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x16 */
- 	{0x5e,0x021f,0x03,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x32 */
-	{0x62,0x0a3f,0x03,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x63,0x2a3f,0x04,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x32 */
-	{0x64,0x0a7f,0x05,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x65,0x0eff,0x06,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x66,0x06ff,0x07,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x68,0x067b,0x08,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x69,0x06fd,0x08,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6b,0x07ff,0x08,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6c,0x067b,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x8 - not in BIOS! */
-	{0x6d,0x06fd,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x16 - not in BIOS! */
-	{0x70,0x2a1b,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x8 */
-	{0x71,0x0a1b,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x8 */
-	{0x74,0x0a1d,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x16 */
-	{0x75,0x0e3d,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x16 */
-	{0x76,0x2a1f,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x32 */
-	{0x77,0x0a3f,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x32 */
-	{0x78,0x0eff,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x32 */
-	{0x79,0x0e3b,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x8 */
-	{0x7a,0x2a1d,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x16 */
-	{0x7c,0x0a3b,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x8 */
-	{0x7d,0x0a7d,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x16 */
-	{0x7e,0x0aff,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x32 */
-	{0x20,0x0a1b,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},  /* 1024x600 */
-	{0x21,0x0a3d,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x22,0x0a7f,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x23,0x0a1b,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},  /* 1152x768 */
-	{0x24,0x0a3d,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x25,0x0a7f,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x29,0x0e1b,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},  /* 1152x864 */
-	{0x2a,0x0e3d,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x2b,0x0e7f,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x39,0x2a1b,0x0d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},  /* 848x480 */
-	{0x3b,0x2a3d,0x0d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3e,0x2a7f,0x0d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3f,0x2a1b,0x0d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},  /* 856x480 */
-	{0x42,0x2a3d,0x0d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x45,0x2a7f,0x0d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x48,0x223b,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},  /* 1360x768 */
-	{0x4b,0x227d,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4e,0x22ff,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4f,0x921f,0x00,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x32 */
-	{0x53,0x921f,0x00,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x32 */
-	{0x54,0xb21f,0x01,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x32 */
-	{0x55,0x2e3b,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},  /* 1280x768   */
-	{0x5a,0x2e7d,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5b,0x2eff,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5f,0x2a1b,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x8 */
-	{0x60,0x2a1d,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x16 */
-	{0x61,0x2a1f,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x32 */
-	{0x67,0x2e3b,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x8 (BARCO) */
-	{0x6f,0x2e7d,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x16 (BARCO) */
-	{0x72,0x2eff,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x32 (BARCO) */
-	{0xff,0x0000,0x00,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
-};
-
-typedef struct _SiS300_Ext2Struct
-{
-	USHORT Ext_InfoFlag;
-	UCHAR  Ext_CRT1CRTC;  /* Index in SiS300_CRT1Table */
-	UCHAR  Ext_CRTVCLK;   /* Index in VCLK array */
-	UCHAR  Ext_CRT2CRTC;  /* Index in LCD Paneltype arrays (&3f) */
-	UCHAR  ModeID;
-	USHORT XRes;
-	USHORT YRes;
-	UCHAR  Ext_PDC;
-} SiS300_Ext2Struct;
-
-static const SiS300_Ext2Struct  SiS300_RefIndex[] =
-{
-	{0x085f,0x0d,0x03,0x05,0x6a, 800, 600, 0}, /* 00 */
-	{0x0467,0x0e,0x44,0x05,0x6a, 800, 600, 0}, /* 01 */
-	{0x0067,0x0f,0x07,0x48,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */
-	{0x0067,0x10,0x06,0x8b,0x6a, 800, 600, 0}, /* 03 */
-	{0x0147,0x11,0x08,0x00,0x6a, 800, 600, 0}, /* 04 */
-	{0x0147,0x12,0x0c,0x00,0x6a, 800, 600, 0}, /* 05 */
-	{0x0047,0x11,0x4e,0x00,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */
-	{0x0047,0x11,0x13,0x00,0x6a, 800, 600, 0}, /* 07 */
-	{0xc85f,0x05,0x00,0x04,0x2e, 640, 480, 0}, /* 08 */
-	{0xc067,0x06,0x02,0x04,0x2e, 640, 480, 0}, /* 09 */
-	{0xc067,0x07,0x02,0x47,0x2e, 640, 480, 0}, /* 0a */
-	{0xc067,0x08,0x03,0x8a,0x2e, 640, 480, 0}, /* 0b */
-	{0xc047,0x09,0x05,0x00,0x2e, 640, 480, 0}, /* 0c */
-	{0xc047,0x0a,0x08,0x00,0x2e, 640, 480, 0}, /* 0d */
-	{0xc047,0x0b,0x0a,0x00,0x2e, 640, 480, 0}, /* 0e */
-	{0xc047,0x0c,0x10,0x00,0x2e, 640, 480, 0}, /* 0f */
-	{0x487f,0x04,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */
-	{0xc04f,0x31,0x01,0x06,0x31, 720, 480, 0}, /* 11 */
-	{0x004f,0x32,0x03,0x06,0x32, 720, 576, 0}, /* 12 */
-	{0x0187,0x15,0x05,0x00,0x37,1024, 768, 0}, /* 13 */
-        {0xc877,0x16,0x09,0x06,0x37,1024, 768, 0}, /* 14 */
-	{0xc067,0x17,0x0b,0x49,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */
-	{0x0267,0x18,0x0d,0x00,0x37,1024, 768, 0}, /* 16 */
-	{0x0047,0x19,0x11,0x8c,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */
-	{0x0047,0x1a,0x52,0x00,0x37,1024, 768, 0}, /* 18 */
-	{0x0007,0x1b,0x16,0x00,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */
-	{0x0387,0x1c,0x4d,0x00,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */
-	{0x0077,0x1d,0x14,0x07,0x3a,1280,1024, 0}, /* 1b */
-	{0x0047,0x1e,0x17,0x00,0x3a,1280,1024, 0}, /* 1c */
-	{0x0007,0x1f,0x98,0x00,0x3a,1280,1024, 0}, /* 1d */
-	{0x0007,0x20,0x59,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */
-	{0x0007,0x21,0x5a,0x00,0x3c,1600,1200, 0}, /* 1f */
-	{0x0007,0x22,0x1b,0x00,0x3c,1600,1200, 0}, /* 20 */
-	{0x0007,0x23,0x1d,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */
-	{0x0007,0x24,0x1e,0x00,0x3c,1600,1200, 0}, /* 22 */
-	{0x407f,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */
-	{0xc07f,0x01,0x00,0x04,0x50, 320, 240, 0}, /* 24 */
-	{0x0077,0x02,0x04,0x05,0x51, 400, 300, 0}, /* 25 */
-	{0xc877,0x03,0x09,0x06,0x52, 512, 384, 0}, /* 26 */  /* was c077 */
-	{0x8207,0x25,0x1f,0x00,0x68,1920,1440, 0}, /* 27 */
-	{0x0007,0x26,0x20,0x00,0x6c,2048,1536, 0}, /* 28 */
-	{0x0067,0x27,0x14,0x08,0x6e,1280, 960, 0}, /* 29 - TW: 1280x960-60 */
-	{0x0027,0x45,0x3c,0x08,0x6e,1280, 960, 0}, /* 2a - TW: 1280x960-85 */
-	{0xc077,0x33,0x09,0x06,0x20,1024, 600, 0}, /* 2b */
-	{0xc077,0x34,0x0b,0x06,0x23,1152, 768, 0}, /* 2c */	/* VCLK 0x09 */
-	{0x0057,0x35,0x27,0x08,0x70, 800, 480, 0}, /* 2d */
-	{0x0047,0x36,0x37,0x08,0x70, 800, 480, 0}, /* 2e */
-	{0x0047,0x37,0x08,0x08,0x70, 800, 480, 0}, /* 2f */
-	{0x0057,0x38,0x09,0x09,0x71,1024, 576, 0}, /* 30 */
-	{0x0047,0x39,0x38,0x09,0x71,1024, 576, 0}, /* 31 */
-	{0x0047,0x3a,0x11,0x09,0x71,1024, 576, 0}, /* 32 */
-	{0x0057,0x3b,0x39,0x0a,0x75,1280, 720, 0}, /* 33 */
-	{0x0047,0x3c,0x3a,0x0a,0x75,1280, 720, 0}, /* 34 */
-	{0x0007,0x3d,0x3b,0x0a,0x75,1280, 720, 0}, /* 35 */
-	{0x0047,0x3e,0x34,0x06,0x29,1152, 864, 0}, /* 36 1152x864-75Hz */
-	{0x0047,0x44,0x3a,0x06,0x29,1152, 864, 0}, /* 37 1152x864-85Hz */
-	{0x00c7,0x3f,0x28,0x00,0x39, 848, 480, 0}, /* 38 848x480-38Hzi */
-	{0xc067,0x40,0x3d,0x0b,0x39, 848, 480, 0}, /* 39 848x480-60Hz  */
-	{0x00c7,0x41,0x28,0x00,0x3f, 856, 480, 0}, /* 3a 856x480-38Hzi */
-	{0xc047,0x42,0x28,0x00,0x3f, 856, 480, 0}, /* 3b 856x480-60Hz  */
-	{0x0067,0x43,0x3e,0x0c,0x48,1360, 768, 0}, /* 3c 1360x768-60Hz */
-	{0x0077,0x46,0x3f,0x08,0x55,1280, 768, 0}, /* 3d 1280x768-60Hz */
-	{0x004f,0x47,0x03,0x06,0x5f, 768, 576, 0}, /* 3e 768x576 */
-	{0x0027,0x48,0x13,0x08,0x67,1360,1024, 0}, /* 3f 1360x1024-59Hz (BARCO1366 only) */
-	{0xffff,   0,   0,   0,   0,   0,   0, 0}
-};
-
-typedef struct _SiS_VBModeIDTableStruct
-{
-	UCHAR  ModeID;
-	UCHAR  VB_TVDelayIndex;
-	UCHAR  VB_TVFlickerIndex;
-	UCHAR  VB_TVPhaseIndex;
-	UCHAR  VB_TVYFilterIndex;
-	UCHAR  VB_LCDDelayIndex;
-	UCHAR  _VB_LCDHIndex;
-	UCHAR  _VB_LCDVIndex;
-}SiS_VBModeIDTableStruct;
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x2f,0x021b,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},
+	{0x31,0x0a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x8 */
+	{0x32,0x2a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x8 */
+	{0x33,0x0a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x16 */
+	{0x34,0x2a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x16 */
+	{0x35,0x0a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x32 */
+	{0x36,0x2a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},  /* 1280x1024x8 */
+	{0x3c,0x063b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x3d,0x067d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x40,0x921c,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x15 */
+	{0x41,0x921d,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x15 */
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x50,0x921b,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x8  */
+	{0x51,0xb21b,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x8  */
+	{0x52,0x921b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x8  */
+	{0x56,0x921d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x16 */
+	{0x57,0xb21d,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x16 */
+	{0x58,0x921d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x16 */
+	{0x59,0x921b,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x8  */
+	{0x5c,0x921f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x32 */
+	{0x5d,0x021d,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x16 */
+ 	{0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x66,0x06ff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x8 - not in BIOS! */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x16 - not in BIOS! */
+	{0x70,0x2a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x8 */
+	{0x71,0x0a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x8 */
+	{0x74,0x0a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x16 */
+	{0x75,0x0e3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x16 */
+	{0x76,0x2a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x32 */
+	{0x77,0x0a3f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x32 */
+	{0x78,0x0eff,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x32 */
+	{0x79,0x0e3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x8 */
+	{0x7a,0x2a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x16 */
+	{0x7c,0x0a3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x8 */
+	{0x7d,0x0a7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x16 */
+	{0x7e,0x0aff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x32 */
+	{0x20,0x0a1b,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},  /* 1024x600 */
+	{0x21,0x0a3d,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
+	{0x22,0x0a7f,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
+	{0x23,0x0a1b,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},  /* 1152x768 */
+	{0x24,0x0a3d,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
+	{0x25,0x0a7f,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
+	{0x29,0x0e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},  /* 1152x864 */
+	{0x2a,0x0e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
+	{0x2b,0x0e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
+	{0x39,0x2a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38,-1},  /* 848x480 */
+	{0x3b,0x2a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38,-1},
+	{0x3e,0x2a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38,-1},
+	{0x3f,0x2a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a,-1},  /* 856x480 */
+	{0x42,0x2a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a,-1},
+	{0x45,0x2a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a,-1},
+	{0x48,0x223b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c,-1},  /* 1360x768 */
+	{0x4b,0x227d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c,-1},
+	{0x4e,0x22ff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c,-1},
+	{0x4f,0x921f,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x32 */
+	{0x53,0x921f,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x32 */
+	{0x54,0xb21f,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x32 */
+	{0x55,0x2e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d,-1},  /* 1280x768   */
+	{0x5a,0x2e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d,-1},
+	{0x5b,0x2eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d,-1},
+	{0x5f,0x2a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e,-1},  /* 768x576x8 */
+	{0x60,0x2a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e,-1},  /* 768x576x16 */
+	{0x61,0x2a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e,-1},  /* 768x576x32 */
+	{0x67,0x2e3b,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f,-1},  /* 1360x1024x8 (BARCO) */
+	{0x6f,0x2e7d,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f,-1},  /* 1360x1024x16 (BARCO) */
+	{0x72,0x2eff,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f,-1},  /* 1360x1024x32 (BARCO) */
+	{0xff,0x0000,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
+};
+
+static const SiS_Ext2Struct  SiS300_RefIndex[] =
+{
+	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0}, /* 00 */
+	{0x0467,0x0e,0x44,0x05,0x05,0x6a, 800, 600, 0}, /* 01 */
+	{0x0067,0x0f,0x07,0x48,0x00,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */
+	{0x0067,0x10,0x06,0x8b,0x00,0x6a, 800, 600, 0}, /* 03 */
+	{0x0147,0x11,0x08,0x00,0x00,0x6a, 800, 600, 0}, /* 04 */
+	{0x0147,0x12,0x0c,0x00,0x00,0x6a, 800, 600, 0}, /* 05 */
+	{0x0047,0x11,0x4e,0x00,0x00,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */
+	{0x0047,0x11,0x13,0x00,0x00,0x6a, 800, 600, 0}, /* 07 */
+	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0}, /* 08 */
+	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0}, /* 09 */
+	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0}, /* 0a */
+	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0}, /* 0b */
+	{0xc047,0x09,0x05,0x00,0x00,0x2e, 640, 480, 0}, /* 0c */
+	{0xc047,0x0a,0x08,0x00,0x00,0x2e, 640, 480, 0}, /* 0d */
+	{0xc047,0x0b,0x0a,0x00,0x00,0x2e, 640, 480, 0}, /* 0e */
+	{0xc047,0x0c,0x10,0x00,0x00,0x2e, 640, 480, 0}, /* 0f */
+	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */
+	{0xc04f,0x31,0x01,0x06,0x00,0x31, 720, 480, 0}, /* 11 */
+	{0x004f,0x32,0x03,0x06,0x00,0x32, 720, 576, 0}, /* 12 */
+	{0x0187,0x15,0x05,0x00,0x00,0x37,1024, 768, 0}, /* 13 */
+        {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0}, /* 14 */
+	{0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */
+	{0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0}, /* 16 */
+	{0x0047,0x19,0x11,0x8c,0x00,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */
+	{0x0047,0x1a,0x52,0x00,0x00,0x37,1024, 768, 0}, /* 18 */
+	{0x0007,0x1b,0x16,0x00,0x00,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */
+	{0x0387,0x1c,0x4d,0x00,0x00,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */
+	{0x0077,0x1d,0x14,0x07,0x00,0x3a,1280,1024, 0}, /* 1b */
+	{0x0047,0x1e,0x17,0x00,0x00,0x3a,1280,1024, 0}, /* 1c */
+	{0x0007,0x1f,0x98,0x00,0x00,0x3a,1280,1024, 0}, /* 1d */
+	{0x0007,0x20,0x59,0x00,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */
+	{0x0007,0x21,0x5a,0x00,0x00,0x3c,1600,1200, 0}, /* 1f */
+	{0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0}, /* 20 */
+	{0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */
+	{0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0}, /* 22 */
+	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */
+	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0}, /* 24 */
+	{0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0}, /* 25 */
+	{0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0}, /* 26 */  /* was c077 */
+	{0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0}, /* 27 */
+	{0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0}, /* 28 */
+	{0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0}, /* 29 - 1280x960-60 */
+	{0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0}, /* 2a - 1280x960-85 */
+	{0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0}, /* 2b */
+	{0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0}, /* 2c */	/* VCLK 0x09 */
+	{0x0057,0x35,0x27,0x08,0x00,0x70, 800, 480, 0}, /* 2d */
+	{0x0047,0x36,0x37,0x08,0x00,0x70, 800, 480, 0}, /* 2e */
+	{0x0047,0x37,0x08,0x08,0x00,0x70, 800, 480, 0}, /* 2f */
+	{0x0057,0x38,0x09,0x09,0x00,0x71,1024, 576, 0}, /* 30 */
+	{0x0047,0x39,0x38,0x09,0x00,0x71,1024, 576, 0}, /* 31 */
+	{0x0047,0x3a,0x11,0x09,0x00,0x71,1024, 576, 0}, /* 32 */
+	{0x0057,0x3b,0x39,0x0a,0x00,0x75,1280, 720, 0}, /* 33 */
+	{0x0047,0x3c,0x3a,0x0a,0x00,0x75,1280, 720, 0}, /* 34 */
+	{0x0007,0x3d,0x3b,0x0a,0x00,0x75,1280, 720, 0}, /* 35 */
+	{0x0047,0x3e,0x34,0x06,0x00,0x29,1152, 864, 0}, /* 36 1152x864-75Hz */
+	{0x0047,0x44,0x3a,0x06,0x00,0x29,1152, 864, 0}, /* 37 1152x864-85Hz */
+	{0x00c7,0x3f,0x28,0x00,0x00,0x39, 848, 480, 0}, /* 38 848x480-38Hzi */
+	{0xc067,0x40,0x3d,0x0b,0x0b,0x39, 848, 480, 0}, /* 39 848x480-60Hz  */
+	{0x00c7,0x41,0x28,0x00,0x00,0x3f, 856, 480, 0}, /* 3a 856x480-38Hzi */
+	{0xc047,0x42,0x28,0x00,0x00,0x3f, 856, 480, 0}, /* 3b 856x480-60Hz  */
+	{0x0067,0x43,0x3e,0x0c,0x0b,0x48,1360, 768, 0}, /* 3c 1360x768-60Hz */
+	{0x0077,0x46,0x3f,0x08,0x00,0x55,1280, 768, 0}, /* 3d 1280x768-60Hz */
+	{0x004f,0x47,0x03,0x06,0x00,0x5f, 768, 576, 0}, /* 3e 768x576 */
+	{0x0027,0x48,0x13,0x08,0x08,0x67,1360,1024, 0}, /* 3f 1360x1024-59Hz (BARCO1366 only) */
+	{0xffff,   0,   0,   0,   0,   0,   0,   0, 0}
+};
 
-static const SiS_VBModeIDTableStruct  SiS300_VBModeIDTable[] =
+static const SiS_VBModeStruct SiS300_VBModeIDTable[] =
 {
 	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
 	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
@@ -355,12 +302,7 @@
 	{0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
 };
 
-typedef struct _SiS300_CRT1TableStruct
-{
-	UCHAR CR[17];
-} SiS300_CRT1TableStruct;
-
-static const SiS300_CRT1TableStruct  SiS300_CRT1Table[] =
+static const SiS_CRT1TableStruct  SiS300_CRT1Table[] =
 {
 #if 1
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,    /* 0x00 - 320x200 */
@@ -625,13 +567,7 @@
    0x00}}   /* 0x48 */
 };
 
-typedef struct _SiS300_MCLKDataStruct
-{
-	UCHAR SR28,SR29,SR2A;
-	USHORT CLOCK;
-} SiS300_MCLKDataStruct;
-
-static const SiS300_MCLKDataStruct  SiS300_MCLKData_630[] =
+static const SiS_MCLKDataStruct  SiS300_MCLKData_630[] =
 {
 	{ 0x5a,0x64,0x80, 66},
 	{ 0xb3,0x45,0x80, 83},
@@ -643,7 +579,7 @@
 	{ 0x37,0x61,0x80,100}
 };
 
-static const SiS300_MCLKDataStruct  SiS300_MCLKData_300[] =
+static const SiS_MCLKDataStruct  SiS300_MCLKData_300[] =
 {
 	{ 0x68,0x43,0x80,125},
 	{ 0x68,0x43,0x80,125},
@@ -655,13 +591,7 @@
 	{ 0x37,0x61,0x80,100}
 };
 
-typedef struct _SiS300_VCLKDataStruct
-{
-	UCHAR SR2B,SR2C;
-	USHORT CLOCK;
-} SiS300_VCLKDataStruct;
-
-static const SiS300_VCLKDataStruct  SiS300_VCLKData[] =
+static SiS_VCLKDataStruct SiS300_VCLKData[] =
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -736,14 +666,7 @@
 	{ 0x37,0x61,100}, /* 0x43 */  /* 1280x960 LCD */
 	{ 0xe3,0x9a,106}, /* 0x44 */  /* 1360x1024 - special for Barco iQ R300 */
 	{ 0xe2,0x46,135}, /* 0x45 */  /* 1280x1024-75, better clock for VGA2 */
-	{ 0xff,0x00,  0}
-};
-
-static const UCHAR  SiS300_ScreenOffset[] =
-{
-	0x14,0x19,0x20,0x28,0x32,0x40,0x50,
-        0x64,0x78,0x80,0x2d,0x35,0x48,0x35,
-	0x55,0x30,0xff
+	{    0,   0,  0}  /* 0x46 custom (will be filled out) */
 };
 
 #ifndef LINUX_XF86
@@ -789,12 +712,7 @@
 static UCHAR SiS300_CR49[2];
 #endif
 
-typedef struct _SiS300_PanelDelayTblStruct
-{
-	UCHAR timer[2];
-} SiS300_PanelDelayTblStruct;
-
-static const SiS300_PanelDelayTblStruct  SiS300_PanelDelayTbl[] =
+static const SiS_PanelDelayTblStruct  SiS300_PanelDelayTbl[] =
 {
 	{{0x05,0xaa}},
 	{{0x05,0x14}},
@@ -815,7 +733,7 @@
 };
 
 #if 0
-static const SiS300_PanelDelayTblStruct  SiS300_PanelDelayTblLVDS[] =
+static const SiS_PanelDelayTblStruct  SiS300_PanelDelayTblLVDS[] =
 {
 	{{0x05,0xaa}},
 	{{0x05,0x14}},
@@ -840,28 +758,18 @@
 /* SIS VIDEO BRIDGE ----------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS300_LCDDataStruct
+static const SiS_LCDDataStruct  SiS300_St2LCD1024x768Data[] =
 {
-	USHORT RVBHCMAX;
-	USHORT RVBHCFACT;
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS300_LCDDataStruct;
-
-static const SiS300_LCDDataStruct  SiS300_StLCD1024x768Data[] =
-{
-	{   66,  31, 992, 510,1320, 816},
-	{   66,  31, 992, 510,1320, 816},
-	{  176,  75, 900, 510,1320, 816},
-	{  176,  75, 900, 510,1320, 816},
-	{   66,  31, 992, 510,1320, 816},
-	{   27,  16,1024, 650,1350, 832},
+	{   62,  25, 800, 546,1344, 806},
+	{   32,  15, 930, 546,1344, 806},
+	{   32,  15, 930, 546,1344, 806},
+	{  104,  45, 945, 496,1344, 806},
+	{   62,  25, 800, 546,1344, 806},
+	{   31,  18,1008, 624,1344, 806},
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS300_LCDDataStruct  SiS300_ExtLCD1024x768Data[] =
+static const SiS_LCDDataStruct  SiS300_ExtLCD1024x768Data[] =
 {
 	{   12,   5, 896, 512,1344, 806},
 	{   12,   5, 896, 510,1344, 806},
@@ -878,30 +786,19 @@
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS300_LCDDataStruct  SiS300_St2LCD1024x768Data[] =
-{
-	{   62,  25, 800, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-	{  104,  45, 945, 496,1344, 806},
-	{   62,  25, 800, 546,1344, 806},
-	{   31,  18,1008, 624,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const SiS300_LCDDataStruct  SiS300_StLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS300_St2LCD1280x1024Data[] =
 {
-	{    4,   1, 880, 510,1650,1088},
-	{    4,   1, 880, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
 	{  176,  45, 900, 510,1650,1088},
 	{  176,  45, 900, 510,1650,1088},
-	{    4,   1, 880, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
 	{   13,   5,1024, 675,1560,1152},
 	{   16,   9,1266, 804,1688,1072},
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS300_LCDDataStruct  SiS300_ExtLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS300_ExtLCD1280x1024Data[] =
 {
 	{  211,  60,1024, 501,1688,1066},
 	{  211,  60,1024, 508,1688,1066},
@@ -913,74 +810,18 @@
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS300_LCDDataStruct  SiS300_St2LCD1280x1024Data[] =
-{
-	{   22,   5, 800, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{   13,   5,1024, 675,1560,1152},
-	{   16,   9,1266, 804,1688,1072},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const SiS300_LCDDataStruct  SiS300_NoScaleData1024x768[] =
-{
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 800, 525, 800, 525},
-	{    1,   1,1056, 628,1056, 628},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const SiS300_LCDDataStruct  SiS300_NoScaleData1280x1024[] =  /* TW: Fake */
-{
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 800, 525, 800, 525},
-	{    1,   1,1056, 628,1056, 628},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-typedef struct _SiS300_Part2PortTblStruct
-{
- 	UCHAR CR[12];
-} SiS300_Part2PortTblStruct;
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] =
 { /* VESA Timing */
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
+  {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+  {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+  {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_1[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_1[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] =
 {  /* Non-VESA */
  {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
  {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
@@ -991,38 +832,23 @@
  {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] =
 {
  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_2[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] =
 {
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_2[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] =
-{	/* TW: Temporary data, invalid */
   {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_3[] =
-{	/* TW: Temporary data, invalid */
-  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] =
+{
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_3[] =
-{	/* TW: Temporary data, invalid */
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] =
+{
   {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
@@ -1030,15 +856,7 @@
 /* LVDS/Chrontel -------------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS300_LVDSDataStruct
-{
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS300_LVDSDataStruct;
-
-static const SiS300_LVDSDataStruct  SiS300_CHTVUPALData[] =
+static const SiS_LVDSDataStruct  SiS300_CHTVUPALData[] =
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1048,7 +866,7 @@
 	{ 936, 836, 936, 836}
 };
 
-static const SiS300_LVDSDataStruct  SiS300_CHTVOPALData[] =
+static const SiS_LVDSDataStruct  SiS300_CHTVOPALData[] =
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1058,7 +876,7 @@
 	{ 960, 750, 960, 750}
 };
 
-static const SiS300_LVDSDataStruct  SiS300_CHTVSOPALData[] =
+static const SiS_LVDSDataStruct  SiS300_CHTVSOPALData[] =
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1068,13 +886,8 @@
 	{ 944, 625, 944, 625}
 };
 
-typedef struct _SiS300_LVDSDesStruct
-{
-	USHORT LCDHDES;
-	USHORT LCDVDES;
-} SiS300_LVDSDesStruct;
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType00_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType00_1[] =
 {
 	{ 1059, 626 },   /* 2.08 */
 	{ 1059, 624 },
@@ -1098,7 +911,7 @@
 #endif
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType01_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType01_1[] =
 {
 	{   0,   0 },  /* 2.08 */
 	{   0,   0 },
@@ -1122,7 +935,7 @@
 #endif
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType02_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType02_1[] =
 {
 	{ 1059, 626 },  /* 2.08 */
 	{ 1059, 624 },
@@ -1146,7 +959,7 @@
 #endif
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType03_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType03_1[] =
 {
 	{   8, 436},
 	{   8, 440},
@@ -1159,7 +972,7 @@
 	{1343, 794}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_1[] =	/* 1280x1024 */
+static const SiS_LVDSDesStruct  SiS300_PanelType04_1[] =	/* 1280x1024 */
 {
 	{1343, 798},
 	{1343, 794},
@@ -1172,7 +985,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType05_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType05_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1185,7 +998,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType06_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType06_1[] =	/* Clevo Trumpion 1024x768 */
 {
 	{1343, 798},
 	{1343, 794},
@@ -1198,7 +1011,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType07_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType07_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1211,7 +1024,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType08_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType08_1[] =
 {
 	{1059, 626},
 	{1059, 624},
@@ -1224,7 +1037,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType09_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType09_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1237,7 +1050,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0a_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0a_1[] =
 {
 	{1059, 626},
 	{1059, 624},
@@ -1250,7 +1063,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0b_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0b_1[] =
 {
 	{1343,   0},
 	{1343,   0},
@@ -1263,7 +1076,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0c_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0c_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1276,7 +1089,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0d_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0d_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1289,7 +1102,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0e_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0e_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1302,7 +1115,7 @@
 	{   0,   0}     /* 1280x960 - not applicable */
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0f_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0f_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1315,7 +1128,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType00_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType00_2[] =
 {
 	{976, 527},
 	{976, 502},
@@ -1328,7 +1141,7 @@
 	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType01_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType01_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1341,7 +1154,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType02_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType02_2[] =
 {
 	{976, 527},
 	{976, 502},
@@ -1354,7 +1167,7 @@
 	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType03_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType03_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1367,7 +1180,7 @@
 	{1152, 597}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType04_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1380,7 +1193,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType05_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType05_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1393,7 +1206,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType06_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType06_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1406,7 +1219,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType07_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType07_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1419,7 +1232,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType08_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType08_2[] =
 {
  	{976, 527},
  	{976, 502},
@@ -1432,7 +1245,7 @@
  	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType09_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType09_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1445,7 +1258,7 @@
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0a_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0a_2[] =
 {
  	{976, 527},
  	{976, 502},
@@ -1458,7 +1271,7 @@
  	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0b_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0b_2[] =
 {
  	{ 1152, 700},
  	{ 1152, 675},
@@ -1471,7 +1284,7 @@
  	{    0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0c_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0c_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1484,7 +1297,7 @@
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0d_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0d_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1497,7 +1310,7 @@
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0e_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0e_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1510,7 +1323,7 @@
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0f_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0f_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1523,8 +1336,36 @@
  	{   0,   0}
 };
 
+static const SiS_LVDSDesStruct  SiS300_PanelTypeNS_1[]=
+{
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0, 805},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0}
+};
+
+static const SiS_LVDSDesStruct  SiS300_PanelTypeNS_2[] =
+{
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0}
+};
+
 /* Custom data for Barco iQ R200/300/400 (BIOS 2.00.07) */
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_1a[] =	/* 1280x1024 (1366x1024) */
+static const SiS_LVDSDesStruct  SiS300_PanelType04_1a[] =	/* 1280x1024 (1366x1024) */
 {
 	{1330, 798},  /* 320x200 */
 	{1330, 794},
@@ -1537,7 +1378,7 @@
 	{   0,   0}   /* 1360x1024          */
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_2a[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType04_2a[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1551,7 +1392,7 @@
 };
 
 /* Custom data for Barco iQ G200/300/400 (BIOS 2.00.07) */
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_1b[] =	/* 1024x768 */
+static const SiS_LVDSDesStruct  SiS300_PanelType04_1b[] =	/* 1024x768 */
 {
 	{1330, 798},  /* 320x200 */
 	{1330, 794},
@@ -1562,7 +1403,7 @@
 	{   0, 805}   /* 1024x768 / 512x384 */
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_2b[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType04_2b[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1575,12 +1416,7 @@
 
 /* CRT1 CRTC for slave modes */
 
-typedef struct _SiS300_LVDSCRT1DataStruct
-{
-UCHAR CR[15];
-} SiS300_LVDSCRT1DataStruct;
-
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1[] =
 {
 	{{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f,
 	  0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1602,7 +1438,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1_H[] =
 {
 	{{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
 	  0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
@@ -1624,7 +1460,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1[] =
 {
 	{{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
@@ -1649,7 +1485,7 @@
 	  0x01}}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1_H[] =
 {
 	{{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
@@ -1698,7 +1534,7 @@
 #endif
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1[] =
 {
 	{{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
@@ -1723,7 +1559,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1_H[] =
 {
 	{{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x04,
@@ -1748,7 +1584,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2[] =
 {
 	{{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
 	  0xf4,0x88,0x8f,0x73,0x20,0x00,0x06,
@@ -1770,7 +1606,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2_H[] =
 {
 	{{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
 	  0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
@@ -1792,7 +1628,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2[] =
 {
 	{{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
@@ -1817,7 +1653,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2_H[] =
 {
 	{{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
@@ -1842,7 +1678,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2[] =
 {
 	{{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
@@ -1867,7 +1703,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2_H[] =
 {
 	{{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
@@ -1892,7 +1728,64 @@
 	  0x01}}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1UNTSC[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1XXXxXXX_1[] =
+{
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
+   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
+   0x01}}
+};
+
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1XXXxXXX_1_H[] =
+{
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}},
+ {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
+   0x01}},
+ {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+   0x01}}
+};
+
+
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UNTSC[] =
 {
 	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
 	  0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
@@ -1914,7 +1807,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1ONTSC[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1ONTSC[] =
 {
 	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
 	  0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -1936,7 +1829,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1UPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UPAL[] =
 {
 	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
 	  0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1958,7 +1851,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1OPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1OPAL[] =
 {
 	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
 	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1980,7 +1873,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1SOPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1SOPAL[] =
 {
 	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
 	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -2002,12 +1895,7 @@
 	  0x01 }}
 };
 
-typedef struct _SiS300_CHTVRegDataStruct
-{
-	UCHAR Reg[16];
-} SiS300_CHTVRegDataStruct;
-
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
 {
 	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
 	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2017,7 +1905,7 @@
 	{{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 24: 800x600 NTSC 7/10 */
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
 {
 	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
 	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2027,7 +1915,7 @@
 	{{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 23: 800x600 NTSC 3/4 */
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
 {
 	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
 	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2038,7 +1926,7 @@
 
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
 {
 	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
 	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2049,7 +1937,7 @@
 
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] =
 {
 	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
 	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
diff -Nru a/drivers/video/sis/310vtbl.h b/drivers/video/sis/310vtbl.h
--- a/drivers/video/sis/310vtbl.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/sis/310vtbl.h	2004-06-23 19:04:27 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Register settings for SiS 315/330 series
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -52,20 +50,7 @@
  *
  */
 
-typedef struct _SiS310_StStruct
-{
-	UCHAR St_ModeID;
-	USHORT St_ModeFlag;
-	UCHAR St_StTableIndex;
-	UCHAR St_CRT2CRTC;
-	UCHAR St_ResInfo;
-	UCHAR VB_StTVFlickerIndex;
-	UCHAR VB_StTVEdgeIndex;
-	UCHAR VB_StTVYFilterIndex;
-	UCHAR St_PDC;
-} SiS310_StStruct;
-
-static const SiS310_StStruct SiS310_SModeIDTable[]=
+static const SiS_StStruct SiS310_SModeIDTable[]=
 {
 	{0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00, 0x40},
 	{0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00, 0x40},
@@ -89,207 +74,192 @@
 	{0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00, 0x40}
 };
 
-typedef struct _SiS310_ExtStruct
+static const SiS_ExtStruct  SiS310_EModeIDTable[]=
 {
-	UCHAR  Ext_ModeID;
-	USHORT Ext_ModeFlag;
-	UCHAR  Ext_ModeOffset;
-	USHORT Ext_VESAID;
-	UCHAR  Ext_RESINFO;
-	UCHAR  VB_ExtTVFlickerIndex;
-	UCHAR  VB_ExtTVEdgeIndex;
-	UCHAR  VB_ExtTVYFilterIndex;
-	UCHAR  VB_ExtTVYFilterIndexROM661;
-	UCHAR  REFindex;
-} SiS310_ExtStruct;
-
-static const SiS310_ExtStruct  SiS310_EModeIDTable[]=
-{
-	{0x6a,0x2212,0x04,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x? */
-	{0x2e,0x0a1b,0x03,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x8 */
-        {0x2f,0x0a1b,0x03,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10}, /* 640x400x8 */
-	{0x30,0x2a1b,0x04,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x8 */
-        {0x31,0x0a1b,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x8 */
-	{0x32,0x0a1b,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x8 */
-	{0x33,0x0a1d,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x16 */
-	{0x34,0x2a1d,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x16 */
-	{0x35,0x0a1f,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x32 */
-	{0x36,0x2a1f,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x32 */
-	{0x37,0x0212,0x05,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x? */
-	{0x38,0x0a1b,0x05,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x8 */
-	{0x3a,0x0e3b,0x06,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
-	{0x3c,0x0e3b,0x07,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */
-	{0x3d,0x0e7d,0x07,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 */
-	{0x40,0x9a1c,0x00,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x15 */
-	{0x41,0x9a1d,0x00,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x16 */
-	{0x43,0x0a1c,0x03,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08},
-	{0x44,0x0a1d,0x03,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x16 */
-	{0x46,0x2a1c,0x04,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00},
-	{0x47,0x2a1d,0x04,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x16 */
-	{0x49,0x0a3c,0x05,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13},
-	{0x4a,0x0a3d,0x05,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x16 */
-	{0x4c,0x0e7c,0x06,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x06,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */
-	{0x50,0x9a1b,0x00,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x8  */
-	{0x51,0xba1b,0x01,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x8  */
-  	{0x52,0xba1b,0x02,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x8  */
-	{0x56,0x9a1d,0x00,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x16 */
-	{0x57,0xba1d,0x01,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x16 */
- 	{0x58,0xba1d,0x02,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x16 */
-	{0x59,0x9a1b,0x00,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x8  */
-	{0x5a,0x021b,0x00,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x8  fstn */
-	{0x5b,0x0a1d,0x00,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x16 fstn */
-	{0x5c,0xba1f,0x02,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x32 */
-	{0x5d,0x0a1d,0x03,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10},
-	{0x5e,0x0a1f,0x03,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10}, /* 640x400x32 */
-	{0x62,0x0a3f,0x03,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x32 */
-	{0x63,0x2a3f,0x04,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x32 */
-	{0x64,0x0a7f,0x05,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x32 */
-	{0x65,0x0eff,0x06,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */
-	{0x66,0x0eff,0x07,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */
-	{0x68,0x067b,0x08,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */
-	{0x69,0x06fd,0x08,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */
-	{0x6b,0x07ff,0x08,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */
-	{0x6c,0x067b,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */
-	{0x6d,0x06fd,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */
-	{0x6e,0x07ff,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */
-	{0x70,0x2a1b,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x8 */
-	{0x71,0x0a1b,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x8 */
-	{0x74,0x0a1d,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x16 */
-	{0x75,0x0a3d,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */
-	{0x76,0x2a1f,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x32 */
-	{0x77,0x0a1f,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x32 */
-	{0x78,0x0a3f,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */
-	{0x79,0x0a3b,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */
-	{0x7a,0x2a1d,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x16 */
-	{0x7c,0x0e3b,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x8 */
-	{0x7d,0x0e7d,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x16 */
-	{0x7e,0x0eff,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x32 */
-	{0x23,0x0e3b,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x8 */
-	{0x24,0x0e7d,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x16 */
-	{0x25,0x0eff,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x32 */
-	{0x26,0x0e3b,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */
-	{0x27,0x0e7d,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */
-	{0x28,0x0eff,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/
-	{0x29,0x0e1b,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43}, /* 1152x864 */
-	{0x2a,0x0e3d,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x2b,0x0e7f,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x39,0x2a1b,0x0b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45}, /* 848x480 */
-	{0x3b,0x2a3d,0x0b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3e,0x2a7f,0x0b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3f,0x2a1b,0x0b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47}, /* 856x480 */
-	{0x42,0x2a3d,0x0b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x45,0x2a7f,0x0b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x48,0x2a1b,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49}, /* 1360x768 */
-	{0x4b,0x2a3d,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4e,0x2a7f,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4f,0x9a1f,0x00,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x32 */
-	{0x53,0x9a1f,0x00,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x32 */
-	{0x54,0xba1f,0x01,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x32 */
-	{0x5f,0x2a1b,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576x8 */
-	{0x60,0x2a1d,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576x16 */
-	{0x61,0x2a1f,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576x32 */
-	{0xff,0x0000,0x00,0x0000,0,               0x00,0x00,0x00,0x00,0x00}
-};
-
-typedef struct _SiS310_Ext2Struct
-{
-	USHORT Ext_InfoFlag;
-	UCHAR  Ext_CRT1CRTC;
-	UCHAR  Ext_CRTVCLK;
-	UCHAR  Ext_CRT2CRTC;
-	UCHAR  ModeID;
-	USHORT XRes;
-	USHORT YRes;
-	UCHAR  Ext_PDC;
-} SiS310_Ext2Struct;
-
-static const SiS310_Ext2Struct SiS310_RefIndex[]=
-{
-	{0x085f,0x0d,0x03,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */
-	{0x0067,0x0e,0x04,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */
-	{0x0067,0x0f,0x08,0x48,0x6a, 800, 600, 0x40}, /* 0x2 */
-	{0x0067,0x10,0x07,0x8b,0x6a, 800, 600, 0x40}, /* 0x3 */
-	{0x0047,0x11,0x0a,0x00,0x6a, 800, 600, 0x40}, /* 0x4 */
-	{0x0047,0x12,0x0d,0x00,0x6a, 800, 600, 0x40}, /* 0x5 */
-	{0x0047,0x13,0x13,0x00,0x6a, 800, 600, 0x20}, /* 0x6 */
-	{0x0107,0x14,0x1c,0x00,0x6a, 800, 600, 0x20}, /* 0x7 */
-	{0xc85f,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */
-	{0xc067,0x06,0x02,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */
-	{0xc067,0x07,0x02,0x47,0x2e, 640, 480, 0x40}, /* 0xa */
-	{0xc067,0x08,0x03,0x8a,0x2e, 640, 480, 0x40}, /* 0xb */
-	{0xc047,0x09,0x05,0x00,0x2e, 640, 480, 0x40}, /* 0xc */
-	{0xc047,0x0a,0x09,0x00,0x2e, 640, 480, 0x40}, /* 0xd */
-	{0xc047,0x0b,0x0e,0x00,0x2e, 640, 480, 0x40}, /* 0xe */
-	{0xc047,0x0c,0x15,0x00,0x2e, 640, 480, 0x40}, /* 0xf */
-	{0x487f,0x04,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
-	{0xc04f,0x3c,0x01,0x06,0x31, 720, 480, 0x30}, /* 0x11 */
-	{0x004f,0x3d,0x03,0x06,0x32, 720, 576, 0x30}, /* 0x12 */
-	{0x0087,0x15,0x06,0x00,0x37,1024, 768, 0x30}, /* 0x13 */
-	{0xc877,0x16,0x0b,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
-	{0xc067,0x17,0x0f,0x49,0x37,1024, 768, 0x20}, /* 0x15 */
-	{0x0067,0x18,0x11,0x00,0x37,1024, 768, 0x20}, /* 0x16 */
-	{0x0047,0x19,0x16,0x8c,0x37,1024, 768, 0x20}, /* 0x17 */
-	{0x0107,0x1a,0x1b,0x00,0x37,1024, 768, 0x10}, /* 0x18 */
-	{0x0107,0x1b,0x1f,0x00,0x37,1024, 768, 0x10}, /* 0x19 */
-	{0x0087,0x1c,0x11,0x00,0x3a,1280,1024, 0x30}, /* 0x1a */
-	{0x0137,0x1d,0x19,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */
-	{0x0107,0x1e,0x1e,0x00,0x3a,1280,1024, 0x00}, /* 0x1c */
-	{0x0207,0x1f,0x20,0x00,0x3a,1280,1024, 0x00}, /* 0x1d */
-	{0x0227,0x20,0x21,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */
-	{0x0407,0x21,0x22,0x00,0x3c,1600,1200, 0x00}, /* 0x1f */
-	{0x0407,0x22,0x23,0x00,0x3c,1600,1200, 0x00}, /* 0x20 */
-	{0x0407,0x23,0x25,0x00,0x3c,1600,1200, 0x00}, /* 0x21 */
-	{0x0007,0x24,0x26,0x00,0x3c,1600,1200, 0x00}, /* 0x22 */
-	{0x0007,0x25,0x2c,0x00,0x3c,1600,1200, 0x00}, /* 0x23 */
-	{0x0007,0x26,0x34,0x00,0x3c,1600,1200, 0x00}, /* 0x24 */
-	{0x407f,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */
-	{0xc07f,0x01,0x00,0x04,0x50, 320, 240, 0x30}, /* 0x26 */
-	{0x007f,0x02,0x04,0x05,0x51, 400, 300, 0x30}, /* 0x27 */
-	{0xc077,0x03,0x0b,0x06,0x52, 512, 384, 0x30}, /* 0x28 */
-	{0x8007,0x27,0x27,0x00,0x68,1920,1440, 0x00}, /* 0x29 */
-	{0x4007,0x28,0x29,0x00,0x68,1920,1440, 0x00}, /* 0x2a */
-	{0x4007,0x29,0x2e,0x00,0x68,1920,1440, 0x00}, /* 0x2b */
-	{0x4007,0x2a,0x30,0x00,0x68,1920,1440, 0x00}, /* 0x2c */
-	{0x4007,0x2b,0x35,0x00,0x68,1920,1440, 0x00}, /* 0x2d */
-	{0x4005,0x2c,0x39,0x00,0x68,1920,1440, 0x00}, /* 0x2e */
-	{0x4007,0x2d,0x2b,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */
-	{0x4007,0x2e,0x31,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */
-	{0x4007,0x2f,0x33,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
-	{0x4007,0x30,0x37,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
-	{0x4005,0x31,0x38,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
-	{0x0057,0x32,0x40,0x08,0x70, 800, 480, 0x30}, /* 0x34 */
-	{0x0047,0x33,0x07,0x08,0x70, 800, 480, 0x30}, /* 0x35 */
-	{0x0047,0x34,0x0a,0x08,0x70, 800, 480, 0x30}, /* 0x36 */
-	{0x0057,0x35,0x0b,0x09,0x71,1024, 576, 0x30}, /* 0x37 */
-	{0x0047,0x36,0x11,0x09,0x71,1024, 576, 0x30}, /* 0x38 */
-	{0x0047,0x37,0x16,0x09,0x71,1024, 576, 0x30}, /* 0x39 */
-	{0x0117,0x38,0x19,0x0a,0x75,1280, 720, 0x30}, /* 0x3a */
-	{0x0107,0x39,0x1e,0x0a,0x75,1280, 720, 0x30}, /* 0x3b */
-	{0x0207,0x3a,0x20,0x0a,0x75,1280, 720, 0x30}, /* 0x3c */
-	{0x0127,0x3b,0x19,0x08,0x7c,1280, 960, 0x30}, /* 0x3d */
-	{0x0227,0x4c,0x59,0x08,0x7c,1280, 960, 0x20}, /* 0x3e */
-	{0xc07f,0x4e,0x00,0x06,0x5a, 320, 240, 0x30}, /* 0x3f */    /* FSTN 320x240 */
-        {0x0077,0x42,0x5b,0x08,0x23,1280, 768, 0x30}, /* 0x40 */    /* TW: 0x5b was 0x12 */
-	{0x0127,0x43,0x4d,0x08,0x26,1400,1050, 0x30}, /* 0x41 */
-	{0x0207,0x4b,0x5a,0x08,0x26,1400,1050, 0x30}, /* 0x42 Non-BIOS, new */
-	{0x0107,0x44,0x19,0x00,0x29,1152, 864, 0x30}, /* 0x43 Non-BIOS, new */
-	{0x0107,0x4a,0x1e,0x00,0x29,1152, 864, 0x30}, /* 0x44 Non-BIOS, new */
-	{0x0087,0x45,0x57,0x00,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi - Non-BIOS, new */
-	{0xc067,0x46,0x55,0x0b,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz  - Non-BIOS, new */
-	{0x0087,0x47,0x57,0x00,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi - Non-BIOS, new */
-	{0xc047,0x48,0x57,0x00,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz  - Non-BIOS, new */
-	{0x0067,0x49,0x58,0x0c,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz - Non-BIOS, new */
-	{0x004f,0x4d,0x03,0x06,0x5f, 768, 576, 0x30}, /* 0x4a 768x576 */
-	{0xffff,0x00,0x00,0x00,0x00,   0,   0, 0}
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
+        {0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
+        {0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+	{0x32,0x4a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
+	{0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
+	{0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
+	{0x35,0x4a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
+	{0x36,0x6a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x8 */
+	{0x3c,0x0e3b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x8 */
+	{0x3d,0x0e7d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x16 */
+	{0x40,0x9a1c,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x15 */
+	{0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3},
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13, 4},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x16 */
+	{0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x8  */
+	{0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x8  */
+  	{0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8  */
+	{0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x16 */
+	{0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x16 */
+ 	{0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
+	{0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x8  */
+	{0x5a,0x021b,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x8  fstn */
+	{0x5b,0x0a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x16 fstn */
+	{0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x32 */
+	{0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0},
+	{0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x32 */
+	{0x66,0x0eff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x32 */
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x8 */
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x16 */
+	{0x6b,0x07ff,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x32 */
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x8 */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x16 */
+	{0x6e,0x07ff,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x32 */
+	{0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x8 */
+	{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x8 */
+	{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x16 */
+	{0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x16 */
+	{0x76,0x6a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x32 */
+	{0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x32 */
+	{0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x32 */
+	{0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x8 */
+	{0x7a,0x6a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x16 */
+	{0x7c,0x0e3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x8 */
+	{0x7d,0x0e7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x16 */
+	{0x7e,0x0eff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x32 */
+	{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x8 */
+	{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x16 */
+	{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x32 */
+	{0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x8 */
+	{0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x16 */
+	{0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x32*/
+	{0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1}, /* 1152x864 */
+	{0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
+	{0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
+	{0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45,-1}, /* 848x480 */
+	{0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45,-1},
+	{0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45,-1},
+	{0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47,-1}, /* 856x480 */
+	{0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47,-1},
+	{0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47,-1},
+	{0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49,-1}, /* 1360x768 */
+	{0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49,-1},
+	{0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49,-1},
+	{0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x32 */
+	{0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x32 */
+	{0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x32 */
+	{0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a,-1}, /* 768x576 */
+	{0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a,-1},
+	{0x61,0x6a3f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a,-1},
+	{0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b, 7}, /* 1280x800 */
+	{0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b, 7},
+	{0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b, 7},
+	{0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c, 9}, /* 1680x1050 */
+	{0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c, 9},
+	{0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c, 9},
+	{0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4d,-1}, /* 1920x1080(i) */
+	{0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4d,-1},
+	{0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4d,-1},
+	{0x1d,0x6a1b,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x4e,-1}, /* 960x540 */
+	{0x1e,0x6a3d,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x4e,-1},
+	{0x1f,0x6a7f,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x4e,-1},
+	{0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00,-1}
+};
+
+static const SiS_Ext2Struct SiS310_RefIndex[]=
+{
+	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */
+	{0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */
+	{0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40}, /* 0x2 */
+	{0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40}, /* 0x3 */
+	{0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x4 */
+	{0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x5 */
+	{0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x6 */
+	{0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x7 */
+	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */
+	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */
+	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40}, /* 0xa */
+	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40}, /* 0xb */
+	{0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xc */
+	{0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xd */
+	{0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xe */
+	{0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xf */
+	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
+	{0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30}, /* 0x11 */
+	{0x006f,0x3d,0x03,0x06,0x14,0x32, 720, 576, 0x30}, /* 0x12 */
+	{0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30}, /* 0x13 */
+	{0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
+	{0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20}, /* 0x15 */
+	{0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20}, /* 0x16 */
+	{0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20}, /* 0x17 */
+	{0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x18 */
+	{0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x19 */
+	{0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30}, /* 0x1a */
+	{0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */
+	{0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1c */
+	{0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1d */
+	{0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */
+	{0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x1f */
+	{0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x20 */
+	{0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x21 */
+	{0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x22 */
+	{0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x23 */
+	{0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x24 */
+	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */
+	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30}, /* 0x26 */
+	{0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30}, /* 0x27 */
+	{0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30}, /* 0x28 */
+	{0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x29 */
+	{0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2a */
+	{0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2b */
+	{0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2c */
+	{0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2d */
+	{0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2e */
+	{0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */
+	{0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */
+	{0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
+	{0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
+	{0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
+	{0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x34 */
+	{0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x35 */
+	{0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x36 */
+	{0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x37 */
+	{0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x38 */
+	{0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x39 */
+	{0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3a */
+	{0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3b */
+	{0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3c */
+	{0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30}, /* 0x3d */
+	{0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20}, /* 0x3e */
+	{0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30}, /* 0x3f */    /* FSTN 320x240 */
+        {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30}, /* 0x40 */    /* 0x5b was 0x12 */
+	{0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x41 */
+	{0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x42 1400x1050-75Hz */
+	{0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x43 1152x864-75Hz  */
+	{0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x44 1152x864-85Hz  */
+	{0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi  */
+	{0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz   */
+	{0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi  */
+	{0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz   */
+	{0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz  */
+	{0x006f,0x4d,0x03,0x06,0x15,0x5f, 768, 576, 0x30}, /* 0x4a 768x576-56Hz   */
+	{0x0067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30}, /* 0x4b 1280x800-60Hz  */
+	{0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30}, /* 0x4c 1680x1050-60Hz */
+	{0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30}, /* 0x4d 1920x1080 60Hzi */
+	{0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30}, /* 0x4e 960x540 60Hz */
+	{0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0}
 };
 
-typedef struct _SiS310_CRT1TableStruct
-{
- 	UCHAR CR[17];
-} SiS310_CRT1TableStruct;
-
-static const SiS310_CRT1TableStruct SiS310_CRT1Table[]=
+static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
 {
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
    0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
@@ -310,7 +280,7 @@
  {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
    0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
    0x00}}, /* 0x5 */
-#endif   
+#endif
  {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* 0x05 - corrected 640x480-60 */
    0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
    0x00}},
@@ -329,16 +299,16 @@
    0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
    0x00}}, /* 0x8 */
  {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
-   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,  /* TW: Corrected VBE */
+   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,  /* Corrected VBE */
    0x61}}, /* 0x9 */
  {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
    0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
    0x61}}, /* 0xa */
  {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
-   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,  /* TW: Corrected VBE */
+   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,  /* Corrected VBE */
    0x61}}, /* 0xb */
  {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
-   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,  /* TW: Corrected VDE, VBE */
+   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,  /* Corrected VDE, VBE */
    0x00}}, /* 0xc */
  {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
    0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
@@ -466,7 +436,7 @@
  {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
    0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
    0x01}}, /* 0x36 */
- {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,   /* TW: 95 was 15 - illegal HBE! */
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,   /* 95 was 15 - illegal HBE! */
    0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
    0x01}}, /* 0x37 */
  {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
@@ -498,7 +468,7 @@
  {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
    0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
    0x00}}, /* 0x3f */
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,   /* TW: The following from 650/LVDS BIOS */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
    0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
    0x01}},  /* 0x40 */
  {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
@@ -510,31 +480,31 @@
  {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
    0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
    0x00}},  /* 0x43 */
- {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* New, 1152x864-75, not in BIOS */
+ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* 1152x864-75 */
    0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
    0x01}},  /* 0x44 */
- {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* New, 848x480-38i, not in BIOS */
+ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* 848x480-38i */
    0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
    0x00}},  /* 0x45 */
- {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* New, 848x480-60, not in BIOS */
+ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* 848x480-60 */
    0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
    0x00}},  /* 0x46 */
- {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* New, 856x480-38i, not in BIOS */
+ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* 856x480-38i */
    0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
    0x00}},  /* 0x47 */
- {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* New, 856x480-60, not in BIOS */
+ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* 856x480-60 */
    0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
    0x00}},  /* 0x48 */
- {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* New, 1360x768-60, not in BIOS */
+ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* 1360x768-60 */
    0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
    0x01}},  /* 0x49 */
- {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* New, 1152x864-84, not in any BIOS   */
+ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* 1152x864-84  */
    0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
    0x01}},  /* 0x4a */
- {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* New, 1400x1050-75, not in any BIOS  */
+ {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* 1400x1050-75  */
    0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
    0x00}},  /* 0x4b */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* New, 1280x960-85, not in any BIOS */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */
    0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
    0x01}},  /* 0x4c */
  {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
@@ -542,16 +512,22 @@
    0x01}},  /* 0x4d */
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* FSTN 320x480, TEMP - possibly invalid */
    0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}   /* 0x4e */
+   0x00}},  /* 0x4e */
+ {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, /* 1280x800-60 */
+   0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
+   0x21}},  /* 0x4f */
+ {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10, /* 1680x1050-60 */
+   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
+   0x20}},  /* 0x50 */
+ {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0, /* 1920x1080-60i */
+   0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00,
+   0x61}},  /* 0x51 */
+ {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0, /* 960x540-60 */
+   0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02,
+   0x41}}   /* 0x52 */
 };
 
-typedef struct _SiS310_MCLKDataStruct
-{
-	UCHAR SR28,SR29,SR2A;
-	USHORT CLOCK;
-} SiS310_MCLKDataStruct;
-
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_315[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] =
 {
 	{ 0x3b,0x22,0x01,143},
 	{ 0x5c,0x23,0x01,166},
@@ -563,7 +539,7 @@
 	{ 0x5c,0x23,0x01,166}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_650[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] =
 {
 	{ 0x5a,0x64,0x82, 66},
 	{ 0xb3,0x45,0x82, 83},
@@ -575,7 +551,7 @@
 	{ 0x37,0x22,0x82,133}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_330[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] =
 {
 	{ 0x5c,0x23,0x01,166},
 	{ 0x5c,0x23,0x01,166},
@@ -587,7 +563,7 @@
 	{ 0x79,0x06,0x01,250}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_660[] =  /* TODO */
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] =
 {
 	{ 0x5c,0x23,0x82,166},
 	{ 0x5c,0x23,0x82,166},
@@ -599,7 +575,19 @@
 	{ 0x37,0x21,0x82,200}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_1[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] =
+{
+	{ 0x37,0x22,0x82,133},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x7c,0x08,0x82,200},
+	{ 0x29,0x21,0x82,150},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x37,0x21,0x82,200}
+};
+
+static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */
 {
         { 0x29,0x21,0x82,150},
 	{ 0x5c,0x23,0x82,166},
@@ -611,13 +599,7 @@
 	{ 0x37,0x22,0x82,133}
 };
 
-typedef struct _SiS310_VCLKDataStruct
-{
-	UCHAR SR2B,SR2C;
-	USHORT CLOCK;
-} SiS310_VCLKDataStruct;
-
-static const SiS310_VCLKDataStruct SiS310_VCLKData[]=
+static SiS_VCLKDataStruct SiS310_VCLKData[]=
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -630,7 +612,7 @@
 	{ 0x53,0xe2, 50}, /* 0x08 */
 	{ 0x74,0x67, 52}, /* 0x09 */
 	{ 0x6d,0x66, 56}, /* 0x0a */
-	{ 0x5a,0x64, 65}, /* 0x0b */  /* TW: was 6c c3 - WRONG */
+	{ 0x5a,0x64, 65}, /* 0x0b */  /* was 6c c3 - WRONG */
 	{ 0x46,0x44, 67}, /* 0x0c */
 	{ 0xb1,0x46, 68}, /* 0x0d */
 	{ 0xd3,0x4a, 72}, /* 0x0e */
@@ -677,49 +659,58 @@
 	{ 0xea,0x08,340}, /* 0x37 */
 	{ 0xe8,0x07,376}, /* 0x38 */
 	{ 0xde,0x06,389}, /* 0x39 */
-	{ 0x52,0x2a, 54}, /* 0x3a */  /* 301 TV */
-	{ 0x52,0x6a, 27}, /* 0x3b */  /* 301 TV */
-	{ 0x62,0x24, 70}, /* 0x3c */  /* 301 TV */
-	{ 0x62,0x64, 70}, /* 0x3d */  /* 301 TV */
-	{ 0xa8,0x4c, 30}, /* 0x3e */  /* 301 TV */
-	{ 0x20,0x26, 33}, /* 0x3f */  /* 301 TV */
+	{ 0x52,0x2a, 54}, /* 0x3a 301 TV */
+	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
+	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
+	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
 	{ 0x31,0xc2, 39}, /* 0x40 */
-	{ 0x60,0x36, 30}, /* 0x41 */  /* Chrontel */
-	{ 0x40,0x4a, 28}, /* 0x42 */  /* Chrontel */
-	{ 0x9f,0x46, 44}, /* 0x43 */  /* Chrontel */
+	{ 0x60,0x36, 30}, /* 0x41 Chrontel */
+	{ 0x40,0x4a, 28}, /* 0x42 Chrontel */
+	{ 0x9f,0x46, 44}, /* 0x43 Chrontel */
 	{ 0x97,0x2c, 26}, /* 0x44 */
-	{ 0x44,0xe4, 25}, /* 0x45 */  /* Chrontel */
-	{ 0x7e,0x32, 47}, /* 0x46 */  /* Chrontel */
-	{ 0x8a,0x24, 31}, /* 0x47 */  /* Chrontel */
-	{ 0x97,0x2c, 26}, /* 0x48 */  /* Chrontel */
+	{ 0x44,0xe4, 25}, /* 0x45 Chrontel */
+	{ 0x7e,0x32, 47}, /* 0x46 Chrontel */
+	{ 0x8a,0x24, 31}, /* 0x47 Chrontel */
+	{ 0x97,0x2c, 26}, /* 0x48 Chrontel */
 	{ 0xce,0x3c, 39}, /* 0x49 */
-	{ 0x52,0x4a, 36}, /* 0x4a */  /* Chrontel */
+	{ 0x52,0x4a, 36}, /* 0x4a Chrontel */
 	{ 0x34,0x61, 95}, /* 0x4b */
 	{ 0x78,0x27,108}, /* 0x4c - was 102 */
-	{ 0x66,0x43,123}, /* 0x4d */  /* Modes 0x26-0x28 (1400x1050) */
+	{ 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
 	{ 0x41,0x4e, 21}, /* 0x4e */
-	{ 0xa1,0x4a, 29}, /* 0x4f */  /* Chrontel */
+	{ 0xa1,0x4a, 29}, /* 0x4f Chrontel */
 	{ 0x19,0x42, 42}, /* 0x50 */
-	{ 0x54,0x46, 58}, /* 0x51 */  /* Chrontel */
+	{ 0x54,0x46, 58}, /* 0x51 Chrontel */
 	{ 0x25,0x42, 61}, /* 0x52 */
-	{ 0x44,0x44, 66}, /* 0x53 */  /* Chrontel */
-	{ 0x3a,0x62, 70}, /* 0x54 */  /* Chrontel */
-	{ 0x62,0xc6, 34}, /* 0x55 - added for 848x480-60 (not in any BIOS) */
-	{ 0x6a,0xc6, 37}, /* 0x56 - added for 848x480-75 (not in any BIOS)    - TEMP */
-	{ 0xbf,0xc8, 35}, /* 0x57 - added for 856x480-38i,60 (not in any BIOS) */
-	{ 0x30,0x23, 88}, /* 0x58 - added for 1360x768-62 (is 60Hz!) (not in any BIOS) */
-	{ 0x52,0x07,149}, /* 0x59 - added for 1280x960-85 (Not in any BIOS) */
-	{ 0x56,0x07,156}, /* 0x5a - added for 1400x1050-75 */
-   	{ 0x70,0x29, 81}  /* 0x5b - added for 1280x768 LCD */
-};
-
-typedef struct _SiS310_VBVCLKDataStruct
-{
-	UCHAR Part4_A,Part4_B;
-	USHORT CLOCK;
-} SiS310_VBVCLKDataStruct;
+	{ 0x44,0x44, 66}, /* 0x53 Chrontel */
+	{ 0x3a,0x62, 70}, /* 0x54 Chrontel */
+	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
+	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
+	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
+	{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
+	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+   	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+	{ 0x45,0x25, 83}, /* 0x5c 1280x800  */
+	{ 0x70,0x0a,147}, /* 0x5d 1680x1050 */
+	{ 0x70,0x24,162}, /* 0x5e 1600x1200 */
+	{ 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
+	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
+	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
+	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
+	{ 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
+	{ 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
+	{ 0x7c,0x6b, 38}  /* 0x6a 960x540@60 */
+};
 
-static const SiS310_VBVCLKDataStruct SiS310_VBVCLKData[]=
+static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -732,7 +723,7 @@
 	{ 0x53,0x47, 50}, /* 0x08 */
 	{ 0x74,0x67, 52}, /* 0x09 */
 	{ 0x6d,0x66, 56}, /* 0x0a */
-	{ 0x35,0x62, 65}, /* 0x0b */  /* Was 0x5a,0x64 - 650/LVDS+301 bios: 35,62  */
+	{ 0x35,0x62, 65}, /* 0x0b */  /* Was 0x5a,0x64 - 650/LVDS+301: 35,62  */
 	{ 0x46,0x44, 67}, /* 0x0c */
 	{ 0xb1,0x46, 68}, /* 0x0d */
 	{ 0xd3,0x4a, 72}, /* 0x0e */
@@ -785,47 +776,55 @@
 	{ 0xea,0x08,340}, /* 0x37 */
 	{ 0xe8,0x07,376}, /* 0x38 */
 	{ 0xde,0x06,389}, /* 0x39 */
-	{ 0x52,0x2a, 54}, /* 0x3a */  /* 301 TV */
-	{ 0x52,0x6a, 27}, /* 0x3b */  /* 301 TV */
-	{ 0x62,0x24, 70}, /* 0x3c */  /* 301 TV */
-	{ 0x62,0x64, 70}, /* 0x3d */  /* 301 TV */
-	{ 0xa8,0x4c, 30}, /* 0x3e */  /* 301 TV */
-	{ 0x20,0x26, 33}, /* 0x3f */  /* 301 TV */
+	{ 0x52,0x2a, 54}, /* 0x3a 301 TV - start */
+	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
+	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
+	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
 	{ 0x31,0xc2, 39}, /* 0x40 */
-	{ 0x2e,0x48, 25}, /* 0x41 */  /* Replacement for LCD on 315 for index 0 */
-	{ 0x24,0x46, 25}, /* 0x42 */  /* Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */
-	{ 0x26,0x64, 28}, /* 0x43 */  /* Replacement for LCD on 315 for index 1 */
-	{ 0x37,0x64, 40}, /* 0x44 */  /* Replacement for LCD on 315 for index 4 */
-	{ 0xa1,0x42,108}, /* 0x45 */  /* 1280x960 LCD */
-	{ 0x37,0x61,100}, /* 0x46 */  /* 1280x960 LCD */
+	{ 0x2e,0x48, 25}, /* 0x41 Replacement for LCD on 315 for index 0 */
+	{ 0x24,0x46, 25}, /* 0x42 Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */
+	{ 0x26,0x64, 28}, /* 0x43 Replacement for LCD on 315 for index 1 */
+	{ 0x37,0x64, 40}, /* 0x44 Replacement for LCD on 315 for index 4 */
+	{ 0xa1,0x42,108}, /* 0x45 1280x960 LCD */
+	{ 0x37,0x61,100}, /* 0x46 1280x960 LCD */
 	{ 0x78,0x27,108}, /* 0x47 */
-	{ 0x97,0x2c, 26}, /* 0x48 */  /* UNUSED - Entries from here new, not in any BIOS */
-	{ 0xce,0x3c, 39}, /* 0x49 */  /* UNUSED */
-	{ 0x52,0x4a, 36}, /* 0x4a */  /* UNUSED */
-	{ 0x34,0x61, 95}, /* 0x4b */  /* UNUSED */
-	{ 0x78,0x27,108}, /* 0x4c */  /* UNUSED */
-	{ 0x66,0x43,123}, /* 0x4d */  /* 1400x1050-60 */
-	{ 0x41,0x4e, 21}, /* 0x4e */  /* UNUSED */
-	{ 0xa1,0x4a, 29}, /* 0x4f */  /* UNUSED */
-	{ 0x19,0x42, 42}, /* 0x50 */  /* UNUSED */
-	{ 0x54,0x46, 58}, /* 0x51 */  /* UNUSED */
-	{ 0x25,0x42, 61}, /* 0x52 */  /* UNUSED */
-	{ 0x44,0x44, 66}, /* 0x53 */  /* UNUSED */
-	{ 0x3a,0x62, 70}, /* 0x54 */  /* UNUSED */
-	{ 0x62,0xc6, 34}, /* 0x55 */  /* 848x480-60 */
-	{ 0x6a,0xc6, 37}, /* 0x56 */  /* 848x480-75 - TEMP, UNUSED */
-	{ 0xbf,0xc8, 35}, /* 0x57 */  /* 856x480-38i,60  */
-	{ 0x30,0x23, 88}, /* 0x58 */  /* 1360x768-62 (is 60Hz!) TEMP, UNUSED */
-	{ 0x52,0x07,149}, /* 0x59 */  /* 1280x960-85  */
-	{ 0x56,0x07,156}, /* 0x5a */  /* 1400x1050-75 */
-   	{ 0x70,0x29, 81}  /* 0x5b */  /* 1280x768 LCD */
-};
-
-static const UCHAR SiS310_ScreenOffset[] =
-{
-        0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64,
-	0x78,0x80,0x2d,0x35,0x57,0x48,0x55,0x30,
-	0xff
+	{ 0x97,0x2c, 26}, /* 0x48 UNUSED */
+	{ 0xce,0x3c, 39}, /* 0x49 UNUSED */
+	{ 0x52,0x4a, 36}, /* 0x4a UNUSED */
+	{ 0x34,0x61, 95}, /* 0x4b UNUSED */
+	{ 0x78,0x27,108}, /* 0x4c UNUSED */
+	{ 0x66,0x43,123}, /* 0x4d 1400x1050-60 */
+	{ 0x41,0x4e, 21}, /* 0x4e UNUSED */
+	{ 0xa1,0x4a, 29}, /* 0x4f UNUSED */
+	{ 0x19,0x42, 42}, /* 0x50 UNUSED */
+	{ 0x54,0x46, 58}, /* 0x51 UNUSED */
+	{ 0x25,0x42, 61}, /* 0x52 UNUSED */
+	{ 0x44,0x44, 66}, /* 0x53 UNUSED */
+	{ 0x3a,0x62, 70}, /* 0x54 UNUSED */
+	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP, UNUSED */
+	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60  */
+	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) TEMP, UNUSED */
+	{ 0x52,0x07,149}, /* 0x59 1280x960-85  */
+	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+   	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+	{ 0x45,0x25, 83}, /* 0x5c 1280x800 LCD - (was 0x9c,0x62, 69 - wrong?) */
+	{ 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */
+	{ 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */
+	{ 0x52,0x27, 75}, /* 0x5f 1280x720 LCD TMDS + HDTV (correct) */
+	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
+	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
+	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
+	{ 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
+	{ 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced (UNUSED) */
+	{ 0x7c,0x6b, 38}  /* 0x6a 960x540@60 */
 };
 
 static const DRAM4Type SiS310_SR15[8] = {
@@ -873,12 +872,7 @@
 static const USHORT SiS310_YCSenseData2    = 0x016b;
 #endif
 
-typedef struct _SiS310_PanelDelayTblStruct
-{
- 	UCHAR timer[2];
-} SiS310_PanelDelayTblStruct;
-
-static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
+static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
 {
         {{0x10,0x40}},
 	{{0x10,0x40}},
@@ -898,7 +892,7 @@
 	{{0x10,0x40}}
 };
 
-static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
+static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
 {
 	{{0x28,0xc8}},
 	{{0x28,0xc8}},
@@ -922,28 +916,18 @@
 /* SIS VIDEO BRIDGE ----------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS310_LCDDataStruct
-{
-	USHORT RVBHCMAX;
-	USHORT RVBHCFACT;
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS310_LCDDataStruct;
-
-static const SiS310_LCDDataStruct  SiS310_StLCD1024x768Data[]=
+static const SiS_LCDDataStruct  SiS310_St2LCD1024x768Data[] =
 {
 	{   62,  25, 800, 546,1344, 806},
 	{   32,  15, 930, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
+        {   62,  25, 800, 546,1344, 806},
 	{  104,  45, 945, 496,1344, 806},
 	{   62,  25, 800, 546,1344, 806},
 	{   31,  18,1008, 624,1344, 806},
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS310_LCDDataStruct  SiS310_ExtLCD1024x768Data[] =   
+static const SiS_LCDDataStruct  SiS310_ExtLCD1024x768Data[] =
 {
 	{   42,  25,1536, 419,1344, 806},
 	{   48,  25,1536, 369,1344, 806},
@@ -951,28 +935,10 @@
 	{   48,  25,1536, 369,1344, 806},
 	{   12,   5, 896, 500,1344, 806},
 	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-	 
-};
-
-static const SiS310_LCDDataStruct  SiS310_St2LCD1024x768Data[] =  
-{
-	{   62,  25, 800, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-        {   62,  25, 800, 546,1344, 806},    
-	{  104,  45, 945, 496,1344, 806},
-	{   62,  25, 800, 546,1344, 806},
-	{   31,  18,1008, 624,1344, 806},
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS310_LCDDataStruct  SiS310_StLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS310_St2LCD1280x1024Data[] =
 {
 	{   22,   5, 800, 510,1650,1088},
 	{   22,   5, 800, 510,1650,1088},
@@ -984,7 +950,7 @@
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS310_LCDDataStruct  SiS310_ExtLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS310_ExtLCD1280x1024Data[] =
 {
 	{  211,  60,1024, 501,1688,1066},
 	{  211,  60,1024, 508,1688,1066},
@@ -993,53 +959,10 @@
 	{  211,  60,1024, 500,1688,1066},
 	{  211,  75,1024, 625,1688,1066},
 	{  211, 120,1280, 798,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1800,1000,1688,1066}  /* 1280x960 - does not work, use panel scaler instead */
-};
-
-static const SiS310_LCDDataStruct  SiS310_St2LCD1280x1024Data[] =
-{
-	{   22,   5, 800, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{   13,   5,1024, 675,1560,1152},
-	{   16,   9,1266, 804,1688,1072},
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS310_LCDDataStruct  SiS310_NoScaleData1024x768[] =  
-{
-        {    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},  /* 640x400 - does not work */
-	{    1,   1,1344, 806,1344, 806},  /* 640x480 - does not work */
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const SiS310_LCDDataStruct  SiS310_NoScaleData1280x1024[] =
-{
-        {    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-typedef struct _SiS310_Part2PortTblStruct
-{
- 	UCHAR CR[12];
-} SiS310_Part2PortTblStruct;
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] =
+static const SiS_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] =
 {
  {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
  {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
@@ -1047,646 +970,37 @@
  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
  {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
  {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
+ {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
 };
 
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_2[] =
-{
- {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x2c,0x12,0x38,0x55,0x2f,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x2c,0x12,0x38,0x55,0x2f,0xc1,0x35,0xb1,0x47,0xe9,0x71,0x33}},
- {{0x2d,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x29,0x12,0xb5,0xd2,0xac,0xe9,0x35,0xd9,0x47,0x11,0x99,0x33}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},  /* others  */
-/* 0x36,0x13,0x02,0x25,0xff,0x03,0x45,0x09,0x07,0xf9,0x00,0x24        my      */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
+/* *** LCDA *** */
 
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_3[] =
-{
-#if 1   /* Data from 650/301LVx 1.10.6s and others */
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x25,0x13,0xc9,0x24,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x13,0xc9,0x25,0xff,0xf9,0x45,0x09,0x07,0xf9,0x09,0x24}}
+#if 0
+static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_1[]=
+{ /* Clevo, 651+301C */
+	{1200, 450, 2048,1250},
+	{1200, 400, 2048,1250},
+	{1280, 450, 2048,1250},
+	{1280, 400, 2048,1250},
+	{1200, 530, 2048,1250},
+	{1360, 650, 2048,1250},
+	{1584, 818, 2048,1250},
+	{1688,1066, 2048,1250},
+	{1688,1066, 2048,1250},
+#if 0
+	{2048,1250, 2048,1250}   /* this should be correct */
 #endif
-#if 0    /* Data from my 301LV */
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},   /* TEST */
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}
+#if 1
+	{2160,1250, 2048,1250}   /* ? */
 #endif
 };
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_1[] =
-{ /* Acer; BIOS data invalid, last row taken from _3 */
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xC1,0x35,0xB1,0x47,0xE9,0x71,0x33}},
- {{0x2D,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x29,0x12,0xB5,0xD2,0xAC,0xE9,0x35,0xD9,0x47,0x11,0x99,0x33}},
- {{0x36,0x13,0x02,0x25,0xFF,0x03,0x45,0x09,0x07,0xF9,0x00,0x24}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_2[] =
-{ /* Acer */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-/*   1     2    4    5    6   1c   1d   1f   20   21   23   25   */
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_3[] =
-{ /* Acer */
- {{0x31,0x1B,0xC4,0xDA,0xB0,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x34,0x1B,0x9F,0xC0,0x80,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x3E,0x1B,0xCF,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_1[] =
-{
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_2[] =
-{
- {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x33,0x13,0x01,0x0d,0xfd,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x3f,0x1b,0x3d,0x49,0x39,0x54,0x23,0xc0,0x27,0x66,0x30,0x42}},
- {{0x33,0x1b,0x91,0x9d,0x8d,0x8c,0x23,0xf8,0x27,0x9e,0x68,0x42}},
- {{0x43,0x24,0x11,0x1d,0x0d,0xcc,0x23,0x38,0x37,0xde,0xa8,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_3[] =
-{
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_1[] =
-{
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_2[] =
-{
- {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x3A,0x1B,0x54,0x7A,0x48,0x80,0x24,0x52,0x30,0xA3,0x3A,0x02}},
- {{0x36,0x1B,0x90,0xB6,0x84,0xA8,0x24,0x7A,0x30,0xCB,0x62,0x02}},
- {{0x3A,0x1C,0xE4,0x0A,0xD8,0xE0,0x24,0xB2,0x30,0x03,0x9A,0x02}},
- {{0x4A,0x24,0x64,0x8A,0x58,0x20,0x34,0xF2,0x30,0x43,0xDA,0x52}},
- {{0x47,0x24,0x71,0x97,0x65,0x3E,0x34,0x10,0x40,0x61,0xF8,0x02}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_3[] =
-{
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
-};
-
-/* CRT1 CRTC for LCDA */
-
-typedef struct _SiS310_LCDACRT1DataStruct
-{
- 	UCHAR CR[17];
-}SiS310_LCDACRT1DataStruct;
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_1[]=
-{
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x82,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x82,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x04,0x3e,
-   0xE2,0x89,0xdf,0xdf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x87,0x63,0x63,0x8B,0x6D,0x18,0x7c,0xf0,
-   0x5A,0x81,0x57,0x57,0x7D,0x00,0x00,0x06,
-   0x01}},
- {{0xA3,0x7f,0x7f,0x87,0x89,0x94,0x24,0xf5,
-   0x02,0x89,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_1_H[]=
-{
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x82,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x82,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x04,0x3e,
-   0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x55,0x31,0x31,0x99,0x3b,0x06,0x7c,0xf0,
-   0x5A,0x81,0x57,0x57,0x7D,0x00,0x00,0x01,
-   0x01}},
- {{0x63,0x3F,0x3F,0x87,0x49,0x94,0x24,0xF5,
-   0x02,0x89,0xFF,0xFF,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_2[]=
-{
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x06,
-   0x01}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xb3,
-   0x72,0x89,0xdf,0x03,0x02,0x30,0x00,0x06,
-   0x01}},
- {{0xa3,0x63,0x63,0x98,0x78,0x19,0x24,0xf1,
-   0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x89,0x94,0x24,0xf5,
-   0x02,0x89,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_2_H[]=
-{
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xb3,
-   0x72,0x89,0xdf,0x03,0x02,0x30,0x00,0x01,
-   0x01 }},
- {{0x71,0x31,0x31,0x98,0x46,0x17,0x24,0xf1,
-   0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x02,
-   0x01 }},
- {{0x63,0x3f,0x3f,0x87,0x4c,0x97,0x24,0xf5,
-   0x0f,0x86,0xff,0xff,0x25,0x30,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_1[]=
-{ /* Acer */
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x06,
-   0x00}},
- {{0x92,0x63,0x63,0x96,0x6c,0x18,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x06,
-   0x01}},
- {{0xae,0x7f,0x7f,0x92,0x88,0x94,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0xff,0x29,0x01,0x00,0x07,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_1_H[]=
-{  /* Acer */
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x05,
-   0x01}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x05,
-   0x00}},
- {{0x60,0x31,0x31,0x84,0x3a,0x86,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x01,
-   0x01}},
- {{0x6e,0x3f,0x3f,0x92,0x48,0x94,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_2[]=
-{  /* Illegal data in BIOS (Acer, Compaq) */
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1,
-   0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_2_H[]=
-{  /* Illegal data in BIOS (Acer, Compaq) */
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x31,0x31,0x93,0x3e,0x86,0x24,0xf1,
-   0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x01,
-   0x01 }},
- {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_1[]=
-{
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-   0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-   0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-   0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-   0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0xee,0x1f,
-   0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05,
-   0x00}},
- {{0x83,0x63,0x63,0x87,0x68,0x16,0x66,0xf0,
-   0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x06,
-   0x01}},
- {{0x9f,0x7f,0x7f,0x83,0x84,0x92,0x0e,0xf5,
-   0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x02,
-   0x01}},
- {{0xbf,0x9f,0x9f,0x83,0xa4,0x12,0x0e,0x5a,
-   0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x07,
-   0x01}},
- {{0xce,0xae,0xae,0x92,0xb3,0x01,0x28,0x10,
-   0x1a,0x80,0x19,0x19,0x29,0x0f,0x00,0x03,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_1_H[]=
-{
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
-    0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-    0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
-    0x92,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-    0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
-    0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05,
-    0x00}},
-  {{0x51,0x31,0x31,0x95,0x36,0x04,0x66,0xf0,
-    0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x01,
-    0x01}},
-  {{0x5f,0x3f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
-    0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x01,
-    0x01}},
-  {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
-    0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x05,
-    0x01}},
-  {{0x76,0x56,0x56,0x9a,0x5b,0x89,0x28,0x10,
-    0x1c,0x80,0x19,0x19,0x29,0x0b,0x00,0x05,
-    0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_2[]=
-{
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03,
-   0x01}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9e,
-   0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x03,
-   0x00}},
- {{0xce,0x63,0x63,0x92,0x96,0x04,0x28,0xd4,
-   0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x07,
-   0x01}},
- {{0xce,0x7f,0x7f,0x92,0xa4,0x12,0x28,0xd4,
-   0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x9f,0x92,0xb4,0x02,0x28,0x5a,
-   0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x03,
-   0x01}},
- {{0xce,0xae,0xae,0x92,0xbc,0x0a,0x28,0x10,
-   0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x03,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_2_H[]=
-{
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9e,
-   0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0x9c,0x31,0x31,0x80,0x64,0x92,0x28,0xd4,
-   0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x06,
-   0x01}},
- {{0x8e,0x3f,0x3f,0x92,0x64,0x12,0x28,0xd4,
-   0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x06,
-   0x01}},
- {{0x7e,0x4f,0x4f,0x82,0x64,0x12,0x28,0x5a,
-   0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x06,
-   0x01}},
- {{0x76,0x56,0x56,0x9a,0x64,0x92,0x28,0x10,
-   0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x05,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_1[]=
-{
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x8F,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x8F,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x10,0x3E,
-   0xE0,0x84,0xDF,0xDF,0x11,0x00,0x00,0x06,
-   0x00}},
- {{0x97,0x63,0x63,0x9B,0x65,0x1D,0x88,0xF0,
-   0x58,0x8C,0x57,0x57,0x89,0x20,0x00,0x06,
-   0x01}},
- {{0xB3,0x7F,0x7F,0x97,0x81,0x99,0x30,0xF5,
-   0x00,0x84,0xFF,0xFF,0x31,0x10,0x00,0x02,
-   0x01}},
- {{0xD3,0x9F,0x9F,0x97,0xA1,0x19,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x07,
-   0x01}},
- {{0xE2,0xAE,0xAE,0x86,0xB0,0x88,0x4A,0x10,
-   0x1A,0x8E,0x19,0x19,0x4B,0x2F,0x00,0x03,
-   0x00}},
- {{0xFB,0xC7,0xC7,0x9F,0xC9,0x81,0xE0,0x10,
-   0xB0,0x84,0xAF,0xAF,0xE1,0x2F,0x00,0x07,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_1_H[]=
-{
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x87,0x10,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x87,0x10,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0x10,0x3E,
-   0xE0,0x84,0xDF,0xDF,0x11,0x00,0x00,0x01,
-   0x00}},
- {{0x73,0x31,0x31,0x97,0x3A,0x92,0x88,0xF0,
-   0x58,0x8C,0x57,0x57,0x89,0x20,0x00,0x01,
-   0x01}},
- {{0x81,0x3F,0x3F,0x85,0x48,0x00,0x30,0xF5,
-   0x00,0x84,0xFF,0xFF,0x31,0x10,0x00,0x06,
-   0x01}},
- {{0x91,0x4F,0x4F,0x95,0x58,0x10,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x06,
-   0x01}},
- {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03,
-   0x01}},
- {{0xA5,0x63,0x63,0x89,0x6C,0x84,0xE0,0x10,
-   0xB0,0x84,0xAF,0xAF,0xE1,0x2F,0x00,0x02,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_2[]=
-{
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x5F,0x83,0xDF,0xDF,0xE1,0x01,0x01,0x04,
-   0x00}},
- {{0x09,0x63,0x63,0x8D,0xAD,0x05,0xE0,0xD4,
-   0x9B,0x8F,0x57,0x57,0xE1,0x21,0x01,0x00,
-   0x01}},
- {{0x09,0x7F,0x7F,0x8D,0xBB,0x13,0xE0,0xD4,
-   0xEF,0x83,0xFF,0xFF,0xE1,0x21,0x01,0x00,
-   0x01}},
- {{0x09,0x9F,0x9F,0x8D,0xCB,0x03,0xE0,0x5A,
-   0x6F,0x83,0xFF,0xFF,0xE1,0x29,0x01,0x04,
-   0x01}},
- {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03,
-   0x01}},
- {{0x09,0xC7,0xC7,0x8D,0xDF,0x17,0xE0,0x10,
-   0xC7,0x8B,0xAF,0xAF,0xE1,0x0F,0x01,0x04,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_2_H[]=
-{
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x5F,0x83,0xDF,0xDF,0xE1,0x01,0x00,0x03,
-   0x00}},
- {{0xD7,0x31,0x31,0x9B,0x7B,0x13,0xE0,0xD4,
-   0x9B,0x8F,0x57,0x57,0xE1,0x21,0x00,0x03,
-   0x01}},
- {{0xC9,0x3F,0x3F,0x8D,0x7B,0x13,0xE0,0xD4,
-   0xEF,0x83,0xFF,0xFF,0xE1,0x21,0x00,0x03,
-   0x01}},
- {{0xB9,0x4F,0x4F,0x9D,0x7B,0x93,0xE0,0x5A,
-   0x6F,0x83,0xFF,0xFF,0xE1,0x29,0x00,0x02,
-   0x01}},
- {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03,
-   0x01}},
- {{0xA5,0x63,0x63,0x89,0x7B,0x93,0xE0,0x10,
-   0xC7,0x8B,0xAF,0xAF,0xE1,0x0F,0x00,0x02,
-   0x00}}
-};
-
+#endif
 
 /**************************************************************/
 /* LVDS, CHRONTEL ------------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS310_LVDSDataStruct
-{
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS310_LVDSDataStruct;
-
-static const SiS310_LVDSDataStruct  SiS310_CHTVUPALData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVUPALData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1697,7 +1011,7 @@
 	{1400,1000,1400,1000}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVOPALData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVOPALData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1708,7 +1022,7 @@
         {1400, 875,1400, 875}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVUPALMData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVUPALMData[]=
 {
 	{ 840, 600, 840, 600},
 	{ 840, 600, 840, 600},
@@ -1719,7 +1033,7 @@
         {1160, 945,1160, 945}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVOPALMData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVOPALMData[]=
 {
 	{ 840, 525, 840, 525},
 	{ 840, 525, 840, 525},
@@ -1730,7 +1044,7 @@
         {1160, 840,1160, 840}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVUPALNData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVUPALNData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1741,7 +1055,7 @@
 	{1400,1000,1400,1000}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVOPALNData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVOPALNData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1752,7 +1066,7 @@
         {1400, 875,1400, 875}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVSOPALData[]=   /* TW: (super overscan - no effect on 7019) */
+static const SiS_LVDSDataStruct  SiS310_CHTVSOPALData[]=   /* (super overscan - no effect on 7019) */
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1763,13 +1077,8 @@
         {1400, 875,1400, 875}
 };
 
-typedef struct _SiS310_LVDSDesStruct
-{
-	USHORT LCDHDES;
-	USHORT LCDVDES;
-} SiS310_LVDSDesStruct;
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType00_1[]=  /* 800x600 */
+static const SiS_LVDSDesStruct  SiS310_PanelType00_1[]=  /* 800x600 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1782,7 +1091,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType01_1[]=  /* 1024x768 */
+static const SiS_LVDSDesStruct  SiS310_PanelType01_1[]=  /* 1024x768 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1795,7 +1104,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType02_1[]=  /* 1280x1024 */
+static const SiS_LVDSDesStruct  SiS310_PanelType02_1[]=  /* 1280x1024 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1810,7 +1119,7 @@
 };
 
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType03_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType03_1[]=
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1823,7 +1132,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType04_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType04_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1836,7 +1145,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType05_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType05_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1849,7 +1158,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType06_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType06_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1862,7 +1171,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType07_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType07_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1875,7 +1184,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType08_1[]=   /* 1400x1050 */
+static const SiS_LVDSDesStruct  SiS310_PanelType08_1[]=   /* 1400x1050 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1890,7 +1199,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType09_1[]=   /* 1280x768 */
+static const SiS_LVDSDesStruct  SiS310_PanelType09_1[]=   /* 1280x768 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1905,7 +1214,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0a_1[]=  /* 1600x1200 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0a_1[]=  /* 1600x1200 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1920,7 +1229,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0b_1[]=  /* 640x480_2 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0b_1[]=  /* 640x480_2 */
 {
 	{ 0, 524},
 	{ 0, 524},
@@ -1932,7 +1241,7 @@
 	{ 0, 524}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0c_1[]=  /* 640x480_3 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0c_1[]=  /* 640x480_3 */
 {
 	{ 0, 524},
 	{ 0, 524},
@@ -1944,7 +1253,7 @@
 	{ 0, 524}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0d_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType0d_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1957,7 +1266,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0e_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType0e_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1970,7 +1279,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0f_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType0f_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1983,7 +1292,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType00_2[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType00_2[]=
 {
 	{980, 528},
 	{980, 503},
@@ -1996,7 +1305,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType01_2[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType01_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2009,7 +1318,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType02_2[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType02_2[]=
 {
 	{1368, 754},
 	{1368, 729},
@@ -2024,7 +1333,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType03_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType03_2[]=
 {
 	{ 0,   0},
 	{ 0,   0},
@@ -2035,7 +1344,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType04_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType04_2[]=
 {
 	{ 0,   0},
 	{ 0,   0},
@@ -2048,7 +1357,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType05_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType05_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2061,7 +1370,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType06_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType06_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2074,7 +1383,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType07_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType07_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2087,7 +1396,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType08_2[]=  /* 1400x1050 */
+static const SiS_LVDSDesStruct  SiS310_PanelType08_2[]=  /* 1400x1050 */
 {
 	{1308, 741},
 	{1308, 716},
@@ -2102,7 +1411,7 @@
 	{   0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType09_2[]= /* 1280x768 */
+static const SiS_LVDSDesStruct  SiS310_PanelType09_2[]= /* 1280x768 */
 {
 	{1083, 622},
 	{1083, 597},
@@ -2115,7 +1424,7 @@
 	{   0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0a_2[]=  /* 1600x1200 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0a_2[]=  /* 1600x1200 */
 {
 	{1568, 920},
 	{1568, 895},
@@ -2141,7 +1450,7 @@
 #endif
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0b_2[]=  /* 640x480_2 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0b_2[]=  /* 640x480_2 */
 {
 	{1152, 622},
 	{1152, 597},
@@ -2154,7 +1463,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0c_2[]=  /* 640x480_3 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0c_2[]=  /* 640x480_3 */
 {
 	{1152, 622},
 	{1152, 597},
@@ -2167,7 +1476,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0d_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType0d_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2180,7 +1489,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0e_2[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType0e_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2193,7 +1502,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0f_2[] =
+static const SiS_LVDSDesStruct  SiS310_PanelType0f_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -2206,14 +1515,37 @@
 	{ 0,   0}
 };
 
-/* CRT1 CRTC for SlaveModes and LCDA */
+static const SiS_LVDSDesStruct  SiS310_PanelTypeNS_1[]=
+{
+	{ 8,   0},
+	{ 8,   0},
+	{ 8,   0},
+	{ 8,   0},
+	{ 8,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0, 806},
+	{ 0,   0}
+};
 
-typedef struct _SiS310_LVDSCRT1DataStruct
+static const SiS_LVDSDesStruct  SiS310_PanelTypeNS_2[] =
 {
- 	UCHAR CR[15];
-} SiS310_LVDSCRT1DataStruct;
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0}
+};
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1[] =
+/* CRT1 CRTC for SlaveModes and LCDA */
+
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1[] =
 {
  {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
    0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -2235,7 +1567,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1_H[] =
 {
  {{0x43,0x27,0x87,0x2d,0x1d,0xaa,0x1f,
    0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -2257,7 +1589,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2[]=
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2[]=
 {
  {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
    0xff,0x84,0x8f,0x73,0x00,0x00,0x06,
@@ -2279,7 +1611,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2_H[] =
 {
  {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
    0xff,0x84,0x8f,0x73,0x00,0x00,0x01,
@@ -2301,7 +1633,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1[] =
 {
  {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f,
    0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
@@ -2326,7 +1658,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1_H[] =
 {
  {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f,
    0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
@@ -2351,7 +1683,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2[] =
 {
  {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
    0x57,0x8e,0x8f,0x25,0x30,0x00,0x06,
@@ -2376,7 +1708,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2_H[] =
 {
  {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
    0x57,0x8e,0x8f,0x25,0x30,0x00,0x01,
@@ -2401,7 +1733,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1[] =
 {
  {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f,
    0x90,0x84,0x8f,0xb9,0x30,0x00,0x06,
@@ -2429,7 +1761,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1_H[] =
 {
  {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
    0x90,0x84,0x8f,0xb9,0x30,0x00,0x05,
@@ -2454,7 +1786,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2[] =
 {
  {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
    0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02,
@@ -2482,7 +1814,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2_H[] = 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2_H[] =
 {
  {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
    0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06,
@@ -2507,7 +1839,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1[] =
 {
   {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
     0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
@@ -2567,7 +1899,7 @@
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1_H[] = 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1_H[] =
 {
  {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
    0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
@@ -2627,7 +1959,7 @@
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2[] =
 {
  {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
    0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02,
@@ -2687,7 +2019,7 @@
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2_H[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2_H[] =
 {
  {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
    0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06,
@@ -2747,7 +2079,7 @@
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1[] =
 {
  {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E,
    0xB3,0x86,0x8F,0x07,0x20,0x00,0x06,
@@ -2813,7 +2145,7 @@
 #endif
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1_H[] =
 {
  {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E,
    0xB3,0x86,0x8F,0x07,0x20,0x00,0x01,
@@ -2879,7 +2211,7 @@
 #endif
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2[] =
 {
  {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
    0x43,0x86,0xDB,0xDA,0x11,0x00,0x07,
@@ -2945,7 +2277,7 @@
 #endif
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2_H[] = 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2_H[] =
 {
  {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97,
    0x43,0x86,0xDB,0xDA,0x11,0x00,0x02,
@@ -3011,9 +2343,66 @@
 #endif
 };
 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1XXXxXXX_1[] =
+{
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
+   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
+   0x01}}
+};
+
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1XXXxXXX_1_H[] =
+{
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}},
+ {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
+   0x01}},
+ {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+   0x01}}
+};
+
+
 /* CRT1 CRTC for Chrontel TV slave modes */
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1UNTSC[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UNTSC[] =
 { 
  {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
    0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
@@ -3038,7 +2427,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1ONTSC[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1ONTSC[] =
 {
  {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
    0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -3063,7 +2452,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1UPAL[] =    
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UPAL[] =
 { 
  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
    0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -3088,7 +2477,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1OPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1OPAL[] =
 {
  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
    0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -3113,12 +2502,8 @@
    0x01 }}
 };
 
-typedef struct _SiS310_CHTVRegDataStruct
-{
- 	UCHAR Reg[16];
-} SiS310_CHTVRegDataStruct;
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
 {
  {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3138,7 +2523,7 @@
       for PAL-M and PAL-N all above is corrected.
     */
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
 {
  {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3149,7 +2534,7 @@
  {{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}}
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
 {
  {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3160,7 +2545,7 @@
  {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}}
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
 {
  {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3171,7 +2556,7 @@
  {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}}
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
 {
  {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3187,7 +2572,7 @@
 #endif
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
 {
  {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3203,7 +2588,7 @@
 #endif
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
 {
  {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
  {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
@@ -3219,7 +2604,7 @@
 #endif
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
 {
  {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
  {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
diff -Nru a/drivers/video/sis/init.c b/drivers/video/sis/init.c
--- a/drivers/video/sis/init.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/sis/init.c	2004-06-23 19:04:26 -07:00
@@ -1,8 +1,9 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Mode initializing code (CRT1 section) for
  * for SiS 300/305/540/630/730 and
- *     SiS 315/550/650/M650/651/661FX/M661FX/740/741/M741/330/660/M660/760/M760
+ *     SiS 315/550/650/M650/651/661FX/M661FX/740/741(GX)/M741/330/660/M660/760/M760
  * (Universal module for Linux kernel framebuffer and XFree86 4.x)
  *
  * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
@@ -34,13 +35,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -78,13 +76,13 @@
 
 #if defined(ALLOC_PRAGMA)
 #pragma alloc_text(PAGE,SiSSetMode)
-#pragma alloc_text(PAGE,SiSInit)
 #endif
 
 /*********************************************/
 /*         POINTER INITIALIZATION            */
 /*********************************************/
 
+#if defined(SIS300) || defined(SIS315H)
 static void
 InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
@@ -134,16 +132,17 @@
    SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
    SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;
 
+   SiS_Pr->SiS_LCD1280x720Data      = SiS_LCD1280x720Data;
+   SiS_Pr->SiS_StLCD1280x768_2Data  = SiS_StLCD1280x768_2Data;
+   SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
+   SiS_Pr->SiS_LCD1280x768_3Data    = SiS_LCD1280x768_3Data;
+   SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;
    SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
-   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
-   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
    SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
+   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
+   SiS_Pr->SiS_LCD1680x1050Data     = SiS_LCD1680x1050Data;
    SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;
-   SiS_Pr->SiS_NoScaleData1400x1050 = SiS_NoScaleData1400x1050;
-   SiS_Pr->SiS_NoScaleData1600x1200 = SiS_NoScaleData1600x1200;
-   SiS_Pr->SiS_ExtLCD1280x768Data   = SiS_ExtLCD1280x768Data;
-   SiS_Pr->SiS_StLCD1280x768Data    = SiS_StLCD1280x768Data;
-   SiS_Pr->SiS_NoScaleData1280x768  = SiS_NoScaleData1280x768;
+   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
    SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;
 
    SiS_Pr->SiS_LVDS320x480Data_1   = SiS_LVDS320x480Data_1;
@@ -172,41 +171,12 @@
    SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
    SiS_Pr->SiS_LVDS640x480Data_2   = SiS_LVDS640x480Data_2;
 
-   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
-   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
-   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
-   SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
    SiS_Pr->SiS_LVDS848x480Data_1   = SiS_LVDS848x480Data_1;
    SiS_Pr->SiS_LVDS848x480Data_2   = SiS_LVDS848x480Data_2;
-
-   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
-   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
-
-   SiS_Pr->SiS_LCDA1024x768Data_1  = SiS_LCDA1024x768Data_1;
-   SiS_Pr->SiS_LCDA1024x768Data_2  = SiS_LCDA1024x768Data_2;
-   SiS_Pr->SiS_LCDA1280x1024Data_1 = SiS_LCDA1280x1024Data_1;
-   SiS_Pr->SiS_LCDA1280x1024Data_2 = SiS_LCDA1280x1024Data_2;
-   SiS_Pr->SiS_LCDA1400x1050Data_1 = SiS_LCDA1400x1050Data_1;
-   SiS_Pr->SiS_LCDA1400x1050Data_2 = SiS_LCDA1400x1050Data_2;
-   SiS_Pr->SiS_LCDA1600x1200Data_1 = SiS_LCDA1600x1200Data_1;
-   SiS_Pr->SiS_LCDA1600x1200Data_2 = SiS_LCDA1600x1200Data_2;
-
-   SiS_Pr->LVDS1024x768Des_1  = SiS_PanelType1076_1;
-   SiS_Pr->LVDS1280x1024Des_1 = SiS_PanelType1210_1;
-   SiS_Pr->LVDS1400x1050Des_1 = SiS_PanelType1296_1;
-   SiS_Pr->LVDS1600x1200Des_1 = SiS_PanelType1600_1;
-   SiS_Pr->LVDS1024x768Des_2  = SiS_PanelType1076_2;
-   SiS_Pr->LVDS1280x1024Des_2 = SiS_PanelType1210_2;
-   SiS_Pr->LVDS1400x1050Des_2 = SiS_PanelType1296_2;
-   SiS_Pr->LVDS1600x1200Des_2 = SiS_PanelType1600_2;
-
-   SiS_Pr->SiS_PanelTypeNS_1 = SiS_PanelTypeNS_1;
-   SiS_Pr->SiS_PanelTypeNS_2 = SiS_PanelTypeNS_2;
-
-   SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
-   SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
-   SiS_Pr->SiS_CHTVUPALDesData  = SiS_CHTVUPALDesData;
-   SiS_Pr->SiS_CHTVOPALDesData  = SiS_CHTVOPALDesData;
+   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
+   SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
+   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
+   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
 
    SiS_Pr->SiS_LVDSCRT11280x768_1    = SiS_LVDSCRT11280x768_1;
    SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
@@ -221,15 +191,25 @@
    SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
    SiS_Pr->SiS_LVDSCRT11152x768_2_H  = SiS_LVDSCRT11152x768_2_H;
    SiS_Pr->SiS_LVDSCRT1320x480_1     = SiS_LVDSCRT1320x480_1;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS_LVDSCRT1XXXxXXX_1;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS_LVDSCRT1XXXxXXX_1_H;
    SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
    SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
    SiS_Pr->SiS_LVDSCRT1640x480_2     = SiS_LVDSCRT1640x480_2;
    SiS_Pr->SiS_LVDSCRT1640x480_2_H   = SiS_LVDSCRT1640x480_2_H;
    SiS_Pr->SiS_LVDSCRT1640x480_3     = SiS_LVDSCRT1640x480_3;
    SiS_Pr->SiS_LVDSCRT1640x480_3_H   = SiS_LVDSCRT1640x480_3_H;
+
+   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
+   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
+
+   SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
+   SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
+   SiS_Pr->SiS_CHTVUPALDesData  = SiS_CHTVUPALDesData;
+   SiS_Pr->SiS_CHTVOPALDesData  = SiS_CHTVOPALDesData;
+
+   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
+   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
 }
+#endif
 
 #ifdef SIS300
 static void
@@ -265,19 +245,18 @@
    SiS_StandTable[0x1c].CRTC[4] = 0x54;
    SiS_StandTable[0x1c].CRTC[5] = 0x80;
 
-   SiS_Pr->SiS_SModeIDTable  = (SiS_StStruct *)SiS300_SModeIDTable;
-   SiS_Pr->SiS_VBModeIDTable = (SiS_VBModeStruct *)SiS300_VBModeIDTable;
-   SiS_Pr->SiS_EModeIDTable  = (SiS_ExtStruct *)SiS300_EModeIDTable;
-   SiS_Pr->SiS_RefIndex      = (SiS_Ext2Struct *)SiS300_RefIndex;
-   SiS_Pr->SiS_CRT1Table     = (SiS_CRT1TableStruct *)SiS300_CRT1Table;
+   SiS_Pr->SiS_SModeIDTable  = SiS300_SModeIDTable;
+   SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
+   SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;
+   SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;
+   SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;
    if(HwInfo->jChipType == SIS_300) {
-      SiS_Pr->SiS_MCLKData_0    = (SiS_MCLKDataStruct *)SiS300_MCLKData_300; /* 300 */
+      SiS_Pr->SiS_MCLKData_0    = SiS300_MCLKData_300; /* 300 */
    } else {
-      SiS_Pr->SiS_MCLKData_0    = (SiS_MCLKDataStruct *)SiS300_MCLKData_630; /* 630, 730 */
+      SiS_Pr->SiS_MCLKData_0    = SiS300_MCLKData_630; /* 630, 730 */
    }
-   SiS_Pr->SiS_VCLKData      = (SiS_VCLKDataStruct *)SiS300_VCLKData;
+   SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;
    SiS_Pr->SiS_VBVCLKData    = (SiS_VBVCLKDataStruct *)SiS300_VCLKData;
-   SiS_Pr->SiS_ScreenOffset  = SiS300_ScreenOffset;
 
    SiS_Pr->SiS_SR15  = SiS300_SR15;
 
@@ -306,97 +285,102 @@
    SiS_Pr->pSiS_YCSenseData2    = &SiS300_YCSenseData2;
 #endif
 
-   SiS_Pr->SiS_StLCD1024x768Data    = (SiS_LCDDataStruct *)SiS300_StLCD1024x768Data;
-   SiS_Pr->SiS_ExtLCD1024x768Data   = (SiS_LCDDataStruct *)SiS300_ExtLCD1024x768Data;
-   SiS_Pr->SiS_St2LCD1024x768Data   = (SiS_LCDDataStruct *)SiS300_St2LCD1024x768Data;
-   SiS_Pr->SiS_StLCD1280x1024Data   = (SiS_LCDDataStruct *)SiS300_StLCD1280x1024Data;
-   SiS_Pr->SiS_ExtLCD1280x1024Data  = (SiS_LCDDataStruct *)SiS300_ExtLCD1280x1024Data;
-   SiS_Pr->SiS_St2LCD1280x1024Data  = (SiS_LCDDataStruct *)SiS300_St2LCD1280x1024Data;
-   SiS_Pr->SiS_NoScaleData1024x768  = (SiS_LCDDataStruct *)SiS300_NoScaleData1024x768;
-   SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS300_NoScaleData1280x1024;
-
-   SiS_Pr->SiS_PanelDelayTbl     = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl;
-   SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl;
-#if 0
-   SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTblLVDS;
-#endif
+   SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;
+   SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
 
-   SiS_Pr->SiS_CHTVUPALData  = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData;
-   SiS_Pr->SiS_CHTVOPALData  = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData;
-   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData; 			   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData; 			   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVSOPALData;
-
-   SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS300_PanelType00_1;
-   SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS300_PanelType01_1;
-   SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS300_PanelType02_1;
-   SiS_Pr->SiS_PanelType03_1 = (SiS_LVDSDesStruct *)SiS300_PanelType03_1;
-   SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1;
-   SiS_Pr->SiS_PanelType05_1 = (SiS_LVDSDesStruct *)SiS300_PanelType05_1;
-   SiS_Pr->SiS_PanelType06_1 = (SiS_LVDSDesStruct *)SiS300_PanelType06_1;
-   SiS_Pr->SiS_PanelType07_1 = (SiS_LVDSDesStruct *)SiS300_PanelType07_1;
-   SiS_Pr->SiS_PanelType08_1 = (SiS_LVDSDesStruct *)SiS300_PanelType08_1;
-   SiS_Pr->SiS_PanelType09_1 = (SiS_LVDSDesStruct *)SiS300_PanelType09_1;
-   SiS_Pr->SiS_PanelType0a_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0a_1;
-   SiS_Pr->SiS_PanelType0b_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0b_1;
-   SiS_Pr->SiS_PanelType0c_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0c_1;
-   SiS_Pr->SiS_PanelType0d_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_1;
-   SiS_Pr->SiS_PanelType0e_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_1;
-   SiS_Pr->SiS_PanelType0f_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_1;
-   SiS_Pr->SiS_PanelType00_2 = (SiS_LVDSDesStruct *)SiS300_PanelType00_2;
-   SiS_Pr->SiS_PanelType01_2 = (SiS_LVDSDesStruct *)SiS300_PanelType01_2;
-   SiS_Pr->SiS_PanelType02_2 = (SiS_LVDSDesStruct *)SiS300_PanelType02_2;
-   SiS_Pr->SiS_PanelType03_2 = (SiS_LVDSDesStruct *)SiS300_PanelType03_2;
-   SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2;
-   SiS_Pr->SiS_PanelType05_2 = (SiS_LVDSDesStruct *)SiS300_PanelType05_2;
-   SiS_Pr->SiS_PanelType06_2 = (SiS_LVDSDesStruct *)SiS300_PanelType06_2;
-   SiS_Pr->SiS_PanelType07_2 = (SiS_LVDSDesStruct *)SiS300_PanelType07_2;
-   SiS_Pr->SiS_PanelType08_2 = (SiS_LVDSDesStruct *)SiS300_PanelType08_2;
-   SiS_Pr->SiS_PanelType09_2 = (SiS_LVDSDesStruct *)SiS300_PanelType09_2;
-   SiS_Pr->SiS_PanelType0a_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0a_2;
-   SiS_Pr->SiS_PanelType0b_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0b_2;
-   SiS_Pr->SiS_PanelType0c_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0c_2;
-   SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_2;
-   SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_2;
-   SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_2;
+   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS300_ExtLCD1024x768Data;
+   SiS_Pr->SiS_St2LCD1024x768Data   = SiS300_St2LCD1024x768Data;
+   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS300_ExtLCD1280x1024Data;
+   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;
+
+   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;
+   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = SiS300_CRT2Part2_1280x1024_1;
+   SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;
+   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = SiS300_CRT2Part2_1280x1024_2;
+   SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;
+   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = SiS300_CRT2Part2_1280x1024_3;
+
+   SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;
+   SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;
+   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData;    /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData;    /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
+
+   SiS_Pr->SiS_PanelType00_1 = SiS300_PanelType00_1;
+   SiS_Pr->SiS_PanelType01_1 = SiS300_PanelType01_1;
+   SiS_Pr->SiS_PanelType02_1 = SiS300_PanelType02_1;
+   SiS_Pr->SiS_PanelType03_1 = SiS300_PanelType03_1;
+   SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1;
+   SiS_Pr->SiS_PanelType05_1 = SiS300_PanelType05_1;
+   SiS_Pr->SiS_PanelType06_1 = SiS300_PanelType06_1;
+   SiS_Pr->SiS_PanelType07_1 = SiS300_PanelType07_1;
+   SiS_Pr->SiS_PanelType08_1 = SiS300_PanelType08_1;
+   SiS_Pr->SiS_PanelType09_1 = SiS300_PanelType09_1;
+   SiS_Pr->SiS_PanelType0a_1 = SiS300_PanelType0a_1;
+   SiS_Pr->SiS_PanelType0b_1 = SiS300_PanelType0b_1;
+   SiS_Pr->SiS_PanelType0c_1 = SiS300_PanelType0c_1;
+   SiS_Pr->SiS_PanelType0d_1 = SiS300_PanelType0d_1;
+   SiS_Pr->SiS_PanelType0e_1 = SiS300_PanelType0e_1;
+   SiS_Pr->SiS_PanelType0f_1 = SiS300_PanelType0f_1;
+   SiS_Pr->SiS_PanelType00_2 = SiS300_PanelType00_2;
+   SiS_Pr->SiS_PanelType01_2 = SiS300_PanelType01_2;
+   SiS_Pr->SiS_PanelType02_2 = SiS300_PanelType02_2;
+   SiS_Pr->SiS_PanelType03_2 = SiS300_PanelType03_2;
+   SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2;
+   SiS_Pr->SiS_PanelType05_2 = SiS300_PanelType05_2;
+   SiS_Pr->SiS_PanelType06_2 = SiS300_PanelType06_2;
+   SiS_Pr->SiS_PanelType07_2 = SiS300_PanelType07_2;
+   SiS_Pr->SiS_PanelType08_2 = SiS300_PanelType08_2;
+   SiS_Pr->SiS_PanelType09_2 = SiS300_PanelType09_2;
+   SiS_Pr->SiS_PanelType0a_2 = SiS300_PanelType0a_2;
+   SiS_Pr->SiS_PanelType0b_2 = SiS300_PanelType0b_2;
+   SiS_Pr->SiS_PanelType0c_2 = SiS300_PanelType0c_2;
+   SiS_Pr->SiS_PanelType0d_2 = SiS300_PanelType0d_2;
+   SiS_Pr->SiS_PanelType0e_2 = SiS300_PanelType0e_2;
+   SiS_Pr->SiS_PanelType0f_2 = SiS300_PanelType0f_2;
+   SiS_Pr->SiS_PanelTypeNS_1 = SiS300_PanelTypeNS_1;
+   SiS_Pr->SiS_PanelTypeNS_2 = SiS300_PanelTypeNS_2;
 
    if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-      SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1a;
-      SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2a;
+      SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1a;
+      SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2a;
    }
    if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-      SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1b;
-      SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2b;
+      SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1b;
+      SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2b;
    }
 
-   SiS_Pr->SiS_LVDSCRT1800x600_1     = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1;
-   SiS_Pr->SiS_LVDSCRT11024x768_1    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1;
-   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1_H;
-   SiS_Pr->SiS_LVDSCRT1800x600_2     = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2;
-   SiS_Pr->SiS_LVDSCRT11024x768_2    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2;
-   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2_H;
-   SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL  = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL  = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1SOPAL;
-   SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC;
-   SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC;
-   SiS_Pr->SiS_CHTVReg_UPAL  = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL;
-   SiS_Pr->SiS_CHTVReg_OPAL  = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL;
-   SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_SOPAL;
+   SiS_Pr->SiS_LVDSCRT1800x600_1     = SiS300_LVDSCRT1800x600_1;
+   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = SiS300_LVDSCRT1800x600_1_H;
+   SiS_Pr->SiS_LVDSCRT1800x600_2     = SiS300_LVDSCRT1800x600_2;
+   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = SiS300_LVDSCRT1800x600_2_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_1    = SiS300_LVDSCRT11024x768_1;
+   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = SiS300_LVDSCRT11024x768_1_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_2    = SiS300_LVDSCRT11024x768_2;
+   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = SiS300_LVDSCRT11024x768_2_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1   = SiS300_LVDSCRT11280x1024_1;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS300_LVDSCRT11280x1024_1_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2   = SiS300_LVDSCRT11280x1024_2;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS300_LVDSCRT11280x1024_2_H;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS300_LVDSCRT1XXXxXXX_1;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS300_LVDSCRT1XXXxXXX_1_H;
+
+   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS300_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS300_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;
+   SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;
+   SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;
+   SiS_Pr->SiS_CHTVReg_UPAL  = SiS300_CHTVReg_UPAL;
+   SiS_Pr->SiS_CHTVReg_OPAL  = SiS300_CHTVReg_OPAL;
+   SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;
    SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
    SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
    SiS_Pr->SiS_CHTVVCLKUPAL  = SiS300_CHTVVCLKUPAL;
@@ -406,40 +390,6 @@
    SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL;   /* not supported on 300 series */
    SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */
    SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
-
-   SiS_Pr->SiS_CRT2Part2_1024x768_1  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_1;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_1;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_1;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_1;
-   SiS_Pr->SiS_CRT2Part2_1024x768_2  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_2;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_2;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_2;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_2;
-   SiS_Pr->SiS_CRT2Part2_1024x768_3  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_3;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_3;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_3;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_3;
-
-   /* LCDResInfo will on 300 series be translated to 315 series definitions */
-   SiS_Pr->SiS_Panel320x480   = Panel_320x480;
-   SiS_Pr->SiS_Panel640x480   = Panel_640x480;
-   SiS_Pr->SiS_Panel800x600   = Panel_800x600;
-   SiS_Pr->SiS_Panel1024x768  = Panel_1024x768;
-   SiS_Pr->SiS_Panel1280x1024 = Panel_1280x1024;
-   SiS_Pr->SiS_Panel1280x960  = Panel_1280x960;
-   SiS_Pr->SiS_Panel1024x600  = Panel_1024x600;
-   SiS_Pr->SiS_Panel1152x768  = Panel_1152x768;
-   SiS_Pr->SiS_Panel1280x768  = Panel_1280x768;
-   SiS_Pr->SiS_Panel1600x1200 = 255;  		   /* Something illegal */
-   SiS_Pr->SiS_Panel1400x1050 = 255;
-   SiS_Pr->SiS_Panel640x480_2 = 255;
-   SiS_Pr->SiS_Panel640x480_3 = 255;
-   SiS_Pr->SiS_Panel1152x864  = 255;
-   SiS_Pr->SiS_PanelMax       = Panel_320x480;     /* highest value */
-   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;     /* Lowest value LVDS */
-   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;    /* lowest value 301 */
-   SiS_Pr->SiS_PanelCustom    = Panel_Custom;
-   SiS_Pr->SiS_PanelBarco1366 = Panel_Barco1366;
 }
 #endif
 
@@ -477,23 +427,24 @@
    SiS_StandTable[0x1c].CRTC[4] = 0x55;
    SiS_StandTable[0x1c].CRTC[5] = 0x81;
 
-   SiS_Pr->SiS_SModeIDTable  = (SiS_StStruct *)SiS310_SModeIDTable;
-   SiS_Pr->SiS_EModeIDTable  = (SiS_ExtStruct *)SiS310_EModeIDTable;
+   SiS_Pr->SiS_SModeIDTable  = SiS310_SModeIDTable;
+   SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;
    SiS_Pr->SiS_RefIndex      = (SiS_Ext2Struct *)SiS310_RefIndex;
-   SiS_Pr->SiS_CRT1Table     = (SiS_CRT1TableStruct *)SiS310_CRT1Table;
-   if(HwInfo->jChipType >= SIS_661) {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_660;  /* 661/741/760 */
+   SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;
+   if(HwInfo->jChipType >= SIS_760) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */
+   } else if(HwInfo->jChipType >= SIS_661) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */
    } else if(HwInfo->jChipType == SIS_330) {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_330;  /* 330 */
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */
    } else if(HwInfo->jChipType > SIS_315PRO) {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_650;  /* 550, 650, 740 */
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */
    } else {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_315;  /* 315 */
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */
    }
-   SiS_Pr->SiS_MCLKData_1    = (SiS_MCLKDataStruct *)SiS310_MCLKData_1;
-   SiS_Pr->SiS_VCLKData      = (SiS_VCLKDataStruct *)SiS310_VCLKData;
-   SiS_Pr->SiS_VBVCLKData    = (SiS_VBVCLKDataStruct *)SiS310_VBVCLKData;
-   SiS_Pr->SiS_ScreenOffset  = SiS310_ScreenOffset;
+   SiS_Pr->SiS_MCLKData_1    = SiS310_MCLKData_1;
+   SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;
+   SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;
 
    SiS_Pr->SiS_SR15  = SiS310_SR15;
 
@@ -522,124 +473,96 @@
    SiS_Pr->pSiS_YCSenseData2    = &SiS310_YCSenseData2;
 #endif
 
-   SiS_Pr->SiS_StLCD1024x768Data    = (SiS_LCDDataStruct *)SiS310_StLCD1024x768Data;
-   SiS_Pr->SiS_ExtLCD1024x768Data   = (SiS_LCDDataStruct *)SiS310_ExtLCD1024x768Data;
-   SiS_Pr->SiS_St2LCD1024x768Data   = (SiS_LCDDataStruct *)SiS310_St2LCD1024x768Data;
-   SiS_Pr->SiS_StLCD1280x1024Data   = (SiS_LCDDataStruct *)SiS310_StLCD1280x1024Data;
-   SiS_Pr->SiS_ExtLCD1280x1024Data  = (SiS_LCDDataStruct *)SiS310_ExtLCD1280x1024Data;
-   SiS_Pr->SiS_St2LCD1280x1024Data  = (SiS_LCDDataStruct *)SiS310_St2LCD1280x1024Data;
-   SiS_Pr->SiS_NoScaleData1024x768  = (SiS_LCDDataStruct *)SiS310_NoScaleData1024x768;
-   SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS310_NoScaleData1280x1024;
-
-   SiS_Pr->SiS_PanelDelayTbl     = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl;
-   SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTblLVDS;
-
-   SiS_Pr->SiS_CHTVUPALData  = (SiS_LVDSDataStruct *)SiS310_CHTVUPALData;
-   SiS_Pr->SiS_CHTVOPALData  = (SiS_LVDSDataStruct *)SiS310_CHTVOPALData;
-   SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALMData;
-   SiS_Pr->SiS_CHTVOPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALMData;
-   SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALNData;
-   SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALNData;
-   SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVSOPALData;
-
-   SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS310_PanelType00_1;
-   SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS310_PanelType01_1;
-   SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS310_PanelType02_1;
-   SiS_Pr->SiS_PanelType03_1 = (SiS_LVDSDesStruct *)SiS310_PanelType03_1;
-   SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS310_PanelType04_1;
-   SiS_Pr->SiS_PanelType05_1 = (SiS_LVDSDesStruct *)SiS310_PanelType05_1;
-   SiS_Pr->SiS_PanelType06_1 = (SiS_LVDSDesStruct *)SiS310_PanelType06_1;
-   SiS_Pr->SiS_PanelType07_1 = (SiS_LVDSDesStruct *)SiS310_PanelType07_1;
-   SiS_Pr->SiS_PanelType08_1 = (SiS_LVDSDesStruct *)SiS310_PanelType08_1;
-   SiS_Pr->SiS_PanelType09_1 = (SiS_LVDSDesStruct *)SiS310_PanelType09_1;
-   SiS_Pr->SiS_PanelType0a_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0a_1;
-   SiS_Pr->SiS_PanelType0b_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0b_1;
-   SiS_Pr->SiS_PanelType0c_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0c_1;
-   SiS_Pr->SiS_PanelType0d_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_1;
-   SiS_Pr->SiS_PanelType0e_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_1;
-   SiS_Pr->SiS_PanelType0f_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_1;
-   SiS_Pr->SiS_PanelType00_2 = (SiS_LVDSDesStruct *)SiS310_PanelType00_2;
-   SiS_Pr->SiS_PanelType01_2 = (SiS_LVDSDesStruct *)SiS310_PanelType01_2;
-   SiS_Pr->SiS_PanelType02_2 = (SiS_LVDSDesStruct *)SiS310_PanelType02_2;
-   SiS_Pr->SiS_PanelType03_2 = (SiS_LVDSDesStruct *)SiS310_PanelType03_2;
-   SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS310_PanelType04_2;
-   SiS_Pr->SiS_PanelType05_2 = (SiS_LVDSDesStruct *)SiS310_PanelType05_2;
-   SiS_Pr->SiS_PanelType06_2 = (SiS_LVDSDesStruct *)SiS310_PanelType06_2;
-   SiS_Pr->SiS_PanelType07_2 = (SiS_LVDSDesStruct *)SiS310_PanelType07_2;
-   SiS_Pr->SiS_PanelType08_2 = (SiS_LVDSDesStruct *)SiS310_PanelType08_2;
-   SiS_Pr->SiS_PanelType09_2 = (SiS_LVDSDesStruct *)SiS310_PanelType09_2;
-   SiS_Pr->SiS_PanelType0a_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0a_2;
-   SiS_Pr->SiS_PanelType0b_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0b_2;
-   SiS_Pr->SiS_PanelType0c_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0c_2;
-   SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_2;
-   SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_2;
-   SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_2;
-
-   SiS_Pr->SiS_CRT2Part2_1024x768_1  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_1;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_1;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_1;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_1;
-   SiS_Pr->SiS_CRT2Part2_1024x768_2  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_2;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_2;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_2;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_2;
-   SiS_Pr->SiS_CRT2Part2_1024x768_3  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_3;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_3;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_3;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_3;
-
-   SiS_Pr->SiS_LVDSCRT1800x600_1     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1;
-   SiS_Pr->SiS_LVDSCRT11024x768_1    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1;
-   SiS_Pr->SiS_LVDSCRT11400x1050_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1;
-   SiS_Pr->SiS_LVDSCRT11600x1200_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1;
-   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1_H;
-   SiS_Pr->SiS_LVDSCRT11400x1050_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1_H;
-   SiS_Pr->SiS_LVDSCRT11600x1200_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1_H;
-   SiS_Pr->SiS_LVDSCRT1800x600_2     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2;
-   SiS_Pr->SiS_LVDSCRT11024x768_2    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2;
-   SiS_Pr->SiS_LVDSCRT11400x1050_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2;
-   SiS_Pr->SiS_LVDSCRT11600x1200_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2;
-   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2_H;
-   SiS_Pr->SiS_LVDSCRT11400x1050_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2_H;
-   SiS_Pr->SiS_LVDSCRT11600x1200_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2_H;
-   SiS_Pr->SiS_CHTVCRT1UNTSC         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL          = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL          = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
-
-   SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UNTSC;
-   SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_ONTSC;
-   SiS_Pr->SiS_CHTVReg_UPAL  = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPAL;
-   SiS_Pr->SiS_CHTVReg_OPAL  = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPAL;
-   SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALM;
-   SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALM;
-   SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALN;
-   SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALN;
-   SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPAL;
-
-   SiS_Pr->SiS_LCDACRT11024x768_1    = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1;
-   SiS_Pr->SiS_LCDACRT11280x1024_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1;
-   SiS_Pr->SiS_LCDACRT11400x1050_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1;
-   SiS_Pr->SiS_LCDACRT11600x1200_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1;
-   SiS_Pr->SiS_LCDACRT11024x768_1_H  = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1_H;
-   SiS_Pr->SiS_LCDACRT11280x1024_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1_H;
-   SiS_Pr->SiS_LCDACRT11400x1050_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1_H;
-   SiS_Pr->SiS_LCDACRT11600x1200_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1_H;
-   SiS_Pr->SiS_LCDACRT11024x768_2    = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2;
-   SiS_Pr->SiS_LCDACRT11280x1024_2   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2;
-   SiS_Pr->SiS_LCDACRT11400x1050_2   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2;
-   SiS_Pr->SiS_LCDACRT11600x1200_2   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2;
-   SiS_Pr->SiS_LCDACRT11024x768_2_H  = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2_H;
-   SiS_Pr->SiS_LCDACRT11280x1024_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2_H;
-   SiS_Pr->SiS_LCDACRT11400x1050_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2_H;
-   SiS_Pr->SiS_LCDACRT11600x1200_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2_H;
+   SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;
+   SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
+
+   SiS_Pr->SiS_St2LCD1024x768Data   = SiS310_St2LCD1024x768Data;
+   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS310_ExtLCD1024x768Data;
+   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS310_St2LCD1280x1024Data;
+   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS310_ExtLCD1280x1024Data;
+
+   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;
+
+   SiS_Pr->SiS_PanelType00_1 = SiS310_PanelType00_1;
+   SiS_Pr->SiS_PanelType01_1 = SiS310_PanelType01_1;
+   SiS_Pr->SiS_PanelType02_1 = SiS310_PanelType02_1;
+   SiS_Pr->SiS_PanelType03_1 = SiS310_PanelType03_1;
+   SiS_Pr->SiS_PanelType04_1 = SiS310_PanelType04_1;
+   SiS_Pr->SiS_PanelType05_1 = SiS310_PanelType05_1;
+   SiS_Pr->SiS_PanelType06_1 = SiS310_PanelType06_1;
+   SiS_Pr->SiS_PanelType07_1 = SiS310_PanelType07_1;
+   SiS_Pr->SiS_PanelType08_1 = SiS310_PanelType08_1;
+   SiS_Pr->SiS_PanelType09_1 = SiS310_PanelType09_1;
+   SiS_Pr->SiS_PanelType0a_1 = SiS310_PanelType0a_1;
+   SiS_Pr->SiS_PanelType0b_1 = SiS310_PanelType0b_1;
+   SiS_Pr->SiS_PanelType0c_1 = SiS310_PanelType0c_1;
+   SiS_Pr->SiS_PanelType0d_1 = SiS310_PanelType0d_1;
+   SiS_Pr->SiS_PanelType0e_1 = SiS310_PanelType0e_1;
+   SiS_Pr->SiS_PanelType0f_1 = SiS310_PanelType0f_1;
+   SiS_Pr->SiS_PanelType00_2 = SiS310_PanelType00_2;
+   SiS_Pr->SiS_PanelType01_2 = SiS310_PanelType01_2;
+   SiS_Pr->SiS_PanelType02_2 = SiS310_PanelType02_2;
+   SiS_Pr->SiS_PanelType03_2 = SiS310_PanelType03_2;
+   SiS_Pr->SiS_PanelType04_2 = SiS310_PanelType04_2;
+   SiS_Pr->SiS_PanelType05_2 = SiS310_PanelType05_2;
+   SiS_Pr->SiS_PanelType06_2 = SiS310_PanelType06_2;
+   SiS_Pr->SiS_PanelType07_2 = SiS310_PanelType07_2;
+   SiS_Pr->SiS_PanelType08_2 = SiS310_PanelType08_2;
+   SiS_Pr->SiS_PanelType09_2 = SiS310_PanelType09_2;
+   SiS_Pr->SiS_PanelType0a_2 = SiS310_PanelType0a_2;
+   SiS_Pr->SiS_PanelType0b_2 = SiS310_PanelType0b_2;
+   SiS_Pr->SiS_PanelType0c_2 = SiS310_PanelType0c_2;
+   SiS_Pr->SiS_PanelType0d_2 = SiS310_PanelType0d_2;
+   SiS_Pr->SiS_PanelType0e_2 = SiS310_PanelType0e_2;
+   SiS_Pr->SiS_PanelType0f_2 = SiS310_PanelType0f_2;
+   SiS_Pr->SiS_PanelTypeNS_1 = SiS310_PanelTypeNS_1;
+   SiS_Pr->SiS_PanelTypeNS_2 = SiS310_PanelTypeNS_2;
+
+   SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;
+   SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;
+   SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
+   SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;
+   SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;
+   SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
+   SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
+
+   SiS_Pr->SiS_LVDSCRT1800x600_1     = SiS310_LVDSCRT1800x600_1;
+   SiS_Pr->SiS_LVDSCRT11024x768_1    = SiS310_LVDSCRT11024x768_1;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1   = SiS310_LVDSCRT11280x1024_1;
+   SiS_Pr->SiS_LVDSCRT11400x1050_1   = SiS310_LVDSCRT11400x1050_1;
+   SiS_Pr->SiS_LVDSCRT11600x1200_1   = SiS310_LVDSCRT11600x1200_1;
+   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = SiS310_LVDSCRT1800x600_1_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = SiS310_LVDSCRT11024x768_1_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS310_LVDSCRT11280x1024_1_H;
+   SiS_Pr->SiS_LVDSCRT11400x1050_1_H = SiS310_LVDSCRT11400x1050_1_H;
+   SiS_Pr->SiS_LVDSCRT11600x1200_1_H = SiS310_LVDSCRT11600x1200_1_H;
+   SiS_Pr->SiS_LVDSCRT1800x600_2     = SiS310_LVDSCRT1800x600_2;
+   SiS_Pr->SiS_LVDSCRT11024x768_2    = SiS310_LVDSCRT11024x768_2;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2   = SiS310_LVDSCRT11280x1024_2;
+   SiS_Pr->SiS_LVDSCRT11400x1050_2   = SiS310_LVDSCRT11400x1050_2;
+   SiS_Pr->SiS_LVDSCRT11600x1200_2   = SiS310_LVDSCRT11600x1200_2;
+   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = SiS310_LVDSCRT1800x600_2_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = SiS310_LVDSCRT11024x768_2_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS310_LVDSCRT11280x1024_2_H;
+   SiS_Pr->SiS_LVDSCRT11400x1050_2_H = SiS310_LVDSCRT11400x1050_2_H;
+   SiS_Pr->SiS_LVDSCRT11600x1200_2_H = SiS310_LVDSCRT11600x1200_2_H;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS310_LVDSCRT1XXXxXXX_1;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS310_LVDSCRT1XXXxXXX_1_H;
+   SiS_Pr->SiS_CHTVCRT1UNTSC         = SiS310_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC         = SiS310_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL          = SiS310_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL          = SiS310_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL         = SiS310_CHTVCRT1OPAL;
+
+   SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
+   SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
+   SiS_Pr->SiS_CHTVReg_UPAL  = SiS310_CHTVReg_UPAL;
+   SiS_Pr->SiS_CHTVReg_OPAL  = SiS310_CHTVReg_OPAL;
+   SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;
+   SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;
+   SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;
+   SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;
+   SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;
 
    SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
    SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
@@ -648,28 +571,8 @@
    SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;
    SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;
    SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;
-   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;   
+   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;
    SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;
-
-   SiS_Pr->SiS_Panel320x480   = Panel_320x480;
-   SiS_Pr->SiS_Panel640x480   = Panel_640x480;
-   SiS_Pr->SiS_Panel800x600   = Panel_800x600;
-   SiS_Pr->SiS_Panel1024x768  = Panel_1024x768;
-   SiS_Pr->SiS_Panel1280x1024 = Panel_1280x1024;
-   SiS_Pr->SiS_Panel1280x960  = Panel_1280x960;
-   SiS_Pr->SiS_Panel1600x1200 = Panel_1600x1200;
-   SiS_Pr->SiS_Panel1400x1050 = Panel_1400x1050;
-   SiS_Pr->SiS_Panel1152x768  = Panel_1152x768;
-   SiS_Pr->SiS_Panel1152x864  = Panel_1152x864;
-   SiS_Pr->SiS_Panel1280x768  = Panel_1280x768;
-   SiS_Pr->SiS_Panel1024x600  = Panel_1024x600;
-   SiS_Pr->SiS_Panel640x480_2 = Panel_640x480_2;
-   SiS_Pr->SiS_Panel640x480_3 = Panel_640x480_3;
-   SiS_Pr->SiS_PanelMax       = Panel_320x480;    /* highest value */
-   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
-   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
-   SiS_Pr->SiS_PanelCustom    = Panel_Custom;
-   SiS_Pr->SiS_PanelBarco1366 = 255;
 }
 #endif
 
@@ -710,7 +613,8 @@
 /*********************************************/
 
 USHORT
-SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN)
+SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
+              int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
 {
    USHORT ModeIndex = 0;
 
@@ -734,54 +638,58 @@
 	  else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
           break;
      case 720:
-          if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
-             else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
-          }
+          if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+          else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
           break;
      case 768:
-          if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
-          }
+          if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 	  break;
      case 800:
-	  if(VDisplay == 600)    ModeIndex = ModeIndex_800x600[Depth];
-	  else if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
-	  }
+	  if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
+	  else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
           break;
      case 848:
-          if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
-	  }
+	  if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
 	  break;
      case 856:
-          if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+	  if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+	  break;
+     case 960:
+	  if(VGAEngine == SIS_315_VGA) {
+	     if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
 	  }
 	  break;
      case 1024:
-          if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
-	  else if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 576)    ModeIndex = ModeIndex_1024x576[Depth];
-	     else if(VGAEngine == SIS_300_VGA) {
-	        if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
-             }
+          if(VDisplay == 768)      ModeIndex = ModeIndex_1024x768[Depth];
+	  else if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+	  else if((!(VBFlags & CRT1_LCDA)) && (VGAEngine == SIS_300_VGA)) {
+	     if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
 	  }
           break;
      case 1152:
-          if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 864)    ModeIndex = ModeIndex_1152x864[Depth];
-             else if(VGAEngine == SIS_300_VGA) {
-	        if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
-             }
+          if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+          if((!(VBFlags & CRT1_LCDA)) && (VGAEngine == SIS_300_VGA)) {
+	     if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
 	  }
 	  break;
      case 1280:
-          if(VDisplay == 1024)        ModeIndex = ModeIndex_1280x1024[Depth];
-	  else if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 960)      ModeIndex = ModeIndex_1280x960[Depth];
-	     else if(VDisplay == 720) ModeIndex = ModeIndex_1280x720[Depth];
+          if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
+	  else if(VDisplay == 800) {
+	     if(VGAEngine == SIS_315_VGA) {
+	        if((VBFlags & CRT1_LCDA) && (LCDwidth == 1280) && (LCDheight == 800)) {
+	           ModeIndex = ModeIndex_1280x800[Depth];
+	        } else if(!(VBFlags & CRT1_LCDA)) {
+	           ModeIndex = ModeIndex_1280x800[Depth];
+	        }
+	     }
+	  } else if(VDisplay == 720) {
+	     if((VBFlags & CRT1_LCDA) && (LCDwidth == 1280) && (LCDheight == 720)) {
+	        ModeIndex = ModeIndex_1280x720[Depth];
+	     } else if(!(VBFlags & CRT1_LCDA)) {
+	        ModeIndex = ModeIndex_1280x720[Depth];
+	     }
+	  } else if(!(VBFlags & CRT1_LCDA)) {
+             if(VDisplay == 960) ModeIndex = ModeIndex_1280x960[Depth];
 	     else if(VDisplay == 768) {
 	        if(VGAEngine == SIS_300_VGA) {
 	           ModeIndex = ModeIndex_300_1280x768[Depth];
@@ -792,23 +700,39 @@
 	  }
           break;
      case 1360:
+          if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
           if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 768)     ModeIndex = ModeIndex_1360x768[Depth];
-	     else if(VGAEngine == SIS_300_VGA) {
+	     if(VGAEngine == SIS_300_VGA) {
 	        if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
              }
 	  }
           break;
      case 1400:
           if(VGAEngine == SIS_315_VGA) {
-	     if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+	     if(VDisplay == 1050) {
+	        if((VBFlags & CRT1_LCDA) &&
+	           (((LCDwidth == 1400) && (LCDheight == 1050)) ||
+		    ((LCDwidth == 1600) && (LCDheight == 1200)))) {
+	           ModeIndex = ModeIndex_1400x1050[Depth];
+	        } else if(!(VBFlags & CRT1_LCDA)) {
+	           ModeIndex = ModeIndex_1400x1050[Depth];
+	        }
+	     }
 	  }
           break;
      case 1600:
           if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
           break;
+     case 1680:
+          if(VGAEngine == SIS_315_VGA) {
+             if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+	  }
+          break;
      case 1920:
           if(!(VBFlags & CRT1_LCDA)) {
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
+	     }
              if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
 	  }
           break;
@@ -851,14 +775,18 @@
              break;
      	case 400:
 	     if(CustomT != CUT_PANEL848) {
-          	if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+	        if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
+          	   if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+		}
 	     }
              break;
 	case 512:
 	     if(CustomT != CUT_PANEL848) {
-		if(VDisplay == 384) {
+	        if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
 		   if(LCDwidth != 1024 || LCDheight != 600) {
-		      ModeIndex = ModeIndex_512x384[Depth];
+		      if(VDisplay == 384) {
+		         ModeIndex = ModeIndex_512x384[Depth];
+		      }
 		   }
 		}
 	     }
@@ -898,6 +826,9 @@
 	        if((VDisplay == 768) && (LCDheight == 768)) {
 		   ModeIndex = ModeIndex_310_1280x768[Depth];
 		}
+		if((VDisplay == 800) && (LCDheight == 800)) {
+		   ModeIndex = ModeIndex_310_1280x768[Depth];
+		}
 	     }
 	     break;
 	case 1360:
@@ -940,17 +871,54 @@
 	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
 	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 	     break;
+	case 720:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
+	     }
+	     break;
+	case 768:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+	     }
+	     break;
 	case 800:
 	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+	     }
+	     break;
+	case 848:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+	     }
+	     break;
+	case 856:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+	     }
+	     break;
+	case 960:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
+	     }
 	     break;
 	case 1024:
 	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+	     }
+	     break;
+	case 1152:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+	     }
 	     break;
 	case 1280:
 	     if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
 	     else if(VDisplay == 768) {
-		if((LCDheight == 768) ||
-		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		if((LCDheight == 768) ||  (LCDwidth == 1680) ||
+		   (VBFlags & VB_SISTMDS)) {
 		   if(VGAEngine == SIS_300_VGA) {
 		      ModeIndex = ModeIndex_300_1280x768[Depth];
 		   } else {
@@ -958,24 +926,49 @@
 		   }
 		}
 	     } else if(VDisplay == 960) {
-	        if((LCDheight == 960) ||
-		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+	        if((LCDheight == 960) || (VBFlags & VB_SISTMDS)) {
 		   ModeIndex = ModeIndex_1280x960[Depth];
 		}
+	     } else if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 800) {
+		   if((LCDheight == 800) || (LCDwidth == 1680) ||
+		      (VBFlags & VB_SISTMDS)) {
+		      ModeIndex = ModeIndex_1280x800[Depth];
+		   }
+		} else if(VDisplay == 720) {
+		   if((LCDheight == 720) || (LCDwidth == 1680) || (LCDwidth == 1400) ||
+		      (VBFlags & VB_SISTMDS)) {
+		      ModeIndex = ModeIndex_1280x720[Depth];
+		   }
+		}
+	     }
+	     break;
+	case 1360:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
 	     }
 	     break;
 	case 1400:
 	     if(VGAEngine == SIS_315_VGA) {
 	        if(VBFlags & (VB_301B | VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
-		   if(LCDheight != 1200) {
-	              if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+		   if((LCDwidth == 1400) || (LCDwidth == 1600) || (LCDwidth == 1680)) {
+		      ModeIndex = ModeIndex_1400x1050[Depth];
 		   }
 		}
 	     }
 	     break;
 	case 1600:
-	     if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
-	        if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
+	           if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+		}
+	     }
+	     break;
+	case 1680:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
+	           if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+		}
 	     }
 	     break;
       }
@@ -1024,8 +1017,8 @@
              if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
              break;
       	case 512:
-	     if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR525P | TV_YPBPR750P | TV_YPBPR1080I))) ||
-	         (VBFlags & TV_HIVISION) 					    		     ||
+	     if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
+	         (VBFlags & TV_HIVISION) 					      ||
 	         ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
 	        if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
 	     }
@@ -1037,17 +1030,19 @@
 	case 720:
 	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
                 if(VDisplay == 480) {
-		   if((VBFlags & TV_YPBPR) || (VBFlags & (TV_NTSC | TV_PALM)))
+		   /* if((VBFlags & TV_YPBPR) || (VBFlags & (TV_NTSC | TV_PALM))) */
                       ModeIndex = ModeIndex_720x480[Depth];
                 } else if(VDisplay == 576) {
-		   if((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))
+		   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+		       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
                       ModeIndex = ModeIndex_720x576[Depth];
                 }
 	     }
              break;
 	case 768:
 	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
-	        if((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) {
+	        if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+		    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
           	   if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 		}
              }
@@ -1072,9 +1067,16 @@
 	     }
 	     break;
 	case 1280:
-	     if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
-	        if(VDisplay == 720)       ModeIndex = ModeIndex_1280x720[Depth];
-		else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
+	     if(VDisplay == 720) {
+	        if((VBFlags & TV_HIVISION) ||
+		   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
+	           ModeIndex = ModeIndex_1280x720[Depth];
+		}
+	     } else if(VDisplay == 1024) {
+	        if((VBFlags & TV_HIVISION) ||
+		   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+	           ModeIndex = ModeIndex_1280x1024[Depth];
+		}
 	     }
 	     break;
       }
@@ -1122,6 +1124,11 @@
 	case 856:
 		if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
 		break;
+	case 960:
+		if(VGAEngine == SIS_315_VGA) {
+		   if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
+		}
+		break;
 	case 1024:
 		if(VDisplay == 768)      ModeIndex = ModeIndex_1024x768[Depth];
 		else if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
@@ -1141,6 +1148,7 @@
 		   }
 		} else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
 		else if(VDisplay == 720)    ModeIndex = ModeIndex_1280x720[Depth];
+		else if(VDisplay == 800)    ModeIndex = ModeIndex_1280x800[Depth];
 		else if(VDisplay == 960)    ModeIndex = ModeIndex_1280x960[Depth];
 		break;
         case 1360:
@@ -1158,6 +1166,13 @@
 		   }
 		}
 		break;
+	case 1680:
+		if(VGAEngine == SIS_315_VGA) {
+		   if(VBFlags & (VB_301B|VB_301C|VB_302B)) {
+	              if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+		   }
+		}
+		break;
    }
 
    return ModeIndex;
@@ -1255,13 +1270,13 @@
 void
 SiS_DisplayOn(SiS_Private *SiS_Pr)
 {
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x00);
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
 }
 
 void
 SiS_DisplayOff(SiS_Private *SiS_Pr)
 {
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x20);
+   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
 }
 
 
@@ -1308,9 +1323,11 @@
    /* (SR11 is used for DDC and in enable/disablebridge) */
    SiS_Pr->SiS_SensibleSR11 = FALSE;
    SiS_Pr->SiS_MyCR63 = 0x63;
-   if(HwInfo->jChipType >= SIS_661) {
-      SiS_Pr->SiS_SensibleSR11 = TRUE;
+   if(HwInfo->jChipType >= SIS_330) {
       SiS_Pr->SiS_MyCR63 = 0x53;
+      if(HwInfo->jChipType >= SIS_661) {
+         SiS_Pr->SiS_SensibleSR11 = TRUE;
+      }
    }
 
    /* You should use the macros, not these flags directly */
@@ -1350,6 +1367,10 @@
 	 }
       }
    }
+   if(HwInfo->jChipType == SIS_760) {
+      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78);
+      if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760LFB;
+   }
 }
 
 /*********************************************/
@@ -1411,7 +1432,7 @@
 void
 SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-   ULONG   temp;
+   USHORT temp;
 
    SiS_Pr->SiS_IF_DEF_LVDS = 0;
    SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
@@ -1422,18 +1443,19 @@
 
    SiS_Pr->SiS_ChrontelInit = 0;
 
+   /* Check for SiS30x first */
+   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+   if((temp == 1) || (temp == 2)) return;
+
    switch(HwInfo->jChipType) {
 #ifdef SIS300
    case SIS_540:
    case SIS_630:
    case SIS_730:
-        /* Check for SiS30x first */
-        temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-	if((temp == 1) || (temp == 2)) return;
       	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
       	temp = (temp & 0x0E) >> 1;
-      	if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      	if(temp == 3)   SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
+      	if((temp >= 2) && (temp <= 5)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      	if(temp == 3)   		SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
       	if((temp == 4) || (temp == 5)) {
 		/* Save power status (and error check) - UNUSED */
 		SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
@@ -1448,8 +1470,8 @@
    case SIS_330:
         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
       	temp = (temp & 0x0E) >> 1;
-      	if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      	if(temp == 3)  SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+      	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      	if(temp == 3)  			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
         break;
    case SIS_661:
    case SIS_741:
@@ -1457,9 +1479,9 @@
    case SIS_760:
         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       	temp = (temp & 0xe0) >> 5;
-      	if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      	if(temp == 3)  SiS_Pr->SiS_IF_DEF_CH70xx = 2;
-	if(temp == 4)  SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
+      	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      	if(temp == 3)  			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+	if(temp == 4)  			SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
         break;
 #endif
    default:
@@ -1487,44 +1509,78 @@
 /*        HELPER: Determine ROM usage        */
 /*********************************************/
 
+BOOLEAN
+SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+   USHORT romversoffs, romvmaj = 1, romvmin = 0;
+
+   if(HwInfo->jChipType >= SIS_661) {
+      if((ROMAddr[0x1a] == 'N') &&
+         (ROMAddr[0x1b] == 'e') &&
+         (ROMAddr[0x1c] == 'w') &&
+         (ROMAddr[0x1d] == 'V')) {
+	 return TRUE;
+      }
+      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
+      if(romversoffs) {
+	 if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
+	    romvmaj = ROMAddr[romversoffs] - '0';
+	    romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
+	 }
+      }
+      if((romvmaj != 0) || (romvmin >= 92)) {
+	 return TRUE;
+      }
+   } else if(IS_SIS650740) {
+      if((ROMAddr[0x1a] == 'N') &&
+         (ROMAddr[0x1b] == 'e') &&
+         (ROMAddr[0x1c] == 'w') &&
+         (ROMAddr[0x1d] == 'V')) {
+	 return TRUE;
+      }
+   }
+   return FALSE;
+}
+
 static void
 SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
    UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+   USHORT romptr = 0;
+
+   SiS_Pr->SiS_UseROM = FALSE;
+   SiS_Pr->SiS_ROMNew = FALSE;
 
    if((ROMAddr) && (HwInfo->UseROM)) {
-      if((ROMAddr[0x00] != 0x55) || (ROMAddr[0x01] != 0xAA)) {
-         SiS_Pr->SiS_UseROM = FALSE;
-      } else if(HwInfo->jChipType == SIS_300) {
-        /* 300: We check if the code starts below 0x220 by
-	 * checking the jmp instruction at the beginning
-	 * of the BIOS image.
-	 */
-	 if((ROMAddr[3] == 0xe9) &&
-	    ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
+      if(HwInfo->jChipType == SIS_300) {
+         /* 300: We check if the code starts below 0x220 by
+	  * checking the jmp instruction at the beginning
+	  * of the BIOS image.
+	  */
+	 if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
 	    SiS_Pr->SiS_UseROM = TRUE;
-	 else
-	    SiS_Pr->SiS_UseROM = FALSE;
       } else if(HwInfo->jChipType < SIS_315H) {
-#if 0
-        /* Rest of 300 series: We don't use the ROM image if
-	 * the BIOS version < 2.0.0 as such old BIOSes don't
-	 * have the needed data at the expected locations.
-	 */
-         if(ROMAddr[0x06] < '2')  SiS_Pr->SiS_UseROM = FALSE;
-	 else                     SiS_Pr->SiS_UseROM = TRUE;
-#else
-	/* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
-	 * the others do as well
-	 */
+	 /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
+	  * the others do as well
+	  */
 	 SiS_Pr->SiS_UseROM = TRUE;
-#endif
       } else {
-         /* 315/330 series stick to the standard */
+         /* 315/330 series stick to the standard(s) */
 	 SiS_Pr->SiS_UseROM = TRUE;
+	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr, HwInfo))) {
+	    /* Find out about LCD data table entry size */
+	    if((romptr = SISGETROMW(0x0102))) {
+	       if(ROMAddr[romptr + (32 * 16)] == 0xff)
+	          SiS_Pr->SiS661LCD2TableSize = 32;
+	       else if(ROMAddr[romptr + (34 * 16)] == 0xff)
+	          SiS_Pr->SiS661LCD2TableSize = 34;
+	       else if(ROMAddr[romptr + (36 * 16)] == 0xff)
+	          SiS_Pr->SiS661LCD2TableSize = 36;  /* 0.94 final */
+	    }
+	 }
       }
-   } else SiS_Pr->SiS_UseROM = FALSE;
-
+   }
 }
 
 /*********************************************/
@@ -1609,7 +1665,8 @@
 
   SiS_Pr->SiS_VBType = 0;
 
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) return;
+  if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
+     return;
 
   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
 
@@ -1620,7 +1677,6 @@
   if(flag >= 2) {
      SiS_Pr->SiS_VBType = VB_SIS302B;
   } else if(flag == 1) {
-     SiS_Pr->SiS_VBType = VB_SIS301;
      if(rev >= 0xC0) {
        	SiS_Pr->SiS_VBType = VB_SIS301C;
      } else if(rev >= 0xB0) {
@@ -1628,102 +1684,22 @@
 	/* Check if 30xB DH version (no LCD support, use Panel Link instead) */
     	nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
         if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
+     } else {
+        SiS_Pr->SiS_VBType = VB_SIS301;
      }
   }
   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
-     if(rev >= 0xD0) {
-	SiS_Pr->SiS_VBType &= ~(VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_NoLCD);
-	if(rev >= 0xE0) {
-	   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
-	   if(flag == 0xff)
-	      SiS_Pr->SiS_VBType |= VB_SIS302LV;
-	   else
-	      SiS_Pr->SiS_VBType |= VB_SIS302ELV;
-	} else {
-	   SiS_Pr->SiS_VBType |= VB_SIS301LV;
-	}
+     if(rev >= 0xE0) {
+	flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
+	if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
+	else 	 	 SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
+     } else if(rev >= 0xD0) {
+	SiS_Pr->SiS_VBType = VB_SIS301LV;
      }
   }
 }
 
 /*********************************************/
-/*            HELPER: GetDRAMSize            */
-/*********************************************/
-
-#ifndef LINUX_XF86
-static ULONG
-GetDRAMSize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
-  ULONG   AdapterMemorySize = 0;
-#ifdef SIS315H
-  USHORT  counter;
-#endif
-
-  switch(HwInfo->jChipType) {
-#ifdef SIS315H
-  case SIS_315H:
-  case SIS_315:
-  case SIS_315PRO:
-    	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-	AdapterMemorySize = 1 << ((counter & 0xF0) >> 4);
-	counter >>= 2;
-	counter &= 0x03;
-	if(counter == 0x02) {
-		AdapterMemorySize += (AdapterMemorySize / 2);      /* DDR asymetric */
-	} else if(counter != 0) {
-		AdapterMemorySize <<= 1;                           /* SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK */
-	}
-	AdapterMemorySize *= (1024*1024);
-        break;
-
-  case SIS_330:
-    	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-	AdapterMemorySize = 1 << ((counter & 0xF0) >> 4);
-	counter &= 0x0c;
-	if(counter != 0) {
-		AdapterMemorySize <<= 1;
-	}
-	AdapterMemorySize *= (1024*1024);
-	break;
-
-  case SIS_550:
-  case SIS_650:
-  case SIS_740:
-  	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x3F;
-      	counter++;
-      	AdapterMemorySize = counter * 4;
-      	AdapterMemorySize *= (1024*1024);
-	break;
-
-  case SIS_661:
-  case SIS_741:
-  case SIS_660:
-  case SIS_760:
-        counter = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x79) & 0xf0) >> 4;
-	AdapterMemorySize = 1 << counter;
-      	AdapterMemorySize *= (1024*1024);
-        break;
-#endif
-
-#ifdef SIS300
-  case SIS_300:
-  case SIS_540:
-  case SIS_630:
-  case SIS_730:
-      	AdapterMemorySize = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x3F;
-      	AdapterMemorySize++;
-      	AdapterMemorySize *= (1024*1024);
-	break;
-#endif
-  default:
-        break;
-  }
-
-  return AdapterMemorySize;
-}
-#endif
-
-/*********************************************/
 /*           HELPER: Check RAM size          */
 /*********************************************/
 
@@ -1732,8 +1708,8 @@
 SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
                     USHORT ModeNo, USHORT ModeIdIndex)
 {
+  USHORT AdapterMemSize = HwInfo->ulVideoMemorySize / (1024*1024);
   USHORT memorysize,modeflag;
-  ULONG  temp;
 
   if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
@@ -1749,11 +1725,8 @@
   memorysize >>= MemorySizeShift;		/* Get required memory size */
   memorysize++;
 
-  temp = GetDRAMSize(SiS_Pr, HwInfo);       	/* Get adapter memory size (in MB) */
-  temp /= (1024*1024);
-
-  if(temp < memorysize) return(FALSE);
-  else return(TRUE);
+  if(AdapterMemSize < memorysize) return FALSE;
+  return TRUE;
 }
 #endif
 
@@ -1767,11 +1740,14 @@
 {
    UCHAR data, temp;
 
-   if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) {
-     data = *SiS_Pr->pSiS_SoftSetting & 0x03;
+   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
+     data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
    } else {
      if(HwInfo->jChipType >= SIS_661) {
         data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
+	if(SiS_Pr->SiS_ROMNew) {
+	   data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
+	}
      } else if(IS_SIS550650740) {
         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
      } else {	/* 315, 330 */
@@ -1798,10 +1774,14 @@
 USHORT
 SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
   USHORT index;
 
   index = SiS_Get310DRAMType(SiS_Pr, HwInfo);
   if(HwInfo->jChipType >= SIS_661) {
+     if(SiS_Pr->SiS_ROMNew) {
+        return((USHORT)(SISGETROMW((0x90 + (index * 5) + 3))));
+     }
      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
   } else if(index >= 4) {
      index -= 4;
@@ -1827,20 +1807,17 @@
 
   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
      if(ModeNo > 0x13) {
-        AdapterMemorySize = GetDRAMSize(SiS_Pr, HwInfo);
-        SiS_SetMemory(VideoMemoryAddress,AdapterMemorySize,0);
+        SiS_SetMemory(VideoMemoryAddress, AdapterMemorySize, 0);
      } else {
         pBuffer = (USHORT *)VideoMemoryAddress;
-        for(i=0; i<0x4000; i++)
-           pBuffer[i] = 0x0000;
+        for(i=0; i<0x4000; i++) pBuffer[i] = 0x0000;
      }
   } else {
-     pBuffer = (USHORT *)VideoMemoryAddress;
      if(SiS_Pr->SiS_ModeType < ModeCGA) {
-        for(i=0; i<0x4000; i++)
-           pBuffer[i] = 0x0720;
+        pBuffer = (USHORT *)VideoMemoryAddress;
+        for(i=0; i<0x4000; i++) pBuffer[i] = 0x0720;
      } else {
-        SiS_SetMemory(VideoMemoryAddress,0x8000,0);
+        SiS_SetMemory(VideoMemoryAddress, 0x8000, 0);
      }
   }
 }
@@ -1896,10 +1873,10 @@
    UCHAR index;
 
    if(ModeNo <= 0x13) {
-     	index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
+      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
    } else {
-     	if(SiS_Pr->SiS_ModeType <= 0x02) index = 0x1B;    /* 02 -> ModeEGA  */
-     	else index = 0x0F;
+      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;
+      else index = 0x0F;
    }
    return index;
 }
@@ -1914,7 +1891,7 @@
     USHORT temp,temp1,temp2;
 
     if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
-       return(1);
+       return(TRUE);
     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
     SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
     temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
@@ -1924,13 +1901,13 @@
     SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
     if((HwInfo->jChipType >= SIS_315H) ||
        (HwInfo->jChipType == SIS_300)) {
-       if(temp2 == 0x55) return(0);
-       else return(1);
+       if(temp2 == 0x55) return(FALSE);
+       else return(TRUE);
     } else {
-       if(temp2 != 0x55) return(1);
+       if(temp2 != 0x55) return(TRUE);
        else {
           SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
-          return(0);
+          return(FALSE);
        }
     }
 }
@@ -1944,6 +1921,43 @@
 }
 
 /*********************************************/
+/*            HELPER: ENABLE CRT1            */
+/*********************************************/
+
+static void
+SiS_SetupCR5x(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+      if(IS_SIS650) {
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+	 if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+      } else if(IS_SIS661741660760) {
+         SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+	 if(!SiS_Pr->SiS_ROMNew) {
+	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
+	 }
+      }
+   }
+}
+
+static void
+SiS_HandleCRT1(SiS_Private *SiS_Pr)
+{
+  SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
+#if 0
+  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
+     if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
+        (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
+        SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
+     }
+  }
+#endif
+}
+
+/*********************************************/
 /*           HELPER: GetColorDepth           */
 /*********************************************/
 
@@ -1977,28 +1991,22 @@
 SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
               USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
 {
-  USHORT temp,colordepth,infoflag;
+  USHORT xres, temp, colordepth, infoflag;
 
   if(SiS_Pr->UseCustomMode) {
      infoflag = SiS_Pr->CInfoFlag;
-     temp = SiS_Pr->CHDisplay / 16;
+     xres = SiS_Pr->CHDisplay;
   } else {
      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-     temp = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeOffset;
-     temp = SiS_Pr->SiS_ScreenOffset[temp];
+     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
   }
 
   colordepth = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex);
 
+  temp = xres / 16;
   if(infoflag & InterlaceMode) temp <<= 1;
-
   temp *= colordepth;
-
-  if( ( ((ModeNo >= 0x26) && (ModeNo <= 0x28)) ||
-        ModeNo == 0x3f ||
-	ModeNo == 0x42 ||
-	ModeNo == 0x45 ) ||
-      (SiS_Pr->UseCustomMode && (SiS_Pr->CHDisplay % 16)) ) {
+  if(xres % 16) {
      colordepth >>= 1;
      temp += colordepth;
   }
@@ -2103,9 +2111,15 @@
      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);                     /* Set CRTC(3d4) */
   }
-  if( ( (HwInfo->jChipType == SIS_630) ||
-        (HwInfo->jChipType == SIS_730) )  &&
-      (HwInfo->jChipRevision >= 0x30) ) {       	   /* for 630S0 */
+  if(HwInfo->jChipType >= SIS_661) {
+     SiS_SetupCR5x(SiS_Pr, HwInfo);
+     for(i = 0x13; i <= 0x14; i++) {
+        CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+        SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+     }
+  } else if( ( (HwInfo->jChipType == SIS_630) ||
+               (HwInfo->jChipType == SIS_730) )  &&
+             (HwInfo->jChipRevision >= 0x30) ) {       	   /* for 630S0 */
      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
            SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
@@ -2206,7 +2220,7 @@
 /*********************************************/
 
 static void
-SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 {
   USHORT i;
 
@@ -2216,6 +2230,11 @@
 
   if(HwInfo->jChipType >= SIS_315H) {
      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
+     if(ModeNo <= 0x13) {
+        if(ModeNo == 0x06 || ModeNo >= 0x0e) {
+	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
+	}
+     }
   }
 }
 
@@ -2279,45 +2298,6 @@
 /*                  CRTC/2                   */
 /*********************************************/
 
-#ifdef SIS315H
-static void
-SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-		   USHORT RefreshRateTableIndex, USHORT *ResIndex,
-		   USHORT *DisplayType)
- {
-  USHORT modeflag = 0;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     *ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     *ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-  }
-
-  *ResIndex &= 0x3F;
-
-  *DisplayType = SiS_Pr->SiS_LCDResInfo;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 32;
-  if(modeflag & HalfDCLK)                 *DisplayType += 16;
-
-  if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        *DisplayType = 100;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 2;
-        if(modeflag & HalfDCLK)                 *DisplayType += 1;
-     }
-  } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        *DisplayType = 104;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 2;
-        if(modeflag & HalfDCLK)                 *DisplayType += 1;
-     }
-  }
-
-}
-#endif
-
 static void
 SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                 USHORT RefreshRateTableIndex,
@@ -2325,10 +2305,6 @@
 {
   UCHAR  index;
   USHORT temp,i,j,modeflag;
-#ifdef SIS315H
-  USHORT ResIndex,DisplayType;
-  const SiS_LCDACRT1DataStruct *LCDACRT1Ptr = NULL;
-#endif
 
   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);		/* unlock cr0-7 */
 
@@ -2336,7 +2312,7 @@
 
      modeflag = SiS_Pr->CModeFlag;
 
-     for(i=0,j=0;i<=07;i++,j++) {
+     for(i=0,j=0;i<=7;i++,j++) {
         SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
      }
      for(j=0x10;i<=10;i++,j++) {
@@ -2354,7 +2330,7 @@
 
      temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
      if(modeflag & DoubleScanMode) temp |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
 
   } else {
 
@@ -2364,87 +2340,28 @@
         modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      }
 
-     if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+     index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 
-#ifdef SIS315H
-
-        SiS_GetLCDACRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, &ResIndex, &DisplayType);
-
-        switch(DisplayType) {
-        case Panel_1024x768      : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1;     break;
-        case Panel_1280x1024     : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1;    break;
-        case Panel_1400x1050     : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1;    break;
-        case Panel_1600x1200     : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1;    break;
-        case Panel_1024x768  + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1_H;   break;
-        case Panel_1280x1024 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1_H;  break;
-        case Panel_1400x1050 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1_H;  break;
-        case Panel_1600x1200 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1_H;  break;
-        case Panel_1024x768  + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2;     break;
-        case Panel_1280x1024 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2;    break;
-        case Panel_1400x1050 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2;    break;
-        case Panel_1600x1200 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2;    break;
-        case Panel_1024x768  + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2_H;   break;
-        case Panel_1280x1024 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H;  break;
-        case Panel_1400x1050 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2_H;  break;
-        case Panel_1600x1200 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2_H;  break;
-        case 100:	  	   LCDACRT1Ptr = Compaq1280x1024_LCDACRT1_1;         break;
-        case 101:		   LCDACRT1Ptr = Compaq1280x1024_LCDACRT1_1_H;       break;
-        case 102:		   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2;    break;
-        case 103:		   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H;  break;
-        case 104:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_1;           break;
-        case 105:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_1_H;         break;
-        case 106:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_2;           break;
-        case 107:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_2_H;         break;
-        default:                   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1;     break;
-        }
-
-        for(i=0, j=0; i<=0x07; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-        for(i=0x10, j=8; i<=0x12; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-        for(i=0x15, j=11; i<=0x16; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-        for(i=0x0A, j=13; i<=0x0C; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3c4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-
-        temp = (LCDACRT1Ptr+ResIndex)->CR[16] & 0xE0;
-        SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
-
-        temp = ((LCDACRT1Ptr+ResIndex)->CR[16] & 0x01) << 5;
-        if(modeflag & DoubleScanMode) temp |= 0x80;
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp);
-
-#endif
-
-     } else {
-
-        index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
-        for(i=0,j=0;i<=07;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
-        for(j=0x10;i<=10;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
-        for(j=0x15;i<=12;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
-        for(j=0x0A;i<=15;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
+     for(i=0,j=0;i<=7;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
+     for(j=0x10;i<=10;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
+     for(j=0x15;i<=12;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
+     for(j=0x0A;i<=15;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
 
-        temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
-        SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
+     temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
+     SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
 
-        temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
-        if(modeflag & DoubleScanMode)  temp |= 0x80;
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp);
+     temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
+     if(modeflag & DoubleScanMode)  temp |= 0x80;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
 
-     }
   }
 
   if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
@@ -2482,7 +2399,7 @@
 
    DisplayUnit <<= 5;
    temp = (DisplayUnit & 0xff00) >> 8;
-   if (DisplayUnit & 0xff) temp++;
+   if(DisplayUnit & 0xff) temp++;
    temp++;
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
 }
@@ -2917,7 +2834,8 @@
 {
   USHORT modeflag;
 
-  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);  /* disable auto-threshold */
+  /* disable auto-threshold */
+  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
 
   if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
@@ -2925,30 +2843,19 @@
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  if(HwInfo->jChipType >= SIS_661) {
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
-     if(ModeNo > 0x13) {
+  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
+  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+  if(ModeNo > 0x13) {
+     if(HwInfo->jChipType >= SIS_661) {
         if(!(modeflag & HalfDCLK)) {
 	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-	   if(ModeNo != 0x38) {
-	      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-	   }
+	   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
 	}
-     }
-  } else {
-     if(ModeNo > 0x13) {
-        if( (!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+     } else {
+        if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
            SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-        } else {
-           SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
-        }
-     } else {
-        SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+	}
      }
   }
 }
@@ -2963,33 +2870,29 @@
                  USHORT ModeNo, USHORT RefreshRateTableIndex,
                  USHORT ModeIdIndex)
 {
-  USHORT data, data2=0;
-  USHORT VCLK, index=0;
+  USHORT data=0, VCLK=0, index=0;
 
-  if(ModeNo <= 0x13) VCLK = 0;
-  else {
+  if(ModeNo > 0x13) {
      if(SiS_Pr->UseCustomMode) {
         VCLK = SiS_Pr->CSRClock;
      } else {
         index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,
-	               RefreshRateTableIndex,HwInfo);
+	                      RefreshRateTableIndex,HwInfo);
         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
      }
   }
 
-  if(HwInfo->jChipType < SIS_315H) {		/* 300 series */
+  if(HwInfo->jChipType < SIS_315H) {
 
-     data2 = 0x00;
-     if(VCLK > 150) data2 |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data2);
+     if(VCLK > 150) data |= 0x80;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
 
-     data2 = 0x00;
-     if(VCLK >= 150) data2 |= 0x08;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data2);
+     data = 0x00;
+     if(VCLK >= 150) data |= 0x08;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
 
-  } else { 					/* 315 series */
+  } else {
 
-     data = 0;
      if(VCLK >= 166) data |= 0x0c;
      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
 
@@ -2998,23 +2901,31 @@
      }
   }
 
-  data2 = 0x03;
-  if((VCLK >= 135) && (VCLK < 160))      data2 = 0x02;
-  else if((VCLK >= 160) && (VCLK < 260)) data2 = 0x01;
-  else if(VCLK >= 260)                   data2 = 0x00;
+  /* DAC speed */
+  if(HwInfo->jChipType >= SIS_661) {
 
-  if(HwInfo->jChipType == SIS_540) {
-     if((VCLK == 203) || (VCLK < 234)) data2 = 0x02;
-  }
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
 
-  if(HwInfo->jChipType < SIS_315H) {
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data2);  	/* DAC speed */
   } else {
-     if(HwInfo->jChipType > SIS_315PRO) {
-        /* This "if" is done in 330 and 650/LVDS/301LV BIOSes; Not in 315 BIOS */
-        if(ModeNo > 0x13) data2 &= 0xfc;
+
+     data = 0x03;
+     if((VCLK >= 135) && (VCLK < 160))      data = 0x02;
+     else if((VCLK >= 160) && (VCLK < 260)) data = 0x01;
+     else if(VCLK >= 260)                   data = 0x00;
+
+     if(HwInfo->jChipType == SIS_540) {
+        if((VCLK == 203) || (VCLK < 234))   data = 0x02;
+     }
+
+     if(HwInfo->jChipType < SIS_315H) {
+        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
+     } else {
+        if(HwInfo->jChipType > SIS_315PRO) {
+           if(ModeNo > 0x13) data &= 0xfc;
+        }
+        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
      }
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data2);  	/* DAC speed */
+
   }
 }
 
@@ -3022,75 +2933,51 @@
 SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
                     USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex)
 {
-  USHORT data,data2;
-  USHORT infoflag=0,modeflag;
+  USHORT data,infoflag=0,modeflag;
   USHORT resindex,xres;
 #ifdef SIS315H
-  USHORT data3;
+  USHORT data2,data3;
   ULONG  longdata;
-#if 0
-  resinfo = 0;
-#endif
+  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
 #endif
 
   if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
      infoflag = SiS_Pr->CInfoFlag;
+     xres = SiS_Pr->CHDisplay;
   } else {
+     resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
      if(ModeNo > 0x13) {
     	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
     	infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-#ifdef SIS315H
-#if 0
-	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-#endif
-#endif
+	xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
      } else {
     	modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+	xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
      }
   }
 
   /* Disable DPMS */
   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
 
-  if(ModeNo > 0x13) data = infoflag;
-  else data = 0;
-
-  data2 = 0;
+  data = 0;
   if(ModeNo > 0x13) {
-     if(SiS_Pr->SiS_ModeType > 0x02) {
-        data2 |= 0x02;
-        data2 |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
-     }
-  }
-
-#ifdef TWDEBUG
-  xf86DrvMsg(0, X_INFO, "Debug: Mode infoflag = %x, Chiptype %d\n",
-  	data, HwInfo->jChipType);
-#endif
-
-  if(data & InterlaceMode) data2 |= 0x20;
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data2);
-
-  if(SiS_Pr->UseCustomMode) {
-     xres = SiS_Pr->CHDisplay;
-  } else {
-     resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
-     if(ModeNo <= 0x13) {
-      	xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
-     } else {
-      	xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
+     if(SiS_Pr->SiS_ModeType > ModeEGA) {
+        data |= 0x02;
+        data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
      }
+     if(infoflag & InterlaceMode) data |= 0x20;
   }
+  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
 
   if(HwInfo->jChipType != SIS_300) {
-     data = 0x0000;
+     data = 0;
      if(infoflag & InterlaceMode) {
-        if(xres <= 800) data = 0x0020;
+        if(xres <= 800)       data = 0x0020;
         else if(xres <= 1024) data = 0x0035;
-        else data = 0x0048;
+        else                  data = 0x0048;
      }
-     SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0x00FF));
+     SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0xFF));
      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,(data >> 8));
   }
 
@@ -3098,18 +2985,12 @@
      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
   }
 
+  data = 0;
+  if(modeflag & LineCompareOff) data = 0x08;
   if(HwInfo->jChipType == SIS_300) {
-     if(modeflag & LineCompareOff) {
-        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x08);
-     } else {
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xF7);
-     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
   } else {
-     if(modeflag & LineCompareOff) {
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,0x08);
-     } else {
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xB7);
-     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
      if(SiS_Pr->SiS_ModeType == ModeEGA) {
         if(ModeNo > 0x13) {
   	   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x40);
@@ -3117,9 +2998,13 @@
      }
   }
 
+  if(HwInfo->jChipType >= SIS_661) {
+     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
+  }
+
 #ifdef SIS315H
-  /* 315 BIOS sets SR17 at this point */
   if(HwInfo->jChipType == SIS_315PRO) {
+
      data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
      data = SiS_Pr->SiS_SR15[2][data];
      if(SiS_Pr->SiS_ModeType == ModeText) {
@@ -3138,12 +3023,18 @@
 	}
      }
      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
-  }
 
-  /* 330 BIOS sets SR17 at this point */
-  if(HwInfo->jChipType == SIS_330) {
+  } else if( (HwInfo->jChipType == SIS_330) ||
+             ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760LFB))) {
+
      data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
-     data = SiS_Pr->SiS_SR15[2][data];
+     if(HwInfo->jChipType == SIS_330) {
+        data = SiS_Pr->SiS_SR15[2][data];
+     } else {
+        if(SiS_Pr->SiS_ROMNew) 	    data = ROMAddr[0xf6];
+        else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
+	else                        data = 0xba;
+     }
      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
         data &= 0xc7;
      } else {
@@ -3156,31 +3047,38 @@
 	}
 
 	data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1;
-	if(!data3) data3++;
-
-	data2 *= data3;
+	if(data3) data2 *= data3;
 
 	longdata = SiS_GetMCLK(SiS_Pr, HwInfo) * 1024;
 
 	data2 = longdata / data2;
 
-	if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
-           if(data2 >= 0x19c)      data = 0xba;
-	   else if(data2 >= 0x140) data = 0x7a;
-	   else if(data2 >= 0x101) data = 0x3a;
-	   else if(data2 >= 0xf5)  data = 0x32;
-	   else if(data2 >= 0xe2)  data = 0x2a;
-	   else if(data2 >= 0xc4)  data = 0x22;
-	   else if(data2 >= 0xac)  data = 0x1a;
-	   else if(data2 >= 0x9e)  data = 0x12;
-	   else if(data2 >= 0x8e)  data = 0x0a;
+	if(HwInfo->jChipType == SIS_330) {
+	   if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
+              if     (data2 >= 0x19c) data = 0xba;
+	      else if(data2 >= 0x140) data = 0x7a;
+	      else if(data2 >= 0x101) data = 0x3a;
+	      else if(data2 >= 0xf5)  data = 0x32;
+	      else if(data2 >= 0xe2)  data = 0x2a;
+	      else if(data2 >= 0xc4)  data = 0x22;
+	      else if(data2 >= 0xac)  data = 0x1a;
+	      else if(data2 >= 0x9e)  data = 0x12;
+	      else if(data2 >= 0x8e)  data = 0x0a;
+	      else                    data = 0x02;
+	   } else {
+	      if(data2 >= 0x127)      data = 0xba;
+	      else                    data = 0x7a;
+	   }
+	} else {  /* 760+LFB */
+	   if     (data2 >= 0x190) data = 0xba;
+	   else if(data2 >= 0xff)  data = 0x7a;
+	   else if(data2 >= 0xd3)  data = 0x3a;
+	   else if(data2 >= 0xa9)  data = 0x1a;
+	   else if(data2 >= 0x93)  data = 0x0a;
 	   else                    data = 0x02;
-	 } else {
-	   if(data2 >= 0x127)      data = 0xba;
-	   else                    data = 0x7a;
-	 }
-      }
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+	}
+     }
+     SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
   }
 #endif
 
@@ -3202,46 +3100,6 @@
      } else {
         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
      }
-#if 0   /* What is SR0E[D5:6]? */
-     if(HwInfo->jChipType >= SIS_661) {
-        data = 0;
-        if((ModeNo == 6) || ((ModeNo >= 0x0e) && (ModeNo <= 0x13))) {
-	   data |= 0x20;
-	}
-	if(SiS_Pr->SiS_ModeType != ModeVGA) {
-	   if(SiS_Pr->UseCustomMode) {
-              if((xres >= 640) && (SiS_Pr->CVDisplay >= 480)) {
-	         data |= 0x40;
-	      }
-	      if((xres > 1280) && (SiS_Pr->CVDisplay > 1024)) {
-	         data |= 0x60;
-	      }
-	   }
-	} else if(ModeNo > 0x13) {   /* These are in the CRT1 table, and set by CRT1CRTC */
-	   if(resinfo >= SIS_RI_640x480) {
-	      if(resinfo <= SIS_RI_2048x1536) {
-	         data |= 0x40;
-		 if(resinfo > SIS_RI_1280x1024) {
-		    data |= 0x60;
-		    if(resinfo != SIS_RI_1600x1200) {
-		       data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x0e);
-		       data += 0x60;
-		       SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e);
-		       data = 0;
-		    }
-		 }
-	      }
-	      if(resinfo == SIS_RI_1152x864) {
-		 data = 0x40;
-	      }
-	      if(resinfo == SIS_RI_1400x1050) { /* TW */
-		 data = 0x60;
-	      }
-	   }
-	}
-	SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0e,data);
-     }
-#endif
   }
 #endif
 }
@@ -3416,7 +3274,7 @@
   SiS_SetCRTCRegs(SiS_Pr, HwInfo, StandTableIndex);
   SiS_SetATTRegs(SiS_Pr, StandTableIndex, HwInfo);
   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
-  SiS_ClearExt1Regs(SiS_Pr,HwInfo);
+  SiS_ClearExt1Regs(SiS_Pr, HwInfo, ModeNo);
   SiS_ResetCRT1VCLK(SiS_Pr, HwInfo);
 
   SiS_Pr->SiS_SelectCRT2Rate = 0;
@@ -3482,21 +3340,28 @@
 }
 
 /*********************************************/
-/*            HELPER: ENABLE CRT1            */
+/*         HELPER: RESET VIDEO BRIDGE        */
 /*********************************************/
 
 static void
-SiS_HandleCRT1(SiS_Private *SiS_Pr)
+SiS_ResetVB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
-#if 0
-  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
-     if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
-        (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
-        SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
-     }
-  }
-#endif
+   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+   USHORT temp;
+
+   if(SiS_Pr->SiS_UseROM) {
+      if(HwInfo->jChipType < SIS_330) {
+         temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
+	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
+         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
+      } else if(HwInfo->jChipType >= SIS_661) {
+         temp = ROMAddr[0x7e];
+         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80];
+         if(HwInfo->jChipType >= SIS_660)                  temp |= 0x40;
+         else if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40;
+         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
+      }
+   }
 }
 
 /*********************************************/
@@ -3585,13 +3450,12 @@
 SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
 #endif
 {
-   ULONG   temp;
    USHORT  ModeIdIndex;
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
    SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
    unsigned char backupreg=0;
 #ifndef LINUX_XF86
    USHORT  KeepLockReg;
+   ULONG   temp;
 
    SiS_Pr->UseCustomMode = FALSE;
    SiS_Pr->CRT1UsesCustomMode = FALSE;
@@ -3605,7 +3469,7 @@
    SiSRegInit(SiS_Pr, BaseAddr);
    SiS_GetSysFlags(SiS_Pr, HwInfo);
 
-#ifdef LINUX_XF86
+#if defined(LINUX_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
    if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
    else
 #endif
@@ -3615,20 +3479,13 @@
    SiSSetLVDSetc(SiS_Pr, HwInfo);
    SiSDetermineROMUsage(SiS_Pr, HwInfo);
 
-   if(!SiS_Pr->UseCustomMode) {
-      ModeNo = ((ModeNo & 0x80) << 8) | (ModeNo & 0x7f);
-   }
+   SiS_Pr->SiS_flag_clearbuffer = 0;
 
-#ifdef LINUX_XF86
-   /* We never clear the buffer in X */
-   ModeNo |= 0x8000;
+   if(!SiS_Pr->UseCustomMode) {
+#ifndef LINUX_XF86
+      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
 #endif
-
-   if(ModeNo & 0x8000) {
-     	ModeNo &= 0x7fff;
-     	SiS_Pr->SiS_flag_clearbuffer = 0;
-   } else {
-     	SiS_Pr->SiS_flag_clearbuffer = 1;
+      ModeNo &= 0x7f;
    }
 
 #ifndef LINUX_XF86
@@ -3650,23 +3507,9 @@
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         SiS_UnLockCRT2(SiS_Pr,HwInfo);
-	 if(ROMAddr && SiS_Pr->SiS_UseROM) {
-	    if(HwInfo->jChipType < SIS_330) {
-               temp = ROMAddr[VB310Data_1_2_Offset];
-	       temp |= 0x40;
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-            }
-	    if(HwInfo->jChipType > SIS_330) {
-	       temp = ROMAddr[0x7e];
-	       if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40;
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-	    }
-	 }
+         SiS_ResetVB(SiS_Pr, HwInfo);
 	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
-
 	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
-
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       } else {
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
@@ -3687,27 +3530,7 @@
 #endif
 
    if(HwInfo->jChipType >= SIS_315H) {
-#if 0
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
-         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-            if(ModeNo != 0x10)  SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-            SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         }
-      }
-#endif
-
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-         if(IS_SIS650) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	 } else if(IS_SIS661741660760) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
-	 }
-      }
+      SiS_SetupCR5x(SiS_Pr, HwInfo);
    }
 
    if(SiS_Pr->UseCustomMode) {
@@ -3751,7 +3574,7 @@
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         if(HwInfo->jChipType < SIS_661) {
+         if(!SiS_Pr->SiS_ROMNew) {
 	    if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
 	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
 	    } else {
@@ -3840,9 +3663,7 @@
 SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
                DisplayModePtr mode, BOOLEAN IsCustom)
 {
-   ULONG   temp;
    USHORT  ModeIdIndex;
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
    SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
    UShort  ModeNo   = 0;
    unsigned char backupreg=0;
@@ -3879,7 +3700,11 @@
    SiSRegInit(SiS_Pr, BaseAddr);
    SiSInitPtr(SiS_Pr, HwInfo);
    SiS_GetSysFlags(SiS_Pr, HwInfo);
+#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
    SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
+#else
+   SiS_Pr->SiS_VGAINFO = 0x11;
+#endif
    SiSInitPCIetc(SiS_Pr, HwInfo);
    SiSSetLVDSetc(SiS_Pr, HwInfo);
    SiSDetermineROMUsage(SiS_Pr, HwInfo);
@@ -3941,23 +3766,9 @@
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         SiS_UnLockCRT2(SiS_Pr,HwInfo);
-         if(ROMAddr && SiS_Pr->SiS_UseROM) {
-	    if(HwInfo->jChipType < SIS_330) {
-               temp = ROMAddr[VB310Data_1_2_Offset];
-	       temp |= 0x40;
-               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-            }
-	    if(HwInfo->jChipType > SIS_330) {
-	       temp = ROMAddr[0x7e];
-	       if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40;
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-	    }
-	 }
+	 SiS_ResetVB(SiS_Pr, HwInfo);
 	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
-
 	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
-
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       } else {
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
@@ -3999,7 +3810,7 @@
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         if(HwInfo->jChipType < SIS_661) {
+         if(!SiS_Pr->SiS_ROMNew) {
 	    if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
 	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
 	    } else {
@@ -4069,7 +3880,11 @@
    SiSInitPtr(SiS_Pr, HwInfo);
    SiSRegInit(SiS_Pr, BaseAddr);
    SiS_GetSysFlags(SiS_Pr, HwInfo);
+#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
    SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
+#else
+   SiS_Pr->SiS_VGAINFO = 0x11;
+#endif
    SiSInitPCIetc(SiS_Pr, HwInfo);
    SiSSetLVDSetc(SiS_Pr, HwInfo);
    SiSDetermineROMUsage(SiS_Pr, HwInfo);
@@ -4107,27 +3922,7 @@
    SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
 
    if(HwInfo->jChipType >= SIS_315H) {
-#if 0
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
-         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-            if(ModeNo != 0x10)  SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-            SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         }
-      }
-#endif
-
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-         if(IS_SIS650) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	 } else if(IS_SIS661741660760) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
-	 }
-      }
+      SiS_SetupCR5x(SiS_Pr, HwInfo);
    }
 
    /* Set mode on CRT1 */
@@ -4296,12 +4091,188 @@
 }
 #endif
 
+#ifndef GETBITSTR
+#define BITMASK(h,l)    	(((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
+#define GENMASK(mask)   	BITMASK(1?mask,0?mask)
+#define GETBITS(var,mask)   	(((var) & GENMASK(mask)) >> (0?mask))
+#define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
+#endif
+
+static void
+SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth)
+{
+   SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;		/* CR0 */
+   SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;			/* CR1 */
+   SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;			/* CR2 */
+   SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;	/* CR3 */
+   SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;			/* CR4 */
+   SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |	/* CR5 */
+       			    (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
+
+   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal - 2) & 0xFF;			/* CR6 */
+   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal - 2) & 0x100) >> 8)		/* CR7 */
+ 	 		  | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
+	 		  | ((SiS_Pr->CVSyncStart & 0x100) >> 6)
+	 	  	  | (((SiS_Pr->CVBlankStart - 1) & 0x100) >> 5)
+			  | 0x10
+	 		  | (((SiS_Pr->CVTotal - 2) & 0x200)   >> 4)
+	 		  | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
+	 		  | ((SiS_Pr->CVSyncStart & 0x200) >> 2);
+
+   SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* CR9 */
+
+   if(depth != 8) {
+      if(SiS_Pr->CHDisplay >= 1600)      SiS_Pr->CCRT1CRTC[16] |= 0x60;		/* SRE */
+      else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;
+   }
+
+#if 0
+   if (mode->VScan >= 32)
+	regp->CRTC[9] |= 0x1F;
+   else if (mode->VScan > 1)
+	regp->CRTC[9] |= mode->VScan - 1;
+#endif
+
+   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart     ) & 0xFF;			/* CR10 */
+   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd      ) & 0x0F) | 0x80;		/* CR11 */
+   SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;			/* CR12 */
+   SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;			/* CR15 */
+   SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;			/* CR16 */
+
+   SiS_Pr->CCRT1CRTC[13] =							/* SRA */
+                        GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
+                        GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
+                        GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
+                        GETBITSTR((SiS_Pr->CVSyncStart   ), 10:10, 3:3) |
+                        GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
+                        GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
+
+   SiS_Pr->CCRT1CRTC[14] =							/* SRB */
+                        GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
+                        GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
+                        GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
+                        GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
+
+
+   SiS_Pr->CCRT1CRTC[15] =							/* SRC */
+                        GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
+                        GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
+}
+
+void
+SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
+{
+   USHORT modeflag, tempax, tempbx, VGAHDE = SiS_Pr->SiS_VGAHDE;
+   int i,j;
+
+   /* 1:1 data: use data set by setcrt1crtc() */
+   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
+
+   if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+   } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+   } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
+
+   if(modeflag & HalfDCLK) VGAHDE >>= 1;
+
+   SiS_Pr->CHDisplay = VGAHDE;
+   SiS_Pr->CHBlankStart = VGAHDE;
+
+   SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
+   SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
+
+   tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
+   tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax = SiS_Pr->PanelXRes;
+   }
+   tempbx += tempax;
+   if(modeflag & HalfDCLK) tempbx -= VGAHDE;
+   SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
+
+   tempax = VGAHDE;
+   tempbx = SiS_Pr->CHTotal;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempbx = SiS_Pr->PanelXRes;
+      if(modeflag & HalfDCLK) tempbx >>= 1;
+      tempax += ((tempbx - tempax) >> 1);
+   }
+
+   tempax += SiS_Pr->PanelHRS;
+   SiS_Pr->CHSyncStart = tempax;
+   tempax += SiS_Pr->PanelHRE;
+   SiS_Pr->CHSyncEnd = tempax;
+
+   tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
+   tempax = SiS_Pr->SiS_VGAVDE;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax = SiS_Pr->PanelYRes;
+   }
+   SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
+
+   tempax = SiS_Pr->SiS_VGAVDE;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax += (SiS_Pr->PanelYRes - tempax) >> 1;
+   }
+   tempax += SiS_Pr->PanelVRS;
+   SiS_Pr->CVSyncStart = tempax;
+   tempax += SiS_Pr->PanelVRE;
+   SiS_Pr->CVSyncEnd = tempax;
+
+   SiS_CalcCRRegisters(SiS_Pr, 8);
+   SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
+
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+   for(i=0,j=0;i<=7;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j=0x10;i<=10;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j=0x15;i<=12;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j=0x0A;i<=15;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+
+   tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);
+
+   tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
+   if(modeflag & DoubleScanMode) tempax |= 0x80;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
+
+#ifdef TWDEBUG
+   xf86DrvMsg(0, X_INFO, "%d %d %d %d  %d %d %d %d  (%d %d %d %d)\n",
+       	SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
+	SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
+	SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
+
+   xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+   	SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
+	SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
+	SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
+	SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
+   xf86DrvMsg(0, X_INFO, "   0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+   	SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
+	SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
+	SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
+	SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
+   xf86DrvMsg(0, X_INFO, "   0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
+#endif
+}
 
 /* ================ XFREE86 ================= */
 
 /* Helper functions */
 
 #ifdef LINUX_XF86
+
 USHORT
 SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags)
 {
@@ -4382,73 +4353,16 @@
 
    pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1;
 
-   pSiS->SiS_Pr->CCRT1CRTC[0]  =  ((pSiS->SiS_Pr->CHTotal >> 3) - 5) & 0xff;
-   pSiS->SiS_Pr->CCRT1CRTC[1]  =  (pSiS->SiS_Pr->CHDisplay >> 3) - 1;
-   pSiS->SiS_Pr->CCRT1CRTC[2]  =  (pSiS->SiS_Pr->CHBlankStart >> 3) - 1;
-   pSiS->SiS_Pr->CCRT1CRTC[3]  =  (((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
-   pSiS->SiS_Pr->CCRT1CRTC[4]  =  (pSiS->SiS_Pr->CHSyncStart >> 3) + 3;
-   pSiS->SiS_Pr->CCRT1CRTC[5]  =  ((((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |
-       				  (((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
-
-   pSiS->SiS_Pr->CCRT1CRTC[6]  =  (pSiS->SiS_Pr->CVTotal - 2) & 0xFF;
-   pSiS->SiS_Pr->CCRT1CRTC[7]  =  (((pSiS->SiS_Pr->CVTotal - 2) & 0x100) >> 8)
- 	 			| (((pSiS->SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
-	 			| ((pSiS->SiS_Pr->CVSyncStart & 0x100) >> 6)
-	 			| (((pSiS->SiS_Pr->CVBlankStart - 1) & 0x100) >> 5)
-	 			| 0x10
-	 			| (((pSiS->SiS_Pr->CVTotal - 2) & 0x200)   >> 4)
-	 			| (((pSiS->SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
-	 			| ((pSiS->SiS_Pr->CVSyncStart & 0x200) >> 2);
-
-   pSiS->SiS_Pr->CCRT1CRTC[16] = ((((pSiS->SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* cr9 */
-
-#if 0
-   if (mode->VScan >= 32)
-	regp->CRTC[9] |= 0x1F;
-   else if (mode->VScan > 1)
-	regp->CRTC[9] |= mode->VScan - 1;
-#endif
-
-   pSiS->SiS_Pr->CCRT1CRTC[8] =  (pSiS->SiS_Pr->CVSyncStart     ) & 0xFF;		/* cr10 */
-   pSiS->SiS_Pr->CCRT1CRTC[9] =  ((pSiS->SiS_Pr->CVSyncEnd      ) & 0x0F) | 0x80;	/* cr11 */
-   pSiS->SiS_Pr->CCRT1CRTC[10] = (pSiS->SiS_Pr->CVDisplay    - 1) & 0xFF;		/* cr12 */
-   pSiS->SiS_Pr->CCRT1CRTC[11] = (pSiS->SiS_Pr->CVBlankStart - 1) & 0xFF;		/* cr15 */
-   pSiS->SiS_Pr->CCRT1CRTC[12] = (pSiS->SiS_Pr->CVBlankEnd   - 1) & 0xFF;		/* cr16 */
-
-   pSiS->SiS_Pr->CCRT1CRTC[13] =
-                        GETBITSTR((pSiS->SiS_Pr->CVTotal     -2), 10:10, 0:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
-                        GETBITSTR((pSiS->SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
-                        GETBITSTR((pSiS->SiS_Pr->CVSyncStart   ), 10:10, 3:3) |
-                        GETBITSTR((pSiS->SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
-                        GETBITSTR((pSiS->SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
-
-   pSiS->SiS_Pr->CCRT1CRTC[14] =
-                        GETBITSTR((pSiS->SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
-                        GETBITSTR((pSiS->SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
-                        GETBITSTR((pSiS->SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
-
-
-   pSiS->SiS_Pr->CCRT1CRTC[15] =
-                        GETBITSTR((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
+   SiS_CalcCRRegisters(pSiS->SiS_Pr, depth);
 
    switch(depth) {
-   case 8:
-      	pSiS->SiS_Pr->CModeFlag |= 0x223b;
-	break;
-   case 16:
-      	pSiS->SiS_Pr->CModeFlag |= 0x227d;
-	break;
-   case 32:
-      	pSiS->SiS_Pr->CModeFlag |= 0x22ff;
-	break;		
-   default: 
-   	return 0;	
-   }	
-   
-   if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) 
+   case 8:  pSiS->SiS_Pr->CModeFlag |= 0x223b; break;
+   case 16: pSiS->SiS_Pr->CModeFlag |= 0x227d; break;
+   case 32: pSiS->SiS_Pr->CModeFlag |= 0x22ff; break;
+   default: return 0;
+   }
+
+   if(pSiS->SiS_Pr->CFlags & V_DBLSCAN)
       pSiS->SiS_Pr->CModeFlag |= DoubleScanMode;
 
    if((pSiS->SiS_Pr->CVDisplay >= 1024)	||
@@ -4472,33 +4386,23 @@
 
    pSiS->SiS_Pr->UseCustomMode = TRUE;
 #ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n", 
+   xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n",
    	pSiS->SiS_Pr->CHDisplay,pSiS->SiS_Pr->CVDisplay);
    xf86DrvMsg(0, X_INFO, "Modeflag %04x, Infoflag %04x\n",
    	pSiS->SiS_Pr->CModeFlag, pSiS->SiS_Pr->CInfoFlag);
    xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-   	pSiS->SiS_Pr->CCRT1CRTC[0],
-	pSiS->SiS_Pr->CCRT1CRTC[1],
-	pSiS->SiS_Pr->CCRT1CRTC[2],
-	pSiS->SiS_Pr->CCRT1CRTC[3],
-	pSiS->SiS_Pr->CCRT1CRTC[4],
-	pSiS->SiS_Pr->CCRT1CRTC[5],
-	pSiS->SiS_Pr->CCRT1CRTC[6],
-	pSiS->SiS_Pr->CCRT1CRTC[7]);
+   	pSiS->SiS_Pr->CCRT1CRTC[0], pSiS->SiS_Pr->CCRT1CRTC[1],
+	pSiS->SiS_Pr->CCRT1CRTC[2], pSiS->SiS_Pr->CCRT1CRTC[3],
+	pSiS->SiS_Pr->CCRT1CRTC[4], pSiS->SiS_Pr->CCRT1CRTC[5],
+	pSiS->SiS_Pr->CCRT1CRTC[6], pSiS->SiS_Pr->CCRT1CRTC[7]);
    xf86DrvMsg(0, X_INFO, "  0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-   	pSiS->SiS_Pr->CCRT1CRTC[8],
-	pSiS->SiS_Pr->CCRT1CRTC[9],
-	pSiS->SiS_Pr->CCRT1CRTC[10],
-	pSiS->SiS_Pr->CCRT1CRTC[11],
-	pSiS->SiS_Pr->CCRT1CRTC[12],
-	pSiS->SiS_Pr->CCRT1CRTC[13],
-	pSiS->SiS_Pr->CCRT1CRTC[14],
-	pSiS->SiS_Pr->CCRT1CRTC[15]);
+   	pSiS->SiS_Pr->CCRT1CRTC[8], pSiS->SiS_Pr->CCRT1CRTC[9],
+	pSiS->SiS_Pr->CCRT1CRTC[10], pSiS->SiS_Pr->CCRT1CRTC[11],
+	pSiS->SiS_Pr->CCRT1CRTC[12], pSiS->SiS_Pr->CCRT1CRTC[13],
+	pSiS->SiS_Pr->CCRT1CRTC[14], pSiS->SiS_Pr->CCRT1CRTC[15]);
    xf86DrvMsg(0, X_INFO, "  0x%02x}},\n", pSiS->SiS_Pr->CCRT1CRTC[16]);
    xf86DrvMsg(0, X_INFO, "Clock: 0x%02x, 0x%02x, %d\n",
-   	pSiS->SiS_Pr->CSR2B,
-	pSiS->SiS_Pr->CSR2C,
-	pSiS->SiS_Pr->CSRClock);
+   	pSiS->SiS_Pr->CSR2B, pSiS->SiS_Pr->CSR2C, pSiS->SiS_Pr->CSRClock);
 #endif
    return 1;
 }
@@ -4615,7 +4519,7 @@
       /* Horizontal display enable end */
       HDE = (cr_data & 0xff) |
             ((unsigned short) (sr_data & 0x0C) << 6);
-      E = HDE + 1;
+      E = HDE + 1;  /* 0x80 0x64 */
 
       cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[4];
 	/* inSISIDXREG(SISCR, 0x04, cr_data); */
@@ -4623,7 +4527,7 @@
       /* Horizontal retrace (=sync) start */
       HRS = (cr_data & 0xff) |
             ((unsigned short) (sr_data & 0xC0) << 2);
-      F = HRS - E - 3;
+      F = HRS - E - 3;  /* 0x06 0x06 */
 
       cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[2];
 	/* inSISIDXREG(SISCR, 0x02, cr_data); */
@@ -4653,7 +4557,7 @@
       B = (temp > 0) ? temp : (temp + 256);
 
       temp = HRE - ((E + F + 3) & 63);
-      C = (temp > 0) ? temp : (temp + 64);
+      C = (temp > 0) ? temp : (temp + 64); /* 0x0b 0x0b */
 
       D = B - F - C;
 
@@ -5159,10 +5063,7 @@
 int
 sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 			 unsigned char modeno, unsigned char rateindex,
-			 ULONG *left_margin, ULONG *right_margin, 
-			 ULONG *upper_margin, ULONG *lower_margin,
-			 ULONG *hsync_len, ULONG *vsync_len,
-			 ULONG *sync, ULONG *vmode)
+			 struct fb_var_screeninfo *var)
 {
     USHORT ModeNo = modeno;
     USHORT ModeIdIndex = 0, index = 0;
@@ -5185,7 +5086,7 @@
        return 0;
 #endif
     }
-    
+
     if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
 
     RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
@@ -5250,15 +5151,15 @@
 	 /* Terrible hack, but the correct CRTC data for
 	  * these modes only produces a black screen...
 	  */
-       *left_margin = (400 - 376);
-       *right_margin = (328 - 320);
-       *hsync_len = (376 - 328);
+       var->left_margin = (400 - 376);
+       var->right_margin = (328 - 320);
+       var->hsync_len = (376 - 328);
 
     } else {
 
-       *left_margin = D * 8;
-       *right_margin = F * 8;
-       *hsync_len = C * 8;
+       var->left_margin = D * 8;
+       var->right_margin = F * 8;
+       var->hsync_len = C * 8;
 
     }
 
@@ -5320,47 +5221,47 @@
 
     D = B - F - C;
       
-    *upper_margin = D;
-    *lower_margin = F;
-    *vsync_len = C;
+    var->upper_margin = D;
+    var->lower_margin = F;
+    var->vsync_len = C;
 
     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
-       *sync &= ~FB_SYNC_VERT_HIGH_ACT;
+       var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
     else
-       *sync |= FB_SYNC_VERT_HIGH_ACT;
+       var->sync |= FB_SYNC_VERT_HIGH_ACT;
 
     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)       
-       *sync &= ~FB_SYNC_HOR_HIGH_ACT;
+       var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
     else
-       *sync |= FB_SYNC_HOR_HIGH_ACT;
+       var->sync |= FB_SYNC_HOR_HIGH_ACT;
 		
-    *vmode = FB_VMODE_NONINTERLACED;
+    var->vmode = FB_VMODE_NONINTERLACED;
     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
-       *vmode = FB_VMODE_INTERLACED;
+       var->vmode = FB_VMODE_INTERLACED;
     else {
-      j = 0;
-      while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
+       j = 0;
+       while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
           if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
 	                  SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID) {
               if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
-	      	  *vmode = FB_VMODE_DOUBLE;
+	      	  var->vmode = FB_VMODE_DOUBLE;
               }
 	      break;
           }
 	  j++;
-      }
+       }
     }       
 
-    if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+    if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
 #if 0  /* Do this? */
-       *upper_margin <<= 1;
-       *lower_margin <<= 1;
-       *vsync_len <<= 1;
-#endif
-    } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-       *upper_margin >>= 1;
-       *lower_margin >>= 1;
-       *vsync_len >>= 1;
+       var->upper_margin <<= 1;
+       var->lower_margin <<= 1;
+       var->vsync_len <<= 1;
+#endif
+    } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+       var->upper_margin >>= 1;
+       var->lower_margin >>= 1;
+       var->vsync_len >>= 1;
     }
 
     return 1;       
diff -Nru a/drivers/video/sis/init.h b/drivers/video/sis/init.h
--- a/drivers/video/sis/init.h	2004-06-23 19:04:28 -07:00
+++ b/drivers/video/sis/init.h	2004-06-23 19:04:28 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Data and prototypes for init.c
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -101,6 +99,7 @@
 const USHORT  ModeIndex_800x600[]      = {0x30, 0x47, 0x00, 0x63};
 const USHORT  ModeIndex_848x480[]      = {0x39, 0x3b, 0x00, 0x3e};
 const USHORT  ModeIndex_856x480[]      = {0x3f, 0x42, 0x00, 0x45};
+const USHORT  ModeIndex_960x540[]      = {0x1d, 0x1e, 0x00, 0x1f};  /* 315 series only */
 const USHORT  ModeIndex_1024x768[]     = {0x38, 0x4a, 0x00, 0x64};
 const USHORT  ModeIndex_1024x576[]     = {0x71, 0x74, 0x00, 0x77};
 const USHORT  ModeIndex_1024x600[]     = {0x20, 0x21, 0x00, 0x22};  /* 300 series only */
@@ -111,10 +110,13 @@
 const USHORT  ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
 const USHORT  ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
 const USHORT  ModeIndex_1280x720[]     = {0x79, 0x75, 0x00, 0x78};
+const USHORT  ModeIndex_1280x800[]     = {0x14, 0x15, 0x00, 0x16};
 const USHORT  ModeIndex_1360x768[]     = {0x48, 0x4b, 0x00, 0x4e};
 const USHORT  ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72};  /* 300 series, BARCO only */
 const USHORT  ModeIndex_1400x1050[]    = {0x26, 0x27, 0x00, 0x28};  /* 315 series only */
+const USHORT  ModeIndex_1680x1050[]    = {0x17, 0x18, 0x00, 0x19};  /* 315 series only */
 const USHORT  ModeIndex_1600x1200[]    = {0x3c, 0x3d, 0x00, 0x66};
+const USHORT  ModeIndex_1920x1080[]    = {0x2c, 0x2d, 0x00, 0x73};  /* 315 series only */
 const USHORT  ModeIndex_1920x1440[]    = {0x68, 0x69, 0x00, 0x6b};
 const USHORT  ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
 const USHORT  ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
@@ -253,9 +255,14 @@
 	{ 1024, 600, 8,16},   /* 0x19 */
 	{ 1152, 768, 8,16},   /* 0x1a */
 	{  768, 576, 8,16},   /* 0x1b */
-	{ 1360,1024, 8,16}    /* 0x1c */
+	{ 1360,1024, 8,16},   /* 0x1c */
+	{ 1680,1050, 8,16},   /* 0x1d */
+	{ 1280, 800, 8,16},   /* 0x1e */
+	{ 1920,1080, 8,16},   /* 0x1f */
+	{  960, 540, 8,16}    /* 0x20 */
 };
 
+#if defined(SIS300) || defined(SIS315H)
 static SiS_StandTableStruct SiS_StandTable[]=
 {
 /* 0x00: MD_0_200 */
@@ -694,6 +701,7 @@
    0xff}
  }
 };
+#endif
 
 /**************************************************************/
 /* SIS VIDEO BRIDGE ----------------------------------------- */
@@ -839,7 +847,8 @@
  {   36,  25,1060, 648,1270, 530, 438,   0, 438,0xeb,0x05,0x25,0x16},  /* 800x600, 400x300 - better */
  {    3,   2,1080, 619,1270, 540, 438,   0, 438,0xf3,0x00,0x1d,0x20},  /* 720x576 */
  {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20},  /* 1024x768 */
- {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20}   /* 1024x768 (for NTSC equ) */
+ {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20},  /* 1024x768 (for NTSC equ) */
+ {    9,   4, 848, 528,1270, 530,   0,   0,  50,0xf5,0xfb,0x1b,0x2a}   /* 720x480 test */
 };
 
 static const SiS_TVDataStruct  SiS_StNTSCData[] =
@@ -921,6 +930,22 @@
 
 static const SiS_TVDataStruct  SiS_Ext750pData[] =
 {
+#if 1
+ {  143,  65, 0x35a,0x1bb,0x4f6,0x1b8,0x0ab,  0, 0x0ab, 0x00,0x00,0x00,0x00},
+ {   88,  35, 0x35a,0x189,0x4f6,0x1b8,0x0ab,  0, 0x0ab, 0x00,0x00,0x00,0x00},
+ {   18,   5, 0x339,0x1ae,0x500,0x2d0,0x05c,  0, 0x05c, 0x00,0x00,0x00,0x00},
+ {  143,  70, 0x39c,0x189,0x4f6,0x1b8,0x05c,  0, 0x05c, 0x00,0x00,0x00,0x00},
+ {   99,  32, 0x320,0x1fe,0x500,0x2d0,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 640x480  */
+ {    5,   4, 0x5d8,0x29e,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600  */
+#if 0
+ {    2,   1, 0x35a,0x1f7,0x4f6,0x1e0,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x480  */
+#endif
+ {   99,  32, 0x320,0x1fe,0x500,0x2d0,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 720x480 test WORKS */
+ {   68,  64, 0x55f,0x346,0x500,0x2a8,0x27e,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768 */
+ {    5,   2, 0x3a7,0x226,0x500,0x2a8,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x576  */
+ {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00}   /* 1280x720 WORKS */
+#endif
+#if 0
  {    3,   1, 0x3a7,0x1d6,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},
  {   24,   7, 0x3a7,0x1a4,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},
  {    3,   1, 0x3a7,0x1d6,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},
@@ -929,63 +954,105 @@
  {    5,   4, 0x5d8,0x29e,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600   */
  {    2,   1, 0x35a,0x1f7,0x4f6,0x1e0,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x480   */
  {   68,  64, 0x55f,0x346,0x500,0x2a8,0x27e,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768  */
+ {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00}   /* 1280x720  */
+#endif
+#if 0
+ {  136,  35, 0x339,0x181,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* TEST (0.93) BAD */
+ {   17,   6, 0x339,0x203,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00},
+ {  136,  35, 0x339,0x181,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00},
+ {   17,   6, 0x339,0x203,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00},
+ {   85,  46, 0x3f4,0x27b,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 640x480   */
+ {   17,  16, 0x55f,0x323,0x460,0x2a8,0x2b6,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600   */
+ {  136,  35, 0x339,0x181,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 720x480   */
+ {  187,  74, 0x39d,0x203,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768  */
+ {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00}   /* 1280x720  */
+#endif
 };
 
-static const SiS_LCDDataStruct  SiS_LCD1280x960Data[] =
+static const SiS_LCDDataStruct  SiS_LCD1280x720Data[] =
 {
-	{    9,   2, 800, 500,1800,1000},
-	{    9,   2, 800, 500,1800,1000},
-	{    4,   1, 900, 500,1800,1000},
-	{    4,   1, 900, 500,1800,1000},
-	{    9,   2, 800, 500,1800,1000},
-	{   30,  11,1056, 625,1800,1000},
-	{    5,   3,1350, 800,1800,1000},
-	{    1,   1,1576,1050,1576,1050},
-	{    1,   1,1800,1000,1800,1000}
-};
-
-/* 1280x768 panel data from Fujitsu 7911 (VL-17WDX8).
- * Other 1280x768 panels (with clock != 81000, HTxVT != 1688x802)
- * will be treated as custom panels.
+	{  14,    5,  864,  432, 1344,  806 }, /* 640x400 */
+	{  16,    5,  864,  378, 1344,  806 },
+	{  14,    5,  864,  432, 1344,  806 },
+	{  16,    5,  864,  378, 1344,  806 },
+	{  24,   11,  924,  523, 1344,  806 }, /* 640x480 */
+	{   7,    5, 1152,  664, 1344,  806 }, /* 800x600 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1344,  806, 1344,  806 }  /* 1280x720 */
+};
+
+/* About 1280x768: For TMDS, Panel_1280x768 will only be set if
+ * the panel is a Fujitsu 7911 (VL-17WDX8) (with clock 81, 1688x802)
+ * Other TMDS panels of this resolution will be treated as custom.
+ * For LVDS, we know two types. Data follows:
  */
 
-static const SiS_LCDDataStruct  SiS_StLCD1280x768Data[] =
+static const SiS_LCDDataStruct  SiS_StLCD1280x768_2Data[] =
 {
-	{ 211,  100, 2100,  408, 1688,  802 }, /* These values are *wrong* */
-	{ 211,   64, 1536,  358, 1688,  802 }, /* (which is why they aren't used yet) */
-	{ 211,  100, 2100,  408, 1688,  802 },
-	{ 211,   64, 1536,  358, 1688,  802 },
-	{ 211,   48,  840,  488, 1688,  802 },
-	{ 211,   72, 1008,  609, 1688,  802 },
-	{ 211,  128, 1400,  776, 1688,  802 },
-	{ 211,  205, 1680, 1041, 1688,  802 },
-	{ 1,      1, 1688,  802, 1688,  802 }  /* That's the only one that is correct */
-};
-
-static const SiS_LCDDataStruct  SiS_ExtLCD1280x768Data[] =
-{
-	{ 211,  100, 2100,  408, 1688,  802 }, /* These values are *wrong* */
-	{ 211,   64, 1536,  358, 1688,  802 }, /* (which is why they aren't used yet) */
-	{ 211,  100, 2100,  408, 1688,  802 },
-	{ 211,   64, 1536,  358, 1688,  802 },
-	{ 211,   48,  840,  488, 1688,  802 },
-	{ 211,   72, 1008,  609, 1688,  802 },
-	{ 211,  128, 1400,  776, 1688,  802 },
-	{ 211,  205, 1680, 1041, 1688,  802 },
-	{ 1,      1, 1688,  802, 1688,  802 }  /* That's the only one that is correct */
-};
-
-static const SiS_LCDDataStruct  SiS_NoScaleData1280x768[] =
-{
-        { 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802}
+	{  64,   21,  858,  434, 1408,  806 }, /* 640x400 */
+	{  32,    9,  858,  372, 1408,  806 },
+	{  64,   21,  858,  434, 1408,  806 },
+	{  32,    9,  858,  372, 1408,  806 },
+	{ 143,   68, 1024,  527, 1408,  806 }, /* 640x480 */
+	{  64,   51, 1364,  663, 1408,  806 }, /* 800x600 */
+	{  88,   81, 1296,  806, 1408,  806 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }  /* 1280x768 */
+};
+
+static const SiS_LCDDataStruct  SiS_ExtLCD1280x768_2Data[] =
+{
+	{  64,   25, 1056,  422, 1408,  806 }, /*, 664 */
+	{ 128,   39,  884,  396, 1408,  806 }, /*, 640 */
+	{  64,   25, 1056,  422, 1408,  806 }, /*, 664 */
+	{ 128,   39,  884,  396, 1408,  806 }, /*, 640 */
+	{  32,   15, 1056,  513, 1408,  806 }, /*, 664 */
+	{ 176,  125, 1280,  640, 1408,  806 }, /*, 768 */
+	{  88,   81, 1296,  806, 1408,  806 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1280x768_3Data[] =
+{
+	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
+	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
+	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
+	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
+	{  32,   15, 1056,  513, 1408,  806 }, /* ,664 */	/* 640x480 */
+	{ 176,  125, 1280,  640, 1408,  806 }, /* ,768 */	/* 800x600 */
+	{  64,   61, 1342,  806, 1408,  806 },			/* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }			/* 1280x768 */
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1280x800Data[] =
+{
+	{ 128,   51, 1122,  412, 1408,  816 }, /* 640x400 */
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{ 128,   51, 1122,  412, 1408,  816 },
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{   8,    3,  880,  491, 1408,  816 }, /* 640x480 */
+	{  11,    6, 1024,  612, 1408,  816 }, /* 800x600 */
+	{  22,   21, 1400,  784, 1408,  816 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  816, 1408,  816 }  /* 1280x800 */
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1280x960Data[] =
+{
+	{    9,   2,  800,  500, 1800, 1000 },
+	{    9,   2,  800,  500, 1800, 1000 },
+	{    4,   1,  900,  500, 1800, 1000 },
+	{    4,   1,  900,  500, 1800, 1000 },
+	{    9,   2,  800,  500, 1800, 1000 },
+	{   30,  11, 1056,  625, 1800, 1000 },
+	{    5,   3, 1350,  800, 1800, 1000 },
+	{    1,   1, 1576, 1050, 1576, 1050 },
+	{    1,   1, 1800, 1000, 1800, 1000 }
 };
 
 static const SiS_LCDDataStruct  SiS_StLCD1400x1050Data[] =
@@ -1003,28 +1070,37 @@
 
 static const SiS_LCDDataStruct  SiS_ExtLCD1400x1050Data[] =
 {
-	{ 211,  100, 2100,  408, 1688, 1066 },
+/*	{ 211,   60, 1260,  410, 1688, 1066 },    640x400 (6330) */
+	{ 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 (6325) WORKS */
 	{ 211,   64, 1536,  358, 1688, 1066 },
 	{ 211,  100, 2100,  408, 1688, 1066 },
 	{ 211,   64, 1536,  358, 1688, 1066 },
-	{ 211,   48,  840,  488, 1688, 1066 },
-	{ 211,   72, 1008,  609, 1688, 1066 },
-	{ 211,  128, 1400,  776, 1688, 1066 },
-	{ 211,  205, 1680, 1041, 1688, 1066 },
-	{   1,    1, 1688, 1066, 1688, 1066 }
-};
-
-static const SiS_LCDDataStruct  SiS_NoScaleData1400x1050[] =
-{
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 }
+/*	{ 211,   80, 1400,  490, 1688, 1066 },    640x480 (6330) */
+	{ 211,   48,  840,  488, 1688, 1066 }, /* 640x480 (6325) WORKS */
+/*	{ 211,  117, 1638,  613, 1688, 1066 },    800x600 (6330) */
+	{ 211,   72, 1008,  609, 1688, 1066 }, /* 800x600 (6325) WORKS */
+	{ 211,  128, 1400,  776, 1688, 1066 }, /* 1024x768 */
+	{ 211,  205, 1680, 1041, 1688, 1066 }, /* 1280x1024 - not used (always unscaled) */
+	{   1,    1, 1688, 1066, 1688, 1066 }, /* 1400x1050 */
+	{   0,    0,    0,    0,    0,    0 }, /* kludge */
+	{ 211,  120, 1400,  730, 1688, 1066 }  /* 1280x720 */
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1680x1050Data[] =
+{
+	{  95,   24, 1260,  410, 1900, 1066 }, /*  0 640x400 */
+	{  10,    3, 1710,  362, 1900, 1066 },
+	{  95,   24, 1260,  410, 1900, 1066 },
+	{  10,    3, 1710,  362, 1900, 1066 },
+	{  95,   32, 1400,  490, 1900, 1066 }, /*  4 640x480 */
+	{  95,   42, 1470,  610, 1900, 1066 }, /*  5 800x600 */
+	{  95,   64, 1750,  784, 1900, 1066 }, /*  6 1024x768 */
+	{  95,   94, 1900, 1055, 1900, 1066 }, /*  7 1280x1024 */
+	{  41,   31, 1900,  806, 1900, 1066 }, /*  8 1280x768 */
+	{  95,   69, 1800,  817, 1900, 1066 }, /*  9 1280x800 patch */
+	{  13,    9, 1900,  739, 1900, 1066 }, /* 10 1280x720 */
+	{  95,   94, 1880, 1066, 1900, 1066 }, /* 11 1400x1050 patch */
+	{   1,    1, 1900, 1066, 1900, 1066 }  /* 12 1680x1050 */
 };
 
 static const SiS_LCDDataStruct  SiS_StLCD1600x1200Data[] =
@@ -1037,440 +1113,59 @@
 	{ 4,  1,1080, 625, 2160, 1250 },
 	{ 5,  2,1350, 800, 2160, 1250 },
 	{135,88,1600,1100, 2160, 1250 },
-	{135,88,1600,1100, 2160, 1250 },
+	{72, 49,1680,1092, 2160, 1250 },
 	{ 1,  1,2160,1250, 2160, 1250 }
 };
 
 static const SiS_LCDDataStruct  SiS_ExtLCD1600x1200Data[] =
 {
-	{27, 4, 800, 500, 2160, 1250 },
+	{72,11, 990, 422, 2160, 1250 }, /* 640x400 (6330) WORKS */
+/*	{27, 4, 800, 500, 2160, 1250 },    640x400 (6235) */
 	{27, 4, 800, 500, 2160, 1250 },
 	{ 6, 1, 900, 500, 2160, 1250 },
 	{ 6, 1, 900, 500, 2160, 1250 },
-	{27, 1, 800, 500, 2160, 1250 },
+	{45, 8, 960, 505, 2160, 1250 }, /* 640x480 (6330) WORKS */
+/*	{27, 1, 800, 500, 2160, 1250 },    640x480 (6325) */
 	{ 4, 1,1080, 625, 2160, 1250 },
 	{ 5, 2,1350, 800, 2160, 1250 },
-	{27,16,1500,1064, 2160, 1250 },
-	{27,16,1500,1064, 2160, 1250 },
+	{27,16,1500,1064, 2160, 1250 }, /* 1280x1024 */
+	{72,49,1680,1092, 2160, 1250 }, /* 1400x1050 (6330, was not supported on 6325) */
 	{ 1, 1,2160,1250, 2160, 1250 }
 };
 
-static const SiS_LCDDataStruct  SiS_NoScaleData1600x1200[] =
-{
-        {1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-};
-
 static const SiS_LCDDataStruct  SiS_NoScaleData[] =
 {
-	{ 1, 1, 800, 449, 800, 449 },
+	{ 1, 1, 800, 449, 800, 449 },  /* 0x00: 320x200, 640x400 */
 	{ 1, 1, 800, 449, 800, 449 },
 	{ 1, 1, 900, 449, 900, 449 },
 	{ 1, 1, 900, 449, 900, 449 },
-	{ 1, 1, 800, 525, 800, 525 },
-	{ 1, 1,1056, 628,1056, 628 },
-	{ 1, 1,1344, 806,1344, 806 },
-	{ 1, 1,1688,1066,1688,1066 },
-        { 1, 1,1688, 802,1688, 802 },  /* 1280x768: 802 was 806 in both cases */
-        { 1, 1,2160,1250,2160,1250 },  /* 1600x1200 */
-	{ 1, 1,1800,1000,1800,1000 }   /* 1280x960 */
-};
-
-/* *** LCDA *** */
-
-static const SiS_LVDSDataStruct  SiS_LCDA1024x768Data_1[]=
-{
-	{  960, 438,1344, 806},
-	{  960, 388,1344, 806},
-	{ 1040, 438,1344, 806},
-	{ 1040, 388,1344, 806},
-	{  960, 518,1344, 806},   /* 640x480 */
-	{ 1120, 638,1344, 806},   /* 800x600 */
-	{ 1344, 806,1344, 806},   /* 1024x768 */
-#if 0
-	{ 840, 438,1344, 806},
-	{ 840, 409,1344, 806},
-	{ 840, 438,1344, 806},
-	{ 840, 409,1344, 806},
-	{ 840, 518,1344, 806},   /* 640x480 */
-	{1050, 638,1344, 806},   /* 800x600 */
-	{1344, 806,1344, 806},   /* 1024x768 */
-#endif
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1024x768Data_2[]=
-{
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1280x1024Data_1[]=
-{ /* Acer, Compaq */
-	{1048, 442,1688,1066},
-	{1048, 392,1688,1066},
-	{1128, 442,1688,1066},
-	{1128, 392,1688,1066},
-	{1048, 522,1688,1066},
-	{1208, 642,1688,1066},
-	{1432, 810,1688,1066},
-	{1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1280x1024Data_2[]=
-{ /* Corrected (illegal in Acer, correct in Compaq) */
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1400x1050Data_1[]=
-{ /* Clevo */
-        { 928, 416, 1688,1066},
-	{ 928, 366, 1688,1066},
-	{1008, 416, 1688,1066},
-	{1008, 366, 1688,1066},
-	{1200, 530, 1688,1066},
-	{1088, 616, 1688,1066},
-	{1312, 784, 1688,1066},
-	{1568,1040, 1688,1066},
-	{1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1400x1050Data_2[]=
-{ /* Clevo */
-    	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_1[]=
-{ /* Clevo (Temporary data)  */
-	{1200, 450, 2048,1250},
-	{1200, 400, 2048,1250},
-	{1280, 450, 2048,1250},
-	{1280, 400, 2048,1250},
-	{1200, 530, 2048,1250},
-	{1360, 650, 2048,1250},
-	{1584, 818, 2048,1250},
-	{1688,1066, 2048,1250},
-	{1688,1066, 2048,1250},
-	{2048,1250, 2048,1250}   /* this should be correct */
-#if 0
-	{2160,1250, 2048,1250}   /* ? */
-#endif
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_2[]=
-{ /* Clevo (Temporary data. Seems invalid.) */
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250}
-};
-
-/* LVDS SKEW for LCDA */
-
-static const SiS_LVDSDesStruct SiS_PanelType1076_1[]=
-{  /* 1024x768 */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},   /* 805; was 0, 0 -> top line cut away (26/09/03) */
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1076_2[]=
-{  /* 1024x768; not expanded */
-	{ 1184, 622 },
-	{ 1184, 597 },
-	{ 1184, 622 },
-	{ 1184, 597 },
-	{ 1152, 650 },  /* 622 */
-	{ 1232, 722 },
-	{    0, 0   },  /* 805; was 0, 0 -> top line cut away (26/09/03) */
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1210_1[]=
-{  /* 1280x1024 */
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 , 1065},  /* Acer */
-	{ 0 ,    0}
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1210_2[]=
-{  /* 1280x1024; not expanded */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1296_1[]=
-{  /* 1400x1050 */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 1065}   /* Was 0,0 */
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1296_2[]=
-{  /* 1400x1050; not expanded */
-	{ 1308, 741 },
-	{ 1308, 716 },
-	{ 1308, 741 },
-	{ 1308, 716 },
-	{ 1308, 781 },
-	{ 1388, 841 },
-	{ 1500, 925 },
-	{ 1628,1053 },
-	{    0,1065 }
-#if 0
-	{ 808 , 740},
-	{ 0   , 715},
-	{ 632 , 740},
-	{ 632 , 715},
-	{ 1307, 780},
-	{ 1387,1157},
-	{ 1499, 924},
-	{ 1627,1052},
-	{ 0 , 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1600_1[]=
-{  /* 1600x1200 */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1600_2[]=
-{  /* 1600x1200; not expanded */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
-#ifdef SIS315H
-
-/* LCDA CRT1 custom data */
-
-static const SiS_LCDACRT1DataStruct  Compaq1280x1024_LCDACRT1_1[]=
-{
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x06,
-   0x00}},
- {{0x92,0x63,0x63,0x96,0x6c,0x1a,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x06,
-   0x01}},
- {{0xae,0x7f,0x7f,0x92,0x88,0x96,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x9f,0x92,0xa8,0x16,0x28,0x5a,
-   0x00,0x84,0xff,0xff,0x29,0x01,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Compaq1280x1024_LCDACRT1_1_H[]=
-{
- {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1,
-   0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06,
-   0x01}},
- {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1,
-   0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06,
-   0x01}},
- {{0x56,0x27,0x27,0x9a,0x30,0x1e,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x05,
-   0x00}},
- {{0x60,0x31,0x31,0x84,0x3a,0x88,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x01,
-   0x01}},
- {{0x6e,0x3f,0x3f,0x92,0x48,0x96,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x01,
-   0x01}}
+	{ 1, 1, 800, 525, 800, 525 },  /* 0x04: 320x240, 640x480  */
+	{ 1, 1,1056, 628,1056, 628 },  /* 0x05: 400x300, 800x600  */
+	{ 1, 1,1344, 806,1344, 806 },  /* 0x06: 512x384, 1024x768 */
+	{ 1, 1,1688,1066,1688,1066 },  /* 0x07: 1280x1024 */
+        { 1, 1,1688, 802,1688, 802 },  /* 0x08: 1280x768: Fujitsu, TMDS only */
+        { 1, 1,2160,1250,2160,1250 },  /* 0x09: 1600x1200 */
+	{ 1, 1,1800,1000,1800,1000 },  /* 0x0a: 1280x960  */
+	{ 1, 1,1688,1066,1688,1066 },  /* 0x0b: 1400x1050 */
+	{ 1, 1,1650, 750,1650, 750 },  /* 0x0c: 1280x720 (TMDS, projector)  */
+	{ 1, 1,1656, 841,1656, 841 },  /* 0x0d: 1280x800 (was: 1408, 816) */
+	{ 1, 1,1900,1066,1900,1066 },  /* 0x0e: 1680x1050 (LVDS) */
+	{ 1, 1,1408, 806,1408, 806 },  /* 0x0f: 1280x768_2 */
+	{ 1, 1,1664, 798,1664, 798 },  /* 0x10: 1280x768_3 */
+	{ 1, 1,1688, 802,1688, 802 },  /* 0x11: 1280x768: Std, TMDS only */
+	{ 1, 1,1344, 806,1344, 806 },  /* 0x12: 1280x720 (LVDS)  */
+	{ 1, 1, 896, 497, 896, 497 },  /* 0x13: 720x480 */
+	{ 1, 1, 912, 597, 912, 597 },  /* 0x14: 720x576 */
+	{ 1, 1, 912, 597, 912, 597 },  /* 0x15: 768x576 */
+	{ 1, 1,1056, 497,1056, 497 },  /* 0x16: 848x480 */
+	{ 1, 1,1064, 497,1064, 497 },  /* 0x17: 856x480 */
+	{ 1, 1,1056, 497,1056, 497 },  /* 0x18: 800x480 */
+	{ 1, 1,1328, 739,1328, 739 },  /* 0x19: 1024x576 */
+	{ 1, 1,1680, 892,1680, 892 },  /* 0x1a: 1152x864 */
+	{ 1, 1,1808, 808,1808, 808 },  /* 0x1b: 1360x768 */
+	{ 1, 1,1104, 563,1104, 563 }   /* 0x1c: 960x540 */
 };
 
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_1[]=
-{
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x04,0x3e,
-   0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x87,0x63,0x63,0x8B,0x69,0x1A,0x7c,0xf0,
-   0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x26,
-   0x01}},
- {{0xA3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xFf,0xFf,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_1_H[]=
-{
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x32,0x1b,0x04,0x3e,
-   0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x45,
-   0x00}},
- {{0x55,0x31,0x31,0x99,0x46,0x1d,0x7c,0xf0,
-   0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x55,
-   0x01}},
- {{0x63,0x3F,0x3F,0x87,0x4A,0x93,0x24,0xF5,
-   0x02,0x88,0xFF,0xFF,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_2[]=
-{
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1,
-   0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_2_H[]=
-{
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x57,0x8e,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x3e,0x85,0x5d,0x5d,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x57,0x8e,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x3e,0x85,0x5d,0x5d,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x7f,0x86,0xdf,0xdf,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x71,0x31,0x31,0x95,0x46,0x97,0x24,0xf1,
-   0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x01,
-   0x01 }},
- {{0x63,0x3f,0x3f,0x87,0x46,0x97,0x24,0xf5,
-   0x0f,0x86,0xff,0xff,0x25,0x30,0x00,0x01,
-   0x01 }}
-};
-
-#endif  /* 315 */
 
 /**************************************************************/
 /* LVDS ----------------------------------------------------- */
@@ -1521,9 +1216,7 @@
 	{ 848, 389,1060, 629},
 	{ 848, 518,1060, 629},
 	{1056, 628,1056, 628},
-	{1056, 628,1056, 628},
-	{ 800, 449,1000, 644},
-	{ 800, 525,1000, 635}
+	{1056, 628,1056, 628}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS800x600Data_2[]=
@@ -1534,9 +1227,7 @@
 	{1056, 628,1056, 628},
 	{1056, 628,1056, 628},
 	{1056, 628,1056, 628},
-	{1056, 628,1056, 628},
-	{ 800, 449,1000, 644},
-	{ 800, 525,1000, 635}
+	{1056, 628,1056, 628}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1024x768Data_1[]=
@@ -1548,8 +1239,6 @@
 	{ 840, 518,1344, 806},   /* 640x480 */
 	{1050, 638,1344, 806},   /* 800x600 */
 	{1344, 806,1344, 806},   /* 1024x768 */
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1024x768Data_2[]=
@@ -1561,11 +1250,8 @@
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
 };
 
-
 static const SiS_LVDSDataStruct  SiS_LVDS1280x1024Data_1[]=
 {
 	{1048, 442,1688,1066},
@@ -1716,9 +1402,7 @@
 	{ 840, 560,1344, 800},
 	{ 840, 689,1344, 800},
 	{1050, 800,1344, 800},
-	{1344, 800,1344, 800},
-	{ 800, 449,1280, 789},
-	{ 800, 525,1280, 785}
+	{1344, 800,1344, 800}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1024x600Data_2[] =
@@ -1729,9 +1413,7 @@
 	{1344, 800,1344, 800},
 	{1344, 800,1344, 800},
 	{1344, 800,1344, 800},
-	{1344, 800,1344, 800},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
+	{1344, 800,1344, 800}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1152x768Data_1[] =
@@ -1742,9 +1424,7 @@
 	{ 840, 409,1344, 806},
 	{ 840, 518,1344, 806},
 	{1050, 638,1344, 806},
-	{1344, 806,1344, 806},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
+	{1344, 806,1344, 806}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1152x768Data_2[] =
@@ -1755,9 +1435,7 @@
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
+	{1344, 806,1344, 806}
 };
 
 /* Pass 1:1 data */
@@ -1770,7 +1448,7 @@
 	{ 800, 525,  800, 525},  /*  640x480   */
 	{1056, 628, 1056, 628},  /*  800x600   */
 	{1344, 806, 1344, 806},  /* 1024x768   */
-	{1344,1066, 1344,1066},  /* 1280x1024  */  /* INSERTED ! */
+	{1688,1066, 1688,1066},  /* 1280x1024  */  /* INSERTED ! */
  	{1688, 806, 1688, 806},  /* 1280x768   */
 	/* No other panels ! */
 };
@@ -1885,36 +1563,6 @@
         {1160, 840,1160, 840}
 };
 
-/* LVDS Skew */
-
-static const SiS_LVDSDesStruct  SiS_PanelTypeNS_1[]=
-{
-	{ 8,   0},
-	{ 8,   0},
-	{ 8,   0},
-	{ 8,   0},
-	{ 8,   0},
-	{ 0,   0},
-	{ 0,   0},
-	{ 0,   0},
-	{ 0, 806},
-	{ 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS_PanelTypeNS_2[] =
-{
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
 /* Chrontel TV Skew */
 
 static const SiS_LVDSDesStruct  SiS_CHTVUNTSCDesData[]=
@@ -2453,63 +2101,6 @@
    0x01}}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1XXXxXXX_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1XXXxXXX_1_H[] =
-{
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}},
- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
-   0x01}},
- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-
 /**************************************************************/
 /* COMMON --------------------------------------------------- */
 /**************************************************************/
@@ -2770,7 +2361,8 @@
    { 0x0000 }
 };
 
-USHORT  SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN);
+USHORT  SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
+			  int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
 USHORT  SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN,
                           USHORT CustomT, int LCDwith, int LCDheight);
 USHORT  SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
@@ -2791,6 +2383,7 @@
 void	SiS_DisplayOff(SiS_Private *SiS_Pr);
 void	SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
 void	SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
+BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 void	SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
 void	SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
 void	SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
@@ -2801,6 +2394,7 @@
 USHORT	SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
               USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo);
 void	SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT ModeIdIndex);
+void	SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
 #ifdef LINUX_XF86
 BOOLEAN	SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch);
 BOOLEAN	SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
@@ -2821,10 +2415,7 @@
 			      unsigned char modeno, unsigned char rateindex);
 int    sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 			 unsigned char modeno, unsigned char rateindex,
-			 ULONG *left_margin, ULONG *right_margin,
-			 ULONG *upper_margin, ULONG *lower_margin,
-			 ULONG *hsync_len, ULONG *vsync_len,
-			 ULONG *sync, ULONG *vmode);
+			 struct fb_var_screeninfo *var);
 BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 		       unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
 #endif
diff -Nru a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
--- a/drivers/video/sis/init301.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/video/sis/init301.c	2004-06-23 19:04:25 -07:00
@@ -1,9 +1,10 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Mode initializing code (CRT2 section)
  * for SiS 300/305/540/630/730 and
- *     SiS 315/550/650/M650/651/661FX/M661xX/740/741/M741/330/660/M660/760/M760
- * (Universal module for Linux kernel framebuffer and XFree86 4.x)
+ *     SiS 315/550/650/M650/651/661FX/M661xX/740/741(GX)/M741/330/660/M660/760/M760
+ * (Universal module for Linux kernel framebuffer and XFree86/X.org 4.x)
  *
  * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
  *
@@ -34,13 +35,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -76,10 +74,6 @@
 
 #include "init301.h"
 
-#if 0
-#define TWNEWPANEL
-#endif
-
 #ifdef SIS300
 #include "oem300.h"
 #endif
@@ -91,6 +85,8 @@
 #define SiS_I2CDELAY      1000
 #define SiS_I2CDELAYSHORT  150
 
+static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr);
+
 /*********************************************/
 /*         HELPER: Lock/Unlock CRT2          */
 /*********************************************/
@@ -98,29 +94,19 @@
 void
 SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  if(HwInfo->jChipType >= SIS_315H)
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
-  else
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
+   if(HwInfo->jChipType >= SIS_315H)
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
+   else
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
 }
 
 void
 SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  if(HwInfo->jChipType >= SIS_315H)
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
-  else
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
-}
-
-/*********************************************/
-/*            HELPER: Enable CRT2            */
-/*********************************************/
-
-void
-SiS_EnableCRT2(SiS_Private *SiS_Pr)
-{
-  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+   if(HwInfo->jChipType >= SIS_315H)
+      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
+   else
+      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
 }
 
 /*********************************************/
@@ -130,7 +116,10 @@
 static void
 SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
 {
-   if(HwInfo->jChipType >= SIS_661) DataAND &= 0x0f;
+   if(HwInfo->jChipType >= SIS_661) {
+      DataAND &= 0x0f;
+      DataOR  &= 0x0f;
+   }
    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
 }
 
@@ -138,117 +127,45 @@
 /*    HELPER: Get Pointer to LCD structure   */
 /*********************************************/
 
-/* For 661 series only */
 #ifdef SIS315H
-#if 0   /* Need to wait until hardware using this really exists */
 static UCHAR *
-GetLCDPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int tabletype,
-             USHORT ModeNo, USHORT ModeIdIndex, USHORT RRTI)
+GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  UCHAR *ROMAddr =  HwInfo->pjVirtualRomBase;
-  UCHAR *tableptr = NULL;
-  UCHAR tablelengths[] = { 8, 7, 6, 6, 8, 6, 0, 0, 0 };
-  USHORT modeflag, CRT2Index, tablelength, lcdid, myid, tableptri;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     CRT2Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT2CRTC;
-     /* This is total bullshit: */
-     if(SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO == SIS_RI_720x576) CRT2Index = 10;
-  }
-
-  if(tabletype <= 1) {
-#if 0	/* Not yet implemented */
-     if(ModeNo <= 0x13) {
-        CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex]. + 5;
-     } else {
-        CRT2Index = SiS_Pr->SiS_RefIndex[RRTI]. + 5;
-     }
-     if(tabletype & 1) CRT2Index >>= 4;
-#endif
-  }
-
-  CRT2Index &= 0x0f;
-
-  tablelength = tablelengths[tabletype];
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-     if((tabletype == 5) || (tabletype == 7)) tablelength = 8;
-     if((tabletype == 3) || (tabletype == 8)) tablelength = 8;
-  }
-
-  if(!tablelength) return NULL;
-
-  tableptri = ROMAddr[0x222] | (ROMAddr[0x223] << 8);
-  tableptri += (tabletype << 1);
-  if(!tableptri) return NULL;
-  tableptr = &ROMAddr[tableptri];
+   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+   UCHAR  *myptr = NULL;
+   USHORT romindex = 0;
 
-  do {
-     lcdid = tableptr[0];
-     if(lcdid == 0xff) break;
-     myid = SiS_Pr->SiS_LCDResInfo;
-     if((lcdid & 0x80) && (lcdid != 0x80)) {
-        lcdid &= 0x7f;
-	myid = SiS_Pr->SiS_LCDTypeInfo;
-     }
-     if(SiS_Pr->SiS_LCDInfo & LCDPass11) myid &= ~0x1f;
-
-     if(myid == lcdid) {
-	lcdid = tableptr[1] | (tableptr[2] << 8);
-	myid = SiS_Pr->SiS_LCDInfo661;
-	if(modeflag & HalfDCLK) myid |= 0x200;
-	if(ModeNo <= 0x13)      myid |= 0x400;
-	lcdid &= myid;
-	myid = tableptr[3] | (tableptr[4] << 8);
-	if(lcdid == myid) break;
-     }
-     tableptr += 7;
-  } while (1);
-
-  if(lcdid == myid) {
-     lcdid = tableptr[5] | (tableptr[6] << 8);
-     lcdid += (tablelength * CRT2Index);
-     return((UCHAR *)&ROMAddr[lcdid]);
-  }
+   /* Use the BIOS tables only for LVDS panels; DVI is unreliable
+    * due to the variaty of panels the BIOS doesn't know about.
+    */
 
-  return NULL;
+   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+      myptr = (UCHAR *)SiS_LCDStruct661;
+      romindex = SISGETROMW(0x100);
+      if(romindex) {
+         romindex += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x7d) & 0x1f) * 26);
+         myptr = &ROMAddr[romindex];
+      }
+   }
+   return myptr;
 }
-#endif
 
-static UCHAR *
-GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static USHORT
+GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-   USHORT lcdres = SiS_Pr->SiS_LCDResInfo;
-   USHORT lcdtype = SiS_Pr->SiS_LCDTypeInfo;
-   USHORT romindex=0;
-   UCHAR  *myptr = NULL;
-   UCHAR  lcdid;
+   USHORT romptr = 0;
 
-   if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-      romindex = ROMAddr[0x256] | (ROMAddr[0x257] << 8);
-   }
-   if(romindex) {
-      myptr = &ROMAddr[romindex];
-   } else {
-      myptr = (UCHAR *)SiS_LCDStruct661;
-   }
+   /* Use the BIOS tables only for LVDS panels; DVI is unreliable
+    * due to the variaty of panels the BIOS doesn't know about.
+    */
 
-   while(myptr[0] != 0xff) {
-      lcdid = myptr[0];
-      if((lcdid & 0x80) && (lcdid != 0x80)) {
-         lcdres = lcdtype;
-	 lcdid &= 0x7f;
-      }
-      if(lcdid == lcdres) break;
-      myptr += 26;
+   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+      romptr = SISGETROMW(0x102);
+      romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
    }
-   if(myptr[0] == 0xff) return NULL;
 
-   return myptr;
+   return(romptr);
 }
 #endif
 
@@ -261,71 +178,72 @@
                    USHORT RefreshRateTableIndex, USHORT *i,
 		   PSIS_HW_INFO HwInfo)
 {
-  USHORT tempax,tempbx,infoflag;
-
-  tempbx = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
+  USHORT checkmask=0,modeid,infoflag;
 
-  tempax = 0;
+  modeid = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
 
-      	tempax |= SupportRAMDAC2;
+      	checkmask |= SupportRAMDAC2;
 	if(HwInfo->jChipType >= SIS_315H) {
-	   tempax |= SupportRAMDAC2_135;
+	   checkmask |= SupportRAMDAC2_135;
 	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	      tempax |= SupportRAMDAC2_162;
+	      checkmask |= SupportRAMDAC2_162;
 	      if(SiS_Pr->SiS_VBType & VB_SIS301C) {
-		 tempax |= SupportRAMDAC2_202;
+		 checkmask |= SupportRAMDAC2_202;
 	      }
 	   }
 	}
 
      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 
-     	tempax |= SupportLCD;
+     	checkmask |= SupportLCD;
 	if(HwInfo->jChipType >= SIS_315H) {
-	   if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	         if(tempbx == 0x2e) {  /* 640x480 */
-		    tempax |= Support64048060Hz;
-		 }
+	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	         if(modeid == 0x2e) checkmask |= Support64048060Hz;
 	      }
 	   }
 	}
 
      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
-      	tempax |= SupportHiVision;
+      	checkmask |= SupportHiVision;
 
      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
 
-        tempax |= SupportTV;
+        checkmask |= SupportTV;
 	if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	   tempax |= SupportTV1024;
+	   checkmask |= SupportTV1024;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+	         checkmask |= SupportYPbPr750p;
+	      }
+	   }
 	}
 
      }
 
-  } else {	/* for LVDS  */
+  } else {	/* LVDS */
 
      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      	if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-           tempax |= SupportCHTV;
+           checkmask |= SupportCHTV;
       	}
      }
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     	tempax |= SupportLCD;
+     	checkmask |= SupportLCD;
      }
 
   }
 
   /* Look backwards in table for matching CRT2 mode */
-  for(; SiS_Pr->SiS_RefIndex[RefreshRateTableIndex+(*i)].ModeID == tempbx; (*i)--) {
+  for(; SiS_Pr->SiS_RefIndex[RefreshRateTableIndex+(*i)].ModeID == modeid; (*i)--) {
      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
-     if(infoflag & tempax) return(1);
+     if(infoflag & checkmask) return TRUE;
      if((*i) == 0) break;
   }
 
@@ -333,17 +251,17 @@
    * for a matching CRT2 mode if no mode was found yet.
    */
   for((*i) = 0; ; (*i)++) {
-     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID != tempbx) {
-     	return(0);
+     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID != modeid) {
+     	return FALSE;
      }
      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
-     if(infoflag & tempax) return(1);
+     if(infoflag & checkmask) return TRUE;
   }
-  return(1);
+  return TRUE;
 }
 
 /*********************************************/
-/*              Get rate pointer             */
+/*              Get rate index               */
 /*********************************************/
 
 USHORT
@@ -361,20 +279,19 @@
   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
   if(ModeNo == 0xfe) return 0;
 
-  if(ModeNo <= 0x13)
+  if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  else
+  } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+  }
 
   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     	if(modeflag & HalfDCLK) return(0);
+     	if(modeflag & HalfDCLK) return 0;
      }
   }
 
-  if(ModeNo < 0x14) return(0xFFFF);
-
-  /* CR33 holds refresh rate index for CRT1 [3:0] and CRT2 [7:4]. */
+  if(ModeNo < 0x14) return 0xFFFF;
 
   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
   backupindex = index;
@@ -389,7 +306,7 @@
 	}
 	if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 	   if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
-              temp = LCDRefreshIndex[SiS_Pr->SiS_LCDResInfo];
+              temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
               if(index > temp) index = temp;
 	   }
 	}
@@ -462,37 +379,39 @@
 /*    HELPER: GET SOME DATA FROM BIOS ROM    */
 /*********************************************/
 
+#ifdef SIS300
 static BOOLEAN
 SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+  UCHAR *ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase;
   USHORT temp,temp1;
-  UCHAR *ROMAddr;
 
-  if((ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xff) >> 4);
-        temp1 = (ROMAddr[0x23c] << 8) | ROMAddr[0x23b];
-        if(temp1 & temp) return(1);
+        temp1 = SISGETROMW(0x23b);
+        if(temp1 & temp) return TRUE;
      }
   }
-  return(0);
+  return FALSE;
 }
 
 static BOOLEAN
 SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+  UCHAR *ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase;
   USHORT temp,temp1;
-  UCHAR *ROMAddr;
 
-  if((ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xff) >> 4);
-        temp1 = (ROMAddr[0x23e] << 8) | ROMAddr[0x23d];
-        if(temp1 & temp) return(1);
+        temp1 = SISGETROMW(0x23d);
+        if(temp1 & temp) return TRUE;
      }
   }
-  return(0);
+  return FALSE;
 }
+#endif
 
 /*********************************************/
 /*          HELPER: DELAY FUNCTIONS          */
@@ -508,6 +427,7 @@
   }
 }
 
+#if defined(SIS300) || defined(SIS315H)
 static void
 SiS_GenericDelay(SiS_Private *SiS_Pr, USHORT delay)
 {
@@ -522,6 +442,7 @@
      delay--;
   }
 }
+#endif
 
 #ifdef SIS315H
 static void
@@ -533,6 +454,7 @@
 }
 #endif
 
+#if defined(SIS300) || defined(SIS315H)
 static void
 SiS_ShortDelay(SiS_Private *SiS_Pr, USHORT delay)
 {
@@ -540,12 +462,15 @@
      SiS_GenericDelay(SiS_Pr,0x42);
   }
 }
+#endif
 
 static void
 SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
 {
+#if defined(SIS300) || defined(SIS315H)
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT PanelID, DelayIndex, Delay=0;
+#endif
 
   if(HwInfo->jChipType < SIS_315H) {
 
@@ -560,23 +485,19 @@
          Delay = 3;
       } else {
          if(DelayTime >= 2) DelayTime -= 2;
-
          if(!(DelayTime & 0x01)) {
        	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
          } else {
        	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
          }
-	 if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
+	 if(SiS_Pr->SiS_UseROM) {
             if(ROMAddr[0x220] & 0x40) {
-               if(!(DelayTime & 0x01)) {
-	          Delay = (USHORT)ROMAddr[0x225];
-               } else {
-	    	  Delay = (USHORT)ROMAddr[0x226];
-               }
+               if(!(DelayTime & 0x01)) Delay = (USHORT)ROMAddr[0x225];
+               else 	    	       Delay = (USHORT)ROMAddr[0x226];
             }
          }
       }
-      SiS_ShortDelay(SiS_Pr,Delay);
+      SiS_ShortDelay(SiS_Pr, Delay);
 
 #endif  /* SIS300 */
 
@@ -584,11 +505,19 @@
 
 #ifdef SIS315H
 
-      if(HwInfo->jChipType >= SIS_330) return;
+      if((HwInfo->jChipType >= SIS_661)    ||
+         (HwInfo->jChipType <= SIS_315PRO) ||
+	 (HwInfo->jChipType == SIS_330)) {
+
+         if(!(DelayTime & 0x01)) {
+	    SiS_DDC2Delay(SiS_Pr, 0x1000);
+         } else {
+	    SiS_DDC2Delay(SiS_Pr, 0x4000);
+         }
 
-      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+      } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {			/* 315 series, LVDS; Special */
+	 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) {			/* 315 series, LVDS; Special */
 
          if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
             PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
@@ -609,7 +538,7 @@
                } else {
        		  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
                }
-	       if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
+	       if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
                   if(ROMAddr[0x13c] & 0x40) {
                      if(!(DelayTime & 0x01)) {
 	    	        Delay = (USHORT)ROMAddr[0x17e];
@@ -619,7 +548,7 @@
                   }
                }
             }
-	    SiS_ShortDelay(SiS_Pr,Delay);
+	    SiS_ShortDelay(SiS_Pr, Delay);
 	 }
 
       } else if(SiS_Pr->SiS_VBType & VB_SISVB) {			/* 315 series, all bridges */
@@ -662,7 +591,6 @@
   USHORT watchdog;
 
   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
-
   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
 
   watchdog = 65535;
@@ -671,6 +599,7 @@
   while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
 }
 
+#if defined(SIS300) || defined(SIS315H)
 static void
 SiS_WaitRetrace2(SiS_Private *SiS_Pr, USHORT reg)
 {
@@ -681,6 +610,7 @@
   watchdog = 65535;
   while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
 }
+#endif
 
 static void
 SiS_WaitVBRetrace(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
@@ -718,10 +648,10 @@
        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
        if(temp & 0x01) {
           if((tempal & 0x08))  continue;
-          if(!(tempal & 0x08)) break;
+          else break;
        } else {
           if(!(tempal & 0x08)) continue;
-          if((tempal & 0x08))  break;
+          else break;
        }
     }
     temp ^= 0x01;
@@ -742,15 +672,14 @@
 /*               HELPER: MISC                */
 /*********************************************/
 
+#ifdef SIS300
 static BOOLEAN
 SiS_Is301B(SiS_Private *SiS_Pr)
 {
-  USHORT flag;
-
-  flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
-  if(flag >= 0xb0) return TRUE;
+  if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
   return FALSE;
 }
+#endif
 
 static BOOLEAN
 SiS_CRT2IsLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
@@ -796,6 +725,16 @@
   return FALSE;
 }
 
+#ifdef SIS315H
+static BOOLEAN
+SiS_IsVAorLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+  if(SiS_IsVAMode(SiS_Pr,HwInfo))   return TRUE;
+  if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) return TRUE;
+  return FALSE;
+}
+#endif
+
 static BOOLEAN
 SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
@@ -815,7 +754,7 @@
 SiS_TVEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
-  if(SiS_Pr->SiS_VBType & (VB_301C | VB_SIS301LV302LV)) {
+  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV302LV)) {
      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
   }
   return FALSE;
@@ -835,11 +774,8 @@
 static BOOLEAN
 SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  USHORT flag;
-
   if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
-     if(flag & 0x10) return TRUE;
+     if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
   }
   return FALSE;
 }
@@ -935,12 +871,12 @@
   USHORT flag;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     return FALSE;
+     return TRUE;
   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-     if((flag == 1) || (flag == 2)) return FALSE;
+     if((flag == 1) || (flag == 2)) return TRUE;
   }
-  return TRUE;
+  return FALSE;
 }
 
 static BOOLEAN
@@ -948,21 +884,21 @@
 {
   USHORT flag;
 
-  if(!(SiS_BridgeIsOn(SiS_Pr))) {
+  if(SiS_BridgeIsOn(SiS_Pr)) {
      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
      if(HwInfo->jChipType < SIS_315H) {
        flag &= 0xa0;
-       if((flag == 0x80) || (flag == 0x20)) return FALSE;
+       if((flag == 0x80) || (flag == 0x20)) return TRUE;
      } else {
        flag &= 0x50;
-       if((flag == 0x40) || (flag == 0x10)) return FALSE;
+       if((flag == 0x40) || (flag == 0x10)) return TRUE;
      }
   }
-  return TRUE;
+  return FALSE;
 }
 
 static BOOLEAN
-SiS_BridgeInSlave(SiS_Private *SiS_Pr)
+SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
 {
   USHORT flag1;
 
@@ -985,7 +921,7 @@
    if(!(SiS_Pr->SiS_ChSW)) return;
 
 #ifndef LINUX_XF86
-   SiS_SetRegLong(0xcf8,0x80000874);		   /* get ACPI base */
+   SiS_SetRegLong(0xcf8,0x80000874);		       /* get ACPI base */
    acpibase = SiS_GetRegLong(0xcfc);
 #else
    acpibase = pciReadLong(0x00000800, 0x74);
@@ -1003,22 +939,19 @@
 }
 
 void
-SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo,
-              USHORT ModeIdIndex,PSIS_HW_INFO HwInfo,
-	      int checkcrt2mode)
+SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
+              PSIS_HW_INFO HwInfo, int checkcrt2mode)
 {
   USHORT tempax,tempbx,temp;
   USHORT modeflag, resinfo=0;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-     } else {
-   	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
   SiS_Pr->SiS_SetFlag = 0;
@@ -1026,7 +959,7 @@
   SiS_Pr->SiS_ModeType = modeflag & ModeInfoFlag;
 
   tempbx = 0;
-  if(SiS_BridgeIsOn(SiS_Pr) == 0) {
+  if(SiS_BridgeIsOn(SiS_Pr)) {
     	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 #if 0
    	if(HwInfo->jChipType < SIS_661) {
@@ -1054,7 +987,7 @@
 		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
 	      }
 	      if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
-	         /* Reset LCDA setting */
+	         /* Reset LCDA setting if not driver mode */
 		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
 	      }
 	      if(IS_SIS650) {
@@ -1071,6 +1004,11 @@
           	 tempbx |= SetCRT2ToLCDA;
 	      }
 	   }
+
+	   if(SiS_Pr->SiS_VBType & (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
+	      tempbx &= ~(SetCRT2ToRAMDAC);
+	   }
+
 	   if(HwInfo->jChipType >= SIS_661) {
 	      tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
 	      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
@@ -1148,24 +1086,12 @@
 				SetPALTV 	   |
 				SwitchCRT2	   |
 				SetSimuScanMode );
-      	   if(tempbx & SetCRT2ToLCDA) {
-              tempbx &= (clearmask | SetCRT2ToLCDA);
-      	   }
-	   if(tempbx & SetCRT2ToRAMDAC) {
-              tempbx &= (clearmask | SetCRT2ToRAMDAC);
-      	   }
-	   if(tempbx & SetCRT2ToLCD) {
-              tempbx &= (clearmask | SetCRT2ToLCD);
-      	   }
-	   if(tempbx & SetCRT2ToSCART) {
-              tempbx &= (clearmask | SetCRT2ToSCART);
-      	   }
-	   if(tempbx & SetCRT2ToHiVision) {
-              tempbx &= (clearmask | SetCRT2ToHiVision);
-      	   }
-	   if(tempbx & SetCRT2ToYPbPr525750) {
-	      tempbx &= (clearmask | SetCRT2ToYPbPr525750);
-	   }
+      	   if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
+	   if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
+	   if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
+	   if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
+	   if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
+	   if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
    	} else {
 	   if(HwInfo->jChipType >= SIS_315H) {
 	      if(tempbx & SetCRT2ToLCDA) {
@@ -1193,14 +1119,12 @@
       	   }
     	}
 
-    	if(!(tempbx & DriverMode)){
-      	   tempbx |= SetSimuScanMode;
-    	}
+    	if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
 
 	/* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
 	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
 	   if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
-	       ((tempbx & SetCRT2ToLCD) && (SiS_Pr->SiS_VBType & VB_NoLCD)) ) {
+	       ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
 	       modeflag &= (~CRT2Mode);
 	   }
 	}
@@ -1218,9 +1142,9 @@
 	         }
               }
       	   } else {
-              if(!(SiS_BridgeIsEnabled(SiS_Pr,HwInfo))) {
+              if(SiS_BridgeIsEnabled(SiS_Pr,HwInfo)) {
           	 if(!(tempbx & DriverMode)) {
-            	    if(SiS_BridgeInSlave(SiS_Pr)) {
+            	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
 		       tempbx |= SetSimuScanMode;
             	    }
                  }
@@ -1346,7 +1270,7 @@
 	   if(HwInfo->jChipType >= SIS_330) romindex = 0x11b;
         }
         if(temp) {
-           if(romindex && ROMAddr && SiS_Pr->SiS_UseROM) {
+           if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
 	      OutputSelect = ROMAddr[romindex];
 	      if(!(OutputSelect & EnablePALMN)) {
                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
@@ -1443,6 +1367,22 @@
 	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 	   SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
 	}
+	if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
+	   if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
+	      SiS_Pr->SiS_TVMode |= TVAspect169;
+	   } else {
+	      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
+	      if(temp1 & 0x02) {
+		 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
+		    SiS_Pr->SiS_TVMode |= TVAspect169;
+		 } else {
+		    SiS_Pr->SiS_TVMode |= TVAspect43LB;
+		 }
+	      } else {
+		 SiS_Pr->SiS_TVMode |= TVAspect43;
+	      }
+	   }
+	}
      }
   }
 
@@ -1493,13 +1433,74 @@
 #ifdef TWDEBUG
   xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
 #endif
-
 }
 
 /*********************************************/
 /*               GET LCD INFO                */
 /*********************************************/
 
+static USHORT
+SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr)
+{
+   USHORT temp = SiS_Pr->SiS_LCDResInfo;
+   /* Translate my LCDResInfo to BIOS value */
+   if(temp == Panel_1280x768_2)  temp = Panel_1280x768;
+   if(temp == Panel_1280x768_3)  temp = Panel_1280x768;
+   return temp;
+}
+
+static void
+SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+#ifdef SIS315H
+   UCHAR  *ROMAddr;
+   USHORT temp;
+
+#ifdef TWDEBUG
+   xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
+      	SiS_Pr->PanelHT, SiS_Pr->PanelVT,
+	SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
+	SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
+#endif
+
+   if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+      if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
+         SiS_Pr->SiS_NeedRomModeData = TRUE;
+	 SiS_Pr->PanelHT  = temp;
+      }
+      if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
+         SiS_Pr->SiS_NeedRomModeData = TRUE;
+         SiS_Pr->PanelVT  = temp;
+      }
+      SiS_Pr->PanelHRS = SISGETROMW(10);
+      SiS_Pr->PanelHRE = SISGETROMW(12);
+      SiS_Pr->PanelVRS = SISGETROMW(14);
+      SiS_Pr->PanelVRE = SISGETROMW(16);
+      SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)((UCHAR)ROMAddr[18]);
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
+
+#ifdef TWDEBUG
+      xf86DrvMsg(0, X_INFO, "Paneldata BIOS:  [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
+      	SiS_Pr->PanelHT, SiS_Pr->PanelVT,
+	SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
+	SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
+#endif
+
+   }
+#endif
+}
+
 void
 SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 		  PSIS_HW_INFO HwInfo)
@@ -1515,50 +1516,60 @@
          { 0,  1,  2,  3,  7,  4,  5,  8,
 	   0,  0, 10,  0,  0,  0,  0, 15 };
 
-  SiS_Pr->SiS_LCDResInfo = 0;
+  SiS_Pr->SiS_LCDResInfo  = 0;
   SiS_Pr->SiS_LCDTypeInfo = 0;
-  SiS_Pr->SiS_LCDInfo = 0;
+  SiS_Pr->SiS_LCDInfo     = 0;
+  SiS_Pr->PanelHRS        = 999; /* HSync start */
+  SiS_Pr->PanelHRE        = 999; /* HSync end */
+  SiS_Pr->PanelVRS        = 999; /* VSync start */
+  SiS_Pr->PanelVRE        = 999; /* VSync end */
+  SiS_Pr->SiS_NeedRomModeData = FALSE;
 
-  if(SiS_Pr->UseCustomMode) {
+  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(ModeNo <= 0x13) {
-    	modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
-
   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+  if(!temp) return;
 
-  if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
+  if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+     SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
+  } else if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
      SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
   } else {
      SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
   }
   temp &= 0x0f;
   if(HwInfo->jChipType < SIS_315H) {
-      /* Translate 300 series LCDRes to 315 series for unified usage */
-      temp = SiS300SeriesLCDRes[temp];
+     /* Translate 300 series LCDRes to 315 series for unified usage */
+     temp = SiS300SeriesLCDRes[temp];
   }
-  SiS_Pr->SiS_LCDResInfo = temp;
 
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
-	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
-	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
+  if(HwInfo->jChipType == SIS_550) {
+     if(temp == Panel310_640x480_2) temp = Panel_640x480_2;
+     if(temp == Panel310_640x480_3) temp = Panel_640x480_3;
   }
 
-  if((!SiS_Pr->CP_HaveCustomData) || (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_PanelCustom)) {
-     if(SiS_Pr->SiS_LCDResInfo > SiS_Pr->SiS_PanelMax)
-  	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_Panel1024x768;
+  if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	/* SiS LVDS */
+     if(temp == Panel310_1280x768) {
+        temp = Panel_1280x768_2;
+#ifdef SIS315H
+	if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+	   if((myptr[8] | (myptr[9] << 8)) == 798) temp = Panel_1280x768_3;
+	}
+#endif
+     }
   }
 
+  SiS_Pr->SiS_LCDResInfo = temp;
+
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
         SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
@@ -1567,113 +1578,306 @@
      }
   }
 
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
+	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
+	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
+  }
+
+  SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+  SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+
   switch(SiS_Pr->SiS_LCDResInfo) {
-     case Panel_800x600:   SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600; break;
-     case Panel_1024x768:  SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768; break;
-     case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024; break;
-     case Panel_640x480_3:
+     case Panel_320x480:    SiS_Pr->PanelXRes =  320; SiS_Pr->PanelYRes =  480;
+     			    SiS_Pr->PanelHT   =  400; SiS_Pr->PanelVT   =  525;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
      case Panel_640x480_2:
-     case Panel_640x480:   SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480; break;
-     case Panel_1024x600:  SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600; break;
-     case Panel_1152x864:  SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864; break;
-     case Panel_1280x960:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960; break;
-     case Panel_1152x768:  SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768; break;
-     case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050; break;
-     case Panel_1280x768:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768; break;
-     case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200; break;
-     case Panel_320x480:   SiS_Pr->PanelXRes =  320; SiS_Pr->PanelYRes =  480; break;
-     case Panel_Custom:    SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
-    			   SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
-			   break;
-     case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024; break;
-     case Panel_848x480:   SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480; break;
-     default:		   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768; break;
+     case Panel_640x480_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
+     			    SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
+     case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
+     			    			      SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
+     case Panel_800x600:    SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600;
+     			    SiS_Pr->PanelHT   = 1056; SiS_Pr->PanelVT   =  628;
+			    SiS_Pr->PanelHRS  =   40; SiS_Pr->PanelHRE  =  128;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    4;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK40;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK40;
+			    break;
+     case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
+			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
+			    SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
+     			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+     			    break;
+     case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    if(HwInfo->jChipType < SIS_315H) {
+			       SiS_Pr->PanelHRS = 23;
+			       			      SiS_Pr->PanelVRE  =    5;
+			    }
+			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   24;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    if(HwInfo->jChipType < SIS_315H) {
+			       SiS_Pr->PanelHRS = 23;
+			       			      SiS_Pr->PanelVRE  =    5;
+			    }
+     			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+     			    break;
+     case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
+     			    break;
+     case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
+     			    SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
+			    SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
+			    SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
+			    /* Data above for TMDS (projector); get from BIOS for LVDS */
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRS  =  112;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
+			    break;
+     case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   16; SiS_Pr->PanelHRE  =   64;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x768_3: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1664; SiS_Pr->PanelVT   =  798;
+			    SiS_Pr->PanelHRS   =  64; SiS_Pr->PanelHRE  =  128;
+			    SiS_Pr->PanelVRS   =   3; SiS_Pr->PanelVRE  =    7;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_3;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
+     			    SiS_Pr->PanelHT   = 1656; SiS_Pr->PanelVT   =  841;  /* 1408, 816 */
+			    SiS_Pr->PanelHRS   =  32; SiS_Pr->PanelHRE  =  312;  /*   16,  64 */
+			    SiS_Pr->PanelVRS   =  16; SiS_Pr->PanelVRE  =    8;  /*    4,   3 */
+			    SiS_Pr->PanelVCLKIdx315 = VCLK83_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
+     			    SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
+		 	    if(resinfo == SIS_RI_1280x1024) {
+			       SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
+			       SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
+			    }
+			    break;
+     case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112; /* HRE OK for LVDS, not for LCDA */
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
+     			    SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
+			    SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
+     			    SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
+    			    SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
+			    SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
+			    SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
+			    if(SiS_Pr->CP_PreferredIndex != -1) {
+			       SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
+    			       SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRE  = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVRS  = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVRE  = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
+			       SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
+			       SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
+			       SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
+			    }
+			    break;
+     case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+     			    break;
+     case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
+     			    SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
+     			    break;
+     default:		    SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    break;
   }
 
   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-  if(HwInfo->jChipType < SIS_661) {
-     temp &= ~0xe;
-  } else {
+  SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
+
+  if(!(SiS_Pr->UsePanelScaler))        SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+
 #ifdef SIS315H
-     if(!(temp & 0x10)) {
-        if(temp & 0x08) temp |= LCDPass11;
+  if(HwInfo->jChipType >= SIS_661) {
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
      }
-     temp &= ~0xe;
      if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-        myptr = GetLCDStructPtr661(SiS_Pr, HwInfo);
-        if(myptr) {
-           if(myptr[2] & 0x01) temp |= LCDDualLink;
-        }
+        if(SiS_Pr->SiS_ROMNew) {
+	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	} else if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+           if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	}
+     }
+  } else if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+     }
+     if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
+        SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
+	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+        if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
+	if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	}
      }
+  }
 #endif
+
+  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+     /* Always center screen on LVDS (if scaling is disabled) */
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+        /* Always center screen on SiS LVDS (if scaling is disabled) */
+        SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     } else {
+        /* By default, pass 1:1 on SiS TMDS (if scaling is disabled) */
+        SiS_Pr->SiS_LCDInfo |= LCDPass11;
+        if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     }
   }
-  SiS_Pr->SiS_LCDInfo = temp;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
-        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24 */
+        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
      }
   }
 
-  if(!(SiS_Pr->UsePanelScaler))        SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) {
-	   /* For non-standard LCD resolution, we let the panel scale */
-           SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-	   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e) {
-	      /* We do not scale to 1280x960 (B/C bridges only) */
-              SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	   if(((HwInfo->jChipType >= SIS_315H) && (ModeNo == 0x23 || ModeNo == 0x24 || ModeNo == 0x25)) ||
-	      ((HwInfo->jChipType < SIS_315H)  && (ModeNo == 0x55 || ModeNo == 0x5a || ModeNo == 0x5b))) {
-	      /* We do not scale to 1280x768 (B/C bridges only) */
-              SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	      /* No non-scaling data available for LV bridges */
-	      SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-	   }
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-           /* No idea about the timing and zoom factors */
-           SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
-	      /* We do not scale to 1280x1024 (all bridges) */
-	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-	   if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
-	      /* No idea about the timing and zoom factors (C bridge only) */
-	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	}
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-              if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	         SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-	      }
-	   }
+        if(modeflag & NoSupportLCDScale) {
+	   /* No scaling for this mode on any panel */
+	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	}
+        switch(SiS_Pr->SiS_LCDResInfo) {
+        case Panel_Custom:
+		/* For non-standard LCD resolution, we let the panel scale */
+           	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		break;
+	case Panel_1280x720:
+	      	if(SiS_Pr->PanelHT == 1650) {
+		   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		}
+	case Panel_1280x768:	/* TMDS only */
+		/* No idea about the timing and zoom factors */
+           	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		break;
+	case Panel_1280x960:
+	 	SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+		break;
+	case Panel_1280x1024:
+	        if(SiS_Pr->SiS_VBType & VB_SISTMDS) {
+		   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e ||
+		      ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78 ||
+		      ModeNo == 0x14 || ModeNo == 0x15 || ModeNo == 0x16) {
+	      	      /* We do not scale to 1280x720/800/960 (B/C bridges only) */
+                      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	           }
+	           if(((HwInfo->jChipType >= SIS_315H) &&
+		       (ModeNo == 0x23 || ModeNo == 0x24 || ModeNo == 0x25)) ||
+	              ((HwInfo->jChipType < SIS_315H)  &&
+		       (ModeNo == 0x55 || ModeNo == 0x5a || ModeNo == 0x5b))) {
+	              /* We do not scale to 1280x768 (B/C bridges only) */
+                      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	           }
+		}
+		break;
+	case Panel_1400x1050:
+	 	if(SiS_Pr->SiS_VBType & VB_SISTMDS) {
+	  	   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e ||
+		      ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78 ||
+		      ModeNo == 0x14 || ModeNo == 0x15 || ModeNo == 0x16 ||
+		      ModeNo == 0x23 || ModeNo == 0x24 || ModeNo == 0x25) {
+	      	      /* Do not scale to 1280x720/768/800/960 (B/C bridges only) */
+                      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	           }
+		}
+		if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+		   if(ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78) {
+		      if(SiS_Pr->UsePanelScaler == -1) {
+		         /* Do not scale to 1280x720 by default (LVDS bridges) */
+	      	         SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		      }
+		   }
+		}
+		if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
+	      	   /* Do not scale to 1280x1024 (all bridges) */
+	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	   	}
+		break;
+	case Panel_1600x1200:
+		if(SiS_Pr->SiS_VBType & VB_SISTMDS) {
+	      	   /* No idea about the timing and zoom factors (C bridge only) */
+	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	   	}
+		break;
 	}
      }
   }
 
-  if(HwInfo->jChipType >= SIS_315H) {
-#ifdef SIS315H
-     if(HwInfo->jChipType < SIS_661) {
-        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) {
-           SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
-	   SiS_Pr->SiS_LCDInfo |= LCDPass11;
-	}
-     }
-#endif
-  } else {
 #ifdef SIS300
+  if(HwInfo->jChipType < SIS_315H) {
      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+        if(SiS_Pr->SiS_UseROM) {
 	   if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
               if(!(ROMAddr[0x235] & 0x02)) {
 	         SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
@@ -1685,34 +1889,63 @@
            SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
 	}
      }
+  }
 #endif
+
+  /* Special cases */
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
   }
 
-  /* Trumpion: Assume non-expanding */
-  if(SiS_Pr->SiS_IF_DEF_TRUMPION != 0) {
-     SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+  if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
+     SiS_Pr->SiS_LCDInfo |= LCDPass11;
   }
 
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-     SiS_Pr->SiS_LCDInfo &= (~LCDPass11);
+  if(SiS_Pr->UseCustomMode) {
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
+  }
+
+  /* (In)validate LCDPass11 flag */
+  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+  }
+
+  /* Special cases */
+  if( (SiS_Pr->SiS_IF_DEF_FSTN)              ||
+      (SiS_Pr->SiS_IF_DEF_DSTN)              ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+     SiS_Pr->PanelHRS = 999;
+     SiS_Pr->PanelHRE = 999;
+  }
+
+  if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+     SiS_Pr->PanelVRS = 999;
+     SiS_Pr->PanelVRE = 999;
   }
 
 #ifdef SIS315H
   if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	/* Enable 302LV/302ELV dual link mode.
-	 * For 661, this is done above.
-	 */
-        if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)) {
-	   /* (Sets this in SenseLCD; new paneltypes) */
-	   SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	}
-        if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
-	   SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	}
+     if(!(SiS_Pr->SiS_ROMNew)) {
+        if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	   /* Enable 302LV/302ELV dual link mode.
+	    * For 661, this is done above.
+	    */
+           if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
+	      /* (Sets this in SenseLCD; new paneltypes) */
+	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	   }
+           if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+              (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
+	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	   }
+        }
      }
   }
 #endif
@@ -1720,37 +1953,37 @@
   if(!((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
 
      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-	   if(ModeNo > 0x13) {
-	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-                 if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
-                    SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
+	   if(ModeNo == 0x12) {
+	      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+	         SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	      }
+	   } else if(ModeNo > 0x13) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
+	         if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+	            if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
+                       SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+		    }
 		 }
-              }
-           }
-        }
-	if(ModeNo == 0x12) {
-	   if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-	      SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	      }
 	   }
 	}
      }
 
      if(modeflag & HalfDCLK) {
-        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-           if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-	      if(!(((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (HwInfo->jChipType < SIS_315H)) &&
-	                                      (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480))) {
-                 if(ModeNo > 0x13) {
-                    if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-                       if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-                    } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-                       if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-                    }
-                 }
-	      } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-           } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-        } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+        } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	} else if(ModeNo > 0x13) {
+           if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+              if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+           } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
+              if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+           }
+	}
      }
 
   }
@@ -1763,14 +1996,6 @@
      SiS_Pr->SiS_SetFlag |= LCDVESATiming;
   }
 
-  SiS_Pr->SiS_LCDInfo661 = 0;
-  if(SiS_Pr->SiS_SetFlag & LCDVESATiming) SiS_Pr->SiS_LCDInfo661 |= 0x0001;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) SiS_Pr->SiS_LCDInfo661 |= 0x0002;
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11)     SiS_Pr->SiS_LCDInfo661 |= 0x0008;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) SiS_Pr->SiS_LCDInfo661 |= 0x0010;
-  SiS_Pr->SiS_LCDInfo661 |= (SiS_Pr->SiS_LCDInfo & 0xe0);
-  if(SiS_Pr->SiS_LCDInfo & LCDDualLink)   SiS_Pr->SiS_LCDInfo661 |= 0x0100;
-
 #ifdef LINUX_KERNEL
 #ifdef TWDEBUG
   printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
@@ -1792,54 +2017,21 @@
 SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx;
-  const USHORT LCDXlat0VCLK[4]    = {VCLK40,       VCLK40,       VCLK40,       VCLK40};
-  const USHORT LVDSXlat1VCLK[4]   = {VCLK40,       VCLK40,       VCLK40,       VCLK40};
-  const USHORT LVDSXlat4VCLK[4]   = {VCLK28,       VCLK28,       VCLK28,       VCLK28};
-#ifdef SIS300
-  const USHORT LCDXlat1VCLK300[4] = {VCLK65_300,   VCLK65_300,   VCLK65_300,   VCLK65_300};
-  const USHORT LCDXlat2VCLK300[4] = {VCLK108_2_300,VCLK108_2_300,VCLK108_2_300,VCLK108_2_300};
-  const USHORT LVDSXlat2VCLK300[4]= {VCLK65_300,   VCLK65_300,   VCLK65_300,   VCLK65_300};
-  const USHORT LVDSXlat3VCLK300[4]= {VCLK65_300,   VCLK65_300,   VCLK65_300,   VCLK65_300};
-#endif
-#ifdef SIS315H
-  const USHORT LCDXlat1VCLK310[4] = {VCLK65_315,   VCLK65_315,   VCLK65_315,   VCLK65_315};
-  const USHORT LCDXlat2VCLK310[4] = {VCLK108_2_315,VCLK108_2_315,VCLK108_2_315,VCLK108_2_315};
-  const USHORT LVDSXlat2VCLK310[4]= {VCLK65_315,   VCLK65_315,   VCLK65_315,   VCLK65_315};
-  const USHORT LVDSXlat3VCLK310[4]= {VCLK108_2_315,VCLK108_2_315,VCLK108_2_315,VCLK108_2_315};
-#endif
-  USHORT CRT2Index,VCLKIndex=0;
-  USHORT modeflag,resinfo;
-  const UCHAR  *CHTVVCLKPtr = NULL;
-  const USHORT *LCDXlatVCLK1 = NULL;
-  const USHORT *LCDXlatVCLK2 = NULL;
-  const USHORT *LVDSXlatVCLK2 = NULL;
-  const USHORT *LVDSXlatVCLK3 = NULL;
-
-  if(HwInfo->jChipType >= SIS_315H) {
-#ifdef SIS315H
-     LCDXlatVCLK1 = LCDXlat1VCLK310;
-     LCDXlatVCLK2 = LCDXlat2VCLK310;
-     LVDSXlatVCLK2 = LVDSXlat2VCLK310;
-     LVDSXlatVCLK3 = LVDSXlat3VCLK310;
-#endif
-  } else {
-#ifdef SIS300
-     LCDXlatVCLK1 = LCDXlat1VCLK300;
-     LCDXlatVCLK2 = LCDXlat2VCLK300;
-     LVDSXlatVCLK2 = LVDSXlat2VCLK300;
-     LVDSXlatVCLK3 = LVDSXlat3VCLK300;
-#endif
-  }
+  USHORT CRT2Index,VCLKIndex=0,VCLKIndexGEN=0;
+  USHORT modeflag,resinfo,tempbx;
+  const UCHAR *CHTVVCLKPtr = NULL;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
      CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
      CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+     if(HwInfo->jChipType < SIS_315H) VCLKIndexGEN &= 0x3f;
   }
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
@@ -1847,50 +2039,34 @@
      if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 
         CRT2Index >>= 6;
-        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {      /*  LCD */
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {      	/*  LCD */
 
            if(HwInfo->jChipType < SIS_315H) {
-	      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-	         VCLKIndex = LCDXlat0VCLK[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	    	 VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-	    	 VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
-	    	 VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-	         VCLKIndex = VCLK81_300;	/* guessed */
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-		 VCLKIndex = VCLK108_3_300;
-		 if(resinfo == SIS_RI_1280x1024) VCLKIndex = VCLK100_300;
-	      } else {
-	    	 VCLKIndex = LCDXlatVCLK2[CRT2Index];
-	      }
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
 	   } else {
-	      if( (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) ||
-	          (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
-      	         if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-		    VCLKIndex = VCLK108_2_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-		    VCLKIndex = VCLK81_315;  	/* guessed */
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-		    VCLKIndex = VCLK108_2_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-		    VCLKIndex = VCLK162_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-		    VCLKIndex = VCLK108_3_315;
-		    if(resinfo == SIS_RI_1280x1024) VCLKIndex = VCLK100_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-		    VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	         } else {
-		    VCLKIndex = LCDXlatVCLK2[CRT2Index];
-      	         }
-	      } else {
-                 VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));  /*  Port 3cch */
-         	 VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-        	 if(ModeNo > 0x13) {
-          	    VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-        	 }
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
+	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	         VCLKIndex = VCLKIndexGEN;
+		 switch(resinfo) {
+		 /* Only those whose IndexGEN doesn't match VBVCLK array: */
+		 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720;
+		 		       if(SiS_Pr->SiS_LCDResInfo == Panel_1280x720) {
+		                          if(SiS_Pr->PanelHT == 1344) {
+					     VCLKIndex = VCLK_1280x720_2;
+					  }
+				       }
+		 		       break;
+		 case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
+		 case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
+		 case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
+		 case SIS_RI_848x480:  VCLKIndex = VCLK_848x480;  break;
+		 case SIS_RI_856x480:  VCLKIndex = VCLK_856x480;  break;
+		 case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
+		 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
+		 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
+		 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
+		 }
+
 		 if(ModeNo <= 0x13) {
 		    if(HwInfo->jChipType <= SIS_315PRO) {
 		       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
@@ -1906,34 +2082,28 @@
 	      }
 	   }
 
-        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 /*  TV */
+        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 	/*  TV */
 
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-              if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
-     	      else                                  VCLKIndex = HiTVVCLK;
+              if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) 		VCLKIndex = HiTVVCLKDIV2;
+     	      else                                  		VCLKIndex = HiTVVCLK;
               if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-            	 if(modeflag & Charx8Dot) 	    VCLKIndex = HiTVSimuVCLK;
-            	 else 			  	    VCLKIndex = HiTVTextVCLK;
+            	 if(modeflag & Charx8Dot) 	    		VCLKIndex = HiTVSimuVCLK;
+            	 else 			  	    		VCLKIndex = HiTVTextVCLK;
               }
-           } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK - TVCLKBASE_315;
-	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   VCLKIndex = TVVCLKDIV2;
-	   else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)     VCLKIndex = TVVCLKDIV2;
-           else         		            	  VCLKIndex = TVVCLK;
+           } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) 	VCLKIndex = YPbPr750pVCLK;
+	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   	VCLKIndex = TVVCLKDIV2;
+	   else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)     	VCLKIndex = TVVCLKDIV2;
+           else         		            	  	VCLKIndex = TVVCLK;
 
-	   if(HwInfo->jChipType < SIS_315H) {
-              VCLKIndex += TVCLKBASE_300;
-  	   } else {
-	      VCLKIndex += TVCLKBASE_315;
-	   }
+	   if(HwInfo->jChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
+  	   else 	                    VCLKIndex += TVCLKBASE_315;
 
-        } else {         					/* VGA2 */
+        } else {         						/* VGA2 */
 
-           VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-           VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-           if(ModeNo > 0x13) {
-              VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	      if(HwInfo->jChipType < SIS_315H) {
-          	 VCLKIndex &= 0x3f;
+	   VCLKIndex = VCLKIndexGEN;
+	   if(HwInfo->jChipType < SIS_315H) {
+              if(ModeNo > 0x13) {
 		 if( (HwInfo->jChipType == SIS_630) &&
 		     (HwInfo->jChipRevision >= 0x30)) {
 		    if(VCLKIndex == 0x14) VCLKIndex = 0x34;
@@ -1946,12 +2116,9 @@
 
      } else {   /* If not programming CRT2 */
 
-        VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-        VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-        if(ModeNo > 0x13) {
-           VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	   if(HwInfo->jChipType < SIS_315H) {
-              VCLKIndex &= 0x3f;
+        VCLKIndex = VCLKIndexGEN;
+	if(HwInfo->jChipType < SIS_315H) {
+           if(ModeNo > 0x13) {
 	      if( (HwInfo->jChipType != SIS_630) &&
 		  (HwInfo->jChipType != SIS_300) ) {
 		 if(VCLKIndex == 0x1b) VCLKIndex = 0x35;
@@ -1964,7 +2131,7 @@
 
      VCLKIndex = CRT2Index;
 
-     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {  /* programming CRT2 */
+     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 
         if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
 
@@ -2000,32 +2167,16 @@
 
         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 
-	   VCLKIndex >>= 6;
-     	   if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) ||
-	      (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480))
-     	      VCLKIndex = LVDSXlat1VCLK[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480   ||
-	           SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-		   SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3)
-	      VCLKIndex = LVDSXlat4VCLK[VCLKIndex];
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)
-     	      VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)
-              VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)
-              VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)
-	      VCLKIndex = VCLK68_315;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)
-	      VCLKIndex = VCLK162_315;
-     	   else
-	      VCLKIndex = LVDSXlatVCLK3[VCLKIndex];
-
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-	      /* Special Timing: Barco iQ Pro R series */
-	      VCLKIndex = 0x44;
+	   if(HwInfo->jChipType < SIS_315H) {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
+	   } else {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
 	   }
 
+	   /* Special Timing: Barco iQ Pro R series */
+	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
+
+	   /* Special Timing: 848x480 parallel lvds */
 	   if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
 	      if(HwInfo->jChipType < SIS_315H) {
 		 VCLKIndex = VCLK34_300;
@@ -2038,28 +2189,22 @@
 
         } else {
 
-	   VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-           VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-           if(ModeNo > 0x13) {
-              VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	      if(HwInfo->jChipType < SIS_315H) {
-    	 	 VCLKIndex &= 0x3F;
+	   VCLKIndex = VCLKIndexGEN;
+	   if(HwInfo->jChipType < SIS_315H) {
+              if(ModeNo > 0x13) {
+		 if( (HwInfo->jChipType == SIS_630) &&
+                     (HwInfo->jChipRevision >= 0x30) ) {
+		    if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
+	         }
               }
-	      if( (HwInfo->jChipType == SIS_630) &&
-                  (HwInfo->jChipRevision >= 0x30) ) {
-		 if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
-	      }
 	   }
         }
 
      } else {  /* if not programming CRT2 */
 
-        VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-        VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-        if(ModeNo > 0x13) {
-           VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-           if(HwInfo->jChipType < SIS_315H) {
-	      VCLKIndex &= 0x3F;
+        VCLKIndex = VCLKIndexGEN;
+	if(HwInfo->jChipType < SIS_315H) {
+           if(ModeNo > 0x13) {
 	      if( (HwInfo->jChipType != SIS_630) &&
 	          (HwInfo->jChipType != SIS_300) ) {
 		 if(VCLKIndex == 0x1b) VCLKIndex = 0x35;
@@ -2094,21 +2239,20 @@
 {
   USHORT i,j,modeflag;
   USHORT tempcl,tempah=0;
-#ifdef SIS300
-  USHORT temp;
+#if defined(SIS300) || defined(SIS315H)
+  USHORT tempbl;
 #endif
 #ifdef SIS315H
-  USHORT tempbl, tempah2, tempbl2;
+  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+  USHORT tempah2, tempbl2;
 #endif
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
   /* BIOS does not do this (neither 301 nor LVDS) */
@@ -2123,6 +2267,9 @@
   } else {
 
      for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
+     if(HwInfo->jChipType >= SIS_315H) {
+        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
+     }
 
      tempcl = SiS_Pr->SiS_ModeType;
 
@@ -2132,14 +2279,14 @@
 
         /* For 301BDH: (with LCD via LVDS) */
         if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-	   temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
-	   temp &= 0xef;
-	   temp |= 0x02;
+	   tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
+	   tempbl &= 0xef;
+	   tempbl |= 0x02;
 	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-	      temp |= 0x10;
-	      temp &= 0xfd;
+	      tempbl |= 0x10;
+	      tempbl &= 0xfd;
 	   }
-	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
         }
 
         if(ModeNo > 0x13) {
@@ -2226,8 +2373,8 @@
         }
 
         if((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301)) {
-	   if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-	      (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)) {
+	   if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1280x960)) {
 	      tempah |= 0x80;
 	   }
         } else {
@@ -2254,9 +2401,9 @@
        	   }
         }
 
-	if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)  ||
-	   ((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) &&
+	if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	   (SiS_Pr->SiS_LCDResInfo == Panel_1280x960)  ||
+	   ((SiS_Pr->SiS_LCDResInfo == Panel_Custom) &&
 	    (SiS_Pr->CP_MaxX >= 1280) && (SiS_Pr->CP_MaxY >= 960))) {
 	   tempah |= 0x80;
         }
@@ -2344,10 +2491,11 @@
 	 * in a 650 box (Jake). What is the criteria?
 	 */
 
-	if((IS_SIS740) || (HwInfo->jChipType >= SIS_661)) {
+	if((IS_SIS740) || (HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
 	   tempah = 0x30;
 	   tempbl = 0xc0;
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
+	   if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
+	      ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
 	      tempah = 0x00;
 	      tempbl = 0x00;
 	   }
@@ -2378,23 +2526,23 @@
 
 	if(IS_SIS740) {
 	   tempah = 0x80;
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
-	      tempah = 0x00;
-	   }
+	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
 	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
 	} else {
 	   tempah = 0x00;
            tempbl = 0x7f;
            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
               tempbl = 0xff;
-	      if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) {
-	         tempah = 0x80;
-	      }
+	      if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) tempah = 0x80;
            }
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
 	}
 
-	/* 661: Sets p4 27 and 34 here, done in SetGroup4 here */
+#if 0
+	if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0xc0);
+	}
+#endif
 
 #endif /* SIS315H */
 
@@ -2423,9 +2571,7 @@
 	   tempbl = 0xfb;
            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
               tempah = 0x00;
-	      if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
-	         tempbl = 0xff;
-	      }
+	      if(SiS_IsDualEdge(SiS_Pr, HwInfo)) tempbl = 0xff;
            }
 	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
 
@@ -2456,14 +2602,8 @@
 USHORT
 SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
 {
-  USHORT resindex;
-
-  if(ModeNo <= 0x13)
-     resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-  else
-     resindex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-
-  return(resindex);
+  if(ModeNo <= 0x13) return((USHORT)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
+  else               return((USHORT)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
 }
 
 static void
@@ -2473,8 +2613,12 @@
   USHORT xres,yres,modeflag=0,resindex;
 
   if(SiS_Pr->UseCustomMode) {
-     SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = SiS_Pr->CHDisplay;
-     SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
+     xres = SiS_Pr->CHDisplay;
+     if(SiS_Pr->CModeFlag & HalfDCLK) xres *= 2;
+     SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+     yres = SiS_Pr->CVDisplay;
+     if(SiS_Pr->CModeFlag & DoubleScanMode) yres *= 2;
+     SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
      return;
   }
 
@@ -2489,7 +2633,7 @@
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  if((!SiS_Pr->SiS_IF_DEF_DSTN) && (!SiS_Pr->SiS_IF_DEF_FSTN)) {
+  if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
 
      if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
         if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
@@ -2500,72 +2644,66 @@
         }
      }
 
-     if(ModeNo > 0x13) {
-  	if(modeflag & HalfDCLK)       xres *= 2;
-  	if(modeflag & DoubleScanMode) yres *= 2;
-     }
+     if(modeflag & HalfDCLK)       xres *= 2;
+     if(modeflag & DoubleScanMode) yres *= 2;
 
   }
 
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+
+#if 0
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
            if(xres == 720) xres = 640;
-	} else {
-	   if(SiS_Pr->SiS_VBType & VB_NoLCD) {           /* 301BDH */
-	        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
-                   if(xres == 720) xres = 640;
-		}
-		if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-	           yres = 400;
-	           if(HwInfo->jChipType >= SIS_315H) {
-	              if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
-	           } else {
-	              if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
-	           }
-	        }
-	   } else {
-	      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
-	         if(xres == 720) xres = 640;
-	      }
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		 if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-		    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        	       if(yres == 1024) yres = 1056;
-      		    }
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-		    if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-		       /* BIOS bug - does this regardless of scaling */
-      		       if(yres == 400) yres = 405;
-		    }
-      		    if(yres == 350) yres = 360;
-      		    if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-        	       if(yres == 360) yres = 375;
-      		    }
-   	         } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-      		    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        	       if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-          	          if(yres == 350) yres = 357;
-          	          if(yres == 400) yres = 420;
-            	          if(yres == 480) yres = 525;
-        	       }
-      		    }
-    	         }
+	}
+#endif
+
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	   switch(SiS_Pr->SiS_LCDResInfo) {
+	   case Panel_1024x768:
+	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+                 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+          	    if(yres == 350) yres = 357;
+          	    if(yres == 400) yres = 420;
+            	    if(yres == 480) yres = 525;
+        	 }
+      	      }
+	      break;
+	   case Panel_1280x1024:
+	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+		 /* BIOS bug - does this regardless of scaling */
+      		 if(yres == 400) yres = 405;
 	      }
+      	      if(yres == 350) yres = 360;
+      	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+                 if(yres == 360) yres = 375;
+      	      }
+	      break;
+	   case Panel_1600x1200:
+	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+        	 if(yres == 1024) yres = 1056;
+      	      }
+	      break;
 	   }
 	}
+
   } else {
-    	if(xres == 720) xres = 640;
-	if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-	   yres = 400;
-	   if(HwInfo->jChipType >= SIS_315H) {
-	      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
-	   } else {
-	      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
-	   }
-	   if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
-	      yres = 480;
-	   }
+
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
+           if(xres == 720) xres = 640;
 	}
+     } else if(xres == 720) xres = 640;
+
+     if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+	yres = 400;
+        if(HwInfo->jChipType >= SIS_315H) {
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
+        } else {
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
+        }
+        if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN)  yres = 480;
+     }
+
   }
   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
@@ -2580,103 +2718,84 @@
 		   USHORT RefreshRateTableIndex, USHORT *ResIndex,
 		   USHORT *DisplayType)
  {
-  USHORT tempbx,modeflag=0;
-  USHORT Flag,CRT2CRTC;
+  USHORT modeflag=0;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
      }
   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
+     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))    return FALSE;
   } else
      return FALSE;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     CRT2CRTC = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     CRT2CRTC = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
   }
 
-  Flag = 1;
-  tempbx = 0;
-  if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-        Flag = 0;
-        tempbx = 18;
-        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-      	   tempbx += 2;
-	   if(SiS_Pr->SiS_ModeType > ModeVGA) {
-	      if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
-	   }
-	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-	      tempbx = 18;  /* PALM uses NTSC data */
-	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-	   } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-	      tempbx = 20;  /* PALN uses PAL data  */
-	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-	   }
-        }
+  (*ResIndex) &= 0x3F;
+
+  if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+     (*DisplayType) = 18;
+     if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+      	(*DisplayType) += 2;
+	if(SiS_Pr->SiS_ModeType > ModeVGA) {
+	   if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 99;
+	}
+	if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+	   (*DisplayType) = 18;  /* PALM uses NTSC data */
+	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+	} else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+	   (*DisplayType) = 20;  /* PALN uses PAL data  */
+	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+	}
      }
-  }
-  if(Flag) {
-     tempbx = SiS_Pr->SiS_LCDResInfo;
-     tempbx -= SiS_Pr->SiS_PanelMinLVDS;
-     if(SiS_Pr->SiS_LCDResInfo <= SiS_Pr->SiS_Panel1280x1024) {
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 6;
-        if(modeflag & HalfDCLK) tempbx += 3;
-     } else {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-           tempbx = 14;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-           tempbx = 23;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
-           tempbx = 27;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-           tempbx = 36;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-           tempbx = 40;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-           tempbx = 54;
-	   if(modeflag & HalfDCLK) tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2) {
-           tempbx = 52;
-	   if(modeflag & HalfDCLK) tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-           tempbx = 50;
-	   if(modeflag & HalfDCLK) tempbx++;
-        }
+  } else {
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:   (*DisplayType) = 50; break;
+     case Panel_640x480_2: (*DisplayType) = 52; break;
+     case Panel_640x480_3: (*DisplayType) = 54; break;
+     case Panel_800x600:   (*DisplayType) =  0; break;
+     case Panel_1024x600:  (*DisplayType) = 23; break;
+     case Panel_1024x768:  (*DisplayType) =  4; break;
+     case Panel_1152x768:  (*DisplayType) = 27; break;
+     case Panel_1280x768:  (*DisplayType) = 40; break;
+     case Panel_1280x1024: (*DisplayType) =  8; break;
+     case Panel_1400x1050: (*DisplayType) = 14; break;
+     case Panel_1600x1200: (*DisplayType) = 36; break;
+     default: return FALSE;
+     }
+
+     if(modeflag & HalfDCLK) (*DisplayType)++;
 
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:
+     case Panel_640x480_2:
+     case Panel_640x480_3:
+        break;
+     default:
+        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
      }
+
      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-        tempbx = 12;
-	if(modeflag & HalfDCLK) tempbx++;
+        (*DisplayType) = 12;
+	if(modeflag & HalfDCLK) (*DisplayType)++;
      }
   }
 
 #if 0
   if(SiS_Pr->SiS_IF_DEF_FSTN) {
      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
-        tempbx = 22;
+        (*DisplayType) = 22;
      }
   }
 #endif
 
-  *ResIndex = CRT2CRTC & 0x3F;
-  *DisplayType = tempbx;
   return TRUE;
 }
 
@@ -2685,8 +2804,7 @@
 	       USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex,
 	       PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx=0,tempal=0;
-  USHORT Flag,resinfo=0;
+  USHORT tempbx=0,tempal=0,resinfo=0;
 
   if(ModeNo <= 0x13) {
      tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -2699,55 +2817,35 @@
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
 
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-	   tempbx = 15;
-  	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   tempbx = 20;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 21;
-	   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 22;
- 	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-	   tempbx = 23;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 24;
-	   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 25;
-#if 0
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-	   tempbx = 26;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 27;
-	   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 28;
-#endif
- 	} else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)       tempbx = 13;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempbx = 14;
-	      else {
-	         tempbx = 29;
-		 if(ModeNo >= 0x13) {
-	            /* see below */
-	            if(resinfo == SIS_RI_1280x960) tempal = 10;
-	         }
-              }
-	   } else {
-	      tempbx = 29;
-	      if(ModeNo >= 0x13) {
-	         /* 1280x768 and 1280x960 have same CRT2CRTC,
-	          * so we change it here if 1280x960 is chosen
-	          */
-	         if(resinfo == SIS_RI_1280x960) tempal = 10;
+        tempbx = SiS_Pr->SiS_LCDResInfo;
+	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
+
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
+	   if     (resinfo == SIS_RI_1280x800)  tempal =  9;
+	   else if(resinfo == SIS_RI_1400x1050) tempal = 11;
+	}
+
+  	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {  /* Pass 1:1 only (center-screen handled outside) */
+	   tempbx = 100;
+	   if(ModeNo >= 0x13) {
+	      tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+	      if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+	         (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes ==  768)) {
+	         /* Special for Fujitsu 7911 (VL-17WDX8), others custom */
+	         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768)        tempal = 0x08;
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_2) tempal = 0x0f;
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_3) tempal = 0x10;
 	      }
-   	   }
-	} else {
-      	   tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_Panel1024x768;
-      	   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-              tempbx += 10;
-       	   }
+	   }
 	}
 
 #ifdef SIS315H
 	if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-	      tempbx = 50;
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 51;
-	      else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 52;
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+	         tempbx = 200;
+	         if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
+	      }
 	   }
 	}
 #endif
@@ -2783,12 +2881,20 @@
 	      (resinfo == SIS_RI_720x576) ||
 	      (resinfo == SIS_RI_768x576)) {
 	      tempal = 6;
+	      if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) {
+	         if(resinfo == SIS_RI_720x480) tempal = 9;
+	      }
 	   }
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
               if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
-	         if(resinfo == SIS_RI_1024x768) {
+	         if(resinfo == SIS_RI_1024x768) tempal = 8;
+	      }
+	      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+		 if((resinfo == SIS_RI_720x576) ||
+	            (resinfo == SIS_RI_768x576)) {
 	            tempal = 8;
 	         }
+		 if(resinfo == SIS_RI_1280x720) tempal = 9;
 	      }
 	   }
 	}
@@ -2799,70 +2905,54 @@
 
   } else {   /* LVDS, 301B-DH (if running on LCD) */
 
-     Flag = 1;
      tempbx = 0;
-     if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-        if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-           Flag = 0;
-           tempbx = 10;
-	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-           if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	      tempbx += 2;
-	      if(SiS_Pr->SiS_ModeType > ModeVGA) {
-		 if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
-	      }
-	      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-		 tempbx = 90;
-		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-	      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-		 tempbx = 92;
-		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-	      }
-           }
-        }
-     }
-
-     if(Flag) {
-
-	if(SiS_Pr->SiS_LCDResInfo <= SiS_Pr->SiS_Panel1280x1024) {
-	   tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_PanelMinLVDS;
-   	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 3;
-
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-	      tempbx = 82;
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
+     if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+        tempbx = 10;
+	if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	   tempbx += 2;
+	   if(SiS_Pr->SiS_ModeType > ModeVGA) {
+	      if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
 	   }
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-	   tempbx = 18;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-	   tempbx = 6;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2) {
-	   tempbx = 30;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-	   tempbx = 30;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-	   tempbx = 15;
-  	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 2;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
-	   tempbx = 16;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 2;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   tempbx = 8;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-	   tempbx = 21;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelBarco1366) {
-	   tempbx = 80;
-   	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
+	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+	      tempbx = 90;
+	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+	   } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+	      tempbx = 92;
+	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+	   }
+        }
+     } else {
+        switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_640x480:   tempbx = 6;  break;
+	case Panel_640x480_2: tempbx = 30; break;
+	case Panel_640x480_3: tempbx = 30; break;
+	case Panel_800x600:   tempbx = 0;  break;
+	case Panel_1024x600:  tempbx = 15; break;
+	case Panel_1024x768:  tempbx = 2;  break;
+	case Panel_1152x768:  tempbx = 17; break;
+	case Panel_1280x768:  tempbx = 18; break;
+	case Panel_1280x1024: tempbx = 4;  break;
+	case Panel_1400x1050: tempbx = 8;  break;
+	case Panel_1600x1200: tempbx = 21; break;
+	case Panel_Barco1366: tempbx = 80; break;
+	}
+
+	switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_640x480:
+	case Panel_640x480_2:
+	case Panel_640x480_3:
+	   break;
+	default:
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
 	}
 
-	if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-	   tempbx = 7;
-        }
+	if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 7;
 
-	if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
+	if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+	   tempbx = 82;
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
+	} else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
 	   tempbx = 84;
 	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
 	}
@@ -2870,45 +2960,17 @@
      }
 
      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) tempal = 7;
+        if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) tempal = 7;
   	if(HwInfo->jChipType < SIS_315H) {
 	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) tempal++;
 	}
      }
 
-     *CRT2Index = tempbx;
-     *ResIndex = tempal & 0x1F;
+     (*CRT2Index) = tempbx;
+     (*ResIndex) = tempal & 0x1F;
   }
 }
 
-#ifdef SIS315H
-static void
-SiS_GetCRT2PtrA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-		USHORT RefreshRateTableIndex,USHORT *CRT2Index,
-		USHORT *ResIndex)
-{
-  USHORT tempbx,tempal;
-
-  tempbx = SiS_Pr->SiS_LCDResInfo;
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)      tempbx = 4;
-  else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempbx = 3;
-  else tempbx -= SiS_Pr->SiS_Panel1024x768;
-
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 5;
-
-  if(ModeNo <= 0x13)
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  else
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  /* No customs required yet (Clevo, Compaq, etc) */
-
-  *CRT2Index = tempbx;
-  *ResIndex = tempal & 0x1F;
-}
-#endif
-
 static void
 SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
                    USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
@@ -2969,8 +3031,7 @@
 
 static void
 SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-                    USHORT RefreshRateTableIndex,
-		    PSIS_HW_INFO HwInfo)
+                    USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
 {
    USHORT CRT2Index, ResIndex;
    const SiS_LVDSDataStruct *LVDSData = NULL;
@@ -2988,23 +3049,55 @@
       SiS_Pr->SiS_RY4COE = 0;
    }
 
-   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
 #ifdef SIS315H
-      SiS_GetCRT2PtrA(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-                      &CRT2Index,&ResIndex);
-
-      switch (CRT2Index) {
-      	case  0:  LVDSData = SiS_Pr->SiS_LCDA1024x768Data_1;    break;
-      	case  1:  LVDSData = SiS_Pr->SiS_LCDA1280x1024Data_1;   break;
-	case  3:  LVDSData = SiS_Pr->SiS_LCDA1400x1050Data_1;   break;
-	case  4:  LVDSData = SiS_Pr->SiS_LCDA1600x1200Data_1;   break;
-      	case  5:  LVDSData = SiS_Pr->SiS_LCDA1024x768Data_2;    break;
-      	case  6:  LVDSData = SiS_Pr->SiS_LCDA1280x1024Data_2;   break;
-	case  8:  LVDSData = SiS_Pr->SiS_LCDA1400x1050Data_2;   break;
-	case  9:  LVDSData = SiS_Pr->SiS_LCDA1600x1200Data_2;   break;
-	default:  LVDSData = SiS_Pr->SiS_LCDA1024x768Data_1;    break;
+      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+         if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+	    if(SiS_Pr->UseCustomMode) {
+	       SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
+	       SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+	    } else {
+	       if(ModeNo < 0x13) {
+	          ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+	       } else {
+	          ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+		  /* Special for our 3 types, others custom (works with default) */
+		  if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+	             (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes ==  768)) {
+	             if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768)        ResIndex = 0x08;
+		     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_2) ResIndex = 0x0f;
+		     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_3) ResIndex = 0x10;
+	          }
+		  /* Special for 1280x720 TMDS <> LVDS */
+		  if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+	             (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes ==  720)) {
+		     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x720) {
+		        if(SiS_Pr->PanelHT == 1344) ResIndex = 0x12;
+		     }
+	          }
+	       }
+	       SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
+               SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
+               SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
+               SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
+	    }
+	 } else {
+     	    SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+            SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+	 }
+      } else {
+	 /* This handles custom modes and custom panels */
+	 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+         SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+         SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
+         SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
+	 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
+	 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
       }
+
+      SiS_CalcLCDACRT1Timing(SiS_Pr,ModeNo,ModeIdIndex);
+
 #endif
 
    } else {
@@ -3015,7 +3108,7 @@
       }
 
       SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                     &CRT2Index, &ResIndex, HwInfo);
+                     		&CRT2Index, &ResIndex, HwInfo);
 
       /* 301BDH needs LVDS Data */
       if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
@@ -3023,72 +3116,59 @@
       }
 
       switch (CRT2Index) {
-      	case  0:  LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
-      	case  1:  LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
-      	case  2:  LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1;  break;
-      	case  3:  LVDSData = SiS_Pr->SiS_LVDS800x600Data_2;    break;
-      	case  4:  LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2;   break;
-      	case  5:  LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2;  break;
-	case  6:  LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
-        case  7:  LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1;    break;
-	case  8:  LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1;  break;
-	case  9:  LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2;  break;
-      	case 10:  LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
-      	case 11:  LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
-      	case 12:  LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
-      	case 13:  LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
-      	case 14:  LVDSData = SiS_Pr->SiS_LVDS320x480Data_1;    break;
-	case 15:  LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
-	case 16:  LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1;   break;
-	case 17:  LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2;   break;
-	case 18:  LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2;   break;
-	case 19:  LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1;   break;
-	case 20:  LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2;   break;
-	case 21:  LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1;  break;
-	case 22:  LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2;  break;
-	case 30:  LVDSData = SiS_Pr->SiS_LVDS640x480Data_2;    break;
-	case 80:  LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
-	case 81:  LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
-	case 82:  LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
-	case 83:  LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2;  break;
-	case 84:  LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
-	case 85:  LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
-	case 90:  LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
-      	case 91:  LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
-      	case 92:  LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
-      	case 93:  LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
-	case 99:  LVDSData = SiS_Pr->SiS_CHTVSOPALData;	       break;  /* Super Overscan */
-	default:  LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
-      }
-   }
+      	 case  0: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
+	 case  1: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2;    break;
+      	 case  2: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
+	 case  3: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2;   break;
+      	 case  4: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1;  break;
+      	 case  5: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2;  break;
+	 case  6: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
+         case  7: LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1;    break;
+	 case  8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1;  break;
+	 case  9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2;  break;
+      	 case 10: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
+      	 case 11: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
+      	 case 12: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
+      	 case 13: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
+      	 case 14: LVDSData = SiS_Pr->SiS_LVDS320x480Data_1;    break;
+	 case 15: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
+	 case 16: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2;   break;
+	 case 17: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1;   break;
+	 case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2;   break;
+	 case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1;   break;
+	 case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2;   break;
+	 case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1;  break;
+	 case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2;  break;
+	 case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2;    break;
+	 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
+	 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
+	 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
+	 case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2;  break;
+	 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
+	 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
+	 case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
+      	 case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
+      	 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
+      	 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
+	 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;	       break;  /* Super Overscan */
+	 default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
+      }
+
+      SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
+      SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
+      SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
+      SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
 
-   SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
-   SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
-   SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
-   SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
-
-   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-         SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-         SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-      }
-
-   } else {
-
-      if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
+      if(!(SiS_Pr->SiS_VBType & VB_SISVB)) {
          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-            if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-               if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-	          SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-                  SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-
-	 	  if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-		     if(ResIndex < 0x08) {
-		        SiS_Pr->SiS_HDE = 1280;
-                        SiS_Pr->SiS_VDE = 1024;
-		     }
-		  }
+            if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+	       SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+               SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+	       if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+		  if(ResIndex < 0x08) {
+		     SiS_Pr->SiS_HDE = 1280;
+                     SiS_Pr->SiS_VDE = 1024;
+                  }
                }
             }
          }
@@ -3101,23 +3181,38 @@
                    USHORT RefreshRateTableIndex,
 		   PSIS_HW_INFO HwInfo)
 {
-  USHORT tempax,tempbx,modeflag;
-  USHORT resinfo;
-  USHORT CRT2Index,ResIndex;
+  UCHAR  *ROMAddr = NULL;
+  USHORT tempax,tempbx,modeflag,romptr=0;
+  USHORT resinfo,CRT2Index,ResIndex;
   const SiS_LCDDataStruct *LCDPtr = NULL;
   const SiS_TVDataStruct  *TVPtr  = NULL;
+#ifdef SIS315H
+  SHORT  resinfo661;
+#endif
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	resinfo = 0;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+#ifdef SIS315H
+     resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
+     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
+         (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
+         (resinfo661 >= 0)                     &&
+	 (SiS_Pr->SiS_NeedRomModeData) ) {
+        if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+	   if((romptr = (SISGETROMW(21)))) {
+              romptr += (resinfo661 * 10);
+	      ROMAddr = HwInfo->pjVirtualRomBase;
+	   }
+	}
      }
+#endif
   }
   
   SiS_Pr->SiS_NewFlickerMode = 0;
@@ -3145,6 +3240,7 @@
      } else {
 
         SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+
      }
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
@@ -3153,20 +3249,20 @@
                     &CRT2Index,&ResIndex,HwInfo);
 
      switch(CRT2Index) {
-       case  2:  TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
-       case  3:  TVPtr = SiS_Pr->SiS_ExtPALData;    break;
-       case  4:  TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
-       case  5:  TVPtr = SiS_Pr->SiS_Ext525iData;   break;
-       case  6:  TVPtr = SiS_Pr->SiS_Ext525pData;   break;
-       case  7:  TVPtr = SiS_Pr->SiS_Ext750pData;   break;
-       case  8:  TVPtr = SiS_Pr->SiS_StPALData;     break;
-       case  9:  TVPtr = SiS_Pr->SiS_StNTSCData;    break;
-       case 10:  TVPtr = SiS_Pr->SiS_St525iData;    break;
-       case 11:  TVPtr = SiS_Pr->SiS_St525pData;    break;
-       case 12:  TVPtr = SiS_Pr->SiS_St750pData;    break;
-       case 13:  TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
-       case 14:  TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
-       default:  TVPtr = SiS_Pr->SiS_StPALData;     break;
+        case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
+        case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
+        case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
+        case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
+        case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
+        case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
+        case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
+        case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
+        case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
+        case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
+        case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
+        case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
+        case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
+        default: TVPtr = SiS_Pr->SiS_StPALData;     break;
      }
 
      SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
@@ -3247,10 +3343,11 @@
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 
+     SiS_Pr->SiS_RVBHCMAX  = 1;
+     SiS_Pr->SiS_RVBHCFACT = 1;
+
      if(SiS_Pr->UseCustomMode) {
 
-        SiS_Pr->SiS_RVBHCMAX  = 1;
-        SiS_Pr->SiS_RVBHCFACT = 1;
         SiS_Pr->SiS_VGAHT     = SiS_Pr->CHTotal;
         SiS_Pr->SiS_VGAVT     = SiS_Pr->CVTotal;
         SiS_Pr->SiS_HT        = SiS_Pr->CHTotal;
@@ -3260,58 +3357,85 @@
 
      } else {
 
-        SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-                      &CRT2Index,&ResIndex,HwInfo);
+        BOOLEAN gotit = FALSE;
 
-        switch(CRT2Index) {
-         case  0: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;        break; /* VESA Timing */
-         case  1: LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;       break; /* VESA Timing */
-         case  5: LCDPtr = SiS_Pr->SiS_StLCD1024x768Data;         break; /* Obviously unused */
-         case  6: LCDPtr = SiS_Pr->SiS_StLCD1280x1024Data;        break; /* Obviously unused */
-         case 10: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;        break; /* Non-VESA Timing */
-         case 11: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;       break; /* Non-VESA Timing */
-         case 13: LCDPtr = SiS_Pr->SiS_NoScaleData1024x768;       break; /* Non-expanding */
-         case 14: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024;      break; /* Non-expanding */
-         case 15: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;           break; /* 1280x960 */
-         case 20: LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;       break; /* VESA Timing */
-         case 21: LCDPtr = SiS_Pr->SiS_NoScaleData1400x1050;      break; /* Non-expanding (let panel scale) */
-         case 22: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;        break; /* Non-VESA Timing (let panel scale) */
-         case 23: LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;       break; /* VESA Timing */
-         case 24: LCDPtr = SiS_Pr->SiS_NoScaleData1600x1200;      break; /* Non-expanding */
-         case 25: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;        break; /* Non-VESA Timing */
-         case 26: LCDPtr = SiS_Pr->SiS_ExtLCD1280x768Data;        break; /* VESA Timing */
-         case 27: LCDPtr = SiS_Pr->SiS_NoScaleData1280x768;       break; /* Non-expanding */
-         case 28: LCDPtr = SiS_Pr->SiS_StLCD1280x768Data;         break; /* Non-VESA Timing */
-         case 29: LCDPtr = SiS_Pr->SiS_NoScaleData;	          break; /* Generic no-scale data */
-#ifdef SIS315H
-	 case 50: LCDPtr = (SiS_LCDDataStruct *)SiS310_ExtCompaq1280x1024Data;	break;
-	 case 51: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024;			break;
-	 case 52: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;	  		break;
-#endif
-         default: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;	  break;
-        }
-
-        SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
-        SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
-        SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
-        SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
-        SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
-        SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
+        if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+
+           SiS_Pr->SiS_VGAHT     = SiS_Pr->PanelHT;
+           SiS_Pr->SiS_VGAVT     = SiS_Pr->PanelVT;
+           SiS_Pr->SiS_HT        = SiS_Pr->PanelHT;
+           SiS_Pr->SiS_VT        = SiS_Pr->PanelVT;
+	   gotit = TRUE;
+
+	} else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
+
+#ifdef SIS315H
+	   SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
+           SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
+           SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
+           SiS_Pr->SiS_VGAVT     = ROMAddr[romptr+4] | ((ROMAddr[romptr+3] & 0xf0) << 4);
+           SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
+           SiS_Pr->SiS_VT        = ROMAddr[romptr+7] | ((ROMAddr[romptr+6] & 0xf0) << 4);
+	   if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
+#endif
+
+	}
+
+	if(!gotit) {
+
+           SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+                          &CRT2Index,&ResIndex,HwInfo);
+
+           switch(CRT2Index) {
+	      case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
+	      case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
+	      case Panel_1280x720      :
+	      case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
+	      case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
+              case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
+	      case Panel_1280x768_3    :
+	      case Panel_1280x768_3+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x768_3Data;    break;
+	      case Panel_1280x800      :
+	      case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
+	      case Panel_1280x960      :
+	      case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
+              case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
+              case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
+              case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
+              case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
+              case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
+              case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
+	      case Panel_1680x1050     :
+	      case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
+	      case 100		       : LCDPtr = SiS_Pr->SiS_NoScaleData;	    break;
+#ifdef SIS315H
+	      case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
+	      case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
+#endif
+              default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
+           }
 
 #ifdef TWDEBUG
-        xf86DrvMsg(0, X_INFO,
-    	    "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+           xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
 #endif
 
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-           tempax = 1024;
+           SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
+           SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
+           SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
+           SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
+           SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
+           SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
+
+        }
+
+	tempax = SiS_Pr->PanelXRes;
+        tempbx = SiS_Pr->PanelYRes;
+
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
            if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
               if(HwInfo->jChipType < SIS_315H) {
                  if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
                  else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-                 else                               tempbx = 768;
-              } else {
-                 tempbx = 768;
               }
            } else {
               if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
@@ -3320,43 +3444,27 @@
               else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
               else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
               else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-              else                               tempbx = 768;
            }
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-           tempax = 1280;
-           if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
-           else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
-           else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
-           else                               tempbx = 1024;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-           tempax = 1280;
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) {
            if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
            else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
            else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
-           else                                tempbx = 960;
-	} else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) &&
-	          (HwInfo->jChipType >= SIS_661)) {
-	   tempax = 1400;
-	   tempbx = 1050;
-	   if(SiS_Pr->SiS_VGAVDE == 1024) {
-	      tempax = 1280;
-	      tempbx = 1024;
-	   }
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-           tempax = 1600;
-	   tempbx = 1200;
-	   if((HwInfo->jChipType < SIS_661) || (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))) {
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+           if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
+           else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
+           else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
+        } else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) {
+	   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
               if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
               else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
            }
-        } else {
-	   tempax = SiS_Pr->PanelXRes;
-           tempbx = SiS_Pr->PanelYRes;
-	}
+        }
+
         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
            tempax = SiS_Pr->SiS_VGAHDE;
            tempbx = SiS_Pr->SiS_VGAVDE;
         }
+
         SiS_Pr->SiS_HDE = tempax;
         SiS_Pr->SiS_VDE = tempbx;
      }
@@ -3370,31 +3478,15 @@
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-
-           SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
-        } else {
-
-	   if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-
-	      /* Need LVDS Data for LCD on 301B-DH */
-	      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
-	   } else {
-
-	      SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
-           }
-
-        }
-
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+        SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
      } else {
-
-     	SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
+	if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+	   /* Need LVDS Data for LCD on 301B-DH */
+	   SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+	} else {
+	   SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+        }
      }
 
   } else {
@@ -3405,7 +3497,7 @@
 }
 
 /*********************************************/
-/*            GET LVDS DES DATA              */
+/*         GET LVDS DES (SKEW) DATA          */
 /*********************************************/
 
 static void
@@ -3413,107 +3505,56 @@
                   USHORT RefreshRateTableIndex, USHORT *PanelIndex,
 		  USHORT *ResIndex, PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx,tempal,modeflag;
+  USHORT modeflag;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
   }
 
-  tempbx = 0;
+  (*ResIndex) &= 0x1F;
+  (*PanelIndex) = 0;
+
   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        tempbx = 50;
-        if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) tempbx += 2;
-        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+        (*PanelIndex) = 50;
+        if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) (*PanelIndex) += 2;
+        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*PanelIndex) += 1;
         /* Nothing special needed for SOverscan    */
-        /*     PALM uses NTSC data, PALN uses PAL data */
+        /* PALM uses NTSC data, PALN uses PAL data */
      }
   }
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     tempbx = SiS_Pr->SiS_LCDTypeInfo;
+     *PanelIndex = SiS_Pr->SiS_LCDTypeInfo;
      if(HwInfo->jChipType >= SIS_661) {
         /* As long as we don's use the BIOS tables, we
 	 * need to convert the TypeInfo as for 315 series
 	 */
-        tempbx = SiS_Pr->SiS_LCDResInfo - 1;
+        (*PanelIndex) = SiS_Pr->SiS_LCDResInfo - 1;
      }
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 16;
-     if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-        tempbx = 32;
-        if(modeflag & HalfDCLK) tempbx++;
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        (*PanelIndex) += 16;
+        if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+           (*PanelIndex) = 32;
+           if(modeflag & HalfDCLK) (*PanelIndex)++;
+	}
      }
   }
 
   if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)  {
-        tempal = 0x07;
+     if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
+        (*ResIndex) = 7;
         if(HwInfo->jChipType < SIS_315H) {
-           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) tempal++;
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) (*ResIndex)++;
         }
      }
   }
-
-  *PanelIndex = tempbx;
-  *ResIndex = tempal & 0x1F;
 }
 
-#ifdef SIS315H
-static void
-SiS_GetLVDSDesPtrA(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                   USHORT RefreshRateTableIndex, USHORT *PanelIndex, USHORT *ResIndex,
-		   PSIS_HW_INFO HwInfo)
-{
-  USHORT tempbx=0,tempal;
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)      tempbx = 2;
-  else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempbx = 3;
-  else tempbx = SiS_Pr->SiS_LCDResInfo - 2;
-
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 4;
-
-  if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-	   tempbx = 80;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-	}
-     }
-  }
-  if((SiS_Pr->SiS_CustomT == CUT_UNIWILL1024) ||
-     (SiS_Pr->SiS_CustomT == CUT_UNIWILL10242)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	tempbx = 82;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-     }
-  }
-  if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-	tempbx = 84;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-     }
-  }
-  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	tempbx = 86;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-     }
-  }
-
-  if(ModeNo <= 0x13)
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  else
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  *PanelIndex = tempbx;
-  *ResIndex = tempal & 0x1F;
-}
-#endif
-
 static void
 SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
                    USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
@@ -3522,39 +3563,45 @@
   USHORT PanelIndex,ResIndex;
   const  SiS_LVDSDesStruct *PanelDesPtr = NULL;
 
-  if((SiS_Pr->UseCustomMode) ||
-     (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) ||
-     (SiS_Pr->SiS_CustomT == CUT_PANEL848)) {
-     SiS_Pr->SiS_LCDHDES = 0;
-     SiS_Pr->SiS_LCDVDES = 0;
+  SiS_Pr->SiS_LCDHDES = 0;
+  SiS_Pr->SiS_LCDVDES = 0;
+
+  if( (SiS_Pr->UseCustomMode) 		         ||
+      (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
+      ((SiS_Pr->SiS_VBType & VB_SISVB) &&
+       (SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
+       (SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
      return;
   }
 
   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
 #ifdef SIS315H
-     SiS_GetLVDSDesPtrA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                        &PanelIndex, &ResIndex, HwInfo);
-
-     switch (PanelIndex)
-     {
-     	case  0: PanelDesPtr = SiS_Pr->LVDS1024x768Des_1;   break;  /* --- expanding --- */
-     	case  1: PanelDesPtr = SiS_Pr->LVDS1280x1024Des_1;  break;
-	case  2: PanelDesPtr = SiS_Pr->LVDS1400x1050Des_1;  break;
-	case  3: PanelDesPtr = SiS_Pr->LVDS1600x1200Des_1;  break;
-     	case  4: PanelDesPtr = SiS_Pr->LVDS1024x768Des_2;   break;  /* --- non expanding --- */
-     	case  5: PanelDesPtr = SiS_Pr->LVDS1280x1024Des_2;  break;
-	case  6: PanelDesPtr = SiS_Pr->LVDS1400x1050Des_2;  break;
-	case  7: PanelDesPtr = SiS_Pr->LVDS1600x1200Des_2;  break;
-	case 80: PanelDesPtr = (SiS_LVDSDesStruct *)Clevo1024x768Des_1;   break;  /*  custom  */
-	case 81: PanelDesPtr = (SiS_LVDSDesStruct *)Clevo1024x768Des_2;   break;
-	case 82: PanelDesPtr = (SiS_LVDSDesStruct *)Uniwill1024x768Des_1; break;
-	case 83: PanelDesPtr = (SiS_LVDSDesStruct *)Uniwill1024x768Des_2; break;
-	case 84: PanelDesPtr = (SiS_LVDSDesStruct *)Compaq1280x1024Des_1; break;
-	case 85: PanelDesPtr = (SiS_LVDSDesStruct *)Compaq1280x1024Des_2; break;
-	case 86: PanelDesPtr = (SiS_LVDSDesStruct *)Asus1024x768Des_1;    break;  /*  custom  */
-	case 87: PanelDesPtr = (SiS_LVDSDesStruct *)Asus1024x768Des_2;    break;
-	default: PanelDesPtr = SiS_Pr->LVDS1024x768Des_1;   break;
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        /* non-pass 1:1 only, see above */
+        if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
+           SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+	}
+	if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+	   SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
+	}
+     }
+     if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+        switch(SiS_Pr->SiS_CustomT) {
+        case CUT_UNIWILL1024:
+        case CUT_UNIWILL10242:
+        case CUT_CLEVO1400:
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   }
+	   break;
+	}
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+	   if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   }
+	}
      }
 #endif
 
@@ -3563,87 +3610,68 @@
      SiS_GetLVDSDesPtr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
                        &PanelIndex, &ResIndex, HwInfo);
 
-     switch (PanelIndex)
-     {
-     	case  0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1;   break;   /* ---  */
-     	case  1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1;   break;
-     	case  2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1;   break;
-     	case  3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1;   break;
-     	case  4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1;   break;
-     	case  5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1;   break;
-     	case  6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1;   break;
-     	case  7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1;   break;
-     	case  8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1;   break;
-     	case  9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1;   break;
-     	case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1;   break;
-     	case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1;   break;
-     	case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1;   break;
-     	case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1;   break;
-     	case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;   break;
-     	case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1;   break;
-     	case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2;   break;    /* --- */
-     	case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2;   break;
-     	case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2;   break;
-     	case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2;   break;
-     	case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2;   break;
-     	case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2;   break;
-     	case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2;   break;
-     	case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2;   break;
-     	case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2;   break;
-     	case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2;   break;
-     	case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2;   break;
-     	case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2;   break;
-     	case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2;   break;
-     	case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2;   break;
-     	case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2;   break;
-     	case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2;   break;
-	case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1;   break;    /* pass 1:1 */
-	case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2;   break;
-     	case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData;   break; /* TV */
-     	case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData;   break;
-     	case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData;    break;
-     	case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData;    break;
-	default:
-		 if(HwInfo->jChipType < SIS_315H)
-		    PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;
-		 else
-		    PanelDesPtr = SiS_Pr->SiS_PanelType01_1;
-		 break;
-     }
-  }
-  SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
-  SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
-
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD){
-     if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-        if(ModeNo <= 0x13) {
-           modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-	   if(!(modeflag & HalfDCLK)) {
-	      SiS_Pr->SiS_LCDHDES = 632;
-	   }
-        }
-     } else {
-        if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) {
-              if(SiS_Pr->SiS_LCDResInfo >= SiS_Pr->SiS_Panel1024x768) {
-                 if(ModeNo <= 0x13) {
-	            modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-	            if(HwInfo->jChipType < SIS_315H) {
-	               if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
-	            } else {
-	               if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)
-	                  SiS_Pr->SiS_LCDHDES = 480;
-                       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)
-	                  SiS_Pr->SiS_LCDHDES = 804;
-		       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)
-	                  SiS_Pr->SiS_LCDHDES = 704;
-                       if(!(modeflag & HalfDCLK)) {
-                          SiS_Pr->SiS_LCDHDES = 320;
-	                  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)
-	                     SiS_Pr->SiS_LCDHDES = 632;
-		          else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)
-	                     SiS_Pr->SiS_LCDHDES = 542;
-                       }
+     switch(PanelIndex) {
+     	case  0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1;    break;   /* ---  */
+     	case  1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1;    break;
+     	case  2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1;    break;
+     	case  3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1;    break;
+     	case  4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1;    break;
+     	case  5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1;    break;
+     	case  6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1;    break;
+     	case  7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1;    break;
+     	case  8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1;    break;
+     	case  9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1;    break;
+     	case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1;    break;
+     	case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1;    break;
+     	case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1;    break;
+     	case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1;    break;
+     	case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;    break;
+     	case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1;    break;
+     	case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2;    break;    /* --- */
+     	case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2;    break;
+     	case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2;    break;
+     	case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2;    break;
+     	case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2;    break;
+     	case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2;    break;
+     	case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2;    break;
+     	case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2;    break;
+     	case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2;    break;
+     	case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2;    break;
+     	case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2;    break;
+     	case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2;    break;
+     	case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2;    break;
+     	case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2;    break;
+     	case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2;    break;
+     	case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2;    break;
+	case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1;    break;    /* pass 1:1 */
+	case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2;    break;
+     	case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData; break;    /* TV */
+     	case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break;
+     	case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData;  break;
+     	case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData;  break;
+	default: return;
+     }
+
+     SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
+     SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
+
+     if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+        modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+        if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+	   if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
+        } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+           if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+              if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
+	         if(HwInfo->jChipType < SIS_315H) {
+	            if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
+	         } else {
+	            if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
+                    if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
+		    if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
+                    if(!(modeflag & HalfDCLK)) {
+                       SiS_Pr->SiS_LCDHDES = 320;
+	               if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
+		       if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
                     }
                  }
               }
@@ -3654,18 +3682,6 @@
 }
 
 /*********************************************/
-/*          SET CRT2 AUTO-THRESHOLD          */
-/*********************************************/
-
-#ifdef SIS315H
-static void
-SiS_CRT2AutoThreshold(SiS_Private *SiS_Pr)
-{
-  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
-}
-#endif
-
-/*********************************************/
 /*           DISABLE VIDEO BRIDGE            */
 /*********************************************/
 
@@ -3683,55 +3699,40 @@
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
+     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
 
         if(HwInfo->jChipType < SIS_315H) {
 
 #ifdef SIS300	   /* 300 series */
 
-           if(HwInfo->jChipType == SIS_300) {  /* For 300+301LV (A907) */
-
-	      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	         if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-		    SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-		 }
+	   if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+	      } else {
+		 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	      }
+	      SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	   }
+	   if(SiS_Is301B(SiS_Pr)) {
 	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
 	      SiS_ShortDelay(SiS_Pr,1);
-	      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
-	      SiS_DisplayOff(SiS_Pr);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	         if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
-	             (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-		 }
-	      }
-
-	   } else {
-
-	      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	         SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
-	         SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-	      }
-	      if(SiS_Is301B(SiS_Pr)) {
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
-	         SiS_ShortDelay(SiS_Pr,1);
-	      }
-	      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
-	      SiS_DisplayOff(SiS_Pr);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	      SiS_UnLockCRT2(SiS_Pr,HwInfo);
+           }
+	   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
+	   SiS_DisplayOff(SiS_Pr);
+	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	   SiS_UnLockCRT2(SiS_Pr,HwInfo);
+	   if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
 	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
 	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
-	      if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
-	          (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
-	         SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+	   }
+	   if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
+	       (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
+	      SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+	      } else {
+		 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	      }
 	   }
 
@@ -3741,149 +3742,99 @@
 
 #ifdef SIS315H	   /* 315 series */
 
-           if(IS_SIS550650740660) {		/* 550, 650, 740, 660 */
+	   BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+	                      (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
 
-	      modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
+	   modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
+
+           if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 
-              if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {			/* LV */
 #ifdef SET_EMI
-	         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-		    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
-	               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		    }
+	      if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+		 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
+	            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 		 }
+	      }
 #endif
-		 if( (modenum <= 0x13) ||
-		     (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-		     (SiS_IsVAMode(SiS_Pr,HwInfo)) ) {
-	     	    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-		    if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		       (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		       SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-		    }
-	         }
+	      if( (modenum <= 0x13)                  ||
+		  (SiS_IsVAMode(SiS_Pr,HwInfo))      ||
+		  (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
+	     	 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+		 if(custom1) SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	      }
 
-		 if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-		    (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-		    SiS_DDC2Delay(SiS_Pr,0xff00);
-		    SiS_DDC2Delay(SiS_Pr,0xe000);
+	      if(!custom1) {
+		 SiS_DDC2Delay(SiS_Pr,0xff00);
+		 SiS_DDC2Delay(SiS_Pr,0xe000);
+	         SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+                 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+		 if(IS_SIS740) {
+		    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
+		 }
+	         SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	      }
 
-	            SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+           }
 
-                    pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+	   if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
+	      tempah = 0xef;
+	      if(SiS_IsVAMode(SiS_Pr,HwInfo)) tempah = 0xf7;
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+	   }
 
-		    if(IS_SIS740) {
-		       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
-		    }
+	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
+	   }
 
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	   tempah = 0x3f;
+	   if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
+	      tempah = 0x7f;
+	      if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) tempah = 0xbf;
+	   }
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
 
-		    if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
-	               tempah = 0xef;
-	               if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
-	                  tempah = 0xf7;
-                       }
-	               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	            }
-		 }
+           if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
+	      ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
 
-              } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {			/* B-DH */
+	      SiS_DisplayOff(SiS_Pr);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+		 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+	      }
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
 
-	         if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,0xef);
-	         }
+	   }
 
-	      }
+	   if((!(SiS_IsVAMode(SiS_Pr,HwInfo))) ||
+	      ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
 
-	      if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	         (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,0xef);
+	      if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
+		 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
+		 SiS_DisplayOff(SiS_Pr);
 	      }
+	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
 
-              if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	         (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	         tempah = 0x3f;
-	         if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	            tempah = 0x7f;
-	            if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-		       tempah = 0xbf;
-                    }
-	         }
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+		 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 	      }
 
-              if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	         ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
-
-	         if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-		    (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		    (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
-		    SiS_DisplayOff(SiS_Pr);
-		    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-		 } else {
-	            SiS_DisplayOff(SiS_Pr);
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
-		    if((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13)) {
-		       SiS_DisplayOff(SiS_Pr);
-	               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-	               SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	               temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-                       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-		    }
-		 }
-
-	      } else {
-
-	         if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-		    (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		    (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		    if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
-		       SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
-		       SiS_DisplayOff(SiS_Pr);
-		    }
-		    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-		 } else {
-                    SiS_DisplayOff(SiS_Pr);
-	            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-		 }
-
-		 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	         temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-
-	      }
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	      temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
 
-	      if((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) &&
-	         (SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-		 (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
+	   }
 
-		 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,~0x10);
+	   if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+	   }
 
-	         tempah = 0x3f;
-	         if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	            tempah = 0x7f;
-	            if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-		       tempah = 0xbf;
-                    }
-	         }
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 
-		 if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-		 }
+	      if(!custom1) {
 
 	         if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
 	            if(!(SiS_CRT2IsLCD(SiS_Pr,HwInfo))) {
 	               if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
 		          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
@@ -3894,95 +3845,39 @@
 	         SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
 
 		 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	            if( (SiS_IsVAMode(SiS_Pr, HwInfo)) ||
-	                (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
+	            if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
 		       SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 20);
 		    }
 	         }
 
-  	      } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-
-	         /* NIL */
+	      } else {
 
-	      } else if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	                (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-			(SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-
-		 if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	            tempah = 0xef;
-	            if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-		       if(modenum > 0x13) {
-	                  tempah = 0xf7;
-		       }
-                    }
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-		 }
-		 if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		    (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		    if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-		       (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
-		       if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
-		          (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
-			  SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	     	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-			  SiS_PanelDelay(SiS_Pr, HwInfo, 4);
-	               }
+		 if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
+		    (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
+		    if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
+		       (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
+		       SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+	     	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+		       SiS_PanelDelay(SiS_Pr, HwInfo, 4);
 		    }
 		 }
 
 	      }
-
-	  } else {			/* 315, 330 - all bridge types */
-
-	     if(SiS_Is301B(SiS_Pr)) {
-	        tempah = 0x3f;
-	        if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	           tempah = 0x7f;
-	           if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-		      tempah = 0xbf;
-                   }
-	        }
-	        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
-	        if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
-	           SiS_DisplayOff(SiS_Pr);
-		   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	        }
-	     }
-	     if( (!(SiS_Is301B(SiS_Pr))) ||
-	         (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
-
- 	 	if( (!(SiS_Is301B(SiS_Pr))) ||
-		    (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
-
-	           SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
-	           SiS_DisplayOff(SiS_Pr);
-
-		}
-
-                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-
-                SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-
-	        temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-
-	     }
-
-	  }    /* 315/330 */
+           }
 
 #endif /* SIS315H */
 
 	}
 
-      } else {     /* ============ For 301 ================ */
+     } else {     /* ============ For 301 ================ */
 
         if(HwInfo->jChipType < SIS_315H) {
+#ifdef SIS300
            if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
 	      SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	      SiS_PanelDelay(SiS_Pr, HwInfo, 3);
 	   }
+#endif
 	}
 
         SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
@@ -4000,12 +3895,14 @@
 	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
 	    SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
 	} else {
+#ifdef SIS300
             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
 	    if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
 	        (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
 		SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 		SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	    }
+#endif
 	}
 
       }
@@ -4064,6 +3961,10 @@
 
 #ifdef SIS315H	/* 315 series */
 
+        if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
+          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
+        }
+
 	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 
 	   if(HwInfo->jChipType == SIS_740) {
@@ -4194,7 +4095,6 @@
   BOOLEAN delaylong = FALSE;
 #endif
 
-
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ====== For 301B et al  ====== */
@@ -4203,28 +4103,55 @@
 
 #ifdef SIS300     /* 300 series */
 
-         if(HwInfo->jChipType == SIS_300) {
-
-	    if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-	       if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-	          if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
-	             SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-	          }
+	 if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
+	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+	    } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
+	    }
+	    if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_NoLCD)) {
+	       if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
+	          SiS_PanelDelay(SiS_Pr, HwInfo, 0);
 	       }
 	    }
+	 }
+
+	 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
+	    (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
+
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);   		/* Enable CRT2 */
+            SiS_DisplayOn(SiS_Pr);
+	    SiS_UnLockCRT2(SiS_Pr,HwInfo);
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
+	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+      	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+      	    } else {
+      	       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+            }
+	    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+		  if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
+		     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
+                  }
+		  SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
+               }
+	    }
+
+	 } else {
+
 	    temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
-            if(SiS_BridgeInSlave(SiS_Pr)) {
+            if(SiS_BridgeInSlavemode(SiS_Pr)) {
                tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-               if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
+               if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
             }
             SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
 	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
 	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
 	    SiS_DisplayOn(SiS_Pr);
-	    if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-	       if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	       if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	          if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
 		     if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
 		        SiS_PanelDelay(SiS_Pr, HwInfo, 1);
@@ -4234,440 +4161,279 @@
 	       }
 	    }
 
-	 } else {
+	 }
 
-	    if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
-	       (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
-	       /* This is only for LCD output on 301B-DH via LVDS */
-	       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
-	       if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-	       }
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);   /* Enable CRT2 */
-               SiS_DisplayOn(SiS_Pr);
-	       SiS_UnLockCRT2(SiS_Pr,HwInfo);
-	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
-	       if(SiS_BridgeInSlave(SiS_Pr)) {
-      		  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
-      	       } else {
-      		  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
-               }
-	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
-	           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
-		       if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-		           SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-                       }
-		       SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-                       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
-                   }
-	       }
-            } else {
-	       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
-               if(SiS_BridgeInSlave(SiS_Pr)) {
-                  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-                  if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
-               }
-               SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-	       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
-	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
-	       SiS_DisplayOn(SiS_Pr);
-	    }
 
-         }
 #endif /* SIS300 */
 
       } else {
 
 #ifdef SIS315H    /* 315 series */
 
-	 if(IS_SIS550650740660) {		/* 550, 650, 740, 660 */
-
-	    UCHAR r30=0, r31=0, r32=0, r33=0, cr36=0;
-
-	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+#ifdef SET_EMI
+	 UCHAR   r30=0, r31=0, r32=0, r33=0, cr36=0;
+	 /* USHORT  emidelay=0; */
+#endif
 
-	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
+	 if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
 #ifdef SET_EMI
-		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		  }
+	    if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+	    }
 #endif
-	       }
+	 }
 
-               if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	          tempah = 0x10;
-		  if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
-		     if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
-		     else 			       tempah = 0x08;
-		  }
-		  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	       }
+         if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
+	    tempah = 0x10;
+	    if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
+	       if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
+	       else 			         tempah = 0x08;
+	    }
+	    SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+	 }
 
-	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
-	          SiS_DisplayOff(SiS_Pr);
-	          pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
-	          if(IS_SIS740) {
-	             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
-	          }
-	       }
+	 if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 
-	       if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	           (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-                  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
-		     if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-		        (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-		        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
-			SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-			if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-			   SiS_GenericDelay(SiS_Pr, 0x4500);
-			}
-	                SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
-		     } else {
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-			SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-		     }
-	          }
-	       }
+	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+	    SiS_DisplayOff(SiS_Pr);
+	    pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+	    if(IS_SIS740) {
+	       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
+	    }
 
-               if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
-                     SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
-		     delaylong = TRUE;
+	    if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
+               if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+		  SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
+		  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+		  SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
+		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+		     SiS_GenericDelay(SiS_Pr, 0x4500);
 		  }
 	       }
+	    }
 
-	    } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	    if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
+               SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+	       delaylong = TRUE;
+	    }
 
-	       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x10);
-	       }
+	 }
 
-  	    } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	 if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
 
-	       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	          tempah = 0x10;
-		  if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
-		     if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
-		     else 			       tempah = 0x08;
-		  }
-		  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+            temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+               if(!(tempah & SetCRT2ToRAMDAC)) {
+		  if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
 	       }
+            }
+            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 
-	    }
-
-	    if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-               temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
-	       if(SiS_BridgeInSlave(SiS_Pr)) {
-                  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-                  if(!(tempah & SetCRT2ToRAMDAC)) {
-		     if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
-		  }
-               }
-               SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
 
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
 
-	       if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		  (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-		  temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2e);
-		  if(!(temp & 0x80)) {
-		     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-		  }
-	       } else {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	       }
-	    } else {
-	       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	       SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 	    }
 
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
+	 } else {
 
-	    if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	       (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	       (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	       temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2e);
-	       if(!(temp & 0x80)) {
-		  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-	       }
-	    }
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
 
-	    tempah = 0xc0;
-	    if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
-	       tempah = 0x80;
-	       if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) {
-	          tempah = 0x40;
-               }
-	    }
-            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+	 }
 
-	    if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	       (((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	         (SiS_Pr->SiS_CustomT == CUT_CLEVO1400))     &&
-	        (!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))))) {
-               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-	    }
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
+	 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
 
-	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	 tempah = 0xc0;
+	 if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+	    tempah = 0x80;
+	    if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) tempah = 0x40;
+	 }
+         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
 
-	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	       }
-#ifdef COMPAQ_HACK
-	       if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	       }
-#endif
+	 if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 
-	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
+	    SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 
-	       if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
+	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+
+	    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
 #ifdef SET_EMI
-	          if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		  }
+	       if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+	       }
 #endif
-	          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
-#ifdef SET_EMI
-	          if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
 
-		     cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+	       if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+#ifdef SET_EMI
+		  cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
 
-		     /*                                              (P4_30|0x40)  */
-		     /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
-		     /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
-		     /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
-		     /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
-		     /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
-		     /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
-		     /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
-		     /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
-		     /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
-
-		     if(SiS_Pr->HaveEMI) {
-		        r30 = SiS_Pr->EMI_30;
-			r31 = SiS_Pr->EMI_31;
-			r32 = SiS_Pr->EMI_32;
-			r33 = SiS_Pr->EMI_33;
-		     } else {
-		        r30 = 0;
+		  if(SiS_Pr->SiS_ROMNew) {
+		     UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+		     USHORT romptr   = GetLCDStructPtr661_2(SiS_Pr, HwInfo);
+		     if(romptr) {
+		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
+			SiS_Pr->EMI_30 = 0;
+			SiS_Pr->EMI_31 = ROMAddr[romptr + 14];
+			SiS_Pr->EMI_32 = ROMAddr[romptr + 15];
+			SiS_Pr->EMI_33 = ROMAddr[romptr + 16];
+			if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
+			/* emidelay = SISGETROMW((romptr + 0x22)); */
+			SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = TRUE;
 		     }
+		  }
 
-		     /* EMI_30 is read at driver start; however, the BIOS sets this
-		      * (if it is used) only if the LCD is in use. In case we caught
-		      * the machine while on TV output, this bit is not set and we
-		      * don't know if it should be set - hence our detection is wrong.
-		      * Work-around this here:
-		      */
-
-		     if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
-		        if((cr36 & 0x0f) == 0x02) {			/* 1024x768 */
-		           r30 |= 0x40;
-			   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-			      r30 &= ~0x40;
-			   }
-		        } else if((cr36 & 0x0f) == 0x03) {		/* 1280x1024 */
-		           r30 |= 0x40;
-			   if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
-			      r30 &= ~0x40;
-			   }
-		        } else if((cr36 & 0x0f) == 0x09) {		/* 1400x1050 */
-		           r30 |= 0x40;
-		        } else if((cr36 & 0x0f) == 0x0b) {		/* 1600x1200 - unknown */
-		           r30 |= 0x40;
-		        }
-                     }
+		  /*                                              (P4_30|0x40)  */
+		  /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
+		  /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
+		  /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
+		  /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
+		  /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
+		  /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
+		  /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
+		  /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
+		  /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
+
+		  if(SiS_Pr->HaveEMI) {
+		     r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
+		     r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
+		  } else {
+		     r30 = 0;
+		  }
 
-		     if(!SiS_Pr->HaveEMI) {
-		        if((cr36 & 0x0f) == 0x02) {
+		  /* EMI_30 is read at driver start; however, the BIOS sets this
+		   * (if it is used) only if the LCD is in use. In case we caught
+		   * the machine while on TV output, this bit is not set and we
+		   * don't know if it should be set - hence our detection is wrong.
+		   * Work-around this here:
+		   */
+
+		  if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
+		     switch((cr36 & 0x0f)) {
+		     case 2:
+			r30 |= 0x40;
+			if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x05; r32 = 0x60; r33 = 0x33;
 			   if((cr36 & 0xf0) == 0x30) {
 			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;
-			   } else {
-			      r31 = 0x05; r32 = 0x60; r33 = 0x33;
 			   }
-		        } else if((cr36 & 0x0f) == 0x03) {
+			}
+			break;
+		     case 3:  /* 1280x1024 */
+			if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
 			   if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
 			      r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
-			   } else {
-			      r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
 			   }
-			} else if((cr36 & 0x0f) == 0x09) {
+			}
+			break;
+		     case 9:  /* 1400x1050 */
+			r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
 			   if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
 			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;  /* BIOS values */
-			   } else {
-			      r31 = 0x05; r32 = 0x60; r33 = 0x00;
 			   }
-			} else {
+			}
+			break;
+		     case 11: /* 1600x1200 - unknown */
+			r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
 			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
 			}
 		     }
+                  }
 
-		     /* BIOS values don't work so well sometimes */
-		     if(!SiS_Pr->OverruleEMI) {
+		  /* BIOS values don't work so well sometimes */
+		  if(!SiS_Pr->OverruleEMI) {
 #ifdef COMPAL_HACK
-		        if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
-		           if((cr36 & 0x0f) == 0x09) {
-			      r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
-			   }
- 		        }
+		     if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
+		        if((cr36 & 0x0f) == 0x09) {
+			   r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
+			}
+ 		     }
 #endif
 #ifdef COMPAQ_HACK
-		        if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-		           if((cr36 & 0x0f) == 0x03) {
-			      r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;     /* rev 1 */
-			   }
+		     if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
+		        if((cr36 & 0x0f) == 0x03) {
+			   r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
 			}
+		     }
 #endif
 #ifdef ASUS_HACK
-		        if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-		           if((cr36 & 0x0f) == 0x02) {
-			      /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
-			      /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
-			      /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
-			      /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
-			   }
+		     if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
+		        if((cr36 & 0x0f) == 0x02) {
+			   /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
+			   /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
+			   /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
+			   /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
 			}
-#endif
- 		     }
-		     if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
-		     }
-		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
-		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
-		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
-		     if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
-		        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
-		     } else {
-		        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x00);
 		     }
-		     if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	                 (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-	                if(r30 & 0x40) {
-		           SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
-			   if(delaylong) {
-			      SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
-			      delaylong = FALSE;
-			   }
-			   SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-			   if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-			      SiS_GenericDelay(SiS_Pr, 0x500);
-			   }
-	                   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);
-	                }
-		     }
-		  }
 #endif
-	       }
-
-	       if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-
-	          if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	              (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-		     SiS_DisplayOn(SiS_Pr);
-		     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-		     SiS_WaitVBRetrace(SiS_Pr, HwInfo);
-		     SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-		     if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-	  	     }
-		  }
+ 		  }
 
-	       } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
-
-	          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-	             if( (SiS_IsVAMode(SiS_Pr, HwInfo)) ||
-	                 (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-		        SiS_DisplayOn(SiS_Pr);
-		        SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-		        SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-		     }
+		  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
+		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
 		  }
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
+#endif	/* SET_EMI */
 
-	       } else {
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 
-	          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-	          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-	             if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	                 ((SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ) {
-		        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
-		        if(delaylong) {
-			   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
-		        }
-                        SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-			if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+#ifdef SET_EMI
+		  if( (SiS_LCDAEnabled(SiS_Pr, HwInfo)) ||
+	              (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
+	             if(r30 & 0x40) {
+		        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+			if(delaylong) {
+			   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+			   delaylong = FALSE;
+			}
+			SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+			if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
 			   SiS_GenericDelay(SiS_Pr, 0x500);
 			}
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
+	                SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);
 	             }
-	          }
-
-	          SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
-	          SiS_DisplayOn(SiS_Pr);
-	          SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
-
-	          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-	             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-	          }
-
+		  }
+#endif
 	       }
-
 	    }
 
-	 } else {			/* 315, 330 */
-
-	    if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-	       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
-	       if(SiS_BridgeInSlave(SiS_Pr)) {
-                  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-                  if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
-               }
-               SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
-
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
-
-	       temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
-               if(!(temp & 0x80))
-                  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
-            }
-
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
-
-	    if(SiS_Is301B(SiS_Pr)) {
-
-	       temp=SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
-               if(!(temp & 0x80))
-                  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
-
-	       tempah = 0xc0;
-	       if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	          tempah = 0x80;
-	          if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-	             tempah = 0x40;
-                  }
+	    if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
+	       if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
+		  SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+		  if(delaylong) {
+		     SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+		  }
+                  SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	 	     SiS_GenericDelay(SiS_Pr, 0x500);
+		  }
+		  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
 	       }
-               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
-
-	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-
-	    } else {
+	    }
 
-	       SiS_VBLongWait(SiS_Pr);
-               SiS_DisplayOn(SiS_Pr);
-	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7F);
-               SiS_VBLongWait(SiS_Pr);
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+	    SiS_DisplayOn(SiS_Pr);
+	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
 
-	    }
+	 }
 
-	 }   /* 315, 330 */
+	 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+	 }
 
 #endif /* SIS315H */
 
@@ -4683,9 +4449,9 @@
        }
 
        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
-       if(SiS_BridgeInSlave(SiS_Pr)) {
+       if(SiS_BridgeInSlavemode(SiS_Pr)) {
           tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-          if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
+          if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
        }
        SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 
@@ -4734,11 +4500,11 @@
 	  }
        }
 
-       SiS_EnableCRT2(SiS_Pr);
+       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
        SiS_DisplayOn(SiS_Pr);
        SiS_UnLockCRT2(SiS_Pr,HwInfo);
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
-       if(SiS_BridgeInSlave(SiS_Pr)) {
+       if(SiS_BridgeInSlavemode(SiS_Pr)) {
       	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
        } else {
       	  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
@@ -4770,6 +4536,10 @@
 
 #ifdef SIS315H    /* 315 series */
 
+       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
+          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
+       }
+
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
 	  if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	     SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
@@ -4777,7 +4547,7 @@
           }
        }
 
-       SiS_EnableCRT2(SiS_Pr);
+       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
        SiS_UnLockCRT2(SiS_Pr,HwInfo);
 
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
@@ -4868,33 +4638,31 @@
 /*         SET PART 1 REGISTER GROUP         */
 /*********************************************/
 
-/********** Set CRT2 OFFSET / PITCH **********/
+/* Set CRT2 OFFSET / PITCH */
 static void
-SiS_SetCRT2Offset(SiS_Private *SiS_Pr,USHORT ModeNo,
-                  USHORT ModeIdIndex ,USHORT RefreshRateTableIndex,
-	          PSIS_HW_INFO HwInfo)
+SiS_SetCRT2Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
+	          USHORT RRTI, PSIS_HW_INFO HwInfo)
 {
   USHORT offset;
   UCHAR temp;
 
   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
 
-  offset = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                         HwInfo);
+  offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI,HwInfo);
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-     SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) offset >>= 1;
+  if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
+     (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
+     offset >>= 1;
+  }
 
-  temp = (UCHAR)(offset & 0xFF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,temp);
-  temp = (UCHAR)(offset >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
   temp = (UCHAR)(((offset >> 3) & 0xFF) + 1);
   if(offset % 8) temp++;
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
 }
 
-/************* Set CRT2 Sync *************/
+/* Set CRT2 sync and PanelLink mode */
 static void
 SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT RefreshRateTableIndex,
                 PSIS_HW_INFO HwInfo)
@@ -4916,23 +4684,27 @@
      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
         tempah = SiS_Pr->SiS_LCDInfo;
      } else tempah = infoflag >> 8;
-
      tempah &= 0xC0;
-
      tempah |= 0x20;
      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
         if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
            (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-	   tempah |= 0xc0;
+	   tempah |= 0xf0;
+        }
+	if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+            (SiS_Pr->SiS_IF_DEF_DSTN) ||
+            (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
+            (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+           tempah |= 0x30;
         }
      }
-
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
         if(HwInfo->jChipType >= SIS_315H) {
            tempah >>= 3;
+	   tempah &= 0x18;
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
+	   /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
         } else {
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
         }
@@ -4949,19 +4721,21 @@
         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {			/* 630 - 301B(-DH) */
 
 	   tempah = infoflag >> 8;
+	   tempbl = 0;
            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 	      if(SiS_Pr->SiS_LCDInfo & LCDSync) {
 	         tempah = SiS_Pr->SiS_LCDInfo;
+		 tempbl = (tempah >> 6) & 0x03;
               }
            }
            tempah &= 0xC0;
-
            tempah |= 0x20;
            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-
- 	   tempah &= 0x3f;
-  	   tempah |= tempbl;
+  	   tempah |= 0xc0;
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+	      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+	   }
 
         } else {							/* 630 - 301 */
 
@@ -4979,43 +4753,72 @@
 
 #ifdef SIS315H  /* ------- 315 series ------ */
 
-        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	  		/* 315 - 30xLV */
+        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	  		/* 315 - LVDS */
 
-	   if(((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) ||
-	      ((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050))) {
+	   tempbl = 0;
+	   if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
 	      tempah = infoflag >> 8;
+	      if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+	        tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
+	      }
+	   } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
+	             (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
+       	      tempah = infoflag >> 8;
+	      tempbl = 0x03;
 	   } else {
               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
+	      tempbl = (tempah >> 6) & 0x03;
+	      tempbl |= 0x08;
+	      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
 	   }
 	   tempah &= 0xC0;
-
            tempah |= 0x20;
            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+	      }
+	   }
 
-        } else {							/* 315 - 301, 301B */
+        } else {							/* 315 - TMDS */
 
-           tempah = infoflag >> 8;
+           tempah = tempbl = infoflag >> 8;
 	   if(!SiS_Pr->UseCustomMode) {
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      tempbl = 0;
+	      if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+	         if(ModeNo <= 0x13) {
+	            tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+  	         }
+	      }
+	      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 	         if(SiS_Pr->SiS_LCDInfo & LCDSync) {
 	            tempah = SiS_Pr->SiS_LCDInfo;
+		    tempbl = (tempah >> 6) & 0x03;
 	         }
 	      }
 	   }
 	   tempah &= 0xC0;
-
            tempah |= 0x20;
            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-
-	   if(SiS_Pr->SiS_VBType & VB_NoLCD) {			/* TEST, imitate BIOS bug */
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	         tempah |= 0xc0;
+	   if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	      /* Imitate BIOS bug */
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
+	   }
+	   if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+	      tempah >>= 3;
+	      tempah &= 0x18;
+	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
+	   } else {
+              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+	         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	            SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+		 }
 	      }
 	   }
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
 
         }
 #endif  /* SIS315H */
@@ -5023,7 +4826,7 @@
    }
 }
 
-/******** Set CRT2 FIFO on 300/630/730 *******/
+/* Set CRT2 FIFO on 300/630/730 */
 #ifdef SIS300
 static void
 SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
@@ -5078,7 +4881,7 @@
 
   if(!SiS_Pr->CRT1UsesCustomMode) {
 
-     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 	/* get CRT1 ModeNo */
+     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 /* get CRT1 ModeNo */
      SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
      SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
      SiS_Pr->SiS_SelectCRT2Rate = 0;
@@ -5087,7 +4890,7 @@
      if(CRT1ModeNo >= 0x13) {
         index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
         index &= 0x3F;
-        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;				/* Get VCLK */
+        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;			/* Get VCLK */
 
 	colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex); 	/* Get colordepth */
         colorth >>= 1;
@@ -5097,9 +4900,9 @@
   } else {
 
      CRT1ModeNo = 0xfe;
-     VCLK = SiS_Pr->CSRClock_CRT1;						/* Get VCLK */
+     VCLK = SiS_Pr->CSRClock_CRT1;					/* Get VCLK */
      data2 = (SiS_Pr->CModeFlag_CRT1 & ModeInfoFlag) - 2;
-     switch(data2) {								/* Get color depth */
+     switch(data2) {							/* Get color depth */
         case 0 : colorth = 1; break;
         case 1 : colorth = 1; break;
         case 2 : colorth = 2; break;
@@ -5246,10 +5049,10 @@
 
        index = SiS_GetVCLK2Ptr(SiS_Pr,CRT2ModeNo,modeidindex,
                                refreshratetableindex,HwInfo);
-       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                         	/* Get VCLK  */
+       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                /* Get VCLK  */
 
        if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-          if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+          if(SiS_Pr->SiS_UseROM) {
 	     if(ROMAddr[0x220] & 0x01) {
                 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
 	     }
@@ -5259,11 +5062,11 @@
     } else {
 
        CRT2ModeNo = 0xfe;
-       VCLK = SiS_Pr->CSRClock;							/* Get VCLK */
+       VCLK = SiS_Pr->CSRClock;					/* Get VCLK */
 
     }
 
-    colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex);   	/* Get colordepth */
+    colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex); /* Get colordepth */
     colorth >>= 1;
     if(!colorth) colorth++;
 
@@ -5282,8 +5085,8 @@
     if(HwInfo->jChipType == SIS_300) {
        if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13;
        else             temp = (temp & (~0x1F)) | 0x16;
-       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-       		temp = (temp & (~0x1F)) | 0x13;
+       if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+       	  temp = (temp & (~0x1F)) | 0x13;
        }
     } else {
        if( ( (HwInfo->jChipType == SIS_630) ||
@@ -5313,317 +5116,72 @@
 }
 #endif
 
-/**** Set CRT2 FIFO on 315/330 series ****/
+/* Set CRT2 FIFO on 315/330 series */
 #ifdef SIS315H
 static void
-SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr)
+SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3F,0x04);
-}
-#endif
-
-/*************** Set LCD-A ***************/
-#ifdef SIS315H
-static void
-SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
-{
-  USHORT modeflag,resinfo;
-  USHORT push2,tempax,tempbx,tempcx,temp;
-  ULONG tempeax=0,tempebx,tempecx,tempvcfact;
-
-  /* This is not supported with LCDA */
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
-  if(SiS_Pr->UseCustomMode) return;
-
-  if(IS_SIS330) {
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);			/* Xabre 1.01.03 */
-  } else if(IS_SIS740) {
-     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {					/* 740/LVDS */
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);      	/* 740/LVDS */
-	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
-     } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);			/* 740/301LV, 301BDH */
-     }
-  } else {
-     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {					/* 650/LVDS */
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);      	/* 650/LVDS */
-	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);			/* 650/LVDS 1.10.07 */
-     } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);			/* 650/30xLv 1.10.6s */
-     }
-  }
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-  }
-
-  tempax = SiS_Pr->SiS_LCDHDES;
-
-  temp = (tempax & 0x0007);                        		/* BPLHDESKEW[2:0]   */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                         /* Part1_1Ah  */
-  temp = (tempax >> 3) & 0x00FF;                               	/* BPLHDESKEW[10:3]  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                         /* Part1_16h  */
-
-  tempbx = SiS_Pr->SiS_HDE;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-     tempbx = SiS_Pr->PanelXRes;
-  }
-
-  tempax += tempbx;	                                    	/* HDE + HSKEW = lcdhdee  */
-  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
-
-  temp = tempax;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(temp & 0x07) temp += 8;
-  }
-  temp >>= 3;                                        		/* BPLHDEE  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                        	/* Part1_17h  */
-
-  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;     	            	/* (HT-HDE) / 4  */
-
-  /* 650/30xLV 1.10.6s, 740/LVDS */
-  if( ((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) ||
-      ((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)        tempcx = 0x28;
- 	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  tempcx = 0x18;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x30;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x40;
-	else                                                          tempcx = 0x30;
-     }
-  }
-
-  tempcx += tempax;  	                                  	/* lcdhrs  */
-  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
-
-  temp = (tempcx >> 3) & 0x00FF;				/* BPLHRS */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);                 		/* Part1_14h  */
-
-  temp += 10;
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   temp += 6;
-	   if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	      temp++;
-	      if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) {
-	         temp += 7;
-		 if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) {
-		    temp -= 10;
-		 }
-	      }
-	   }
-	}
-     }
-  }
-  temp &= 0x1F;
-  temp |= ((tempcx & 0x07) << 5);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);                         /* Part1_15h  */
-
-  if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-     tempax = SiS_Pr->PanelYRes;
+  if( (HwInfo->jChipType == SIS_760)      &&
+      (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
+      (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
+      (SiS_Pr->SiS_VGAHDE >= 1280)	  &&
+      (SiS_Pr->SiS_VGAVDE >= 1024) ) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
   } else {
-     tempax = SiS_Pr->SiS_VGAVDE;
-  }
-
-  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
-  push2 = tempbx;
-
-  tempcx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 2;
-
-  if( ((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) ||
-      ((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 1;
-   	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)   tempcx = 3;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)   tempcx = 3;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 1;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 1;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)  tempcx = 1;
-	else                                                           tempcx = 0x0057;
-     }
-  }
-
-  tempbx += tempcx;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     tempbx++;                                                	/* BPLVRS  */
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
   }
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);                             /* Part1_18h  */
 
-  tempcx >>= 3;
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 3;
-   	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)   tempcx = 5;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)   tempcx = 5;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 5;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 2;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)  tempcx = 2;
-	}
-     }
-  }
-  tempcx += tempbx;
-  tempcx++;                                                	/* BPLVRE  */
-  temp = tempcx & 0x000F;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     temp |= 0xC0;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); 		/* Part1_19h  */
-  } else {
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);
-  }
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)   temp |= 0x40;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     /* Don't check Part1Port,0x00 -> is not being set if LCDA! */
-     /* We check SR06 instead here: */
-     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-        if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
-     }
-  } else {
-     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-        if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
-     }
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x07,temp);            /* Part1_1Ah */
-
-  tempbx = push2;                                      		/* BPLVDEE */
-
-  tempcx = SiS_Pr->SiS_LCDVDES;                        		/* NPLVDES */
-  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-        if(resinfo == SIS_RI_800x600) tempcx++;
-     }
-  }
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-     tempbx = tempcx = SiS_Pr->SiS_VGAVDE;
-     tempbx--;
-  }
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  temp = temp | ((tempcx >> 8) & 0x07);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);                          /* Part1_1Dh */
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,temp);                          /* Part1_1Ch  */
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,temp);                          /* Part1_1Bh  */
-
-  tempeax = SiS_Pr->SiS_VGAVDE << 18;
-  tempebx = SiS_Pr->SiS_VDE;
-  temp = (USHORT)(tempeax % tempebx);
-  tempeax = tempeax / tempebx;
-  if(temp) tempeax++;
-  tempvcfact = tempeax;
-
-  temp = (USHORT)(tempeax & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
-
-  temp = (USHORT)((tempeax & 0x00FF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
-
-  temp = (USHORT)((tempeax & 0x00030000) >> 16);
-  if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
-
-  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
-     temp = (USHORT)(tempeax & 0x00FF);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
-     temp = (USHORT)((tempeax & 0x00FF00) >> 8);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
-     temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
-     temp = 0;
-     if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
-  }
-
-  tempeax = SiS_Pr->SiS_VGAHDE << 16;
-  tempebx = SiS_Pr->SiS_HDE;
-  temp = tempeax % tempebx;
-  tempeax /= tempebx;
-  if(temp) tempeax++;
-  if(tempebx == SiS_Pr->SiS_VGAHDE) tempeax = 0xFFFF;
-  tempecx = tempeax;
-  tempeax = ((SiS_Pr->SiS_VGAHDE << 16) / tempecx) - 1;
-  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
-  temp = (USHORT)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);                          /* Part1_1Fh  */
-
-  tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
-  tempbx = (USHORT)(tempeax & 0x0FFFF);
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx--;
-
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)  tempbx = 1;
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  temp = temp | ((tempecx >> 8) & 0x07);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);                         /* Part1_20h */
-
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,temp);                         /* Part1_21h */
-
-  tempecx >>= 16;   	                                  	/* BPLHCFACT  */
-  if(modeflag & HalfDCLK) tempecx >>= 1;
-  temp = (USHORT)((tempecx & 0x0000FF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);                         /* Part1_22h */
-
-  temp = (USHORT)(tempecx & 0x000000FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
-
-  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
-  }
 }
-#endif  /* SIS 315 */
+#endif
 
 static USHORT
 SiS_GetVGAHT2(SiS_Private *SiS_Pr)
 {
   ULONG tempax,tempbx;
 
-  tempbx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX) & 0xFFFF;
+  tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
   tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
   tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
-  return((USHORT) tempax);
+  return((USHORT)tempax);
 }
 
-/******* Set Part 1 / SiS bridge *********/
+/* Set Part 1 / SiS bridge slave mode */
 static void
 SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
                   PSIS_HW_INFO HwInfo,USHORT RefreshRateTableIndex)
 {
   USHORT  push1,push2;
   USHORT  tempax,tempbx,tempcx,temp;
-  USHORT  resinfo,modeflag;
+  USHORT  resinfo,modeflag,xres=0;
   unsigned char p1_7, p1_8;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
+     xres = SiS_Pr->CHDisplay;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	resinfo = 0;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
   }
 
   /* The following is only done if bridge is in slave mode: */
 
+  if((HwInfo->jChipType >= SIS_661) && (ModeNo > 0x13)) {
+     if(xres >= 1600) {
+        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
+     }
+  }
+
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0xff);                  /* set MAX HT */
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)  modeflag |= Charx8Dot;
@@ -5684,21 +5242,20 @@
      } else {
         if(!(modeflag & HalfDCLK)) {
            temp -= 4;
-           if((SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) &&
-	      (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200)) {
+           if((SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
+	      (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)) {
               if(SiS_Pr->SiS_VGAHDE >= 800) {
                  temp -= 7;
 	         if(HwInfo->jChipType < SIS_315H) {
-	            /* 650/301LV(x) does not do this, 630/301B, 300/301LV do */
                     if(SiS_Pr->SiS_ModeType == ModeEGA) {
                        if(SiS_Pr->SiS_VGAVDE == 1024) {
                           temp += 15;
-                          if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)
+                          if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
 		  	     temp += 7;
                        }
                     }
 	         }
-		 if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) {
+		 if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
                     if(SiS_Pr->SiS_VGAHDE >= 1280) {
                        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
 		    }
@@ -5762,6 +5319,10 @@
 	      p1_7 = 0xab;
 	   }
 	}
+     } else {
+        if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
+	   if(modeflag & HalfDCLK) p1_7 = 0x30;
+	}
      }
   }
 
@@ -5784,7 +5345,7 @@
   else if(tempbx == 525) tempbx = 480;
   push2 = tempbx;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
       	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
            if     (tempbx == 350) tempbx += 5;
            else if(tempbx == 480) tempbx += 5;
@@ -5830,7 +5391,7 @@
 	tempbx += (tempax << 1);
      }
   } else if(HwInfo->jChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) {
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
 	tempbx += (tempax << 1);
      }
   }
@@ -5907,521 +5468,465 @@
      }
   }
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                	/* 0x1A SR0E */
+
+  temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
 }
 
-/*********** Set Part 1 / LVDS ***********/
+/* Setup panel link
+ * This is used for LVDS, LCDA and Chrontel TV output
+ * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
+ */
 static void
 SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- 		   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+                   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
 {
-  USHORT modeflag, resinfo;
-  USHORT push1, push2, tempax, tempbx, tempcx, temp;
+  USHORT modeflag,resinfo;
+  USHORT push2,tempax,tempbx,tempcx,temp;
+  ULONG tempeax=0,tempebx,tempecx,tempvcfact=0;
+  BOOLEAN islvds = FALSE, issis  = FALSE, chkdclkfirst = FALSE;
+#ifdef SIS300
+  USHORT crt2crtc;
+#endif
 #ifdef SIS315H
   USHORT pushcx;
 #endif
-  ULONG  tempeax=0, tempebx, tempecx, tempvcfact=0;
-
-  /* This is not supported on LVDS */
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
-  if(SiS_Pr->UseCustomMode) return;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+#ifdef SIS300
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+#endif
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
+#ifdef SIS300
+     crt2crtc = 0;
+#endif
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+#ifdef SIS300
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+#endif
   }
 
-  /* Set up Panel Link */
-
-  /* 1. Horizontal setup */
-
-  tempax = SiS_Pr->SiS_LCDHDES;
-
-  if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-     if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) &&
-         (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
-  	   tempax -= 8;
-     }
+  /* is lvds if really LVDS, or SiS 301B-DH with external LVDS transmitter */
+  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+     ((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBType & VB_NoLCD))) {
+     islvds = TRUE;
   }
 
-  tempcx = SiS_Pr->SiS_HT;    				  /* Horiz. Total */
-
-  tempbx = SiS_Pr->SiS_HDE;                               /* Horiz. Display End */
+  /* is really sis if sis bridge, but not 301B-DH */
+  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+     issis = TRUE;
+  }
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-     SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-     tempbx >>= 1;
+  if((HwInfo->jChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
+     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
+        chkdclkfirst = TRUE;
+     }
   }
 
-  if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-        if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
-	   tempbx = SiS_Pr->PanelXRes;
-	} else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   tempbx = SiS_Pr->PanelXRes;
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-	      tempbx = 800;
-	      if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	         tempbx = 1024;
+#ifdef SIS315H
+  if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+     if(IS_SIS330) {
+        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
+     } else if(IS_SIS740) {
+        if(islvds) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
+        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
+        }
+     } else {
+        if(islvds) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
+        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
+	   if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	      if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
+	         (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+	         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
 	      }
 	   }
         }
      }
   }
-  tempcx = (tempcx - tempbx) >> 2;		 /* HT-HDE / 4 */
-
-  push1 = tempax;
-
-  tempax += tempbx;
-
-  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
+#endif
 
-  push2 = tempax;
+  /* Horizontal */
 
-  if((!SiS_Pr->SiS_IF_DEF_FSTN) &&
-     (!SiS_Pr->SiS_IF_DEF_DSTN) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-     (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-     	      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)        tempcx = 0x0028;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)  tempcx = 0x0018;
-     	      else if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
-	            (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) ) {
-	  	   if(HwInfo->jChipType < SIS_315H) {
-		      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		         tempcx = 0x0017;  /* A901; sometimes 0x0018; */
-		      } else {
-		         tempcx = 0x0017;
-#ifdef TWNEWPANEL
-			 tempcx = 0x0018;
-#endif
-		      }
-		   } else {
-		      tempcx = 0x0018;
-		   }
-	      }
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)  tempcx = 0x0028;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0030;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0030;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0040;
+  tempax = SiS_Pr->SiS_LCDHDES;
+  if(islvds) {
+     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+        if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
+           if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
+              (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+  	      tempax -= 8;
 	   }
-        }
+	}
      }
   }
 
-  tempcx += tempax;                              /* lcdhrs  */
-  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
-
-  tempax = tempcx >> 3;                          /* BPLHRS */
-  temp = tempax & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);		 /* Part1_14h; Panel Link Horizontal Retrace Start  */
+  temp = (tempax & 0x0007);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);			/* BPLHDESKEW[2:0]   */
+  temp = (tempax >> 3) & 0x00FF;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);			/* BPLHDESKEW[10:3]  */
 
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-     temp = (tempax & 0x00FF) + 2;
-  } else {
-     temp = (tempax & 0x00FF) + 10;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if((!SiS_Pr->SiS_IF_DEF_DSTN) &&
-	   (!SiS_Pr->SiS_IF_DEF_FSTN) &&
-	   (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-	   (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-	   (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	      temp += 6;
-              if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	         temp++;
-	         if(HwInfo->jChipType >= SIS_315H) {
-	            if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) {
-	               temp += 7;
-		       if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) {
-		          temp -= 0x14;
-			  if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x768) {
-			     temp -= 10;
-			  }
-		       }
-	            }
-	         }
-	      }
-           }
-        }
+  tempbx = SiS_Pr->SiS_HDE;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
+        (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
+        tempbx >>= 1;
+     }
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        tempbx = SiS_Pr->PanelXRes;
      }
   }
 
-  temp &= 0x1F;
-  temp |= ((tempcx & 0x0007) << 5);
-#if 0
-  if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;       /* WRONG? BIOS loads cl, not ah */
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);    	 /* Part1_15h; Panel Link Horizontal Retrace End/Skew */
-
-  tempbx = push2;
-  tempcx = push1;                                /* lcdhdes  */
+  tempax += tempbx;
+  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
 
-  temp = (tempcx & 0x0007);                      /* BPLHDESKEW  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);   	 /* Part1_1Ah; Panel Link Vertical Retrace Start (2:0) */
+  temp = tempax;
+  if(temp & 0x07) temp += 8;
+  temp >>= 3;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);			/* BPLHDEE  */
 
-  tempcx >>= 3;                                  /* BPLHDES */
-  temp = (tempcx & 0x00FF);
-#if 0 /* Not 550 FSTN */
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(ModeNo == 0x5b) temp--; */
-  }
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);    	 /* Part1_16h; Panel Link Horizontal Display Enable Start  */
+  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
 
-  if((HwInfo->jChipType < SIS_315H) ||
-     (SiS_Pr->SiS_IF_DEF_FSTN) ||
-     (SiS_Pr->SiS_IF_DEF_DSTN)) {
-     if(tempbx & 0x07) tempbx += 8;
-  }
-  tempbx >>= 3;                                  /* BPLHDEE  */
-  temp = tempbx & 0x00FF;
-#if 0 /* Not 550 FSTN */
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(ModeNo == 0x5b) temp--;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
+     }
   }
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);   	 /* Part1_17h; Panel Link Horizontal Display Enable End  */
 
-  /* 2. Vertical setup */
+  tempcx += tempax;
+  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
 
-  if(HwInfo->jChipType < SIS_315H) {
-     tempcx = SiS_Pr->SiS_VGAVT;
-     tempbx = SiS_Pr->SiS_VGAVDE;
-     if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) && (SiS_Pr->SiS_CustomT != CUT_BARCO1024)) {
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	      tempbx = SiS_Pr->PanelYRes;
+  temp = (tempcx >> 3) & 0x00FF;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+           switch(ModeNo) {
+           case 0x04:
+           case 0x05:
+           case 0x0d: temp = 0x56; break;
+           case 0x10: temp = 0x60; break;
+           case 0x13: temp = 0x5f; break;
+           case 0x40:
+           case 0x41:
+           case 0x4f:
+           case 0x43:
+           case 0x44:
+           case 0x62:
+           case 0x56:
+           case 0x53:
+           case 0x5d:
+           case 0x5e: temp = 0x54; break;
            }
-	}
+        }
      }
-     tempcx -= tempbx;
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);			/* BPLHRS */
 
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     temp += 2;
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        temp += 8;
+        if(SiS_Pr->PanelHRE != 999) {
+           temp = tempcx + SiS_Pr->PanelHRE;
+	   if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
+	   temp >>= 3;
+        }
+     }
   } else {
-
-     tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;           /* VGAVT-VGAVDE  */
-
+     temp += 10;
   }
 
-  tempbx = SiS_Pr->SiS_LCDVDES;	   		 	 	/* VGAVDES  */
-  push1 = tempbx;
+  temp &= 0x1F;
+  temp |= ((tempcx & 0x07) << 5);
+#if 0
+  if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;       		/* WRONG? BIOS loads cl, not ah */
+#endif
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);			/* BPLHRE */
 
-  tempax = SiS_Pr->SiS_VGAVDE;
+  /* Vertical */
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-           tempax = 600;
-	   if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	      tempax = 768;
-	   }
-	}
-     } else if( (SiS_Pr->SiS_IF_DEF_TRUMPION == 0)   &&
-                (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
-                ((SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) ||
-	         (SiS_Pr->SiS_IF_DEF_FSTN) ||
-	         (SiS_Pr->SiS_IF_DEF_DSTN)) ) {
+  tempax = SiS_Pr->SiS_VGAVDE;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 	tempax = SiS_Pr->PanelYRes;
      }
   }
 
-  tempbx += tempax;
+  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
   if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
 
   push2 = tempbx;
 
-  tempcx >>= 1;
-
-  if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
-     (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-     (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-	tempcx = 0x0017;
-     } else if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
-	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 0x0003;
-  	   else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
-	           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)) tempcx = 0x0003;
-           else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 0x0001;
-           else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 0x0001;
-	   else 							  tempcx = 0x0057;
-        } else  {
-     	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 0x0001;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)   tempcx = 0x0001;
-     	   else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
-	           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)) {
-		   if(HwInfo->jChipType < SIS_315H) {
-		      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		         tempcx = 0x0002;   /* A901; sometimes 0x0003; */
-		      } else {
-			 tempcx = 0x0002;
-#ifdef TWNEWPANEL
-			 tempcx = 0x0003;
-#endif
-		      }
-		   } else tempcx = 0x0003;
-           }
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)  tempcx = 0x0003;
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0001;
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0001;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0001;
-     	   else 							 tempcx = 0x0057;
+  tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
+  if(HwInfo->jChipType < SIS_315H) {
+     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	   tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
 	}
      }
   }
+  if(islvds) tempcx >>= 1;
+  else       tempcx >>= 2;
 
-  tempbx += tempcx;			 	/* BPLVRS  */
-
-  if((HwInfo->jChipType < SIS_315H) ||
-     (SiS_Pr->SiS_IF_DEF_FSTN) ||
-     (SiS_Pr->SiS_IF_DEF_DSTN)) {
-     tempbx++;
+  if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
+      (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) 		    &&
+      (SiS_Pr->PanelVRS != 999) ) {
+     tempcx = SiS_Pr->PanelVRS;
+     tempbx += tempcx;
+     if(issis) tempbx++;
+  } else {
+     tempbx += tempcx;
+     if(HwInfo->jChipType < SIS_315H) tempbx++;
+     else if(issis)                   tempbx++;
   }
 
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
+  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;	/* BPLVRS  */
 
   temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);       	 /* Part1_18h; Panel Link Vertical Retrace Start  */
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(ModeNo == 0x10) temp = 0xa9;
+     }
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
 
   tempcx >>= 3;
+  tempcx++;
 
-  if((!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-     (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if( (HwInfo->jChipType < SIS_315H) &&
-            (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) )     tempcx = 0x0001;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2)  tempcx = 0x0002;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3)  tempcx = 0x0002;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)    tempcx = 0x0003;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)   tempcx = 0x0005;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)   tempcx = 0x0005;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)   tempcx = 0x0011;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 0x0005;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 0x0002;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)  tempcx = 0x0011;
-        else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)  {
-     		if(HwInfo->jChipType < SIS_315H) {
-		   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		      tempcx = 0x0004;   /* A901; Other BIOS sets 0x0005; */
-		   } else {
-		      tempcx = 0x0004;
-#ifdef TWNEWPANEL
-		      tempcx = 0x0005;
-#endif
-		   }
-		} else {
-		   tempcx = 0x0005;
-		}
-        }
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
      }
   }
 
-  tempcx = tempcx + tempbx + 1;                  /* BPLVRE  */
+  tempcx += tempbx;
   temp = tempcx & 0x000F;
-  if(SiS_Pr->SiS_IF_DEF_FSTN ||
-     SiS_Pr->SiS_IF_DEF_DSTN ||
-     (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
-     (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
-     (SiS_Pr->SiS_CustomT == CUT_PANEL848)) {
-     temp |= 0x30;
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xf0,temp); /* Part1_19h; Panel Link Vertical Retrace End (3:0); Misc.  */
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);	/* BPLVRE  */
 
-  temp = ((tempbx & 0x0700) >> 8) << 3;          /* BPLDESKEW =0 */
+  temp = ((tempbx >> 8) & 0x07) << 3;
   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
      if(SiS_Pr->SiS_HDE != 640) {
-        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)   temp |= 0x40;
+        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
      }
-  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)           temp |= 0x40;
-  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-     if(HwInfo->jChipType >= SIS_315H) {
-        if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
-           temp |= 0x80;
+  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
+  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
+  tempbx = 0x87;
+  if((HwInfo->jChipType >= SIS_315H) ||
+     (HwInfo->jChipRevision >= 0x30)) {
+     tempbx = 0x07;
+     if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+	if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
+     }
+     /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit mutliplexed) via VGA2 */
+     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
+	} else {
+	   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
+	}
+     }
+  }
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
+
+  tempbx = push2;                                      		/* BPLVDEE */
+
+  tempcx = SiS_Pr->SiS_LCDVDES;                        		/* BPLVDES */
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:
+        tempbx = SiS_Pr->SiS_VGAVDE - 1;
+        tempcx = SiS_Pr->SiS_VGAVDE;
+	break;
+     case Panel_800x600:
+        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+           if(resinfo == SIS_RI_800x600) tempcx++;
         }
-     } else {
-	if( (HwInfo->jChipType == SIS_630) ||
-	    (HwInfo->jChipType == SIS_730) ) {
-	   if(HwInfo->jChipRevision >= 0x30) {
-	      temp |= 0x80;
+	break;
+     case Panel_1024x600:
+        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+           if(resinfo == SIS_RI_1024x600) tempcx++;
+           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	      if(resinfo == SIS_RI_800x600) tempcx++;
 	   }
-	}
+        }
+	break;
+     case Panel_1024x768:
+        if(HwInfo->jChipType < SIS_315H) {
+           if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+              if(resinfo == SIS_RI_1024x768) tempcx++;
+	   }
+        }
+	break;
      }
   }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x87,temp);  /* Part1_1Ah; Panel Link Control Signal (7:3); Vertical Retrace Start (2:0) */
 
-  if (HwInfo->jChipType < SIS_315H) {
+  temp = ((tempbx >> 8) & 0x07) << 3;
+  temp = temp | ((tempcx >> 8) & 0x07);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
+  /* if(SiS_Pr->SiS_IF_DEF_FSTN) tempbx++;  */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
 
-#ifdef SIS300      /* 300 series */
+  /* Vertical scaling */
 
-        tempeax = SiS_Pr->SiS_VGAVDE << 6;
-        temp = (USHORT)(tempeax % (ULONG)SiS_Pr->SiS_VDE);
-        tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
-        if(temp != 0) tempeax++;
-        tempebx = tempeax;                         /* BPLVCFACT  */
+  if(HwInfo->jChipType < SIS_315H) {
 
-  	if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
-	   tempebx = 0x003F;
-	}
+#ifdef SIS300      /* 300 series */
+     tempeax = SiS_Pr->SiS_VGAVDE << 6;
+     temp = (tempeax % (ULONG)SiS_Pr->SiS_VDE);
+     tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
+     if(temp) tempeax++;
 
-  	temp = (USHORT)(tempebx & 0x00FF);
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);      /* Part1_1Eh; Panel Link Vertical Scaling Factor */
+     if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
 
+     temp = (USHORT)(tempeax & 0x00FF);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);      	/* BPLVCFACT */
+     tempvcfact = temp;
 #endif /* SIS300 */
 
   } else {
 
 #ifdef SIS315H  /* 315 series */
+     tempeax = SiS_Pr->SiS_VGAVDE << 18;
+     tempebx = SiS_Pr->SiS_VDE;
+     temp = (tempeax % tempebx);
+     tempeax = tempeax / tempebx;
+     if(temp) tempeax++;
+     tempvcfact = tempeax;
 
-        if(HwInfo->jChipType == SIS_740) {
-           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x03);
-        } else {
-	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,0x23);
-	}
-
-	tempeax = SiS_Pr->SiS_VGAVDE << 18;
-    	temp = (USHORT)(tempeax % (ULONG)SiS_Pr->SiS_VDE);
-    	tempeax = tempeax / SiS_Pr->SiS_VDE;
-    	if(temp != 0) tempeax++;
-    	tempebx = tempeax;                         /* BPLVCFACT  */
-        tempvcfact = tempeax;
-    	temp = (USHORT)(tempebx & 0x00FF);
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);      /* Part1_37h; Panel Link Vertical Scaling Factor */
-    	temp = (USHORT)((tempebx & 0x00FF00) >> 8);
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);      /* Part1_36h; Panel Link Vertical Scaling Factor */
-    	temp = (USHORT)((tempebx & 0x00030000) >> 16);
-	temp &= 0x03;
-    	if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);      /* Part1_35h; Panel Link Vertical Scaling Factor */
-
-#endif /* SIS315H */
-
-  }
-
-  tempbx = push2;                                  /* BPLVDEE  */
-  tempcx = push1;
-
-  push1 = temp;
-
-  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-   	if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
-		if(HwInfo->jChipType < SIS_315H) {
-			if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-      				if(resinfo == SIS_RI_1024x600) tempcx++;
-				if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-					if(resinfo == SIS_RI_800x600) tempcx++;
-		    		}
-			} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-      				if(resinfo == SIS_RI_800x600)  tempcx++;
-				if(resinfo == SIS_RI_1024x768) tempcx++; /* Doesnt make sense anyway... */
-			} else  if(resinfo == SIS_RI_1024x768) tempcx++;
-		} else {
-			if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-      				if(resinfo == SIS_RI_800x600)  tempcx++;
-			}
-		}
-	}
-  }
+     temp = (USHORT)(tempeax & 0x00FF);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
+     temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
+     temp = (USHORT)((tempeax & 0x00030000) >> 16);
+     if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        tempcx = SiS_Pr->SiS_VGAVDE;
-        tempbx = SiS_Pr->SiS_VGAVDE - 1;
+     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
+        temp = (USHORT)(tempeax & 0x00FF);
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
+        temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
+        temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
+        temp = 0;
+        if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
      }
-  }
-
-  temp = ((tempbx & 0x0700) >> 8) << 3;
-  temp |= ((tempcx & 0x0700) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);     	/* Part1_1Dh; Vertical Display Overflow; Control Signal */
-
-  temp = tempbx & 0x00FF;
-  /* if(SiS_Pr->SiS_IF_DEF_FSTN) temp++;  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,temp);      	/* Part1_1Ch; Panel Link Vertical Display Enable End  */
+#endif
 
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,temp);      	/* Part1_1Bh; Panel Link Vertical Display Enable Start  */
+  }
 
-  /* 3. Additional horizontal setup (scaling, etc) */
+  /* Horizontal scaling */
 
-  tempecx = SiS_Pr->SiS_VGAHDE;
-  if(HwInfo->jChipType >= SIS_315H) {
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        if(modeflag & HalfDCLK) tempecx >>= 1;
-     }
+  tempeax = SiS_Pr->SiS_VGAHDE;		/* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
+  if(chkdclkfirst) {
+     if(modeflag & HalfDCLK) tempeax >>= 1;
   }
-  tempebx = SiS_Pr->SiS_HDE;
-  if(tempecx == tempebx) tempeax = 0xFFFF;
-  else {
-     tempeax = tempecx;
-     tempeax <<= 16;
-     temp = (USHORT)(tempeax % tempebx);
-     tempeax = tempeax / tempebx;
+  tempebx = tempeax << 16;
+  if(SiS_Pr->SiS_HDE == tempeax) {
+     tempecx = 0xFFFF;
+  } else {
+     tempecx = tempebx / SiS_Pr->SiS_HDE;
      if(HwInfo->jChipType >= SIS_315H) {
-        if(temp) tempeax++;
+        if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
      }
   }
-  tempecx = tempeax;
 
   if(HwInfo->jChipType >= SIS_315H) {
-     tempeax = SiS_Pr->SiS_VGAHDE;
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        if(modeflag & HalfDCLK) tempeax >>= 1;
-     }
-     tempeax <<= 16;
-     tempeax = (tempeax / tempecx) - 1;
+     tempeax = (tempebx / tempecx) - 1;
   } else {
      tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
   }
-  tempecx <<= 16;
-  tempecx |= (tempeax & 0xFFFF);
+  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
   temp = (USHORT)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);  	 /* Part1_1Fh; Panel Link DDA Operational Number in each horiz. line */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
 
-  tempbx = SiS_Pr->SiS_VDE;
   if(HwInfo->jChipType >= SIS_315H) {
      tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
-     tempbx = (USHORT)(tempeax & 0x0FFFF);
+     tempbx = (USHORT)(tempeax & 0xFFFF);
   } else {
      tempeax = SiS_Pr->SiS_VGAVDE << 6;
-     tempbx = push1 & 0x3f;
+     tempbx = tempvcfact & 0x3f;
      if(tempbx == 0) tempbx = 64;
      tempeax /= tempbx;
-     tempbx = (USHORT)(tempeax & 0x0FFFF);
+     tempbx = (USHORT)(tempeax & 0xFFFF);
   }
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx--;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
   if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
-     else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)  tempbx = 1;
+     else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480)             tempbx = 1;
   }
 
-  temp = ((tempbx & 0xFF00) >> 8) << 3;
-  temp |= (USHORT)((tempecx & 0x0700) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);  	/* Part1_20h; Overflow register */
-
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,temp);  	/* Part1_21h; Panel Link Vertical Accumulator Register */
+  temp = ((tempbx >> 8) & 0x07) << 3;
+  temp = temp | ((tempecx >> 8) & 0x07);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
 
-  tempecx >>= 16;                               /* BPLHCFACT  */
-  if((HwInfo->jChipType < SIS_315H) || (SiS_Pr->SiS_IF_DEF_FSTN) || (SiS_Pr->SiS_IF_DEF_DSTN)) {
+  tempecx >>= 16;   	                                  	/* BPLHCFACT  */
+  if(!chkdclkfirst) {
      if(modeflag & HalfDCLK) tempecx >>= 1;
   }
   temp = (USHORT)((tempecx & 0xFF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);     	/* Part1_22h; Panel Link Horizontal Scaling Factor High */
-
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
   temp = (USHORT)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);         /* Part1_22h; Panel Link Horizontal Scaling Factor Low */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
+
+#ifdef SIS315H
+  if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+        if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
+           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+	}
+     } else {
+        if(islvds) {
+           if(HwInfo->jChipType == SIS_740) {
+              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
+           } else {
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
+           }
+        }
+     }
+  }
+#endif
+
+#ifdef SIS300
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     int i;
+     UCHAR TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
+     UCHAR TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
+     UCHAR TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
 
-  /* 630/301B and 630/LVDS do something for 640x480 panels here */
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
+     for(i=0; i<5; i++) {
+        SiS_SetTrumpionBlock(SiS_Pr, &SiS300_TrumpionData[crt2crtc][0]);
+     }
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(ModeNo == 0x13) {
+	   for(i=0; i<4; i++) {
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
+	   }
+	} else if(ModeNo == 0x10) {
+	   for(i=0; i<4; i++) {
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
+	   }
+	}
+     }
+     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
+  }
+#endif
 
 #ifdef SIS315H
   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
@@ -6431,10 +5936,10 @@
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x007,0x03);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
      tempax = SiS_Pr->SiS_HDE;                       		/* Blps = lcdhdee(lcdhdes+HDE) + 64 */
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempax += 64;
      temp = tempax & 0x00FF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,temp);
@@ -6448,8 +5953,8 @@
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
 
      tempax = SiS_Pr->SiS_VDE;
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempax >>= 1;
      temp = tempax & 0x00FF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,temp);
@@ -6457,8 +5962,8 @@
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
 
      tempeax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempeax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempeax >>= 1;
      tempeax <<= 2;                       			/* BDxFIFOSTOP = (HDE*4)/128 */
      tempebx = 128;
      temp = (USHORT)(tempeax % tempebx);
@@ -6472,8 +5977,8 @@
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
 
      tempax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempax >>= 4;                        			/* BDxWadroff = HDE*4/8/8 */
      pushcx = tempax;
      temp = tempax & 0x00FF;
@@ -6482,8 +5987,8 @@
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
 
      tempax = SiS_Pr->SiS_VDE;                             	/* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempeax = (tempax * pushcx);
      tempebx = 0x00100000 + tempeax;
      temp = (USHORT)tempebx & 0x000000FF;
@@ -6525,496 +6030,380 @@
      }
   }
 #endif  /* SIS315H */
-
 }
 
-/************** Set Part 1 ***************/
+/* Set Part 1 */
 static void
 SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
               PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
 {
-  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
-  USHORT  temp=0, tempax=0, tempbx=0, tempcx=0;
-  USHORT  pushbx=0, CRT1Index=0;
+#if defined(SIS300) || defined(SIS315H)
+  UCHAR   *ROMAddr = HwInfo->pjVirtualRomBase;
+#endif
+  USHORT  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
+  USHORT  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
 #ifdef SIS315H
   USHORT  tempbl=0;
 #endif
-  USHORT  modeflag, resinfo=0;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+     SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     return;
+  }
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-	modeflag = SiS_Pr->CModeFlag;
-     } else {
-    	CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
+     CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-
-#ifdef SIS315H
-     SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
-     SiS_SetGroup1_LCDA(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
-#endif
-
-  } else {
+  SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
 
-     if( (HwInfo->jChipType >= SIS_315H) &&
+  if( ! ((HwInfo->jChipType >= SIS_315H) &&
          (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
-	 (SiS_Pr->SiS_VBInfo & SetInSlaveMode) ) {
-
-        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
-
-     } else {
-
-        SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex,
-      		          RefreshRateTableIndex, HwInfo);
+         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
 
-        if (HwInfo->jChipType < SIS_315H ) {
+     if(HwInfo->jChipType < SIS_315H ) {
 #ifdef SIS300
-    	      SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
+  	SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
 #endif
-        } else {
+     } else {
 #ifdef SIS315H
-              SiS_SetCRT2FIFO_310(SiS_Pr);
+        SiS_SetCRT2FIFO_310(SiS_Pr, HwInfo);
 #endif
-	}
-
-        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+     }
 
-	/* 1. Horizontal setup */
+     /* 1. Horizontal setup */
 
-        if(HwInfo->jChipType < SIS_315H ) {
+     if(HwInfo->jChipType < SIS_315H ) {
 
 #ifdef SIS300   /* ------------- 300 series --------------*/
 
-    		temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;   			/* BTVGA2HT 0x08,0x09 */
-    		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);                   /* CRT2 Horizontal Total */
+    	temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;   		  /* BTVGA2HT 0x08,0x09 */
+    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
 
-    		temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
-    		SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);          /* CRT2 Horizontal Total Overflow [7:4] */
+    	temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+    	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
 
-    		temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                       /* BTVGA2HDEE 0x0A,0x0C */
-    		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);                   /* CRT2 Horizontal Display Enable End */
+    	temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
+    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
 
-    		pushbx = SiS_Pr->SiS_VGAHDE + 12;                               /* bx  BTVGA@HRS 0x0B,0x0C */
-    		tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
-    		tempbx = pushbx + tempcx;
-    		tempcx <<= 1;
-    		tempcx += tempbx;
-
-    		if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-		   if(SiS_Pr->UseCustomMode) {
-		      tempbx = SiS_Pr->CHSyncStart + 12;
-		      tempcx = SiS_Pr->CHSyncEnd + 12;
-		   }
+	pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
+    	tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
+    	tempbx = pushbx + tempcx;
+    	tempcx <<= 1;
+    	tempcx += tempbx;
 
-      		   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-		      unsigned char cr4, cr14, cr5, cr15;
-		      if(SiS_Pr->UseCustomMode) {
-		         cr4  = SiS_Pr->CCRT1CRTC[4];
-			 cr14 = SiS_Pr->CCRT1CRTC[14];
-			 cr5  = SiS_Pr->CCRT1CRTC[5];
-			 cr15 = SiS_Pr->CCRT1CRTC[15];
-		      } else {
-		         cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
-			 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-			 cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
-			 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
-		      }
-        	      tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 1) << 3;
-        	      tempcx = (((cr5 & 0x1F) | ((cr15 & 0x04) << (6-2))) - 1) << 3;
-      		   }
-
-    		   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == SIS_RI_1024x768)){
-        	      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)){
-      			 tempbx = 1040;
-      			 tempcx = 1042;
-      		      }
-    		   }
-	        }
+	bridgeadd = 12;
 
-    		temp = tempbx & 0x00FF;
-    		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);                   /* CRT2 Horizontal Retrace Start */
 #endif /* SIS300 */
 
- 	} else {
+     } else {
 
 #ifdef SIS315H  /* ------------------- 315/330 series --------------- */
 
-	        tempcx = SiS_Pr->SiS_VGAHT;				       /* BTVGA2HT 0x08,0x09 */
-		if(modeflag & HalfDCLK) {
-		    if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		       tempcx >>= 1;
-		    } else {
-		       tempax = SiS_Pr->SiS_VGAHDE >> 1;
-		       tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
-		       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-			  tempcx = SiS_Pr->SiS_HT - tempax;
-		       }
-		    }
-		}
-		tempcx--;
+	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HT 0x08,0x09 */
+	if(modeflag & HalfDCLK) {
+	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	      tempcx >>= 1;
+	   } else {
+	      tempax = SiS_Pr->SiS_VGAHDE >> 1;
+	      tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
+	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	         tempcx = SiS_Pr->SiS_HT - tempax;
+	      }
+	   }
+	}
+	tempcx--;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx);            /* CRT2 Horizontal Total */
+	temp = (tempcx >> 4) & 0xF0;
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
 
-		temp = tempcx & 0xff;
-		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);                  /* CRT2 Horizontal Total */
+	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HDEE 0x0A,0x0C */
+	tempbx = SiS_Pr->SiS_VGAHDE;
+	tempcx -= tempbx;
+	tempcx >>= 2;
+	if(modeflag & HalfDCLK) {
+	   tempbx >>= 1;
+	   tempcx >>= 1;
+	}
+	tempbx += 16;
 
-		temp = ((tempcx & 0xff00) >> 8) << 4;
-		SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);         /* CRT2 Horizontal Total Overflow [7:4] */
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx);            /* CRT2 Horizontal Display Enable End */
 
-		tempcx = SiS_Pr->SiS_VGAHT;				       /* BTVGA2HDEE 0x0A,0x0C */
-		tempbx = SiS_Pr->SiS_VGAHDE;
-		tempcx -= tempbx;
-		tempcx >>= 2;
-		if(modeflag & HalfDCLK) {
-		   tempbx >>= 1;
-		   tempcx >>= 1;
-		}
-		tempbx += 16;
+	pushbx = tempbx;
+	tempcx >>= 1;
+	tempbx += tempcx;
+	tempcx += tempbx;
 
-		temp = tempbx & 0xff;
-		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);                  /* CRT2 Horizontal Display Enable End */
+	bridgeadd = 16;
 
-		pushbx = tempbx;
-		tempcx >>= 1;
-		tempbx += tempcx;
-		tempcx += tempbx;
-
-		if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-		   if(HwInfo->jChipType >= SIS_661) {
-		      if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) ||
-		         (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) {
-			 if(resinfo == SIS_RI_1280x1024) {
-		            tempcx = 0x30;
-			 } else if(resinfo == SIS_RI_1600x1200) {
-			    tempcx = 0xff;
-			 }
-		      }
-		   }
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	   if(HwInfo->jChipType >= SIS_661) {
+	      if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+		 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+		 if(resinfo == SIS_RI_1280x1024) {
+		    tempcx = (tempcx & 0xff00) | 0x30;
+		 } else if(resinfo == SIS_RI_1600x1200) {
+		    tempcx = (tempcx & 0xff00) | 0xff;
+		 }
+	      }
+	   }
+        }
 
-		   if(SiS_Pr->UseCustomMode) {
-		      tempbx = SiS_Pr->CHSyncStart + 16;
-		      tempcx = SiS_Pr->CHSyncEnd + 16;
-		      tempax = SiS_Pr->SiS_VGAHT;
-		      if(modeflag & HalfDCLK) tempax >>= 1;
-		      tempax--;
-		      if(tempcx > tempax)  tempcx = tempax;
-		   }
+#endif  /* SIS315H */
 
-             	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-		      unsigned char cr4, cr14, cr5, cr15;
-		      if(SiS_Pr->UseCustomMode) {
-		         cr4  = SiS_Pr->CCRT1CRTC[4];
-			 cr14 = SiS_Pr->CCRT1CRTC[14];
-			 cr5  = SiS_Pr->CCRT1CRTC[5];
-			 cr15 = SiS_Pr->CCRT1CRTC[15];
-		      } else {
-		         cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
-			 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-			 cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
-			 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
-		      }
-                      tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; 		/* (VGAHRS-3)*8 */
-                      tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; 	/* (VGAHRE-3)*8 */
-		      tempcx &= 0x00FF;
-		      tempcx |= (tempbx & 0xFF00);
-                      tempbx += 16;
-                      tempcx += 16;
-		      tempax = SiS_Pr->SiS_VGAHT;
-		      if(modeflag & HalfDCLK) tempax >>= 1;
-		      tempax--;
-		      if(tempcx > tempax)  tempcx = tempax;
-             	   }
-
-		   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-      		      tempbx = 1040;
-      		      tempcx = 1042;
-      	     	   }
+     }  /* 315/330 series */
 
-                }
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-		temp = tempbx & 0xff;
-	 	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);                 /* CRT2 Horizontal Retrace Start */
-#endif  /* SIS315H */
+        if(SiS_Pr->UseCustomMode) {
+	   tempbx = SiS_Pr->CHSyncStart + bridgeadd;
+	   tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
+	   tempax = SiS_Pr->SiS_VGAHT;
+	   if(modeflag & HalfDCLK) tempax >>= 1;
+	   tempax--;
+	   if(tempcx > tempax) tempcx = tempax;
+	}
+
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+	   unsigned char cr4, cr14, cr5, cr15;
+	   if(SiS_Pr->UseCustomMode) {
+	      cr4  = SiS_Pr->CCRT1CRTC[4];
+	      cr14 = SiS_Pr->CCRT1CRTC[14];
+	      cr5  = SiS_Pr->CCRT1CRTC[5];
+	      cr15 = SiS_Pr->CCRT1CRTC[15];
+	   } else {
+	      cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
+	      cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+	      cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
+	      cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
+	   }
+           tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; 		    /* (VGAHRS-3)*8 */
+           tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
+	   tempcx &= 0x00FF;
+	   tempcx |= (tempbx & 0xFF00);
+           tempbx += bridgeadd;
+           tempcx += bridgeadd;
+	   tempax = SiS_Pr->SiS_VGAHT;
+	   if(modeflag & HalfDCLK) tempax >>= 1;
+	   tempax--;
+	   if(tempcx > tempax) tempcx = tempax;
+        }
 
-     	}  /* 315/330 series */
+        if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+      	   tempbx = 1040;
+      	   tempcx = 1044;   /* HWCursor bug! */
+        }
 
-  	/* The following is done for all bridge/chip types/series */
+     }
 
-  	tempax = tempbx & 0xFF00;
-  	tempbx = pushbx;
-  	tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
-  	tempax |= (tempbx & 0xFF00);
-  	temp = (tempax & 0xFF00) >> 8;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                        /* Overflow */
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx);            	  /* CRT2 Horizontal Retrace Start */
 
-  	temp = tempcx & 0x00FF;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                        /* CRT2 Horizontal Retrace End */
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx);               /* CRT2 Horizontal Retrace End */
 
-  	/* 2. Vertical setup */
+     temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);		  /* Overflow */
 
-  	tempcx = SiS_Pr->SiS_VGAVT - 1;
-  	temp = tempcx & 0x00FF;
+     /* 2. Vertical setup */
 
-	if(HwInfo->jChipType < SIS_661) {
-           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	      if(HwInfo->jChipType < SIS_315H) {
-	         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	            if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
-	               temp--;
-	            }
-                 }
-	      } else {
- 	         temp--;
+     tempcx = SiS_Pr->SiS_VGAVT - 1;
+     temp = tempcx & 0x00FF;
+
+     if(HwInfo->jChipType < SIS_661) {
+        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	   if(HwInfo->jChipType < SIS_315H) {
+	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
+	            temp--;
+	         }
               }
-           } else if(HwInfo->jChipType >= SIS_315H) {
-	      temp--;
-	   }
+	   } else {
+ 	      temp--;
+           }
+        } else if(HwInfo->jChipType >= SIS_315H) {
+	   temp--;
 	}
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                        /* CRT2 Vertical Total */
+     }
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
 
-  	tempbx = SiS_Pr->SiS_VGAVDE - 1;
-  	temp = tempbx & 0x00FF;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,temp);                        /* CRT2 Vertical Display Enable End */
-
-  	temp = ((tempbx & 0xFF00) << 3) >> 8;
-  	temp |= ((tempcx & 0xFF00) >> 8);
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                        /* Overflow (and HWCursor Test Mode) */
-
-	if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-           tempbx++;
-   	   tempax = tempbx;
-	   tempcx++;
-	   tempcx -= tempax;
-	   tempcx >>= 2;
-	   tempbx += tempcx;
-	   if(tempcx < 4) tempcx = 4;
-	   tempcx >>= 2;
-	   tempcx += tempbx;
-	   tempcx++;
-	} else {
-  	   tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
-  	   tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
-	}
+     tempbx = SiS_Pr->SiS_VGAVDE - 1;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx);               /* CRT2 Vertical Display Enable End */
 
-  	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
+
+     if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
+        tempbx++;
+   	tempax = tempbx;
+	tempcx++;
+	tempcx -= tempax;
+	tempcx >>= 2;
+	tempbx += tempcx;
+	if(tempcx < 4) tempcx = 4;
+	tempcx >>= 2;
+	tempcx += tempbx;
+	tempcx++;
+     } else {
+  	tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
+  	tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
+     }
 
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	if(SiS_Pr->UseCustomMode) {
+	   tempbx = SiS_Pr->CVSyncStart;
+	   tempcx = SiS_Pr->CVSyncEnd;
+	}
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+	   unsigned char cr8, cr7, cr13;
 	   if(SiS_Pr->UseCustomMode) {
-	      tempbx = SiS_Pr->CVSyncStart;
-	      tempcx = (tempcx & 0xFF00) | (SiS_Pr->CVSyncEnd & 0x00FF);
-	   }
+	      cr8    = SiS_Pr->CCRT1CRTC[8];
+	      cr7    = SiS_Pr->CCRT1CRTC[7];
+	      cr13   = SiS_Pr->CCRT1CRTC[13];
+	      tempcx = SiS_Pr->CCRT1CRTC[9];
+	   } else {
+	      cr8    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
+	      cr7    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+	      cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+	      tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
+	   }
+      	   tempbx = cr8;
+      	   if(cr7  & 0x04) tempbx |= 0x0100;
+      	   if(cr7  & 0x80) tempbx |= 0x0200;
+      	   if(cr13 & 0x08) tempbx |= 0x0400;
+       	}
+     }
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
 
-    	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-	      unsigned char cr8, cr7, cr13, cr9;
-	      if(SiS_Pr->UseCustomMode) {
-	         cr8  = SiS_Pr->CCRT1CRTC[8];
-		 cr7  = SiS_Pr->CCRT1CRTC[7];
-		 cr13 = SiS_Pr->CCRT1CRTC[13];
-		 cr9  = SiS_Pr->CCRT1CRTC[9];
-	      } else {
-	         cr8  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
-		 cr7  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
-		 cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
-		 cr9  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
-	      }
-      	      tempbx = cr8;
-      	      if(cr7 & 0x04)  tempbx |= 0x0100;
-      	      if(cr7 & 0x80)  tempbx |= 0x0200;
-      	      if(cr13 & 0x08) tempbx |= 0x0400;
-      	      tempcx = (tempcx & 0xFF00) | (cr9 & 0x00FF);
-    	   }
-  	}
-  	temp = tempbx & 0x00FF;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);           /* CRT2 Vertical Retrace Start */
-
-  	temp = ((tempbx & 0xFF00) >> 8) << 4;
-  	temp |= (tempcx & 0x000F);
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);           /* CRT2 Vert. Retrace End; Overflow; "Enable CRTC Check" */
+     temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow */
 
-  	/* 3. Panel compensation delay */
+     /* 3. Panel delay compensation */
 
-  	if(HwInfo->jChipType < SIS_315H) {
+     if(HwInfo->jChipType < SIS_315H) {
 
 #ifdef SIS300  /* ---------- 300 series -------------- */
 
-	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	        temp = 0x20;
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	   temp = 0x20;
+	   if(HwInfo->jChipType == SIS_300) {
+	      temp = 0x10;
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
+	   }
+	   if(SiS_Pr->SiS_VBType & VB_SIS301) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
+	   }
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 	    temp = 0x08;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+      	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	    temp = 0x2c;
+      	      else 					    temp = 0x20;
+    	   }
+	   if(SiS_Pr->SiS_UseROM) {
+	      if(ROMAddr[0x220] & 0x80) {
+	         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
+	   	    temp = ROMAddr[0x221];
+		 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
+		    temp = ROMAddr[0x222];
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
+		    temp = ROMAddr[0x223];
+		 else
+		    temp = ROMAddr[0x224];
+		 temp &= 0x3c;
+	      }
+	   }
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC & 0x3c;
+	   }
 
-		if(HwInfo->jChipType == SIS_300) {
-		   temp = 0x10;
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  temp = 0x2c;
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
-		}
-		if(SiS_Pr->SiS_VBType & VB_SIS301) {
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
-		}
-		if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)     temp = 0x24;
-		if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom)       temp = 0x2c;
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 		temp = 0x08;
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-      		   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	temp = 0x2c;
-      		   else 					temp = 0x20;
-    	        }
-		if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
-		    if(ROMAddr[0x220] & 0x80) {
-		        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
-				temp = ROMAddr[0x221];
-			else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
-				temp = ROMAddr[0x222];
-		        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)
-				temp = ROMAddr[0x223];
-			else
-				temp = ROMAddr[0x224];
-			temp &= 0x3c;
-		    }
-		}
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		   if(SiS_Pr->PDC) {
-			temp = SiS_Pr->PDC & 0x3c;
-		   }
-		}
-	   } else {
-	        temp = 0x20;
-		if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) temp = 0x04;
-		}
-		if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-		    if(ROMAddr[0x220] & 0x80) {
-		        temp = ROMAddr[0x220] & 0x3c;
-		    }
-		}
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		   if(SiS_Pr->PDC) {
-		      temp = SiS_Pr->PDC & 0x3c;
-		   }
-		}
+	} else {
+	   temp = 0x20;
+	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
+	   }
+	   if(SiS_Pr->SiS_UseROM) {
+	      if(ROMAddr[0x220] & 0x80) {
+	         temp = ROMAddr[0x220] & 0x3c;
+	      }
+	   }
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
 	   }
+        }
 
-    	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x03C,temp);         /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
+    	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
 
 #endif  /* SIS300 */
 
-  	} else {
+     } else {
 
 #ifdef SIS315H   /* --------------- 315/330 series ---------------*/
 
-   	   if(HwInfo->jChipType < SIS_661) {
+        if(HwInfo->jChipType < SIS_661) {
 
-	      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-                 temp = 0x10;
-                 if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  temp = 0x2c;
-    	         if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
-    	         if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)  temp = 0x24;
-		 if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom)    temp = 0x2c;
-		 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-		    temp = 0x08;
-		    if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-		       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  temp = 0x2c;
-      		       else 					temp = 0x20;
-		    }
-		 }
-		 if((SiS_Pr->SiS_VBType & VB_SIS301B302B) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-		    tempbl = 0x00;
-		    if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
-		       if(HwInfo->jChipType < SIS_330) {
-		          if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
-		       } else {
-		          if(ROMAddr[0x1bc] & 0x80) tempbl = 0xf0;
-		       }
-		    }
-		 } else {  /* LV (550/301LV checks ROM byte, other LV BIOSes do not) */
-		    tempbl = 0xF0;
-		 }
-		 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {
-		    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-		       if(SiS_Pr->PDC) {
-		          temp = SiS_Pr->PDC;
-		          tempbl = 0;
-		       }
-		    }
-		 }
+	   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 
-	      } else {  /* LVDS */
+	      if(HwInfo->jChipType == SIS_740) temp = 0x03;
+	      else 		               temp = 0x00;
 
-	         if(HwInfo->jChipType == SIS_740) {
-		    temp = 0x03;
-	         } else {
-		    temp = 0x00;
-		 }
-	 	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
-		 tempbl = 0xF0;
-		 if(HwInfo->jChipType == SIS_650) {
-		    if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-		       if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
-		    }
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
+	      tempbl = 0xF0;
+	      if(HwInfo->jChipType == SIS_650) {
+		 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+		    if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
 		 }
+	      }
 
-		 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
-		    temp = 0x08;
-		    tempbl = 0;
-		    if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
-		       if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
-		    }
+	      if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
+		 temp = 0x08;
+		 tempbl = 0;
+		 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+		    if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
 		 }
 	      }
 
 	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp);	    /* Panel Link Delay Compensation */
+	   }
 
-	   } /* < 661 */
+	} /* < 661 */
 
-    	   tempax = 0;
-    	   if (modeflag & DoubleScanMode) tempax |= 0x80;
-    	   if (modeflag & HalfDCLK)       tempax |= 0x40;
-    	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
+    	tempax = 0;
+    	if(modeflag & DoubleScanMode) tempax |= 0x80;
+    	if(modeflag & HalfDCLK)       tempax |= 0x40;
+    	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
 
 #endif  /* SIS315H */
 
-  	}
-
-     }  /* Slavemode */
+     }
 
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+  }  /* Slavemode */
 
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
         /* For 301BDH with LCD, we set up the Panel Link */
-        if( (SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) {
-
-	    SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex,
-	                       HwInfo, RefreshRateTableIndex);
-
-        } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-
-    	    SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex,
-	                      HwInfo, RefreshRateTableIndex);
-        }
-
+	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+    	SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     }
+  } else {
+     if(HwInfo->jChipType < SIS_315H) {
+	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
      } else {
-
-        if(HwInfo->jChipType < SIS_315H) {
-
-	   SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex,
-	                        HwInfo, RefreshRateTableIndex);
+	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+           if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+    	      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
+           }
 	} else {
-
-	   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-              if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-    	          SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,
-	                              HwInfo,RefreshRateTableIndex);
-              }
-	   } else {
-	      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,
-	                         HwInfo,RefreshRateTableIndex);
-	   }
-
+	   SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
 	}
-
      }
-  } /* LCDA */
+  }
 }
 
 /*********************************************/
@@ -7025,9 +6414,8 @@
 static UCHAR *
 SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
 {
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
    const UCHAR  *tableptr = NULL;
-   USHORT a, b, p = 0;
+   USHORT       a, b, p = 0;
 
    a = SiS_Pr->SiS_VGAHDE;
    b = SiS_Pr->SiS_HDE;
@@ -7036,66 +6424,33 @@
       b = SiS_Pr->SiS_VDE;
    }
 
-   if((HwInfo->jChipType >= SIS_661) && (ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
-
-      if(a < b) {
-         p = ROMAddr[0x278] | (ROMAddr[0x279] << 8);
-      } else if(a == b) {
-         p = ROMAddr[0x27a] | (ROMAddr[0x27b] << 8);
-      } else {
-         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	    p = ROMAddr[0x27e] | (ROMAddr[0x27f] << 8);
-	 } else {
-	    p = ROMAddr[0x27c] | (ROMAddr[0x27d] << 8);
-	 }
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	    if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	 p = ROMAddr[0x280] | (ROMAddr[0x281] << 8);
-	    else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) p = ROMAddr[0x282] | (ROMAddr[0x283] << 8);
-	    else 				 	 p = ROMAddr[0x284] | (ROMAddr[0x285] << 8);
-	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	    p = ROMAddr[0x286] | (ROMAddr[0x287] << 8);
-	 }
-	 do {
-	    if((ROMAddr[p] | ROMAddr[p+1] << 8) == a) break;
-	    p += 0x42;
-	 } while((ROMAddr[p] | ROMAddr[p+1] << 8) != 0xffff);
-	 if((ROMAddr[p] | ROMAddr[p+1] << 8) == 0xffff) p -= 0x42;
-      }
-      p += 2;
-      return(&ROMAddr[p]);
-
+   if(a < b) {
+      tableptr = SiS_Part2CLVX_1;
+   } else if(a == b) {
+      tableptr = SiS_Part2CLVX_2;
    } else {
-
-      if(a < b) {
-         tableptr = SiS_Part2CLVX_1;
-      } else if(a == b) {
-         tableptr = SiS_Part2CLVX_2;
+      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	 tableptr = SiS_Part2CLVX_4;
       } else {
-         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	    tableptr = SiS_Part2CLVX_4;
-	 } else {
-	    tableptr = SiS_Part2CLVX_3;
-	 }
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	    if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	 tableptr = SiS_Part2CLVX_3;
-	    else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tableptr = SiS_Part2CLVX_3;
-	    else 				         tableptr = SiS_Part2CLVX_5;
-
-	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	    tableptr = SiS_Part2CLVX_6;
-	 }
-	 do {
-	    if((tableptr[p] | tableptr[p+1] << 8) == a) break;
-	    p += 0x42;
-	 } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
-	 if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
+	 tableptr = SiS_Part2CLVX_3;
       }
-      p += 2;
-      return((UCHAR *)&tableptr[p]);
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	tableptr = SiS_Part2CLVX_3;
+	 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) 	tableptr = SiS_Part2CLVX_3;
+	 else 				         	tableptr = SiS_Part2CLVX_5;
+      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	 tableptr = SiS_Part2CLVX_6;
+      }
+      do {
+	 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
+	 p += 0x42;
+      } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
+      if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
    }
+   p += 2;
+   return((UCHAR *)&tableptr[p]);
 }
 
-
 static void
 SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 	      	    USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
@@ -7121,49 +6476,97 @@
    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
 }
 
-static void
+static BOOLEAN
 SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 		    USHORT RefreshRateTableIndex,USHORT *CRT2Index,
 		    USHORT *ResIndex,PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx,tempal;
+
+  if(HwInfo->jChipType < SIS_315H) return FALSE;
 
   if(ModeNo <= 0x13)
-      	tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   else
-      	tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
-  tempbx = SiS_Pr->SiS_LCDResInfo;
+  (*ResIndex) &= 0x3f;
+  (*CRT2Index) = 0;
 
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)      tempbx += 16;
-  else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx += 32;
-
-  if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        tempbx = 100;
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)      tempbx = 101;
-  	else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 102;
-     }
-  } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-           tempbx = 103;
-           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)      tempbx = 104;
-  	   else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 105;
-	}
-     }
-  } else if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 106;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+        (*CRT2Index) = 200;
      }
   }
 
-  *CRT2Index = tempbx;
-  *ResIndex = tempal & 0x3F;
+  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
+     }
+  }
+  return(((*CRT2Index) != 0));
 }
 #endif
 
 #ifdef SIS300
+static void
+SiS_Group2LCDSpecial(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT crt2crtc)
+{
+   USHORT tempcx;
+   const UCHAR atable[] = {
+       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
+       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
+   };
+
+   if(!SiS_Pr->UseCustomMode) {
+      if( ( ( (HwInfo->jChipType == SIS_630) ||
+              (HwInfo->jChipType == SIS_730) ) &&
+            (HwInfo->jChipRevision > 2) )  &&
+          (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
+          (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
+          (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
+         if(ModeNo == 0x13) {
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
+         } else {
+            if((crt2crtc & 0x3F) == 4) {
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
+            }
+         }
+      }
+
+      if(HwInfo->jChipType < SIS_315H) {
+         if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
+            crt2crtc &= 0x1f;
+            tempcx = 0;
+            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                  tempcx += 7;
+               }
+            }
+            tempcx += crt2crtc;
+            if(crt2crtc >= 4) {
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
+            }
+
+            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                  if(crt2crtc == 4) {
+                     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
+                  }
+               }
+            }
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
+         }
+      }
+   }
+}
+
 /* For ECS A907. Highly preliminary. */
 static void
 SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
@@ -7232,15 +6635,81 @@
 	if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
 	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
 	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
 	   } else {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x15);
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);  /* 15 */
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a);  /* 1b */
 	   }
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
 	}
      }
   } else {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x21);
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x5a);
+     if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
+        (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 21 */
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 5a */
+     } else {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a);  /* 21 */
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53);  /* 5a */
+     }
+  }
+}
+
+static void
+SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
+{
+  USHORT temp;
+
+  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+     if(SiS_Pr->SiS_VGAVDE == 525) {
+	temp = 0xc3;
+	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	   temp++;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
+	}
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
+     } else if(SiS_Pr->SiS_VGAVDE == 420) {
+	temp = 0x4d;
+	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	   temp++;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
+	}
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
+     }
+  }
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
+	if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
+	   /* Not always for LV, see SetGrp2 */
+	}
+	temp = 1;
+	if(ModeNo <= 0x13) temp = 3;
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
+     }
+#if 0
+     /* 651+301C, for 1280x768 - do I really need that? */
+     if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
+        if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
+	   if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
+	      ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
+	      SiS_SetReg(SiS_Part2Port,0x01,0x2b);
+	      SiS_SetReg(SiS_Part2Port,0x02,0x13);
+	      SiS_SetReg(SiS_Part2Port,0x04,0xe5);
+	      SiS_SetReg(SiS_Part2Port,0x05,0x08);
+	      SiS_SetReg(SiS_Part2Port,0x06,0xe2);
+	      SiS_SetReg(SiS_Part2Port,0x1c,0x21);
+	      SiS_SetReg(SiS_Part2Port,0x1d,0x45);
+	      SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
+	      SiS_SetReg(SiS_Part2Port,0x20,0x00);
+	      SiS_SetReg(SiS_Part2Port,0x21,0xa9);
+	      SiS_SetReg(SiS_Part2Port,0x23,0x0b);
+	      SiS_SetReg(SiS_Part2Port,0x25,0x04);
+	   }
+	}
+     }
+#endif
   }
 }
 
@@ -7248,37 +6717,27 @@
 SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
 	      PSIS_HW_INFO HwInfo)
 {
-  USHORT      i, j, tempax, tempbx, tempcx, temp;
-  USHORT      push1, push2, modeflag, crt2crtc;
-  ULONG       longtemp, tempeax;
+  USHORT      i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
+  USHORT      push2, modeflag, crt2crtc, bridgeoffset;
+  ULONG       longtemp;
   const       UCHAR *PhasePoint;
   const       UCHAR *TimingPoint;
 #ifdef SIS315H
   USHORT      resindex, CRT2Index;
   const       SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
-#endif
-#ifdef SIS300
-  const UCHAR atable[] = {
-       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
-       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
-  };
-#endif
 
-#ifdef SIS315H   
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
 #endif
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     crt2crtc = 0;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	crt2crtc = 0;
-     } else {
-        modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
   }
 
   temp = 0;
@@ -7395,7 +6854,7 @@
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) 	tempax = 950;
   else if(SiS_Pr->SiS_TVMode & TVSetPAL)      	tempax = 520;
-  else 			            		tempax = 440;
+  else 			            		tempax = 440; /* NTSC, YPbPr 525, 750 */
 
   if( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) && (SiS_Pr->SiS_VDE <= tempax) ) ||
       ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
@@ -7411,10 +6870,10 @@
      temp = tempax + (USHORT)TimingPoint[1];
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
 
-     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
+     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x19);
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x52);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 19 */
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 52 */
         } else {
            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
@@ -7427,199 +6886,157 @@
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   tempcx--;
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,temp);
-  temp = (tempcx & 0xFF00) >> 8;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,temp);
-
-  tempcx++;
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx++;
-  tempcx >>= 1;
-
-  push1 = tempcx;
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
 
+  tempcx = SiS_Pr->SiS_HT >> 1;
+  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   tempcx += 7;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
-  temp = (tempcx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
 
-  tempbx = TimingPoint[j] | ((TimingPoint[j+1]) << 8);
+  tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
   tempbx += tempcx;
-
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,temp);
-  temp = ((tempbx & 0xFF00) >> 8) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
 
   tempbx += 8;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      tempbx -= 4;
      tempcx = tempbx;
   }
-  temp = (tempbx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
 
   j += 2;
-  tempcx += ((TimingPoint[j] | ((TimingPoint[j+1]) << 8)));
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,temp);
-  temp = ((tempcx & 0xFF00) >> 8) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,temp);
+  tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
 
   tempcx += 8;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
-  temp = (tempcx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,temp);
-
-  tempcx = push1;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
 
+  tempcx = SiS_Pr->SiS_HT >> 1;
+  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   j += 2;
   tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
-  temp = (tempcx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
 
   tempcx -= 11;
   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
      tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
   }
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
 
   tempbx = SiS_Pr->SiS_VDE;
-  if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
-  if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
-  if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
-  if(HwInfo->jChipType < SIS_315H) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempbx >>= 1;
-  } else {
-     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
-         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
-	tempbx >>= 1;
-	if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-	   if(ModeNo <= 0x13) {
-	      if(crt2crtc == 1) tempbx++;
-	   }
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
+     if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
+     if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
+  } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
+             (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
+     tempbx >>= 1;
+     if(HwInfo->jChipType >= SIS_315H) {
+        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+	   if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
 	} else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	   if(crt2crtc == 4) {
-              if(SiS_Pr->SiS_ModeType <= 3) tempbx++;
+	   if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	      if(crt2crtc == 4) tempbx++;
 	   }
 	}
      }
-  }
-  tempbx -= 2;
-  temp = tempbx & 0x00FF;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-        if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) temp++;
-     }
-  }
-
-  if(HwInfo->jChipType < SIS_661) {
-     /* From 1.10.7w - doesn't make sense */
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-           if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {   /* SetFlag?? */
-	         if(ModeNo == 0x03) temp++;
-	      }
-	   }
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	   if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
+	}
+	if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+	   if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
         }
      }
   }
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,temp);
+  tempbx -= 2;
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
 
   temp = (tempcx >> 8) & 0x0F;
-  temp |= (((tempbx >> 8) << 6) & 0xC0);
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750 | SetCRT2ToSCART))) {
+  temp |= ((tempbx >> 2) & 0xC0);
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
      temp |= 0x10;
-     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x20;
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
   }
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
 
-  if((HwInfo->jChipType > SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
-           if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-               (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) ) {
-              SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x10,0x60);
-	   }
-        }
+  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
+  }
+
+#if 0
+  /* TEST qqqq */
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+     for(i=0x01, j=0; i<=0x2D; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
+     }
+     for(i=0x39; i<=0x45; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
      }
   }
+#endif
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
      tempbx = SiS_Pr->SiS_VDE;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
-           tempbx >>= 1;
-	}
+     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
+         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
+        tempbx >>= 1;
      }
      tempbx -= 3;
-     if(HwInfo->jChipType >= SIS_661) {
-        if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {  /* Why not 301B/LV? */
-           temp = 0;
-	   if(tempcx & 0x0400) temp |= 0x20;
-	   if(tempbx & 0x0400) temp |= 0x40;
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x10,temp);
-	}
-     }
-     tempbx &= 0x03ff;
-     temp = ((tempbx & 0xFF00) >> 8) << 5;
-     temp |= 0x18;
+     temp = ((tempbx >> 3) & 0x60) | 0x18;
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
-     temp = tempbx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,temp);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
 
+     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
+     }
   }
 
   tempbx = 0;
   if(!(modeflag & HalfDCLK)) {
      if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
         tempax = 0;
-        tempbx |= 0x2000;
+        tempbx |= 0x20;
      }
   }
 
-  tempcx = 0x0101;
+  tempch = tempcl = 0x01;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
      if(SiS_Pr->SiS_VGAHDE >= 1024) {
         if((!(modeflag & HalfDCLK)) || (HwInfo->jChipType < SIS_315H)) {
-           tempcx = 0x1920;
+           tempch = 0x19;
+	   tempcl = 0x20;
            if(SiS_Pr->SiS_VGAHDE >= 1280) {
-              tempcx = 0x1420;
-              tempbx &= ~0x2000;
+              tempch = 0x14;
+              tempbx &= ~0x20;
            }
         }
      }
   }
 
-  if(!(tempbx & 0x2000)) {
-     if(modeflag & HalfDCLK) {
-        tempcx = (tempcx & 0xFF00) | ((tempcx << 1) & 0x00FF);
-     }
-     longtemp = (SiS_Pr->SiS_VGAHDE * ((tempcx & 0xFF00) >> 8)) / (tempcx & 0x00FF);
-     longtemp <<= 13;
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-     	longtemp <<= 3;
-     }
-     tempeax = longtemp / SiS_Pr->SiS_HDE;
-     if(longtemp % SiS_Pr->SiS_HDE) tempeax++;
-     tempax = (USHORT)tempeax;
-     tempbx |= (tempax & 0x1F00);
-     tempcx = (tempax & 0xFF00) >> (8 + 5);
+  if(!(tempbx & 0x20)) {
+     if(modeflag & HalfDCLK) tempcl <<= 1;
+     longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
+     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) longtemp <<= 3;
+     tempax = longtemp / SiS_Pr->SiS_HDE;
+     if(longtemp % SiS_Pr->SiS_HDE) tempax++;
+     tempbx |= ((tempax >> 8) & 0x1F);
+     tempcx = tempax >> 13;
   }
 
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,(tempbx >> 8));
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
 
-     temp = tempcx & 0x0007;
-     if(tempbx & 0x2000) temp = 0;
-     if((HwInfo->jChipType < SIS_661) || (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
-        temp |= 0x18;
-     }
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xE0,temp);
+     tempcx &= 0x07;
+     if(tempbx & 0x20) tempcx = 0;
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
 
      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
         tempbx = 0x0382;
@@ -7628,11 +7045,9 @@
         tempbx = 0x0369;
         tempcx = 0x0061;
      }
-     temp = (tempbx & 0x00FF) ;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,temp);
-     temp = (tempcx & 0x00FF) ;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,temp);
-     temp = (tempcx & 0x0300) >> (8 - 2);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
+     temp = (tempcx & 0x0300) >> 6;
      temp |= ((tempbx >> 8) & 0x03);
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
         temp |= 0x10;
@@ -7642,7 +7057,7 @@
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
 
      temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(USHORT)(temp - 3));
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
 
      SiS_SetTVSpecial(SiS_Pr, ModeNo);
 
@@ -7657,7 +7072,7 @@
   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
      if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
         temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp - 1);
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
      }
      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
   }
@@ -7675,13 +7090,11 @@
   tempbx = SiS_Pr->SiS_HDE;
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
   tempbx--;			         	/* RHACTE = HDE - 1 */
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,temp);
-  temp = (tempbx & 0xFF00) >> 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
 
   temp = 0x01;
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
      if(SiS_Pr->SiS_ModeType == ModeEGA) {
         if(SiS_Pr->SiS_VGAHDE >= 1024) {
            temp = 0x02;
@@ -7696,49 +7109,19 @@
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
 
   tempbx = SiS_Pr->SiS_VDE - 1;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,temp);
-  temp = ((tempbx & 0xFF00) >> 8) & 0x07;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
 
   tempcx = SiS_Pr->SiS_VT - 1;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,temp);
-
-  temp = ((tempcx & 0xFF00) >> 8) << 5;
-
-  /* Enable dithering; only do this for 32bpp mode */
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
+  temp = (tempcx >> 3) & 0xE0;
   if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+     /* Enable dithering; only do this for 32bpp mode */
      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
         temp |= 0x10;
      }
   }
-
-  /* Must do special for Compaq1280; Acer1280 OK, Clevo1400 OK, COMPAL1400 OK */
-  /* Compaq1280 panel loses sync if using CR37 sync info. */
-  if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-     if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
-	if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) {
-	   if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-	      temp |= ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
-	   }
-	} else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
-	          (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)) {
-	   temp |= 0x03;
-	} else {
-           temp |= (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) >> 6);
-	   temp |= 0x08;
-	   if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) temp |= 0x04;
-	}
-     } else {
-        if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-	   temp |= ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
-	}
-     }
-  }
-
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1A,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
 
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
@@ -7746,154 +7129,13 @@
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
 
-#if 0  /* Use the 315/330 series code for now */
-  if((HwInfo->jChipType >= SIS_661)          &&
-     (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) &&
-     (ROMAddr && SiS_Pr->SiS_UseROM)) {
-
-      /* This is done for the LVDS bridges only, since
-       * the TMDS panels already work correctly with
-       * the old code. Besides, we only do that if
-       * we can get the data from the ROM, I am tired
-       * of carrying a lot of tables around.
-       */
-
-#ifdef SIS315H 							/* ------------ 661/741/760 series --------- */
-      UCHAR *myptr = NULL, myptr1 = NULL;
-
-      myptr = (UCHAR *)GetLCDPtr661(SiS_Pr, HwInfo, 6, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-      myptr1 = (UCHAR *)GetLCDStructPtr661(SiS_Pr, HwInfo);
-
-      tempbx = (myptr[3] | (myptr[4] << 8)) & 0x0fff;
-      tempcx = SiS_Pr->PanelYRes;
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-         tempcx = SiS_Pr->SiS_VDE;
-      }
-
-      tempcx += tempbx;
-      if(tempcx >= SiS_Pr->SiS_VT) tempcx -= SiS_Pr->SiS_VT;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempbx);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempcx);
-
-      tempcx &= 0x07ff;
-      tempbx &= 0x07ff;
-      temp = (tempcx >> 8) << 3;
-      temp |= (tempbx >> 8);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
-
-      tempbx = (myptr[4] | (myptr[5] << 8)) >> 4;
-      tempcx = myptr1[6];
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempcx = myptr[7];
-
-      tempcx += tempbx;
-      if(tempcx >= SiS_Pr->SiS_VT) tempcx -= SiS_Pr->SiS_VT;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);
-      temp = tempcx & 0x000f;
-      temp |= ((tempbx & 0x0f00) >> 4);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
-
-      tempax = SiS_Pr->SiS_HT;
-      tempbx = (myptr[0] | (myptr[1] << 8)) & 0x0fff;
-      tempcx = SiS_Pr->PanelXRes;
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempcx = SiS_Pr->SiS_HDE;
-
-      if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-         tempax >>= 1;
-	 tempbx >>= 1;
-	 tempcx >>= 1;
-      }
-      if(SiS_Pr->SiS_VBType & VB_SIS302LV)                 tempbx++;
-      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) tempbx++;
-
-      tempcx += tempbx;
-      if(tempcx >= tempax) tempcx -= tempax;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,tempbx);
-      temp = ((tempbx & 0xff00) >> 8) << 4;
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x20,temp);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempcx);
-      temp = tempcx >> 8;
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x25,temp);
-
-      tempax = SiS_Pr->SiS_HT;
-      tempbx = (myptr[1] | (myptr[2] << 8)) >> 4;
-      tempcx = myptr1[5];
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-         tempcx = myptr[6];
-      }
-      if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-         tempax >>= 1;
-	 tempbx >>= 1;
-	 tempcx >>= 1;
-      }
-      if(SiS_Pr->SiS_VBType & VB_SIS302LV) tempbx++;
-
-      tempcx += tempbx;
-      if(tempcx >= tempax) tempcx -= tempax;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1c,tempbx);
-      temp = (tempbx & 0x0f00) >> 4;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1d,0x0f,temp);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempcx);
-
-      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-         if(SiS_Pr->SiS_VGAVDE == 525) {
-	    temp = 0xc3;
-	    if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	       temp++;
-	       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
-	    }
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
-	 } else if(SiS_Pr->SiS_VGAVDE == 420) {
-	    temp = 0x4d;
-	    if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	       temp++;
-	       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
-	    }
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	 }
-      }
-
-#endif
-
-  } else
-#endif
-         if((HwInfo->jChipType >= SIS_315H)                    &&
-            (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)            &&
-            ((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  ||
-             (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-             (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-             (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) ) {
-
-#ifdef SIS315H 							/* ------------- 315/330 series ------------ */
-
-      SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                          &CRT2Index, &resindex, HwInfo);
-
+#ifdef SIS315H
+  if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
+                          			&CRT2Index, &resindex, HwInfo)) {
       switch(CRT2Index) {
-        case Panel_1024x768      : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;  break;  /* "Normal" */
-        case Panel_1280x1024     : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_1; break;
-	case Panel_1400x1050     : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_1; break;
-	case Panel_1600x1200     : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_1; break;
-        case Panel_1024x768  + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;  break;  /* Non-Expanding */
-        case Panel_1280x1024 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_2; break;
-	case Panel_1400x1050 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_2; break;
-	case Panel_1600x1200 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_2; break;
-        case Panel_1024x768  + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;  break;  /* VESA Timing */
-        case Panel_1280x1024 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_3; break;
-	case Panel_1400x1050 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_3; break;
-	case Panel_1600x1200 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_3; break;
-	case 100:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_1; break;  /* Custom */
-	case 101:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_2; break;
-	case 102:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_3; break;
-	case 103:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Clevo1024x768_1; break;    /* Custom */
-	case 104:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Clevo1024x768_2; break;
-	case 105:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Clevo1024x768_3; break;
-	case 106:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Asus1024x768_3; break;
-	default:                   CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;  break;
+        case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
+	case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
+	default:  CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;   break;
       }
 
       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
@@ -7910,58 +7152,34 @@
       SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
 
-      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        if(SiS_Pr->SiS_VGAVDE == 525) {
-	  temp = 0xc3;
-	  if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	     temp++;
-	     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
-	  }
-	  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
-	} else if(SiS_Pr->SiS_VGAVDE == 420) {
-	  temp = 0x4d;
-	  if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	     temp++;
-	     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
-	  }
-	  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	}
-     }
-
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   /* See Sync above, 0x1a */
-	   temp = 1;
-	   if(ModeNo <= 0x13) temp = 3;
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
-	}
-     }
-#endif
+      SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
 
-  } else {   /* ------ 300 series and other bridges, other LCD resolutions ------ */
 
-      /* Using this on the 301B with an auto-expanding 1024 panel (CR37=1) makes
-       * the panel scale at modes < 1024 (no black bars); if the panel is non-expanding,
-       * the bridge scales all modes to 1024.
-       * !!! Malfunction at 640x480 and 640x400 when panel is auto-expanding - black screen !!!
-       */
+  } else {
+#endif
 
-    tempcx = SiS_Pr->SiS_VT;
-    tempbx = SiS_Pr->PanelYRes;
+    /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
+    /*             Clevo dual-link 1024x768 */
+    /* 		   Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
+    /*		   Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
 
     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-       tempbx = SiS_Pr->SiS_VDE - 1;
-       tempcx--;
-    }
-
-    tempax = 1;
-    if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-       if(tempbx != SiS_Pr->SiS_VDE) {
-          tempax = tempbx;
-          if(tempax < SiS_Pr->SiS_VDE) {
-             tempax = 0;
-             tempcx = 0;
+       if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
+          tempbx = SiS_Pr->SiS_VDE - 1;
+          tempcx = SiS_Pr->SiS_VT - 1;
+       } else {
+          tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
+	  tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
+       }
+    } else {
+       tempbx = SiS_Pr->PanelYRes;
+       tempcx = SiS_Pr->SiS_VT;
+       tempax = 1;
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+          tempax = SiS_Pr->PanelYRes;
+	  /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
+          if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
+             tempax = tempcx = 0;
           } else {
              tempax -= SiS_Pr->SiS_VDE;
           }
@@ -7971,29 +7189,55 @@
        tempbx -= tempax; /* lcdvdee */
     }
 
-    /* Non-expanding: lcdvdees = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
+    /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
 
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
 #endif
 
-    temp = tempcx & 0x00FF;   				/* RVEQ1EQ=lcdvdes */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,temp);
-    temp = tempbx & 0x00FF;   				/* RVEQ2EQ=lcdvdee */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);	/* lcdvdes  */
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);	/* lcdvdee  */
 
-    temp = ((tempbx & 0xFF00) >> 8) << 3;
-    temp |= ((tempcx & 0xFF00) >> 8);
+    temp = (tempbx >> 5) & 0x38;
+    temp |= ((tempcx >> 8) & 0x07);
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
 
-    tempbx = SiS_Pr->SiS_VT;    /* push2; */
-    tempax = SiS_Pr->SiS_VDE;   /* push1; */
-    tempcx = (tempbx - tempax) >> 4;
-    tempbx += tempax;
-    tempbx >>= 1;
-    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx -= 10;
+    tempax = SiS_Pr->SiS_VDE;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       tempax = SiS_Pr->PanelYRes;
+    }
+    tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+	  tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
+       }
+    }
 
-    /* non-expanding: lcdvrs = tempbx = ((VT + VDE) / 2) - 10 */
+    tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
+    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
+             tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
+	     if(tempax % 4) { tempax >>= 2; tempax++; }
+	     else           { tempax >>= 2;           }
+             tempbx -= (tempax - 1);
+	  } else {
+	     tempbx -= 10;
+	     if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
+	  }
+       }
+    }
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+       tempbx++;
+       if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
+          if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+	     tempbx = 770;
+	     tempcx = 3;
+	  }
+       }
+    }
+
+    /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
 
     if(SiS_Pr->UseCustomMode) {
        tempbx = SiS_Pr->CVSyncStart;
@@ -8003,12 +7247,11 @@
     xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;   				/* RTVACTEE = lcdvrs */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);	    /* lcdvrs */
 
-    temp = ((tempbx & 0xFF00) >> 8) << 4;
+    temp = (tempbx >> 4) & 0xF0;
     tempbx += (tempcx + 1);
-    temp |= (tempbx & 0x000F);
+    temp |= (tempbx & 0x0F);
 
     if(SiS_Pr->UseCustomMode) {
        temp &= 0xf0;
@@ -8021,149 +7264,103 @@
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
 
-    /* Code from 630/301B (I+II) BIOS */
-
 #ifdef SIS300
-    if(!SiS_Pr->UseCustomMode) {
-       if( ( ( (HwInfo->jChipType == SIS_630) ||
-               (HwInfo->jChipType == SIS_730) ) &&
-             (HwInfo->jChipRevision > 2) )  &&
-           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) &&
-           (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
-           (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
-          if(ModeNo == 0x13) {
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
-          } else {
-             if((crt2crtc & 0x3F) == 4) {
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
-             }
-          }
-       }
-
-       if(HwInfo->jChipType < SIS_315H) {
-          if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
-             crt2crtc &= 0x1f;
-             tempcx = 0;
-             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                   tempcx += 7;
-                }
-             }
-             tempcx += crt2crtc;
-             if(crt2crtc >= 4) {
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
-             }
+    SiS_Group2LCDSpecial(SiS_Pr, HwInfo, ModeNo, crt2crtc);
+#endif
 
-             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                   if(crt2crtc == 4) {
-                      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
-                   }
-                }
-             }
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
-          }
+    bridgeoffset = 7;
+    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)          bridgeoffset += 2;
+    if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) bridgeoffset++;
+    if(SiS_IsDualLink(SiS_Pr, HwInfo))        		 bridgeoffset++;
+
+    temp = 0;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
+          temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+	  if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp >>= 1;
        }
     }
-#endif
-
-    tempcx = (SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE) >> 2;     /* (HT - HDE) >> 2 */
-    tempbx = SiS_Pr->SiS_HDE + 7;            		  /* lcdhdee         */
-    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-       tempbx += 2;
+    temp += bridgeoffset;
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	     /* lcdhdes */
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
+
+    tempcx = SiS_Pr->SiS_HT;
+    tempax = tempbx = SiS_Pr->SiS_HDE;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
+          tempax = SiS_Pr->PanelXRes;
+          tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+       }
+    }
+    if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
+       tempcx >>= 1;
+       tempbx >>= 1;
+       tempax >>= 1;
     }
-    push1 = tempbx;
 
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;    			          /* RHEQPLE = lcdhdee */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,temp);
-    temp = (tempbx & 0xFF00) >> 8;
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,temp);
-
-    temp = 7;
-    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-       temp += 2;
-    }
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	  /* RHBLKE = lcdhdes[7:0] */
-    SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x20,0x0F);	  /* lcdhdes [11:8] */
+    tempbx += bridgeoffset;
+
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);	    /* lcdhdee */
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
+
+    tempcx = (tempcx - tempax) >> 2;
 
     tempbx += tempcx;
     push2 = tempbx;
 
-    if(SiS_Pr->UseCustomMode) {
-       tempbx = SiS_Pr->CHSyncStart + 7;
-       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-          tempbx += 2;
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+          if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+             if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
+	  }
        }
     }
 
+    if(SiS_Pr->UseCustomMode) {
+       tempbx = SiS_Pr->CHSyncStart;
+       if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+       tempbx += bridgeoffset;
+    }
+
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;            		          /* RHBURSTS = lcdhrs */
-    if(!SiS_Pr->UseCustomMode) {
-       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-          if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-             if(SiS_Pr->SiS_HDE == 1280) temp = 0x47;
-          }
-       }
-    }
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,temp);
-    temp = (tempbx & 0x0F00) >> 4;
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);	    /* lcdhrs */
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
 
     tempbx = push2;
+
     tempcx <<= 1;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
+    }
     tempbx += tempcx;
 
     if(SiS_Pr->UseCustomMode) {
-       tempbx = SiS_Pr->CHSyncEnd + 7;
-       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-          tempbx += 2;
-       }
+       tempbx = SiS_Pr->CHSyncEnd;
+       if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+       tempbx += bridgeoffset;
     }
 
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;            		          /* RHSYEXP2S = lcdhre */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);	    /* lcdhre */
 
-    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-       if(SiS_Pr->SiS_VGAVDE == 525) {
-          if(SiS_Pr->SiS_ModeType <= ModeVGA)
-    	     temp=0xC6;
-          else
-       	     temp=0xC3;
-          SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-          SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xB3);
-       } else if(SiS_Pr->SiS_VGAVDE == 420) {
-          if(SiS_Pr->SiS_ModeType <= ModeVGA)
-	     temp=0x4F;
-          else
-       	     temp=0x4D;
-          SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-       }
-    }
+    SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
 
 #ifdef SIS300
-    SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex,
-                        RefreshRateTableIndex, ModeNo);
+    SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex, RefreshRateTableIndex, ModeNo);
+#endif
+#ifdef SIS315H
+  } /* CRT2-LCD from table */
 #endif
-
-  } /* HwInfo */
 }
 
 /*********************************************/
@@ -8174,26 +7371,14 @@
 SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
               PSIS_HW_INFO HwInfo)
 {
-  USHORT modeflag, i;
-  const UCHAR  *tempdi;
+  USHORT 	i;
+  const UCHAR  	*tempdi;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
 
-  if(ModeNo<=0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
-  }
-
 #ifndef SIS_CP
   SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
-#endif
-
-#ifdef SIS_CP
+#else
   SIS_CP_INIT301_CP
 #endif
 
@@ -8216,11 +7401,6 @@
      tempdi = SiS_Pr->SiS_HiTVGroup3Data;
      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
         tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
-#if 0
-        if(!(modeflag & Charx8Dot)) {
-           tempdi = SiS_Pr->SiS_HiTVGroup3Text;
-        }
-#endif
      }
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
      if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
@@ -8229,7 +7409,7 @@
      }
   }
   if(tempdi) {
-     for(i=0; i<=0x3E; i++){
+     for(i=0; i<=0x3E; i++) {
         SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
      }
      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
@@ -8239,11 +7419,9 @@
      }
   }
 
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) {
 #ifdef SIS_CP
-     SIS_CP_INIT301_CP2
+  SIS_CP_INIT301_CP2
 #endif
-  }
 }
 
 /*********************************************/
@@ -8252,11 +7430,37 @@
 
 #ifdef SIS315H
 static void
-SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ShiftXPos(SiS_Private *SiS_Pr, int shift)
 {
-   USHORT temp, temp1;
+   USHORT temp, temp1, temp2;
 
-   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
+   temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
+   temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
+   temp = (USHORT)((int)(temp) + shift);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
+   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
+   temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
+}
+
+static void
+SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                    USHORT ModeNo, USHORT ModeIdIndex)
+{
+   USHORT temp, temp1, resinfo = 0;
+
+   if(!(SiS_Pr->SiS_VBType & VB_SIS301C)) return;
+   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
+
+   if(ModeNo > 0x13) {
+      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+   }
 
    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
    temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
@@ -8267,28 +7471,37 @@
          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
       }
       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
-      temp = 0;
-      if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)) {
-         temp |= 0x0002;
-         if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)) {
-	    temp ^= 0x0402;
-	    if(!(SiS_Pr->SiS_TVMode & TVSetHiVision)) {
-	       temp ^= 0x0002;
-	    }
-	 }
-      }
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
+      else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
+      else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
+      else					   temp = 0x0402;
       if(HwInfo->jChipType >= SIS_661) {
-         temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
-         if(temp1 & 0x01) temp |= 0x10;
-         if(temp1 & 0x02) temp |= 0x01;
-	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xec,(temp & 0xff));
+         temp1 = 0;
+	 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
+	 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
       } else {
          temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
 	 if(temp1 == 0x01) temp |= 0x01;
 	 if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
-	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xea,(temp & 0xff));
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
       }
       SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+
+      if(HwInfo->jChipType >= SIS_661) { 		/* ? */
+         if(SiS_Pr->SiS_TVMode & TVAspect43) {
+            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+	       if(resinfo == SIS_RI_1024x768) {
+	          SiS_ShiftXPos(SiS_Pr, 97);
+	       } else {
+	          SiS_ShiftXPos(SiS_Pr, 111);
+	       }
+	    } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
+	       SiS_ShiftXPos(SiS_Pr, 136);
+	    }
+         }
+      }
    }
 }
 #endif
@@ -8330,25 +7543,22 @@
   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
 }
 
-/* Set 301 VGA2 registers */
 static void
 SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   	      USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
 {
-  USHORT tempax,tempcx,tempbx,modeflag,temp,temp2,resinfo;
+  USHORT tempax,tempcx,tempbx,modeflag,temp,resinfo;
   ULONG tempebx,tempeax,templong;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	resinfo = 0;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
   if(HwInfo->jChipType >= SIS_315H) {
@@ -8371,186 +7581,151 @@
 	   if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
 	      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
 	   }
-#ifdef SET_EMI
+
 	   if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 	      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+#ifdef SET_EMI
 	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+#endif
 	      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 	   }
-#endif
 	}
    	return;
      }
   }
 
-  temp = SiS_Pr->SiS_RVBHCFACT;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
 
   tempbx = SiS_Pr->SiS_RVBHCMAX;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
 
-  temp2 = (((tempbx & 0xFF00) >> 8) << 7) & 0x00ff;
+  temp = (tempbx >> 1) & 0x80;
 
   tempcx = SiS_Pr->SiS_VGAHT - 1;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
 
-  temp = (((tempcx & 0xFF00) >> 8) << 3) & 0x00ff;
-  temp2 |= temp;
+  temp |= ((tempcx >> 5) & 0x78);
 
   tempcx = SiS_Pr->SiS_VGAVT - 1;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV))  tempcx -= 5;
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
 
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,temp);
-
-  temp = temp2 | ((tempcx & 0xFF00) >> 8);
+  temp |= ((tempcx >> 8) & 0x07);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
 
   tempbx = SiS_Pr->SiS_VGAHDE;
-  if(modeflag & HalfDCLK)  tempbx >>= 1;
-  if(HwInfo->jChipType >= SIS_661) {
-     if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
-  }
+  if(modeflag & HalfDCLK)            tempbx >>= 1;
+  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
 
-  temp = 0xA0;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
      temp = 0;
-     if(tempbx > 800) {
-        temp = 0xA0;
-        if(tempbx != 1024) {
-           temp = 0xC0;
-           if(tempbx != 1280) temp = 0;
-	}
-     }
-  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(tempbx <= 800) {
-        temp = 0x80;
-     }
+     if(tempbx > 800)        temp = 0x60;
+  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+     temp = 0;
+     if(tempbx == 1024)      temp = 0xA0;
+     else if(tempbx > 1024)  temp = 0xC0;
+  } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
+     temp = 0;
+     if(tempbx >= 1280)      temp = 0x40;
+     else if(tempbx >= 1024) temp = 0x20;
   } else {
      temp = 0x80;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        temp = 0;
-        if(tempbx > 800) temp = 0x60;
-     }
-  }
-
-  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
-     temp = 0;
-     if(SiS_Pr->SiS_VGAHDE == 1024) temp = 0x20;
-  }
-
-  if(HwInfo->jChipType < SIS_661) {
-     if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp = 0;
+     if(tempbx >= 1024)      temp = 0xA0;
   }
 
   if(SiS_Pr->SiS_VBType & VB_SIS301) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)
-        temp |= 0x0A;
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) temp |= 0x0A;
   }
 
   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
 
+  tempeax = SiS_Pr->SiS_VGAVDE;
   tempebx = SiS_Pr->SiS_VDE;
-
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      if(!(temp & 0xE0)) tempebx >>=1;
   }
 
   tempcx = SiS_Pr->SiS_RVBHRS;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
+  tempcx >>= 8;
+  tempcx |= 0x40;
 
-  tempeax = SiS_Pr->SiS_VGAVDE;
-  tempcx |= 0x4000;
   if(tempeax <= tempebx) {
-     tempcx ^= 0x4000;
+     tempcx ^= 0x40;
   } else {
      tempeax -= tempebx;
   }
 
-  templong = (tempeax * 256 * 1024) % tempebx;
-  tempeax = (tempeax * 256 * 1024) / tempebx;
-  tempebx = tempeax;
-  if(templong != 0) tempebx++;
+  tempeax *= (256 * 1024);
+  templong = tempeax % tempebx;
+  tempeax /= tempebx;
+  if(templong) tempeax++;
 
-  temp = (USHORT)(tempebx & 0x000000FF);
+  temp = (USHORT)(tempeax & 0x000000FF);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
-  temp = (USHORT)((tempebx & 0x0000FF00) >> 8);
+  temp = (USHORT)((tempeax & 0x0000FF00) >> 8);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
-
-  tempbx = (USHORT)(tempebx >> 16);
-  temp = tempbx & 0x00FF;
-  temp <<= 4;
-  temp |= ((tempcx & 0xFF00) >> 8);
+  temp = (USHORT)((tempeax >> 12) & 0x70); /* sic! */
+  temp |= (tempcx & 0x4F);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
 
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
 
+     /* Calc Linebuffer max address and set/clear decimode */
      tempbx = 0;
+     if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
      tempax = SiS_Pr->SiS_VGAHDE;
-     if(modeflag & HalfDCLK) 		tempax >>= 1;
+     if(modeflag & HalfDCLK)            tempax >>= 1;
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	if(tempax > 800) tempax -= 800;
-     } else {
-        if(tempax > 800) {
-	   tempbx = 8;
-           if(tempax == 1024)
-	      tempax *= 25;
-           else
-	      tempax *= 20;
-
+     if(tempax > 800) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	   tempax -= 800;
+	} else {  /* 651+301C: Only if TVNoHiviNoYPbPr */
+	   tempbx = 0x08;
+           if(tempax == 1024) tempax *= 25;
+           else	              tempax *= 20;
 	   temp = tempax % 32;
 	   tempax /= 32;
-	   tempax--;
-	   if (temp!=0) tempax++;
-        }
+	   if(temp) tempax++;
+	   tempax++;
+	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) ||
+	      (SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
+	      if(resinfo == SIS_RI_1024x768) {
+	         /* Otherwise white line at right edge */
+	         tempax = (tempax & 0xff00) | 0x20;
+	      }
+	   }
+	}
      }
      tempax--;
-     temp = ((tempax & 0xFF00) >> 8) & 0x03;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {			/* From 1.10.7w */
-	if(ModeNo > 0x13) {					/* From 1.10.7w */
-	   if(resinfo == SIS_RI_1024x768) tempax = 0x1f;	/* From 1.10.7w */
-	}							/* From 1.10.7w */
-     }								/* From 1.10.7w */
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax & 0x00FF);
-     temp <<= 4;
-     temp |= tempbx;
+     temp = ((tempax >> 4) & 0x30) | tempbx;
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	if(IS_SIS550650740660) {
-	   temp = 0x0026;  /* 1.10.7w; 1.10.8r; needs corresponding code in Dis/EnableBridge! */
-	} else {
-	   temp = 0x0036;
-	}
-     } else {
-	temp = 0x0036;
+     temp = 0x0036; tempbx = 0xD0;
+     if((IS_SIS550650740660) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+	temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
      }
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
         if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
 	   temp |= 0x01;
 	   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
 	      if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
-  	         temp &= 0xFE;
+  	         temp &= ~0x01;
 	      }
 	   }
 	}
      }
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
 
-     tempbx = SiS_Pr->SiS_HT;
+     tempbx = SiS_Pr->SiS_HT >> 1;
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
-     tempbx >>= 1;
      tempbx -= 2;
-     temp = ((tempbx & 0x0700) >> 8) << 3;
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
+     temp = (tempbx >> 5) & 0x38;
      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
-     temp = tempbx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,temp);
 
      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
@@ -8562,13 +7737,13 @@
 	      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
 	   }
 	}
-#ifdef SET_EMI
 	if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+#ifdef SET_EMI
 	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+#endif
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 	}
-#endif
      }
 
   }  /* 301B */
@@ -8580,7 +7755,6 @@
 /*         SET PART 5 REGISTER GROUP         */
 /*********************************************/
 
-/* Set 301 Palette address port registers */
 static void
 SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
               PSIS_HW_INFO HwInfo)
@@ -8590,7 +7764,7 @@
 
   if(SiS_Pr->SiS_ModeType == ModeVGA) {
      if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
-        SiS_EnableCRT2(SiS_Pr);
+        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
         SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
      }
   }
@@ -8608,11 +7782,8 @@
   USHORT ResIndex,DisplayType;
   const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL;
 
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
+  if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
@@ -8620,7 +7791,9 @@
      return;
 
   if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                          &ResIndex, &DisplayType))) return;
+                          &ResIndex, &DisplayType))) {
+     return;
+  }
 
   if(HwInfo->jChipType < SIS_315H) {
      if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
@@ -8628,16 +7801,16 @@
 
   switch(DisplayType) {
     case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1;           break;
-    case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
-    case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1;         break;
-    case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H;         break;
-    case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H;        break;
-    case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H;       break;
-    case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2;           break;
-    case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2;          break;
-    case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2;         break;
-    case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H;         break;
-    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H;        break;
+    case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H;         break;
+    case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2;           break;
+    case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H;         break;
+    case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
+    case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H;        break;
+    case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2;          break;
+    case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H;        break;
+    case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1;         break;
+    case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H;       break;
+    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2;         break;
     case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2_H;       break;
     case 12: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1;           break;
     case 13: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H;         break;
@@ -8676,7 +7849,7 @@
     default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
   }
 
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);                        /*unlock cr0-7  */
+  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
 
   tempah = (LVDSCRT1Ptr + ResIndex)->CR[0];
   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,tempah);
@@ -8711,12 +7884,6 @@
   tempah <<= 5;
   if(modeflag & DoubleScanMode)  tempah |= 0x080;
   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
-
-  /* 650/LVDS BIOS - doesn't make sense */
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(modeflag & HalfDCLK)
-        SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-  }
 }
 
 /*********************************************/
@@ -8731,7 +7898,7 @@
   USHORT clkbase, vclkindex=0;
   UCHAR  sr2b, sr2c;
 
-  if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) || (SiS_Pr->SiS_IF_DEF_TRUMPION == 1)) {
+  if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) || (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 	SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
         if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) {
 	   RefreshRateTableIndex--;
@@ -8748,7 +7915,7 @@
   sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
 
   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-     if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+     if(SiS_Pr->SiS_UseROM) {
 	if(ROMAddr[0x220] & 0x01) {
            sr2b = ROMAddr[0x227];
 	   sr2c = ROMAddr[0x228];
@@ -8763,7 +7930,6 @@
      }
   }
 
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
@@ -8783,14 +7949,17 @@
 SiS_SetCHTVReg(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                USHORT RefreshRateTableIndex)
 {
-  USHORT temp, tempbx, tempcl;
+#if defined(SIS300) || defined(SIS315H)
+  USHORT temp, tempbx;
+#endif
+  USHORT tempcl;
   USHORT TVType, resindex;
   const SiS_CHTVRegDataStruct *CHTVRegData = NULL;
 
   if(ModeNo <= 0x13)
-    	tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   else
-    	tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
   TVType = 0;
   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
@@ -8808,16 +7977,16 @@
 	}
   }
   switch(TVType) {
-    	case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
-    	case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
-    	case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
-    	case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
-	case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
-    	case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
-    	case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
-    	case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
-	case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
-	default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+     case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
+     case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
+     case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
+     case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+     case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
+     case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
+     case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
+     case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
+     case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
+     default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
   }
   resindex = tempcl & 0x3F;
 
@@ -9089,21 +8258,21 @@
   /* Set up Power up/down timing */
 
   if(HwInfo->jChipType == SIS_740) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
         else    			          tableptr = table1024_740;
-     } else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-               (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
+     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
 	if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
         else					  tableptr = table1400_740;
      } else return;
   } else {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         tableptr = table1024_650;
-     } else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-               (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
+     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
         tableptr = table1400_650;
      } else return;
   }
@@ -9139,45 +8308,35 @@
   int i;
 
   if(HwInfo->jChipType == SIS_740) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        tableptr = table1024_740;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        tableptr = table1280_740;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-        tableptr = table1400_740;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-        tableptr = table1600_740;
-     } else return;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        tableptr = table1024_650;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        tableptr = table1280_650;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-        tableptr = table1400_650;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-        tableptr = table1600_650;
-     } else return;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
+     else return;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
+     else return;
   }
 
   tempbh = SiS_GetCH701x(SiS_Pr,0x74);
   if((tempbh == 0xf6) || (tempbh == 0xc7)) {
      tempbh = SiS_GetCH701x(SiS_Pr,0x73);
      if(tempbh == 0xc8) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) return;
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
      } else if(tempbh == 0xdb) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) return;
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) return;
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
      } else if(tempbh == 0xde) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) return;
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
      }
   }
 
-  if(HwInfo->jChipType == SIS_740) {
-     tempbh = 0x0d;
-  } else {
-     tempbh = 0x0c;
-  }
+  if(HwInfo->jChipType == SIS_740) tempbh = 0x0d;
+  else     			   tempbh = 0x0c;
+
   for(i = 0; i < tempbh; i++) {
      SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
   }
@@ -9564,13 +8723,12 @@
 
    SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
 
-   /* Set up Panel Link for LVDS, 301BDH and 30xLV(for LCDA) */
+   /* Set up Panel Link for LVDS and LCDA */
+   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
    if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
        ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
        ((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
       SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-   } else {
-      SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
    }
 
 #ifdef LINUX_XF86
@@ -9598,13 +8756,15 @@
       	   SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
       	   SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
 #ifdef SIS315H
-	   SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo);
+	   SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
 #endif
       	   SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
 
+	   SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+
 	   /* For 301BDH (Panel link initialization): */
 	   if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-	      if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+	      if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
 		 if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
 		    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
 		       SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
@@ -9619,15 +8779,13 @@
 
    } else {
 
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-    	      SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
-	                      RefreshRateTableIndex,HwInfo);
-	   }
+        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+
+        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+    	   SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
 	}
 
-        SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,
-	                RefreshRateTableIndex,HwInfo);
+        SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
 
 	if(SiS_Pr->SiS_SetFlag & LowModeTests) {
      	   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
@@ -9639,8 +8797,7 @@
 		 }
 	      }
 	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-       		 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,
-		               RefreshRateTableIndex);
+       		 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
 	      }
      	   }
 	}
@@ -9651,7 +8808,7 @@
    if(HwInfo->jChipType < SIS_315H) {
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
 	 if(SiS_Pr->SiS_UseOEM) {
-	    if((SiS_Pr->SiS_UseROM) && ROMAddr && (SiS_Pr->SiS_UseOEM == -1)) {
+	    if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
 	       if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 	          SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
 	       			    RefreshRateTableIndex);
@@ -9684,13 +8841,11 @@
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
 	 if(HwInfo->jChipType < SIS_661) {
 	    SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-            if(SiS_Pr->SiS_UseOEM) {
-               SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
-            }
+            SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
 	 } else {
 	    SiS_OEM661Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 	 }
-         SiS_CRT2AutoThreshold(SiS_Pr);
+         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
       }
    }
 #endif
@@ -9761,6 +8916,63 @@
   }
 }
 
+#ifdef SIS300
+static UCHAR *
+SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
+{
+  int i, j, num;
+  USHORT tempah,temp;
+  UCHAR *mydataptr;
+
+  for(i=0; i<20; i++) {				/* Do 20 attempts to write */
+     mydataptr = dataptr;
+     num = *mydataptr++;
+     if(!num) return mydataptr;
+     if(i) {
+        SiS_SetStop(SiS_Pr);
+	SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT*2);
+     }
+     if(SiS_SetStart(SiS_Pr)) continue;		/* Set start condition */
+     tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write DAB (S0=0=write) */
+     if(temp) continue;				/*    (ERROR: no ack) */
+     tempah = *mydataptr++;
+     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write register number */
+     if(temp) continue;				/*    (ERROR: no ack) */
+     for(j=0; j<num; j++) {
+        tempah = *mydataptr++;
+        temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
+	if(temp) break;
+     }
+     if(temp) continue;
+     if(SiS_SetStop(SiS_Pr)) continue;
+     return mydataptr;
+  }
+  return NULL;
+}
+
+static BOOLEAN
+SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
+  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;              	/* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;              	/* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+
+  SiS_SetSwitchDDC2(SiS_Pr);
+
+  while(*dataptr) {
+     dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
+     if(!dataptr) return FALSE;
+  }
+#ifdef TWDEBUG
+  xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
+#endif
+  return TRUE;
+}
+#endif
+
 /* The Chrontel 700x is connected to the 630/730 via
  * the 630/730's DDC/I2C port.
  *
@@ -9796,6 +9008,20 @@
   return FALSE;
 }
 
+#ifdef SIS300
+/* Write Trumpion register */
+void
+SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
+  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;              	/* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;              	/* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+  SiS_SetChReg(SiS_Pr, tempbx, 0);
+}
+#endif
+
 /* Write to Chrontel 700x */
 /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
 void
@@ -9831,17 +9057,16 @@
   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
   SiS_SetupDDCN(SiS_Pr);
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;  		/* DAB (Device Address Byte) */
-
   SiS_SetChReg(SiS_Pr, tempbx, 0);
 }
 
 void
 SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
 {
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-      SiS_SetCH700x(SiS_Pr,tempbx);
-   else
-      SiS_SetCH701x(SiS_Pr,tempbx);
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+     SiS_SetCH700x(SiS_Pr,tempbx);
+  else
+     SiS_SetCH701x(SiS_Pr,tempbx);
 }
 
 static USHORT
@@ -9873,6 +9098,21 @@
   return 0xFFFF;
 }
 
+#ifdef SIS300
+/* Read from Trumpion */
+USHORT
+SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;	/* DAB */
+  SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;         /* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;         /* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
+  return(SiS_GetChReg(SiS_Pr,0));
+}
+#endif
+
 /* Read from Chrontel 700x */
 /* Parameter is [Register no (S7-S0)] */
 USHORT
@@ -9925,10 +9165,10 @@
 USHORT
 SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
 {
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-      return(SiS_GetCH700x(SiS_Pr, tempbx));
-   else
-      return(SiS_GetCH701x(SiS_Pr, tempbx));
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+     return(SiS_GetCH700x(SiS_Pr, tempbx));
+  else
+     return(SiS_GetCH701x(SiS_Pr, tempbx));
 }
 
 /* Our own DDC functions */
@@ -10315,6 +9555,8 @@
    for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE;
    SiS_Pr->CP_HaveCustomData = FALSE;
    SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0;
+   SiS_Pr->CP_PreferredX = SiS_Pr->CP_PreferredY = 0;
+   SiS_Pr->CP_PreferredIndex = -1;
 
    if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
    if(pSiS->VBFlags & VB_30xBDH) return 0;
@@ -10409,12 +9651,14 @@
 	 SiS_Pr->CP_PreferredY = yres;
 
          switch(xres) {
+#if 0	    /* Treat as custom */
             case 800:
 	        if(yres == 600) {
 	     	   paneltype = Panel_800x600;
 	     	   checkexpand = TRUE;
 	        }
 	        break;
+#endif
             case 1024:
 	        if(yres == 768) {
 	     	   paneltype = Panel_1024x768;
@@ -10452,9 +9696,11 @@
 #if 0	    /* Treat this as custom, as we have no valid timing data yet */
 	    case 1600:
 	        if(pSiS->VGAEngine == SIS_315_VGA) {
-	           if(yres == 1200) {
-	              paneltype = Panel310_1600x1200;
-		      checkexpand = TRUE;
+		   if(pSiS->VBFlags & VB_301C) {
+	              if(yres == 1200) {
+	                 paneltype = Panel310_1600x1200;
+		         checkexpand = TRUE;
+		      }
 	           }
 	        }
       	        break;
@@ -10580,6 +9826,10 @@
 	          if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres;
 		  if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
 
+		  if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
+	             SiS_Pr->CP_PreferredIndex = i;
+	          }
+
 		  SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
 		  SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
 
@@ -10660,28 +9910,20 @@
       SiS_Pr->CP_MaxX = xres = buffer[0x76] | (buffer[0x77] << 8);
       SiS_Pr->CP_MaxY = yres = buffer[0x78] | (buffer[0x79] << 8);
       switch(xres) {
+#if 0
          case 800:
 	     if(yres == 600) {
 	     	paneltype = Panel_800x600;
 	     	checkexpand = TRUE;
 	     }
 	     break;
+#endif
          case 1024:
 	     if(yres == 768) {
 	     	paneltype = Panel_1024x768;
 	     	checkexpand = TRUE;
 	     }
 	     break;
-	 case 1152:
-	     if(yres == 768) {
-	        if(pSiS->VGAEngine == SIS_300_VGA) {
-		   paneltype = Panel300_1152x768;
-		} else {
-		   paneltype = Panel310_1152x768;
-		}
-	     	checkexpand = TRUE;
-	     }
-	     break;
 	 case 1280:
 	     if(yres == 960) {
 	        if(pSiS->VGAEngine == SIS_315_VGA) {
@@ -10706,9 +9948,11 @@
 #if 0    /* Treat this one as custom since we have no timing data yet */
 	 case 1600:
 	     if(pSiS->VGAEngine == SIS_315_VGA) {
-	        if(yres == 1200) {
-	           paneltype = Panel310_1600x1200;
-		   checkexpand = TRUE;
+	        if(pSiS->VBFlags & VB_301C) {
+	           if(yres == 1200) {
+	              paneltype = Panel310_1600x1200;
+		      checkexpand = TRUE;
+		   }
 	        }
 	     }
       	     break;
@@ -10810,6 +10054,10 @@
 
 	       if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
 
+	       if((SiS_Pr->CP_MaxX == xres) && (SiS_Pr->CP_MaxY == yres)) {
+	          SiS_Pr->CP_PreferredIndex = i;
+	       }
+
 	       SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE;
 	       SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE;
 	       SiS_Pr->CP_SyncValid[i] = TRUE;
@@ -10864,14 +10112,18 @@
    if(paneltype) {
        if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
        if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
-       cr37 &= 0xf1;
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x36,0xf0,paneltype);
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xf1,cr37);
        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
+       SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,paneltype);
+       cr37 &= 0xf1;
+       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0x0c,cr37);
+       SiS_Pr->PanelSelfDetected = TRUE;
 #ifdef TWDEBUG
        xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3, 
-       	"CRT2: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
+       	   "CRT2: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
 #endif	
+   } else {
+       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x32,~0x08);
+       SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,0x00);
    }
    return 0;
 }
@@ -11148,13 +10400,13 @@
   USHORT romptr;
 
   if(HwInfo->jChipType < SIS_330) {
-     romptr = ROMAddr[0x128] | (ROMAddr[0x129] << 8);
+     romptr = SISGETROMW(0x128);
      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
-        romptr = ROMAddr[0x12a] | (ROMAddr[0x12b] << 8);
+        romptr = SISGETROMW(0x12a);
   } else {
-     romptr = ROMAddr[0x1a8] | (ROMAddr[0x1a9] << 8);
+     romptr = SISGETROMW(0x1a8);
      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
-        romptr = ROMAddr[0x1aa] | (ROMAddr[0x1ab] << 8);
+        romptr = SISGETROMW(0x1aa);
   }
   return(romptr);
 }
@@ -11166,13 +10418,13 @@
   USHORT romptr;
 
   if(HwInfo->jChipType < SIS_330) {
-     romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);
+     romptr = SISGETROMW(0x120);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x122] | (ROMAddr[0x123] << 8);
+        romptr = SISGETROMW(0x122);
   } else {
-     romptr = ROMAddr[0x1a0] | (ROMAddr[0x1a1] << 8);
+     romptr = SISGETROMW(0x1a0);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x1a2] | (ROMAddr[0x1a3] << 8);
+        romptr = SISGETROMW(0x1a2);
   }
   return(romptr);
 }
@@ -11184,13 +10436,13 @@
   USHORT romptr;
 
   if(HwInfo->jChipType < SIS_330) {
-     romptr = ROMAddr[0x114] | (ROMAddr[0x115] << 8);
+     romptr = SISGETROMW(0x114);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x11a] | (ROMAddr[0x11b] << 8);
+        romptr = SISGETROMW(0x11a);
   } else {
-     romptr = ROMAddr[0x194] | (ROMAddr[0x195] << 8);
+     romptr = SISGETROMW(0x194);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x19a] | (ROMAddr[0x19b] << 8);
+        romptr = SISGETROMW(0x19a);
   }
   return(romptr);
 }
@@ -11212,9 +10464,9 @@
      }
   }
 
-  index = SiS_Pr->SiS_LCDResInfo & 0x0F;
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)      index -= 5;
-  else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) index -= 6;
+  index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
+  else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
   index--;
   index *= 3;
   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
@@ -11227,12 +10479,9 @@
 {
   USHORT index;
 
-  index = SiS_Pr->SiS_LCDResInfo & 0x0F;
-  index--;
-  index *= 3;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
+  index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
+  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
-
   return index;
 }
 
@@ -11258,7 +10507,7 @@
 }
 
 static ULONG
-GetOEMTVPtr661_2(SiS_Private *SiS_Pr)
+GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
 {
    USHORT index = 0, temp = 0;
 
@@ -11275,7 +10524,7 @@
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
-	 index += 8;
+	 index += addme;
 	 temp++;
       }
       temp += 0x0100;
@@ -11283,16 +10532,37 @@
    return(ULONG)(index | (temp << 16));
 }
 
+static ULONG
+GetOEMTVPtr661_2_OLD(SiS_Private *SiS_Pr)
+{
+   return(GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
+}
+
+#if 0
+static ULONG
+GetOEMTVPtr661_2_NEW(SiS_Private *SiS_Pr)
+{
+   return(GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
+}
+#endif
+
 static int
 GetOEMTVPtr661(SiS_Private *SiS_Pr)
 {
    int index = 0;
 
-   if(SiS_Pr->SiS_TVMode & TVSetPAL)       index = 2;
-   if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
-   if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
-   if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
-   if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
+   if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
+   if(SiS_Pr->SiS_ROMNew) {
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
+      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
+   } else {
+      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
+   }
 
    if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
 
@@ -11306,15 +10576,21 @@
   USHORT delay=0,index,myindex,temp,romptr=0;
   BOOLEAN dochiptest = TRUE;
 
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
+  } else {
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
+  }
+
   /* Find delay (from ROM, internal tables, PCI subsystem) */
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {			/* ------------ VGA */
      
-     if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+     if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
         romptr = GetRAMDACromptr(SiS_Pr, HwInfo);
-	if(!romptr) return;
-	delay = ROMAddr[romptr];
-     } else {
+     }
+     if(romptr) delay = ROMAddr[romptr];
+     else {
         delay = 0x04;
         if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
 	   if(IS_SIS650) {
@@ -11326,8 +10602,7 @@
 	   } else {
 	      delay = 0x0c;
 	   }
-	}
-        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	} else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
            delay = 0x00;
 	}
      }
@@ -11336,13 +10611,39 @@
 
      BOOLEAN gotitfrompci = FALSE;
 
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
+     /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
+
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	if(SiS_Pr->PDC != -1) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
+	   return;
+	}
+     } else {
+	if(SiS_Pr->PDCA != -1) {
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
+	   return;
+	}
+     }
 
-     /* Could we detect a PDC for LCD? If yes, use it */
+     /* Custom Panel? */
 
-     if(SiS_Pr->PDC) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDC & 0x0f) << 4));
+	   delay = 0x00;
+	   if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
+	      delay = 0x20;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
+	} else {
+	   delay = 0x0c;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x03;
+	   else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      if(IS_SIS740) delay = 0x01;
+	      else          delay = 0x03;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
 	}
         return;
      }
@@ -11355,7 +10656,7 @@
      switch(SiS_Pr->SiS_CustomT) {
      case CUT_COMPAQ1280:
      case CUT_COMPAQ12802:
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
 	   gotitfrompci = TRUE;
 	   dochiptest = FALSE;
 	   delay = 0x03;
@@ -11363,15 +10664,13 @@
 	break;
      case CUT_CLEVO1400:
      case CUT_CLEVO14002:
-	/* if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { */
-	   gotitfrompci = TRUE;
-	   dochiptest = FALSE;
-	   delay = 0x02;
-	/* } */
+	gotitfrompci = TRUE;
+	dochiptest = FALSE;
+	delay = 0x02;
 	break;
      case CUT_CLEVO1024:
      case CUT_CLEVO10242:
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   gotitfrompci = TRUE;
 	   dochiptest = FALSE;
 	   delay = 0x33;
@@ -11392,12 +10691,12 @@
 
            if(SiS_IsNotM650orLater(SiS_Pr, HwInfo)) {
 
-              if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+              if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
 	         /* Always use the second pointer on 650; some BIOSes */
                  /* still carry old 301 data at the first location    */
-	         /* romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);  */
+	         /* romptr = SISGETROMW(0x120);                       */
 	         /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
-	         romptr = ROMAddr[0x122] | (ROMAddr[0x123] << 8);
+	         romptr = SISGETROMW(0x122);
 	         if(!romptr) return;
 	         delay = ROMAddr[(romptr + index)];
 	      } else {
@@ -11412,10 +10711,13 @@
 
           }
 
-        } else if((ROMAddr) && SiS_Pr->SiS_UseROM &&
-	          (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)) {
+        } else if(SiS_Pr->SiS_UseROM 			      &&
+		  (!(SiS_Pr->SiS_ROMNew))		      &&
+	          (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
+		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
+		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)) {
 
-	   /* Data for 1280x1024 wrong in BIOS */
+	   /* Data for 1280x1024 wrong in 301B BIOS */
            romptr = GetLCDromptr(SiS_Pr, HwInfo);
 	   if(!romptr) return;
 	   delay = ROMAddr[(romptr + index)];
@@ -11430,7 +10732,11 @@
            delay = SiS310_LCDDelayCompensation_301[myindex];
 	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 	      if(IS_SIS740) delay = 0x01;
+	      else if(HwInfo->jChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
 	      else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
+	   } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	      if(IS_SIS740) delay = 0x01;  /* ? */
+	      else          delay = 0x03;
 	   } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
 	      if(IS_SIS740) delay = 0x01;
 	      else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
@@ -11453,12 +10759,12 @@
 
         if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
 
-           if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+           if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
 	      /* Always use the second pointer on 650; some BIOSes */
               /* still carry old 301 data at the first location    */
-              /* romptr = ROMAddr[0x114] | (ROMAddr[0x115] << 8);  */
-	      /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
-	      romptr = ROMAddr[0x11a] | (ROMAddr[0x11b] << 8);
+              /* romptr = SISGETROMW(0x114);			   */
+	      /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
+	      romptr = SISGETROMW(0x11a);
 	      if(!romptr) return;
 	      delay = ROMAddr[romptr + index];
 
@@ -11491,7 +10797,7 @@
 	   }
         }
 
-     } else if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+     } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
 
         romptr = GetTVromptr(SiS_Pr, HwInfo);
 	if(!romptr) return;
@@ -11507,14 +10813,16 @@
         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
 	   if(IS_SIS740) {
 	      delay = SiS310_TVDelayCompensation_740301B[index];
+	      /* LV: use 301 data? BIOS bug? */
 	   } else {
               delay = SiS310_TVDelayCompensation_301B[index];
+	      if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
 	   }
 	}
 
      }
 
-     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) {  /* LCDA */
+     if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
 	delay &= 0x0f;
 	dochiptest = FALSE;
      }
@@ -11580,15 +10888,18 @@
   temp >>= 1;  	  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
   temp1 = temp;
 
-  if(ROMAddr && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
      if(HwInfo->jChipType >= SIS_661) {
-	romptr = ROMAddr[0x260] | (ROMAddr[0x261] << 8);
-	temp1 = GetOEMTVPtr661(SiS_Pr);
+        temp1 = GetOEMTVPtr661(SiS_Pr);
         temp1 >>= 1;
+        romptr = SISGETROMW(0x260);
+        if(HwInfo->jChipType >= SIS_760) {
+	   romptr = SISGETROMW(0x360);
+	}
      } else if(HwInfo->jChipType >= SIS_330) {
-        romptr = ROMAddr[0x192] | (ROMAddr[0x193] << 8);
+        romptr = SISGETROMW(0x192);
      } else {
-        romptr = ROMAddr[0x112] | (ROMAddr[0x113] << 8);
+        romptr = SISGETROMW(0x112);
      }
   }
 
@@ -11610,24 +10921,25 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,temp1,romptr=0;
 
-  temp = GetTVPtrIndex(SiS_Pr);
-  temp >>= 1;              	/* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
-  temp1 = temp;
+  temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; 	/* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
 
-  if(ModeNo<=0x13)
+  if(ModeNo <= 0x13)
      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
   else
      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
 
-  if(ROMAddr && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
      if(HwInfo->jChipType >= SIS_661) {
-	romptr = ROMAddr[0x26c] | (ROMAddr[0x26d] << 8);
+        romptr = SISGETROMW(0x26c);
+        if(HwInfo->jChipType >= SIS_760) {
+	   romptr = SISGETROMW(0x36c);
+	}
 	temp1 = GetOEMTVPtr661(SiS_Pr);
         temp1 >>= 1;
      } else if(HwInfo->jChipType >= SIS_330) {
-        romptr = ROMAddr[0x1a4] | (ROMAddr[0x1a5] << 8);
+        romptr = SISGETROMW(0x1a4);
      } else {
-        romptr = ROMAddr[0x124] | (ROMAddr[0x125] << 8);
+        romptr = SISGETROMW(0x124);
      }
   }
 
@@ -11645,62 +10957,15 @@
 SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
            USHORT ModeNo,USHORT ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index, myindex, oldindex,temp, i, j, flag1 = 0, flag2 = 0, romptr = 0;
-  ULONG  lindex;
+  USHORT index, temp, i, j;
 
-  if(ModeNo<=0x13) {
-    index =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
+  if(ModeNo <= 0x13) {
+     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
   } else {
-    index =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
+     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
   }
 
-  oldindex = index;
-
-  if((HwInfo->jChipType >= SIS_661) && ROMAddr && SiS_Pr->SiS_UseROM) {
-     if(ModeNo > 0x13) {
-        index =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndexROM661;
-     }
-     lindex = GetOEMTVPtr661_2(SiS_Pr);
-     if(lindex & 0x00ff0000) flag1 = 1;
-     if(lindex & 0xff000000) flag2 = 1;
-     lindex &= 0xffff;
-
-     /* NTSC-J: Use PAL filters */
-     if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) lindex = 1;
-
-     romptr = ROMAddr[0x268] | (ROMAddr[0x269] << 8);
-     if(flag1) myindex = index * 7;
-     else      myindex = index << 2;
-
-     if(romptr) {
-        romptr += (lindex << 1);
-        romptr = (ROMAddr[romptr] | (ROMAddr[romptr+1] << 8)) + myindex;
-	if(romptr) {
-           if((!flag1) && (flag2)) {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,ROMAddr[romptr++]);
-           } else {
-	      for(i=0x35; i<=0x38; i++) {
-                 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr++]);
-              }
-           }
-           if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	      for(j=0, i=0x48; i<=0x4a; i++, j++) {
-                 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr++]);
-              }
-           }
-           return;
-	}
-     }
-  }
-
-  index = oldindex;
-
-  temp = GetTVPtrIndex(SiS_Pr);
-  temp >>= 1;  			/* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
+  temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
 
   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)	     temp = 1;  /* NTSC-J uses PAL */
   else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
@@ -11734,21 +10999,11 @@
   /* NTSC-J data not in BIOS, and already set in SetGroup2 */
   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
 
-  if(HwInfo->jChipType >= SIS_661) {
-     lindex = GetOEMTVPtr661_2(SiS_Pr) & 0xffff;
+  if((HwInfo->jChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
+     lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
      lindex <<= 2;
-     if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-        romptr = ROMAddr[0x264] | (ROMAddr[0x265] << 8);
-     }
-     if(romptr) {
-	romptr += lindex;
-	for(j=0, i=0x31; i<=0x34; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
-        }
-     } else {
-        for(j=0, i=0x31; i<=0x34; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
-        }
+     for(j=0, i=0x31; i<=0x34; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
      }
      return;
   }
@@ -11766,20 +11021,20 @@
   /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
    * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
    */
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-     romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8);
+  if(SiS_Pr->SiS_UseROM) {
+     romptr = SISGETROMW(0x116);
      if(HwInfo->jChipType >= SIS_330) {
-        romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8);
+        romptr = SISGETROMW(0x196);
      }
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-        romptr = ROMAddr[0x11c] | (ROMAddr[0x11d] << 8);
+        romptr = SISGETROMW(0x11c);
 	if(HwInfo->jChipType >= SIS_330) {
-	   romptr = ROMAddr[0x19c] | (ROMAddr[0x19d] << 8);
+	   romptr = SISGETROMW(0x19c);
 	}
 	if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
-	   romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8);
+	   romptr = SISGETROMW(0x116);
 	   if(HwInfo->jChipType >= SIS_330) {
-              romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8);
+              romptr = SISGETROMW(0x196);
            }
 	}
      }
@@ -11832,7 +11087,7 @@
       SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
       SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
       SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-      if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
+      if(SiS_Pr->SiS_VBType & VB_SIS301) {
          SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
       }
    }
@@ -11842,65 +11097,108 @@
 SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
                 USHORT ModeIdIndex, USHORT RTI)
 {
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
    USHORT delay = 0, romptr = 0, index;
-   UCHAR  *myptr = NULL;
-   UCHAR  temp;
+   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
 
    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
       return;
 
-   delay = SiS_Pr->SiS_RefIndex[RTI].Ext_PDC;
+   /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
+
+   if(SiS_Pr->SiS_ROMNew) {
+      if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) 			||
+         ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
+	  (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+         index = 25;
+         if(SiS_Pr->UseCustomMode) {
+	    index = SiS_Pr->CSRClock;
+         } else if(ModeNo > 0x13) {
+            index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI,HwInfo);
+            index = SiS_Pr->SiS_VCLKData[index].CLOCK;
+         }
+	 if(index < 25) index = 25;
+         index = ((index / 25) - 1) << 1;
+         if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
+	    index++;
+	 }
+	 romptr = SISGETROMW(0x104);  /* 0x4ae */
+         delay = ROMAddr[romptr + index];
+         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
+         } else {
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
+         }
+         return;
+      }
+   }
+
+   /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
 
-   delay &= 0xf0;
-   delay >>= 4;
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) delay <<= 12;  /* BIOS: 8, wrong */
+   if(SiS_Pr->UseCustomMode) delay = 0x04;
+   else if(ModeNo <= 0x13)   delay = 0x04;
+   else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
+   delay |= (delay << 8);
 
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+      /* 3. TV */
+
       index = GetOEMTVPtr661(SiS_Pr);
-      if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-         romptr = ROMAddr[0x25c] | (ROMAddr[0x25d] << 8);
-         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-            romptr = ROMAddr[0x25e] | (ROMAddr[0x25f] << 8);
-         }
-      }
-      if(romptr) myptr = &ROMAddr[romptr];
-      if(!myptr) {
-         myptr = (UCHAR *)SiS_TVDelay661_301;
-	 if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	    myptr = (UCHAR *)SiS_TVDelay661_301B;
-	 }
+      if(SiS_Pr->SiS_ROMNew) {
+         romptr = SISGETROMW(0x106);  /* 0x4ba */
+         delay = ROMAddr[romptr + index];
+      } else {
+         delay = 0x04;
       }
-      delay = myptr[index];
-      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) delay >>= 4;  /* Should test dual edge */
+
    } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-      if(SiS_Pr->PDC) {
-         delay = SiS_Pr->PDC & 0x0f;
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-            delay |= (delay << 12);
+
+      /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
+
+      if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
+          ((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) ) {
+
+	 /* For LV, the BIOS must know about the correct value */
+	 delay = ROMAddr[romptr + 0x0d];		/* LCD  */
+	 delay |= (ROMAddr[romptr + 0x0c] << 8);	/* LCDA */
+
+      } else {
+
+         /* TMDS: Set our own, since BIOS has no idea - TODO: Find out about values */
+         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+            if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
+	       delay = 0x0404;
+            } else if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
+	       delay = 0x0404;
+            } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
+	       delay = 0x1004;
+            } else
+	       delay = 0x0000;
+         }
+
+	 /* Override by detected or user-set values */
+	 /* (but only if, for some reason, we can't read value from BIOS) */
+         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
+            delay = SiS_Pr->PDC & 0x1f;
          }
-      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) {
-         delay = 0x4444;  /* TEST THIS */
-      } else if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-         myptr = GetLCDStructPtr661(SiS_Pr, HwInfo);
-         if(myptr) delay = myptr[4];
-         else delay = 0x44;
-         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-            delay |= (delay << 8);
+         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
+            delay = (SiS_Pr->PDCA & 0x1f) << 8;
          }
+
       }
-   }
 
-   temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2d);
-   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToRAMDAC)) {
-      temp &= 0xf0;
-      temp |= (delay & 0x000f);
    }
+
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-      temp &= 0x0f;
-      temp |= ((delay & 0xf000) >> 8);
+      delay >>= 8;
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
+   } else {
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
    }
-   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,temp);
 }
 
 static void
@@ -11909,38 +11207,50 @@
    USHORT infoflag;
    UCHAR temp;
 
-   infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
-   if(ModeNo <= 0x13) {
-      infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
-   }
-   infoflag &= 0xc0;
    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+
+      if(ModeNo <= 0x13) {
+         infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
+      } else if(SiS_Pr->UseCustomMode) {
+         infoflag = SiS_Pr->CInfoFlag;
+      } else {
+         infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
+      }
+      infoflag &= 0xc0;
+
       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-      if(temp & 0x20) infoflag = temp;
+      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+         temp &= 0x3f;
+	 temp |= infoflag;
+      } else {
+         if(temp & 0x20) infoflag = temp;
+      }
       if(temp & 0x01) infoflag |= 0x01;
-   }
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-      temp = 0x0c;
-      if(infoflag & 0x01) temp ^= 0x14;  /* BIOS: 18, wrong */
-      temp |= (infoflag >> 6);
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
-   }
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-      temp = 0;
-      if(infoflag & 0x01) temp |= 0x80;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
-      temp = 0x30;
-      if(infoflag & 0x01) temp = 0x20;
-      infoflag &= 0xc0;
-      temp |= infoflag;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+         temp = 0x0c;
+         if(infoflag & 0x01) temp ^= 0x14;  /* BIOS: 18, wrong */
+         temp |= (infoflag >> 6);
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
+      } else {
+         temp = 0;
+         if(infoflag & 0x01) temp |= 0x80;
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
+         temp = 0x30;
+         if(infoflag & 0x01) temp = 0x20;
+         infoflag &= 0xc0;
+         temp |= infoflag;
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
+      }
+
    }
 }
 
 static void
 SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-   UCHAR *myptr;
+   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+   USHORT romptr, temp1, temp2;
 
    if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
       if(SiS_Pr->LVDSHL != -1) {
@@ -11948,16 +11258,24 @@
       }
    }
 
-   myptr = GetLCDStructPtr661(SiS_Pr, HwInfo);
-   if(myptr) {
-      if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
-         if(SiS_Pr->LVDSHL == -1) {
-            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xE0,myptr[1] & 0x1f);
-	 } else {
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xE3,myptr[1] & 0x1c);
+   if(SiS_Pr->SiS_ROMNew) {
+
+      if((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) {
+         if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+            temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
+	    temp2 = 0xfc;
+	    if(SiS_Pr->LVDSHL != -1) {
+	      temp1 &= 0xfc;
+	      temp2 = 0xf3;
+	    }
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
+         }
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+            temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
 	 }
       }
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0x3f,myptr[2] & 0xc0);
+
    }
 }
 
@@ -11978,7 +11296,7 @@
          SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
          SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
          SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-         if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
+         if(SiS_Pr->SiS_VBType & VB_SIS301) {
             SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
          }
       }
@@ -12007,7 +11325,7 @@
      }
   }
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
   if(SiS_Pr->UseCustomMode) return;
 
   switch(SiS_Pr->SiS_CustomT) {
@@ -12037,7 +11355,7 @@
   }
 
   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         /* Maybe all panels? */
         if(SiS_Pr->LVDSHL == -1) {
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
@@ -12048,7 +11366,7 @@
 
   if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   if(SiS_Pr->LVDSHL == -1) {
 	      /* Maybe all panels? */
               SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
@@ -12068,15 +11386,15 @@
   }
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-#ifdef SET_EMI
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+#ifdef SET_EMI
 	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+#endif
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 	}
-#endif
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+     } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
         if(SiS_Pr->LVDSHL == -1) {
            /* Maybe ACER only? */
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
@@ -12084,9 +11402,9 @@
      }
      tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
 	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   if(tempch == 0x03) {
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
@@ -12167,7 +11485,7 @@
 	tempbh >>= 4;
 	tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
 	tempbx = (tempbh << 8) | tempbl;
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
 	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
 	      	 tempbx = 770;
@@ -12258,19 +11576,16 @@
 
     tempbx = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f) - 2;
     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
-    if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
     }
-    if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+    if(SiS_Pr->SiS_UseROM) {
        if(ROMAddr[0x235] & 0x80) {
           tempbx = SiS_Pr->SiS_LCDTypeInfo;
           if(Flag) {
-	     romptr = ROMAddr[0x255] | (ROMAddr[0x256] << 8);
-	     if(romptr) {
-	        tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
-	     } else {
-	        tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
-	     }
+	     romptr = SISGETROMW(0x255);
+	     if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
+	     else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
              if(tempbx == 0xFF) return 0xFFFF;
           }
 	  tempbx <<= 1;
@@ -12281,13 +11596,10 @@
   } else {
 
     if(Flag) {
-       if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-          romptr = ROMAddr[0x255] | (ROMAddr[0x256] << 8);
-	  if(romptr) {
-	     tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
-	  } else {
-	     tempbx = 0xff;
-	  }
+       if(SiS_Pr->SiS_UseROM) {
+          romptr = SISGETROMW(0x255);
+	  if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
+	  else 	     tempbx = 0xff;
        } else {
           tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
        }
@@ -12311,12 +11623,12 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,romptr=0;
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x237] & 0x01)) return;
      if(!(ROMAddr[0x237] & 0x02)) return;
-     romptr = ROMAddr[0x24b] | (ROMAddr[0x24c] << 8);
+     romptr = SISGETROMW(0x24b);
   }
 
   /* The Panel Compensation Delay should be set according to tables
@@ -12326,7 +11638,7 @@
    * Thus we don't set this if the user select a custom pdc or if
    * we otherwise detected a valid pdc.
    */
-  if(SiS_Pr->PDC) return;
+  if(SiS_Pr->PDC != -1) return;
 
   temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 0);
 
@@ -12338,7 +11650,7 @@
   if(HwInfo->jChipType != SIS_300) {
      if(romptr) {
 	romptr += (temp * 2);
-	romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	romptr = SISGETROMW(romptr);
 	romptr += index;
 	temp = ROMAddr[romptr];
      } else {
@@ -12349,21 +11661,21 @@
         }
      }
   } else {
-     if((ROMAddr) && SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
+     if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
 	if(romptr) {
 	   romptr += (temp * 2);
-	   romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	   romptr = SISGETROMW(romptr);
 	   romptr += index;
 	   temp = ROMAddr[romptr];
 	} else {
 	   temp = SiS300_OEMLCDDelay5[temp][index];
 	}
      } else {
-        if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+        if(SiS_Pr->SiS_UseROM) {
 	   romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
 	   if(romptr) {
 	      romptr += (temp * 2);
-	      romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	      romptr = SISGETROMW(romptr);
 	      romptr += index;
 	      temp = ROMAddr[romptr];
 	   } else {
@@ -12386,7 +11698,7 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if((SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x237] & 0x01)) return;
      if(!(ROMAddr[0x237] & 0x04)) return;
      /* No rom pointer in BIOS header! */
@@ -12436,10 +11748,10 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,romptr=0;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x02)) return;
-     romptr = ROMAddr[0x241] | (ROMAddr[0x242] << 8);
+     romptr = SISGETROMW(0x241);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12448,7 +11760,7 @@
 
   if(romptr) {
      romptr += (temp * 2);
-     romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+     romptr = SISGETROMW(romptr);
      romptr += index;
      temp = ROMAddr[romptr];
   } else {
@@ -12459,7 +11771,7 @@
      }
   }
   temp &= 0x3c;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
 }
 
 static void
@@ -12469,10 +11781,10 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,romptr=0;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x04)) return;
-     romptr = ROMAddr[0x243] | (ROMAddr[0x244] << 8);
+     romptr = SISGETROMW(0x243);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12481,14 +11793,14 @@
 
   if(romptr) {
      romptr += (temp * 2);
-     romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+     romptr = SISGETROMW(romptr);
      romptr += index;
      temp = ROMAddr[romptr];
   } else {
      temp = SiS300_OEMTVFlicker[temp][index];
   }
   temp &= 0x70;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);  /* index 0A D[6:4] */
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
 }
 
 static void
@@ -12502,10 +11814,10 @@
 
   if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x08)) return;
-     romptr = ROMAddr[0x245] | (ROMAddr[0x246] << 8);
+     romptr = SISGETROMW(0x245);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12519,7 +11831,7 @@
   } else {
      if(romptr) {
         romptr += (temp * 2);
-	romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	romptr = SISGETROMW(romptr);
 	romptr += (index * 4);
         for(i=0x31, j=0; i<=0x34; i++, j++) {
 	   SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
@@ -12541,10 +11853,10 @@
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x10)) return;
-     romptr = ROMAddr[0x247] | (ROMAddr[0x248] << 8);
+     romptr = SISGETROMW(0x247);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12565,7 +11877,7 @@
   } else {
       if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
          romptr += (temp * 2);
-	 romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	 romptr = SISGETROMW(romptr);
 	 romptr += (index * 4);
 	 for(i=0x35, j=0; i<=0x38; i++, j++) {
        	    SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
diff -Nru a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
--- a/drivers/video/sis/init301.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/sis/init301.h	2004-06-23 19:04:27 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Data and prototypes for init301.c
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -91,29 +89,41 @@
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
     0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
     0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
-    0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53,
+    0x03,0x0a,0x65,0x9d /*0x8d*/,0x08,0x92,0x8f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53 /*0x50*/,
     0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
   },
   {
     0x1d,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
     0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
+    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4c /*0x4f*/,0x13,
     0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
-    0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
+    0x51,0x5e,0x60,0x57 /*0x49*/,0x7b /*0x7d*/,0x92,0x0f,0x40,
     0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4b,
     0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
   },
   {
+#if 1
     0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
     0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0xed,0x50,0x70,0x9f,0x16,0x59,0x2b,0x13,
+    0xed,0x50,0x70,0x9f,0x16,0x59,0x21 /*0x2b*/,0x13,
     0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
-    0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
+    0x4b,0x4b,0x65 /*0x6f*/,0x2f,0x63,0x92,0x0f,0x40,
     0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
     0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
+#endif
+#if 0
+    0x2a,0x14,0xe8,0x09,0x09,0xed,0x0c,0x0c,  /* TEST (0.93) - BAD */
+    0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+    0xed,0x50,0x70,0x9e,0x16,0x57,0x6c,0x13,
+    0x27,0x0b,0x27,0xfb,0x30,0x27,0x15,0xb0,
+    0x3b,0xdb,0x61,0x24,0x78,0x92,0x0f,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0x14,0x6f,
+    0x00,0x52,0xbb,0x00,0xd5,0xf7,0xa2,0x00
+#endif
   }
 };
 
@@ -139,7 +149,7 @@
     0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
 };
 
-/* 301C / 302ELV (?) extended Part2 TV registers */
+/* 301C / 302ELV extended Part2 TV registers */
 
 static const UCHAR SiS_Part2CLVX_1[] = {
     0x00,0x00,
@@ -208,28 +218,84 @@
     0x00,0x04,
     0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
     0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
-    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x1D /* 0x7D? */ ,0x7C,0x0D,0x18,0x7F,
+    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
     0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
     0xFF,0xFF,
 };
 
-
 #ifdef SIS315H
-/* 661 et al LCD data structure */
+/* 661 et al LCD data structure (0.94.0) */
 static const UCHAR SiS_LCDStruct661[] = {
-    /* 1600x1200 */
-    0x0B,0xEA,0x81,0x10,0x00,0xC0,0x03,0x21,0x5A,0x23,0x5A,0x23,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x30,0x10,
-    /* 1400x1050 */
-    0x09,0xEA,0x81,0x80,0xA3,0x70,0x03,0x19,0xD2,0x2A,0xF8,0x2F,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x30,0x10,
-    /* 1280x1024 */
-    0x03,0xEA,0x81,0x40,0xA1,0x70,0x03,0x19,0xD2,0x2A,0xF8,0x2F,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x30,0x10,
     /* 1024x768 */
-    0x02,0xEA,0x80,0x00,0x11,0x88,0x06,0x0B,0xF5,0x6C,0x35,0x62,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x28,0x10,
-    0xFF,
+/*  type|CR37|   HDE   |   VDE   |    HT   |    VT   |   hss    | hse   */
+    0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
+    0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x00,0x00,0x00,0x00,0x04,
+    /*  | vss      |   vse  |clck|  clock  |CRT2DataP|CRT2DataP|idx     */
+    /*					      VESA    non-VESA  noscale */
+    /* 1280x1024 */
+    0x03,0xC0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x08,
+    /* 1400x1050 */
+    0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x09,
+    /* 1600x1200 */
+    0x0B,0xC0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
+    0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x00,0x00,0x00,0x00,0x0B,
+    /* 1280x768 */
+    0x0A,0xC0,0x00,0x05,0x00,0x03,0x80,0x05,0x26,0x03,0x10,0x00,0x40,
+    0x00,0x03,0x00,0x06,0x00,0x44,0x63,0x46,0x00,0x00,0x00,0x00,0x06,
+    /* 1280x720 */
+    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x80,0x05,0x26,0x03,0x10,0x00,0x02,
+    0x00,0x01,0x00,0x06,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x05,
+    /* 1280x800 */
+    0x0C,0xE0,0x00,0x05,0x20,0x03,0x80,0x05,0x30,0x03,0x10,0x00,0x40,
+    0x00,0x04,0x00,0x03,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x07,
+    /* 1680x1050 */
+    0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
+    0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06,
+    /* 1280x768 (not in 0.93) */
+    0x0A,0xC0,0x00,0x05,0x00,0x03,0x80,0x06,0x1E,0x03,0x40,0x00,0x80,
+    0x00,0x03,0x00,0x07,0x00,0x4F,0x00,0x00,0x00,0x00,0x00,0x00,0x06
+};
+#endif
+
+#ifdef SIS300
+static UCHAR SiS300_TrumpionData[7][80] = {
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
+    0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xBC,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x09,0x04,0x04,0x05,
+    0x04,0x0C,0x09,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5A,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x27,0x00,0x80,0x02,
+    0x20,0x03,0x07,0x00,0x5E,0x01,0x0D,0x02,0x60,0x0C,0x30,0x11,0x00,0x00,0x04,0x23,
+    0x00,0x00,0x03,0x80,0x03,0x28,0x06,0x08,0x40,0x11,0x00,0x11,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x90,0x01,0xFF,0x0F,0xF4,0x19,0x01,0x00,0x05,0x01,0x00,0x04,0x05,
+    0x04,0x0C,0x02,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEC,0x57,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xD9,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x59,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 }
 };
 #endif
 
@@ -271,46 +337,51 @@
 void   	SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 void   	SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
 #endif /* 315 */
+#ifdef SIS300
+void    SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
+USHORT  SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
+static  BOOLEAN SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr);
+#endif
 
-USHORT   SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
-void     SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
-USHORT   SiS_SetStart(SiS_Private *SiS_Pr);
-USHORT   SiS_SetStop(SiS_Private *SiS_Pr);
-void     SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
-USHORT   SiS_SetSCLKLow(SiS_Private *SiS_Pr);
-USHORT   SiS_SetSCLKHigh(SiS_Private *SiS_Pr);
-USHORT   SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT   SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT   SiS_CheckACK(SiS_Private *SiS_Pr);
-
-USHORT   SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
-                         USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32);
-USHORT   SiS_WriteDABDDC(SiS_Private *SiS_Pr);
-USHORT   SiS_PrepareReadDDC(SiS_Private *SiS_Pr);
-USHORT   SiS_PrepareDDC(SiS_Private *SiS_Pr);
-void     SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno);
-USHORT   SiS_DoProbeDDC(SiS_Private *SiS_Pr);
-USHORT   SiS_ProbeDDC(SiS_Private *SiS_Pr);
-USHORT   SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer);
-USHORT   SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
-		       USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
+USHORT  SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
+void    SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
+USHORT  SiS_SetStart(SiS_Private *SiS_Pr);
+USHORT  SiS_SetStop(SiS_Private *SiS_Pr);
+void    SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
+USHORT  SiS_SetSCLKLow(SiS_Private *SiS_Pr);
+USHORT  SiS_SetSCLKHigh(SiS_Private *SiS_Pr);
+USHORT  SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
+USHORT  SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
+USHORT  SiS_CheckACK(SiS_Private *SiS_Pr);
+
+USHORT  SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
+                        USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32);
+USHORT  SiS_WriteDABDDC(SiS_Private *SiS_Pr);
+USHORT  SiS_PrepareReadDDC(SiS_Private *SiS_Pr);
+USHORT  SiS_PrepareDDC(SiS_Private *SiS_Pr);
+void    SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno);
+USHORT  SiS_DoProbeDDC(SiS_Private *SiS_Pr);
+USHORT  SiS_ProbeDDC(SiS_Private *SiS_Pr);
+USHORT  SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer);
+USHORT  SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
+		      USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
 #ifdef LINUX_XF86
-USHORT   SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
-USHORT   SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
+USHORT  SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
+USHORT  SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
 #endif
 
 #ifdef SIS315H
-void     SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                           USHORT ModeNo,USHORT ModeIdIndex);
-void     SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                           USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
-void     SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO);
+void    SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                          USHORT ModeNo,USHORT ModeIdIndex);
+void    SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                          USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
+void    SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO);
 #endif
 #ifdef SIS300
-void     SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                           USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
-void     SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-			USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
+void    SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                          USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
+void    SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+		       USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
 #endif
 
 extern void     SiS_SetReg(SISIOADDRESS, USHORT, USHORT);
@@ -338,5 +409,6 @@
 extern void     SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO,USHORT ModeNo,
                             USHORT ModeIdIndex);
 
+extern void	SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
 
 #endif
diff -Nru a/drivers/video/sis/initdef.h b/drivers/video/sis/initdef.h
--- a/drivers/video/sis/initdef.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/sis/initdef.h	2004-06-23 19:04:27 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Global definitions for init.c and init301.c
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -72,6 +70,8 @@
 #define IS_SIS650740660         (IS_SIS650 || IS_SIS740 || IS_SIS661741660760)
 #define IS_SIS550650740660      (IS_SIS550 || IS_SIS650740660)
 
+#define SISGETROMW(x)		(ROMAddr[(x)] | (ROMAddr[(x)+1] << 8))
+
 /* SiS_VBType */
 #define VB_SIS301	      	0x0001
 #define VB_SIS301B        	0x0002
@@ -85,6 +85,8 @@
 #define VB_SIS301B302B          (VB_SIS301B|VB_SIS301C|VB_SIS302B)
 #define VB_SIS301LV302LV        (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
 #define VB_SISVB		(VB_SIS301 | VB_SIS301BLV302BLV)
+#define VB_SISTMDS		(VB_SIS301 | VB_SIS301B302B)
+#define VB_SISLVDS		VB_SIS301LV302LV
 
 /* VBInfo */
 #define SetSimuScanMode         0x0001   /* CR 30 */
@@ -137,6 +139,7 @@
 #define CRT2Mode                0x0800
 #define HalfDCLK                0x1000
 #define NoSupportSimuTV         0x2000
+#define NoSupportLCDScale	0x4000 /* TMDS: No scaling possible (no matter what panel) */
 #define DoubleScanMode          0x8000
 
 /* Infoflag */
@@ -145,7 +148,7 @@
 #define SupportCHTV 		0x0800
 #define Support64048060Hz       0x0800  /* Special for 640x480 LCD */
 #define SupportHiVision         0x0010
-#define SupportYPbPr            0x1000  /* TODO */
+#define SupportYPbPr750p        0x1000
 #define SupportLCD              0x0020
 #define SupportRAMDAC2          0x0040	/* All           (<= 100Mhz) */
 #define SupportRAMDAC2_135      0x0100  /* All except DH (<= 135Mhz) */
@@ -174,19 +177,22 @@
 #define TVSetPALM		0x0004
 #define TVSetPALN		0x0008
 #define TVSetCHOverScan		0x0010
-#define TVSetYPbPr525i		0x0020
-#define TVSetYPbPr525p		0x0040
-#define TVSetYPbPr750p		0x0080
-#define TVSetHiVision		0x0100  /* = 1080i, software-wise identical */
-#define TVSetTVSimuMode		0x0800
-#define TVRPLLDIV2XO		0x1000
-#define TVSetNTSC1024		0x2000
-
-/* YPbPr flag (>=315, <661) */
-#define YPbPr525p               0x0001	/* 525p */
-#define YPbPr750p               0x0002	/* 750p */
-#define YPbPr525i               0x0004	/* 525p */
-#define YPbPrHiVision           0x0008	/* HiVision or 1080i (bridge type dependent) */
+#define TVSetYPbPr525i		0x0020 /* new 0x10 */
+#define TVSetYPbPr525p		0x0040 /* new 0x20 */
+#define TVSetYPbPr750p		0x0080 /* new 0x40 */
+#define TVSetHiVision		0x0100 /* new 0x80; = 1080i, software-wise identical */
+#define TVSetTVSimuMode		0x0200 /* new 0x200, prev. 0x800 */
+#define TVRPLLDIV2XO		0x0400 /* prev 0x1000 */
+#define TVSetNTSC1024		0x0800 /* new 0x100, prev. 0x2000 */
+#define TVAspect43		0x2000
+#define TVAspect169		0x4000
+#define TVAspect43LB		0x8000
+
+/* YPbPr flag (>=315, <661; converted to TVMode) */
+#define YPbPr525p               0x0001
+#define YPbPr750p               0x0002
+#define YPbPr525i               0x0004
+#define YPbPrHiVision           0x0008
 #define YPbPrModeMask           (YPbPr750p | YPbPr525p | YPbPr525i | YPbPrHiVision)
 
 /* SysFlags (to identify special versions) */
@@ -198,6 +204,7 @@
 #define SF_IsM661		0x0020
 #define SF_IsM741		0x0040
 #define SF_IsM760		0x0080
+#define SF_760LFB		0x8000  /* 760: We have LFB */
 
 /* CR32 (Newer 630, and 315 series)
 
@@ -269,7 +276,7 @@
 #define LCDRGB18Bit           0x0001
 #define LCDNonExpanding       0x0010
 #define LCDSync               0x0020
-#define LCDPass11             0x0100
+#define LCDPass11             0x0100   /* 0: center screen, 1: Pass 1:1 data */
 #define LCDDualLink	      0x0200
 
 #define DontExpandLCD	      LCDNonExpanding
@@ -305,7 +312,7 @@
 #define EnablePALMN             0x40   /* Romflag: 1 = Allow PALM/PALN */
 
 /* CR39 (650 only) */
-#define LCDPass1_1		0x01   /* LVDS only; set by driver to pass 1:1 data to LVDS output  */
+#define LCDPass1_1		0x01   /* 0: center screen, 1: pass 1:1 data output  */
 #define Enable302LV_DualLink    0x04   /* 302LV only; enable dual link */
 
 /* CR39 (661 and later)
@@ -348,7 +355,7 @@
 #define Panel300_1024x600       0x06
 #define Panel300_1152x768       0x07
 #define Panel300_1280x768       0x0a
-#define Panel300_320x480        0x0e 	/* fstn - TW: This is fake, can be any */
+#define Panel300_320x480        0x0e 	/* fstn - This is fake, can be any */
 #define Panel300_Custom		0x0f
 #define Panel300_Barco1366      0x10
 
@@ -368,8 +375,24 @@
 #define Panel310_320x480        0x0e    /* fstn - TW: This is fake, can be any */
 #define Panel310_Custom		0x0f
 
+#define Panel661_800x600        0x01
+#define Panel661_1024x768       0x02
+#define Panel661_1280x1024      0x03
+#define Panel661_640x480        0x04
+#define Panel661_1024x600       0x05
+#define Panel661_1152x864       0x06
+#define Panel661_1280x960       0x07
+#define Panel661_1152x768       0x08
+#define Panel661_1400x1050      0x09
+#define Panel661_1280x768       0x0a
+#define Panel661_1600x1200      0x0b
+#define Panel661_1280x800       0x0c
+#define Panel661_1680x1050      0x0d
+#define Panel661_1280x720       0x0e
+#define Panel661_Custom		0x0f
+
 #define Panel_800x600           0x01	/* Unified values */
-#define Panel_1024x768          0x02
+#define Panel_1024x768          0x02    /* MUST match BIOS values from 0-e */
 #define Panel_1280x1024         0x03
 #define Panel_640x480           0x04
 #define Panel_1024x600          0x05
@@ -377,16 +400,19 @@
 #define Panel_1280x960          0x07
 #define Panel_1152x768          0x08	/* LVDS only */
 #define Panel_1400x1050         0x09
-#define Panel_1280x768          0x0a    /* LVDS only */
+#define Panel_1280x768          0x0a    /* 30xB/C and LVDS only (BIOS: all) */
 #define Panel_1600x1200         0x0b
-#define Panel_640x480_2		0x0c
-#define Panel_640x480_3		0x0d
-#define Panel_320x480           0x0e    /* fstn - TW: This is fake, can be any */
-#define Panel_Custom		0x0f
-#define Panel_Barco1366         0x10
-#define Panel_848x480		0x11
-#define Panel_1280x800		0x12    /* 661etc: 0x0c */
-#define Panel_1680x1050         0x13    /* 661etc: 0x0d */
+#define Panel_1280x800		0x0c    /* 661etc  */
+#define Panel_1680x1050         0x0d    /* 661etc  */
+#define Panel_1280x720		0x0e    /* 661etc  */
+#define Panel_Custom		0x0f	/* MUST BE 0x0f (for DVI DDC detection */
+#define Panel_320x480           0x10    /* SiS 550 fstn - TW: This is fake, can be any */
+#define Panel_Barco1366         0x11
+#define Panel_848x480		0x12
+#define Panel_640x480_2		0x13    /* SiS 550 */
+#define Panel_640x480_3		0x14    /* SiS 550 */
+#define Panel_1280x768_2        0x15	/* 30xLV */
+#define Panel_1280x768_3        0x16    /* 30xLV */
 
 /* Index in ModeResInfo table */
 #define SIS_RI_320x200    0
@@ -411,13 +437,17 @@
 #define SIS_RI_856x480   19
 #define SIS_RI_1280x768  20
 #define SIS_RI_1400x1050 21
-#define SIS_RI_1152x864  22  /* Up to this SiS conforming */
+#define SIS_RI_1152x864  22  /* Up to here SiS conforming */
 #define SIS_RI_848x480   23
 #define SIS_RI_1360x768  24
 #define SIS_RI_1024x600  25
 #define SIS_RI_1152x768  26
 #define SIS_RI_768x576   27
 #define SIS_RI_1360x1024 28
+#define SIS_RI_1680x1050 29
+#define SIS_RI_1280x800  30
+#define SIS_RI_1920x1080 31
+#define SIS_RI_960x540   32
 
 /* CR5F */
 #define IsM650                  0x80
@@ -445,14 +475,32 @@
 #define VCLK108_3_300           0x42   /* Index in VCLKData table (300) */
 #define VCLK100_300             0x43   /* Index in VCLKData table (300) */
 #define VCLK34_300              0x3d   /* Index in VCLKData table (300) */
+#define VCLK_CUSTOM_300		0x46
 #define VCLK65_315              0x0b   /* Index in (VB)VCLKData table (315) */
 #define VCLK108_2_315           0x19   /* Index in (VB)VCLKData table (315) */
 #define VCLK81_315		0x5b   /* Index in (VB)VCLKData table (315) */
-#define VCLK162_315             0x21   /* Index in (VB)VCLKData table (315) */
+#define VCLK162_315             0x5e   /* Index in (VB)VCLKData table (315) */
 #define VCLK108_3_315           0x45   /* Index in VBVCLKData table (315) */
 #define VCLK100_315             0x46   /* Index in VBVCLKData table (315) */
-#define VCLK34_315              0x55   /* Index in VBVCLKData table (315) */
+#define VCLK34_315              0x55
 #define VCLK68_315		0x0d
+#define VCLK69_315		0x5c   /* deprecated ! Index in VBVCLKData table (315) */
+#define VCLK83_315		0x5c   /* Index in VBVCLKData table (315) */
+#define VCLK121_315		0x5d   /* Index in VBVCLKData table (315) */
+#define VCLK_1280x720		0x5f
+#define VCLK_1280x768_2		0x60
+#define VCLK_1280x768_3		0x61
+#define VCLK_CUSTOM_315		0x62
+#define VCLK_1280x720_2		0x63
+#define VCLK_720x480		0x67
+#define VCLK_720x576		0x68
+#define VCLK_768x576		0x68
+#define VCLK_848x480		0x65
+#define VCLK_856x480		0x66
+#define VCLK_800x480		0x65
+#define VCLK_1024x576		0x51
+#define VCLK_1152x864		0x64
+#define VCLK_1360x768		0x58
 
 #define TVCLKBASE_300		0x21   /* Indices on TV clocks in VCLKData table (300) */
 #define TVCLKBASE_315	        0x3a   /* Indices on TV clocks in (VB)VCLKData table (315) */
@@ -462,7 +510,7 @@
 #define HiTVVCLK                0x03   /* Index relative to TVCLKBASE */
 #define HiTVSimuVCLK            0x04   /* Index relative to TVCLKBASE */
 #define HiTVTextVCLK            0x05   /* Index relative to TVCLKBASE */
-#define YPbPr750pVCLK		0x0f   /* NOT relative to TVCLKBASE ! */
+#define YPbPr750pVCLK		0x25   /* Index relative to TVCLKBASE; was 0x0f NOT relative */
 
 /* ------------------------------ */
 
@@ -563,7 +611,7 @@
 
 /*
   =============================================================
-   			  for 315 series
+   		  for 315 series (old data layout)
   =============================================================
 */
 #define SoftDRAMType        0x80
diff -Nru a/drivers/video/sis/oem300.h b/drivers/video/sis/oem300.h
--- a/drivers/video/sis/oem300.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/sis/oem300.h	2004-06-23 19:04:26 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * OEM Data for 300 series
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
diff -Nru a/drivers/video/sis/oem310.h b/drivers/video/sis/oem310.h
--- a/drivers/video/sis/oem310.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/video/sis/oem310.h	2004-06-23 19:04:25 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * OEM Data for 315/330 series
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -91,7 +89,7 @@
 		 0x02,0x02,0x02
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_651301LV[] =	  /* M650/651 301LV */
+static const UCHAR SiS310_LCDDelayCompensation_651301LV[] =	  	/* M650/651 301LV */
 {
                  0x33,0x33,0x33,    /*   800x600 (guessed) - new: PanelType, not PanelRes ! */
 		 0x33,0x33,0x33,    /*  1024x768 */
@@ -110,7 +108,7 @@
 		 0x33,0x33,0x33
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_651302LV[] =	   /* M650/651 302LV */
+static const UCHAR SiS310_LCDDelayCompensation_651302LV[] =	   	/* M650/651 302LV */
 {
                  0x33,0x33,0x33,    /*   800x600 (guessed) */
 		 0x33,0x33,0x33,    /*  1024x768 */
@@ -129,7 +127,7 @@
 		 0x33,0x33,0x33
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB,LV */
+static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB */
 {
 		 0x01,0x01,0x01,    /*   800x600 */
 		 0x0C,0x0C,0x0C,    /*  1024x768 */
@@ -148,6 +146,25 @@
 		 0x02,0x02,0x02
 };
 
+static const UCHAR SiS310_LCDDelayCompensation_3xx301LV[] =	   	/* 315+30xLV */
+{
+		 0x01,0x01,0x01,    /*   800x600 */
+		 0x04,0x04,0x04,    /*  1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
+		 0x0C,0x0C,0x0C,    /* 1280x1024 */
+                 0x08,0x08,0x08,    /*   640x480 */
+		 0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
+		 0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
+		 0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02
+};
+
 static const UCHAR SiS310_TVDelayCompensation_301[] = 		/* 301 */
 {
 		 0x02,0x02,    /* NTSC Enhanced, Standard */
@@ -169,13 +186,6 @@
 		 0x05,0x05
 };
 
-static const UCHAR SiS310_TVDelayCompensation_LVDS[] =		/* LVDS */
-{
-		 0x0a,0x0a,
-		 0x0a,0x0a,
-		 0x0a,0x0a
-};
-
 static const UCHAR SiS310_TVDelayCompensation_651301LV[] =	/* M650, 651, 301LV */
 {
 		 0x33,0x33,
@@ -210,6 +220,13 @@
 		 0x44,0x44
 };
 
+static const UCHAR SiS310_TVDelayCompensation_LVDS[] =		/* LVDS */
+{
+		 0x0a,0x0a,
+		 0x0a,0x0a,
+		 0x0a,0x0a
+};
+
 static const UCHAR SiS310_TVAntiFlick1[6][2] =
 {
             {0x4,0x0},
@@ -412,141 +429,6 @@
 	{    1,   1,1696,1066,1696,1066}
 };
 
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_1[] =
-{
- {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x35,0x1B,0xA0,0xC0,0x80,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x45,0x1C,0x20,0x3F,0xFF,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x49,0x1C,0x40,0x7F,0xFF,0xAD,0x23,0x0A,0x07,0xF3,0x8A,0x12}},
- {{0x4C,0x1C,0x18,0x2F,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_2[] =
-{
- {{0x2B,0x12,0xD9,0xE5,0xD5,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x22,0x12,0xC0,0xCC,0xBC,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x2B,0x12,0xD9,0xE5,0xD5,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x22,0x12,0xC0,0xCC,0xBC,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x33,0x13,0x01,0x0D,0xFD,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x3F,0x1B,0x3D,0x49,0x39,0x54,0x23,0xC0,0x27,0x66,0x30,0x42}},
- {{0x33,0x1B,0x91,0x9D,0x8D,0x8C,0x23,0xF8,0x27,0x9E,0x68,0x42}},
- {{0x43,0x24,0x11,0x1D,0x0D,0xCC,0x23,0x38,0x37,0xDE,0xA8,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xEA,0x23,0x0A,0x07,0x32,0xC6,0x42}}
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_3[] =
-{
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}}
-};
-
-/* LCDA CRT2 data is std */
-
-static const SiS_LVDSDesStruct Compaq1280x1024Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-static const SiS_LVDSDesStruct Compaq1280x1024Des_2[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-/* Clevo L285/287 (dual-link 1024x768) */
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Clevo1024x768_1[] =
-{
- {{0x25,0x12,0xC9,0xDC,0xB6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x2C,0x12,0x9A,0xAE,0x88,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x25,0x12,0xC9,0xDC,0xB6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x16,0x0C,0xE6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xFF,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x12,0xC9,0xDC,0xB6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}}
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Clevo1024x768_2[] =
-{
- {{0x25,0x12,0x51,0x6E,0x48,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x25,0x12,0x51,0x6E,0x48,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xE0,0x12,0xB1,0x47,0x30,0x71,0x33}},
- {{0x2D,0x12,0x79,0x96,0x70,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x29,0x12,0xB5,0xD2,0xAC,0xF4,0x12,0xD9,0x47,0x44,0x99,0x33}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
-#if 0
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xC1,0x35,0xB1,0x47,0xE9,0x71,0x33}},
- {{0x2D,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x29,0x12,0xB5,0xD2,0xAC,0xE9,0x35,0xD9,0x47,0x11,0x99,0x33}},
- {{0x36,0x13,0x13,0x25,0xFF,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}}
-#endif
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Clevo1024x768_3[] =
-{
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}}, /* Corrected */
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x13,0xC9,0x25,0xFF,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}}
-};
-
-/* CRT2 data is std */
-
-static const SiS_LVDSDesStruct Clevo1024x768Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-static const SiS_LVDSDesStruct Clevo1024x768Des_2[] =
-{
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1152, 622 },
-  { 1232, 722 },
-  {    0,   0 }
-};
-
 /* Asus A2xxxH _2 */
 
 static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Asus1024x768_3[] =
@@ -562,52 +444,6 @@
  {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
 };
 
-static const SiS_LVDSDesStruct Asus1024x768Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
 
-static const SiS_LVDSDesStruct Asus1024x768Des_2[] =
-{
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1152, 622 },
-  { 1232, 722 },
-  {    0,   0 }
-};
-
-/* CRT2 data is std */
-
-/* Uniwill N243S9, ECS A928 */
-
-static const SiS_LVDSDesStruct Uniwill1024x768Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 805 }
-};
-
-static const SiS_LVDSDesStruct Uniwill1024x768Des_2[] =
-{
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1152, 650 },
-  { 1232, 722 },
-  {    0, 805 },
-};
 
 
diff -Nru a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h
--- a/drivers/video/sis/osdef.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/video/sis/osdef.h	2004-06-23 19:04:25 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * OS depending defines
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -54,95 +52,77 @@
  */
 
 /* The choices are: */
-
 #define LINUX_KERNEL	   /* Kernel framebuffer */
 /* #define LINUX_XF86 */   /* XFree86 */
 
-/**********************************************************************/
-#ifdef LINUX_KERNEL  /* -------------------------- */
-#include <linux/config.h>
-#include <linux/version.h>
-
-#ifdef CONFIG_FB_SIS_300
-#define SIS300
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-#define SIS315H
-#endif
-
-#if 1
-#define SISFBACCEL	/* Include 2D acceleration */
-#endif
-
-#endif
-
-#ifdef LINUX_XF86 /* ----------------------------- */
-#define SIS300
-#define SIS315H
-#endif
-
-/**********************************************************************/
-#ifdef LINUX_XF86
-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-#define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
-#endif
-
-#ifdef LINUX_KERNEL
-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-#define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
-#endif
-
-/**********************************************************************/
-
 #ifdef OutPortByte
 #undef OutPortByte
-#endif /* OutPortByte */
+#endif
 
 #ifdef OutPortWord
 #undef OutPortWord
-#endif /* OutPortWord */
+#endif
 
 #ifdef OutPortLong
 #undef OutPortLong
-#endif /* OutPortLong */
+#endif
 
 #ifdef InPortByte
 #undef InPortByte
-#endif /* InPortByte */
+#endif
 
 #ifdef InPortWord
 #undef InPortWord
-#endif /* InPortWord */
+#endif
 
 #ifdef InPortLong
 #undef InPortLong
-#endif /* InPortLong */
+#endif
 
 /**********************************************************************/
-/*  LINUX XF86                                                        */
+/*  LINUX KERNEL                                                      */
 /**********************************************************************/
 
-#ifdef LINUX_XF86
-#define OutPortByte(p,v) outb((CARD16)(p),(CARD8)(v))
-#define OutPortWord(p,v) outw((CARD16)(p),(CARD16)(v))
-#define OutPortLong(p,v) outl((CARD16)(p),(CARD32)(v))
-#define InPortByte(p)    inb((CARD16)(p))
-#define InPortWord(p)    inw((CARD16)(p))
-#define InPortLong(p)    inl((CARD16)(p))
+#ifdef LINUX_KERNEL
+#include <linux/config.h>
+
+#ifdef CONFIG_FB_SIS_300
+#define SIS300
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+#define SIS315H
+#endif
+
+#if !defined(SIS300) && !defined(SIS315H)
+#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
+#warning sisfb will not work!
+#endif
+
+#define OutPortByte(p,v) outb((u8)(v),(SISIOADDRESS)(p))
+#define OutPortWord(p,v) outw((u16)(v),(SISIOADDRESS)(p))
+#define OutPortLong(p,v) outl((u32)(v),(SISIOADDRESS)(p))
+#define InPortByte(p)    inb((SISIOADDRESS)(p))
+#define InPortWord(p)    inw((SISIOADDRESS)(p))
+#define InPortLong(p)    inl((SISIOADDRESS)(p))
+#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize)
 #endif
 
 /**********************************************************************/
-/*  LINUX KERNEL                                                      */
+/*  XFree86, X.org                                                    */
 /**********************************************************************/
 
-#ifdef LINUX_KERNEL
-#define OutPortByte(p,v) outb((u8)(v),(u16)(p))
-#define OutPortWord(p,v) outw((u16)(v),(u16)(p))
-#define OutPortLong(p,v) outl((u32)(v),(u16)(p))
-#define InPortByte(p)    inb((u16)(p))
-#define InPortWord(p)    inw((u16)(p))
-#define InPortLong(p)    inl((u16)(p))
+#ifdef LINUX_XF86
+#define SIS300
+#define SIS315H
+
+#define OutPortByte(p,v) outb((IOADDRESS)(p),(CARD8)(v))
+#define OutPortWord(p,v) outw((IOADDRESS)(p),(CARD16)(v))
+#define OutPortLong(p,v) outl((IOADDRESS)(p),(CARD32)(v))
+#define InPortByte(p)    inb((IOADDRESS)(p))
+#define InPortWord(p)    inw((IOADDRESS)(p))
+#define InPortLong(p)    inl((IOADDRESS)(p))
+#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
 #endif
 
 
diff -Nru a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
--- a/drivers/video/sis/sis.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/sis/sis.h	2004-06-23 19:04:27 -07:00
@@ -1,10 +1,505 @@
+/*
+ * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/330/760
+ * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
+ *
+ * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the named License,
+ * or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+
 #ifndef _SIS_H
 #define _SIS_H
 
-#if 1
-#define TWDEBUG(x)
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include "osdef.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <video/sisfb.h>
 #else
+#include <linux/sisfb.h>
+#endif
+
+#include "vgatypes.h"
+#include "vstruct.h"
+
+#define VER_MAJOR                 1
+#define VER_MINOR                 7
+#define VER_LEVEL                 12
+
+#undef SIS_CONFIG_COMPAT
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <linux/spinlock.h>
+#ifdef CONFIG_COMPAT
+#include <linux/ioctl32.h>
+#define SIS_CONFIG_COMPAT
+#endif
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
+#ifdef __x86_64__
+/* Shouldn't we check for CONFIG_IA32_EMULATION here? */
+#include <asm/ioctl32.h>
+#define SIS_CONFIG_COMPAT
+#endif
+#endif
+
+#undef SISFBDEBUG
+
+#ifdef SISFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 #define TWDEBUG(x) printk(KERN_INFO x "\n");
+#else
+#define DPRINTK(fmt, args...)
+#define TWDEBUG(x)
+#endif
+
+#define SISFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
+
+/* To be included in pci_ids.h */
+#ifndef PCI_DEVICE_ID_SI_650_VGA
+#define PCI_DEVICE_ID_SI_650_VGA  0x6325
+#endif
+#ifndef PCI_DEVICE_ID_SI_650
+#define PCI_DEVICE_ID_SI_650      0x0650
+#endif
+#ifndef PCI_DEVICE_ID_SI_651
+#define PCI_DEVICE_ID_SI_651      0x0651
+#endif
+#ifndef PCI_DEVICE_ID_SI_740
+#define PCI_DEVICE_ID_SI_740      0x0740
+#endif
+#ifndef PCI_DEVICE_ID_SI_330
+#define PCI_DEVICE_ID_SI_330      0x0330
+#endif
+#ifndef PCI_DEVICE_ID_SI_660_VGA
+#define PCI_DEVICE_ID_SI_660_VGA  0x6330
+#endif
+#ifndef PCI_DEVICE_ID_SI_661
+#define PCI_DEVICE_ID_SI_661      0x0661
+#endif
+#ifndef PCI_DEVICE_ID_SI_741
+#define PCI_DEVICE_ID_SI_741      0x0741
+#endif
+#ifndef PCI_DEVICE_ID_SI_660
+#define PCI_DEVICE_ID_SI_660      0x0660
+#endif
+#ifndef PCI_DEVICE_ID_SI_760
+#define PCI_DEVICE_ID_SI_760      0x0760
+#endif
+
+/* To be included in fb.h */
+#ifndef FB_ACCEL_SIS_GLAMOUR_2
+#define FB_ACCEL_SIS_GLAMOUR_2	  40	/* SiS 315, 65x, 740, 661, 741  */
+#endif
+#ifndef FB_ACCEL_SIS_XABRE
+#define FB_ACCEL_SIS_XABRE        41	/* SiS 330 ("Xabre"), 760 	*/
+#endif
+
+#define MAX_ROM_SCAN              0x10000
+
+/* ivideo->caps */
+#define HW_CURSOR_CAP             0x80
+#define TURBO_QUEUE_CAP           0x40
+#define AGP_CMD_QUEUE_CAP         0x20
+#define VM_CMD_QUEUE_CAP          0x10
+#define MMIO_CMD_QUEUE_CAP        0x08
+
+/* For 300 series */
+#define TURBO_QUEUE_AREA_SIZE     0x80000 /* 512K */
+#define HW_CURSOR_AREA_SIZE_300   0x1000  /* 4K */
+
+/* For 315/Xabre series */
+#define COMMAND_QUEUE_AREA_SIZE   0x80000 /* 512K */
+#define COMMAND_QUEUE_THRESHOLD   0x1F
+#define HW_CURSOR_AREA_SIZE_315   0x4000  /* 16K */
+
+#define SIS_OH_ALLOC_SIZE         4000
+#define SENTINEL                  0x7fffffff
+
+#define SEQ_ADR                   0x14
+#define SEQ_DATA                  0x15
+#define DAC_ADR                   0x18
+#define DAC_DATA                  0x19
+#define CRTC_ADR                  0x24
+#define CRTC_DATA                 0x25
+#define DAC2_ADR                  (0x16-0x30)
+#define DAC2_DATA                 (0x17-0x30)
+#define VB_PART1_ADR              (0x04-0x30)
+#define VB_PART1_DATA             (0x05-0x30)
+#define VB_PART2_ADR              (0x10-0x30)
+#define VB_PART2_DATA             (0x11-0x30)
+#define VB_PART3_ADR              (0x12-0x30)
+#define VB_PART3_DATA             (0x13-0x30)
+#define VB_PART4_ADR              (0x14-0x30)
+#define VB_PART4_DATA             (0x15-0x30)
+
+#define SISSR			  ivideo->SiS_Pr.SiS_P3c4
+#define SISCR                     ivideo->SiS_Pr.SiS_P3d4
+#define SISDACA                   ivideo->SiS_Pr.SiS_P3c8
+#define SISDACD                   ivideo->SiS_Pr.SiS_P3c9
+#define SISPART1                  ivideo->SiS_Pr.SiS_Part1Port
+#define SISPART2                  ivideo->SiS_Pr.SiS_Part2Port
+#define SISPART3                  ivideo->SiS_Pr.SiS_Part3Port
+#define SISPART4                  ivideo->SiS_Pr.SiS_Part4Port
+#define SISPART5                  ivideo->SiS_Pr.SiS_Part5Port
+#define SISDAC2A                  SISPART5
+#define SISDAC2D                  (SISPART5 + 1)
+#define SISMISCR                  (ivideo->SiS_Pr.RelIO + 0x1c)
+#define SISMISCW                  ivideo->SiS_Pr.SiS_P3c2
+#define SISINPSTAT		  (ivideo->SiS_Pr.RelIO + 0x2a)
+#define SISPEL			  ivideo->SiS_Pr.SiS_P3c6
+
+#define IND_SIS_PASSWORD          0x05  /* SRs */
+#define IND_SIS_COLOR_MODE        0x06
+#define IND_SIS_RAMDAC_CONTROL    0x07
+#define IND_SIS_DRAM_SIZE         0x14
+#define IND_SIS_MODULE_ENABLE     0x1E
+#define IND_SIS_PCI_ADDRESS_SET   0x20
+#define IND_SIS_TURBOQUEUE_ADR    0x26
+#define IND_SIS_TURBOQUEUE_SET    0x27
+#define IND_SIS_POWER_ON_TRAP     0x38
+#define IND_SIS_POWER_ON_TRAP2    0x39
+#define IND_SIS_CMDQUEUE_SET      0x26
+#define IND_SIS_CMDQUEUE_THRESHOLD  0x27
+
+#define IND_SIS_AGP_IO_PAD        0x48
+
+#define SIS_CRT2_WENABLE_300 	  0x24  /* Part1 */
+#define SIS_CRT2_WENABLE_315 	  0x2F
+
+#define SIS_PASSWORD              0x86  /* SR05 */
+#define SIS_INTERLACED_MODE       0x20  /* SR06 */
+#define SIS_8BPP_COLOR_MODE       0x0
+#define SIS_15BPP_COLOR_MODE      0x1
+#define SIS_16BPP_COLOR_MODE      0x2
+#define SIS_32BPP_COLOR_MODE      0x4
+
+#define SIS_ENABLE_2D             0x40  /* SR1E */
+
+#define SIS_MEM_MAP_IO_ENABLE     0x01  /* SR20 */
+#define SIS_PCI_ADDR_ENABLE       0x80
+
+#define SIS_AGP_CMDQUEUE_ENABLE   0x80  /* 315/330 series SR26 */
+#define SIS_VRAM_CMDQUEUE_ENABLE  0x40
+#define SIS_MMIO_CMD_ENABLE       0x20
+#define SIS_CMD_QUEUE_SIZE_512k   0x00
+#define SIS_CMD_QUEUE_SIZE_1M     0x04
+#define SIS_CMD_QUEUE_SIZE_2M     0x08
+#define SIS_CMD_QUEUE_SIZE_4M     0x0C
+#define SIS_CMD_QUEUE_RESET       0x01
+#define SIS_CMD_AUTO_CORR	  0x02
+
+#define SIS_SIMULTANEOUS_VIEW_ENABLE  0x01  /* CR30 */
+#define SIS_MODE_SELECT_CRT2      0x02
+#define SIS_VB_OUTPUT_COMPOSITE   0x04
+#define SIS_VB_OUTPUT_SVIDEO      0x08
+#define SIS_VB_OUTPUT_SCART       0x10
+#define SIS_VB_OUTPUT_LCD         0x20
+#define SIS_VB_OUTPUT_CRT2        0x40
+#define SIS_VB_OUTPUT_HIVISION    0x80
+
+#define SIS_VB_OUTPUT_DISABLE     0x20  /* CR31 */
+#define SIS_DRIVER_MODE           0x40
+
+#define SIS_VB_COMPOSITE          0x01  /* CR32 */
+#define SIS_VB_SVIDEO             0x02
+#define SIS_VB_SCART              0x04
+#define SIS_VB_LCD                0x08
+#define SIS_VB_CRT2               0x10
+#define SIS_CRT1                  0x20
+#define SIS_VB_HIVISION           0x40
+#define SIS_VB_YPBPR              0x80
+#define SIS_VB_TV                 (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
+                                   SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
+
+#define SIS_EXTERNAL_CHIP_MASK    	   0x0E  /* CR37 (< SiS 660) */
+#define SIS_EXTERNAL_CHIP_SIS301           0x01  /* in CR37 << 1 ! */
+#define SIS_EXTERNAL_CHIP_LVDS             0x02
+#define SIS_EXTERNAL_CHIP_TRUMPION         0x03
+#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL    0x04
+#define SIS_EXTERNAL_CHIP_CHRONTEL         0x05
+#define SIS310_EXTERNAL_CHIP_LVDS          0x02
+#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03
+
+#define SIS_AGP_2X                0x20  /* CR48 */
+
+#define HW_DEVICE_EXTENSION	  SIS_HW_INFO
+#define PHW_DEVICE_EXTENSION      PSIS_HW_INFO
+
+/* Useful macros */
+#define inSISREG(base)          inb(base)
+#define outSISREG(base,val)     outb(val,base)
+#define orSISREG(base,val)      do { \
+                                  u8 __Temp = inb(base); \
+                                  outSISREG(base, __Temp | (val)); \
+                                } while (0)
+#define andSISREG(base,val)     do { \
+                                  u8 __Temp = inb(base); \
+                                  outSISREG(base, __Temp & (val)); \
+                                } while (0)
+#define inSISIDXREG(base,idx,var)   do { \
+                                      outb(idx,base); var=inb((base)+1); \
+                                    } while (0)
+#define outSISIDXREG(base,idx,val)  do { \
+                                      outb(idx,base); outb((val),(base)+1); \
+                                    } while (0)
+#define orSISIDXREG(base,idx,val)   do { \
+                                      u8 __Temp; \
+                                      outb(idx,base);   \
+                                      __Temp = inb((base)+1)|(val); \
+                                      outSISIDXREG(base,idx,__Temp); \
+                                    } while (0)
+#define andSISIDXREG(base,idx,and)  do { \
+                                      u8 __Temp; \
+                                      outb(idx,base);   \
+                                      __Temp = inb((base)+1)&(and); \
+                                      outSISIDXREG(base,idx,__Temp); \
+                                    } while (0)
+#define setSISIDXREG(base,idx,and,or)   do { \
+                                          u8 __Temp; \
+                                          outb(idx,base);   \
+                                          __Temp = (inb((base)+1)&(and))|(or); \
+                                          outSISIDXREG(base,idx,__Temp); \
+                                        } while (0)
+
+/* MMIO access macros */
+#define MMIO_IN8(base, offset)  readb((base+offset))
+#define MMIO_IN16(base, offset) readw((base+offset))
+#define MMIO_IN32(base, offset) readl((base+offset))
+
+#define MMIO_OUT8(base, offset, val)  writeb(((u8)(val)), (base+offset))
+#define MMIO_OUT16(base, offset, val) writew(((u16)(val)), (base+offset))
+#define MMIO_OUT32(base, offset, val) writel(((u32)(val)), (base+offset))
+
+/* Queue control MMIO registers */
+#define Q_BASE_ADDR		0x85C0  /* Base address of software queue */
+#define Q_WRITE_PTR		0x85C4  /* Current write pointer */
+#define Q_READ_PTR		0x85C8  /* Current read pointer */
+#define Q_STATUS		0x85CC  /* queue status */
+
+#define MMIO_QUEUE_PHYBASE      Q_BASE_ADDR
+#define MMIO_QUEUE_WRITEPORT    Q_WRITE_PTR
+#define MMIO_QUEUE_READPORT     Q_READ_PTR
+
+enum _SIS_CMDTYPE {
+	MMIO_CMD = 0,
+	AGP_CMD_QUEUE,
+	VM_CMD_QUEUE,
+};
+typedef unsigned int SIS_CMDTYPE;
+
+/* Our "par" */
+struct sis_video_info {
+	int		cardnumber;
+	struct fb_info  *memyselfandi;
+
+	SIS_HW_INFO 	sishw_ext;
+	SiS_Private  	SiS_Pr;
+
+	sisfb_info 	sisfbinfo;	/* For ioctl SISFB_GET_INFO */
+
+	struct fb_var_screeninfo default_var;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	struct fb_fix_screeninfo sisfb_fix;
+	u32 		pseudo_palette[17];
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	struct display 		 sis_disp;
+	struct display_switch 	 sisfb_sw;
+	struct {
+		u16 red, green, blue, pad;
+	} 		sis_palette[256];
+	union {
+#ifdef FBCON_HAS_CFB16
+		u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+		u32 cfb32[16];
+#endif
+	} 		sis_fbcon_cmap;
+#endif
+
+        struct sisfb_monitor {
+		u16 hmin;
+		u16 hmax;
+		u16 vmin;
+		u16 vmax;
+		u32 dclockmax;
+		u8  feature;
+		BOOLEAN datavalid;
+	} 		sisfb_thismonitor;
+
+	int           	chip_id;
+	char		myid[40];
+
+	struct pci_dev  *nbridge;
+
+	int		mni;	/* Mode number index */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	int  		currcon;
+#endif
+
+	unsigned long	video_size;
+	unsigned long 	video_base;
+	unsigned long	mmio_size;
+	unsigned long 	mmio_base;
+	unsigned long 	vga_base;
+
+	unsigned long  	video_vbase;
+	unsigned long 	mmio_vbase;
+	char  *	      	bios_vbase;
+	char  *	      	bios_abase;
+
+	int 		mtrr;
+
+	u32		sisfb_mem;
+
+	u32 		sisfb_parm_mem;
+	int 	   	sisfb_accel;
+	int 		sisfb_ypan;
+	int 		sisfb_max;
+	int 		sisfb_userom;
+	int 		sisfb_useoem;
+	int		sisfb_mode_idx;
+	int		sisfb_parm_rate;
+	int		sisfb_crt1off;
+	int		sisfb_forcecrt1;
+	int		sisfb_crt2type;
+	int		sisfb_crt2flags;
+	int 		sisfb_dstn;
+	int 		sisfb_fstn;
+	int		sisfb_tvplug;
+	int		sisfb_tvstd;
+	int		sisfb_filter;
+	int		sisfb_nocrt2rate;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	int		sisfb_inverse;
+#endif
+
+	u32 		heapstart;        /* offset  */
+	unsigned long  	sisfb_heap_start; /* address */
+	unsigned long  	sisfb_heap_end;   /* address */
+	u32 	      	sisfb_heap_size;
+	int		havenoheap;
+#if 0
+	SIS_HEAP       	sisfb_heap;
 #endif
+
+
+	int    		video_bpp;
+	int    		video_cmap_len;
+	int    		video_width;
+	int    		video_height;
+	unsigned int 	refresh_rate;
+
+	unsigned int 	chip;
+	u8   		revision_id;
+
+	int    		video_linelength;	/* real pitch */
+	int		scrnpitchCRT1;		/* pitch regarding interlace */
+
+        u16 		DstColor;		/* For 2d acceleration */
+	u32  		SiS310_AccelDepth;
+	u32  		CommandReg;
+	int		cmdqueuelength;
+
+	spinlock_t     	lockaccel;		/* Do not use outside of kernel! */
+
+        unsigned int   	pcibus;
+	unsigned int   	pcislot;
+	unsigned int   	pcifunc;
+
+	int 	       	accel;
+
+	u16 		subsysvendor;
+	u16 		subsysdevice;
+
+	u32  		vbflags;		/* Replacing deprecated stuff from above */
+	u32  		currentvbflags;
+
+	int		lcdxres, lcdyres;
+	int		lcddefmodeidx, tvdefmodeidx, defmodeidx;
+
+	int    		current_bpp;
+	int    		current_width;
+	int    		current_height;
+	int    		current_htotal;
+	int    		current_vtotal;
+	int		current_linelength;
+	__u32  		current_pixclock;
+	int    		current_refresh_rate;
+
+	u8  		mode_no;
+	u8  		rate_idx;
+	int    		modechanged;
+	unsigned char 	modeprechange;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	u8 		sisfb_lastrates[128];
+#endif
+
+	int  		newrom;
+	int  		registered;
+#ifdef SIS_CONFIG_COMPAT
+	int		ioctl32registered;
+	int		ioctl32vblankregistered;
+#endif
+
+	int 		sisvga_engine;
+	int 		hwcursor_size;
+	int 		CRT2_write_enable;
+	u8            	caps;
+
+	u8 		detectedpdc;
+	u8 		detectedpdca;
+	u8 		detectedlcda;
+
+	unsigned long 	hwcursor_vbase;
+
+	int 		chronteltype;
+	int    		tvxpos, tvypos;
+	u8              p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
+	int		tvx, tvy;
+
+	u8 		sisfblocked;
+
+	struct sis_video_info *next;
+};
+
+typedef struct _SIS_OH {
+	struct _SIS_OH *poh_next;
+	struct _SIS_OH *poh_prev;
+	u32            offset;
+	u32            size;
+} SIS_OH;
+
+typedef struct _SIS_OHALLOC {
+	struct _SIS_OHALLOC *poha_next;
+	SIS_OH aoh[1];
+} SIS_OHALLOC;
+
+typedef struct _SIS_HEAP {
+	SIS_OH      oh_free;
+	SIS_OH      oh_used;
+	SIS_OH      *poh_freelist;
+	SIS_OHALLOC *poha_chain;
+	u32         max_freesize;
+	struct sis_video_info *vinfo;
+} SIS_HEAP;
 
 #endif
diff -Nru a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c
--- a/drivers/video/sis/sis_accel.c	2004-06-23 19:04:29 -07:00
+++ b/drivers/video/sis/sis_accel.c	2004-06-23 19:04:29 -07:00
@@ -18,9 +18,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  *
- * Based on the XFree86 driver's sis300_accel.c which is
- *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
- * and sis310_accel.c which is
+ * Based on the XFree86/X.org driver which is
  *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
  *
  * Author: Thomas Winischhofer <thomas@winischhofer.net>
@@ -33,36 +31,16 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/console.h>
 #include <linux/selection.h>
 #include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vt_kern.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/agp_backend.h>
-
 #include <linux/types.h>
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include <linux/sisfb.h>
-#else
-#include <video/sisfb.h>
-#endif
-
 #include <asm/io.h>
 
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
@@ -71,17 +49,10 @@
 #include <video/fbcon-cfb32.h>
 #endif
 
-#include "osdef.h"
-#include "vgatypes.h"
-#include "vstruct.h"
-#include "sis_accel.h"
 #include "sis.h"
+#include "sis_accel.h"
 
-extern struct     video_info ivideo;
-extern VGA_ENGINE sisvga_engine;
-extern int sisfb_accel;
-
-static const int sisALUConv[] =
+static const u8 sisALUConv[] =
 {
     0x00,       /* dest = 0;            0,      GXclear,        0 */
     0x88,       /* dest &= src;         DSa,    GXand,          0x1 */
@@ -101,7 +72,7 @@
     0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
 };
 /* same ROP but with Pattern as Source */
-static const int sisPatALUConv[] =
+static const u8 sisPatALUConv[] =
 {
     0x00,       /* dest = 0;            0,      GXclear,        0 */
     0xA0,       /* dest &= src;         DPa,    GXand,          0x1 */
@@ -122,26 +93,26 @@
 };
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
-static const unsigned char myrops[] = {
+static const int myrops[] = {
    	3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
-   };
+};
 #endif
 
 /* 300 series ----------------------------------------------------- */
 #ifdef CONFIG_FB_SIS_300
 static void
-SiS300Sync(void)
+SiS300Sync(struct sis_video_info *ivideo)
 {
 	SiS300Idle
 }
 
 static void
-SiS300SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
-                                unsigned int planemask, int trans_color)
+SiS300SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int xdir, int ydir,
+                                 int rop, int trans_color)
 {
-	SiS300SetupDSTColorDepth(ivideo.DstColor);
-	SiS300SetupSRCPitch(ivideo.video_linelength)
-	SiS300SetupDSTRect(ivideo.video_linelength, -1)
+	SiS300SetupDSTColorDepth(ivideo->DstColor);
+	SiS300SetupSRCPitch(ivideo->video_linelength)
+	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
 
 	if(trans_color != -1) {
 		SiS300SetupROP(0x0A)
@@ -159,29 +130,28 @@
 }
 
 static void
-SiS300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
-                                int width, int height)
+SiS300SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x,
+				   int src_y, int dst_x, int dst_y, int width, int height)
 {
-	long srcbase, dstbase;
+	u32 srcbase = 0, dstbase = 0;
 
-	srcbase = dstbase = 0;
-	if (src_y >= 2048) {
-		srcbase = ivideo.video_linelength * src_y;
+	if(src_y >= 2048) {
+		srcbase = ivideo->video_linelength * src_y;
 		src_y = 0;
 	}
-	if (dst_y >= 2048) {
-		dstbase = ivideo.video_linelength * dst_y;
+	if(dst_y >= 2048) {
+		dstbase = ivideo->video_linelength * dst_y;
 		dst_y = 0;
 	}
 
 	SiS300SetupSRCBase(srcbase);
 	SiS300SetupDSTBase(dstbase);
 
-	if(!(ivideo.CommandReg & X_INC))  {
+	if(!(ivideo->CommandReg & X_INC))  {
 		src_x += width-1;
 		dst_x += width-1;
 	}
-	if(!(ivideo.CommandReg & Y_INC))  {
+	if(!(ivideo->CommandReg & Y_INC))  {
 		src_y += height-1;
 		dst_y += height-1;
 	}
@@ -192,23 +162,22 @@
 }
 
 static void
-SiS300SetupForSolidFill(int color, int rop, unsigned int planemask)
+SiS300SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
 {
 	SiS300SetupPATFG(color)
-	SiS300SetupDSTRect(ivideo.video_linelength, -1)
-	SiS300SetupDSTColorDepth(ivideo.DstColor);
+	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
+	SiS300SetupDSTColorDepth(ivideo->DstColor);
 	SiS300SetupROP(sisPatALUConv[rop])
 	SiS300SetupCMDFlag(PATFG)
 }
 
 static void
-SiS300SubsequentSolidFillRect(int x, int y, int w, int h)
+SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
 {
-	long dstbase;
+	u32 dstbase = 0;
 
-	dstbase = 0;
 	if(y >= 2048) {
-		dstbase = ivideo.video_linelength * y;
+		dstbase = ivideo->video_linelength * y;
 		y = 0;
 	}
 	SiS300SetupDSTBase(dstbase)
@@ -223,19 +192,18 @@
 
 #ifdef CONFIG_FB_SIS_315
 static void
-SiS310Sync(void)
+SiS310Sync(struct sis_video_info *ivideo)
 {
 	SiS310Idle
 }
 
 static void
-SiS310SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
-                                unsigned int planemask, int trans_color)
+SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int trans_color)
 {
-	SiS310SetupDSTColorDepth(ivideo.DstColor);
-	SiS310SetupSRCPitch(ivideo.video_linelength)
-	SiS310SetupDSTRect(ivideo.video_linelength, -1)
-	if (trans_color != -1) {
+	SiS310SetupDSTColorDepth(ivideo->DstColor);
+	SiS310SetupSRCPitch(ivideo->video_linelength)
+	SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+	if(trans_color != -1) {
 		SiS310SetupROP(0x0A)
 		SiS310SetupSRCTrans(trans_color)
 		SiS310SetupCMDFlag(TRANSPARENT_BITBLT)
@@ -244,20 +212,17 @@
 		/* Set command - not needed, both 0 */
 		/* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
 	}
-	SiS310SetupCMDFlag(ivideo.SiS310_AccelDepth)
+	SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth)
 	/* The 315 series is smart enough to know the direction */
 }
 
 static void
-SiS310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
-                                int width, int height)
+SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int src_y,
+			 int dst_x, int dst_y, int width, int height)
 {
-	long srcbase, dstbase;
-	int mymin, mymax;
-
-	srcbase = dstbase = 0;
-	mymin = min(src_y, dst_y);
-	mymax = max(src_y, dst_y);
+	u32 srcbase = 0, dstbase = 0;
+	int mymin = min(src_y, dst_y);
+	int mymax = max(src_y, dst_y);
 	
 	/* Although the chip knows the direction to use
 	 * if the source and destination areas overlap, 
@@ -271,18 +236,18 @@
 	 */
 	if((mymax - mymin) < height) { 
 	   if((src_y >= 2048) || (dst_y >= 2048)) {	      
-	      srcbase = ivideo.video_linelength * mymin;
-	      dstbase = ivideo.video_linelength * mymin;
+	      srcbase = ivideo->video_linelength * mymin;
+	      dstbase = ivideo->video_linelength * mymin;
 	      src_y -= mymin;
 	      dst_y -= mymin;
 	   }
 	} else {
 	   if(src_y >= 2048) {
-	      srcbase = ivideo.video_linelength * src_y;
+	      srcbase = ivideo->video_linelength * src_y;
 	      src_y = 0;
 	   }
 	   if(dst_y >= 2048) {
-	      dstbase = ivideo.video_linelength * dst_y;
+	      dstbase = ivideo->video_linelength * dst_y;
 	      dst_y = 0;
 	   }
 	}
@@ -296,23 +261,22 @@
 }
 
 static void
-SiS310SetupForSolidFill(int color, int rop, unsigned int planemask)
+SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
 {
 	SiS310SetupPATFG(color)
-	SiS310SetupDSTRect(ivideo.video_linelength, -1)
-	SiS310SetupDSTColorDepth(ivideo.DstColor);
+	SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+	SiS310SetupDSTColorDepth(ivideo->DstColor);
 	SiS310SetupROP(sisPatALUConv[rop])
-	SiS310SetupCMDFlag(PATFG | ivideo.SiS310_AccelDepth)
+	SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth)
 }
 
 static void
-SiS310SubsequentSolidFillRect(int x, int y, int w, int h)
+SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
 {
-	long dstbase;
+	u32 dstbase = 0;
 
-	dstbase = 0;
 	if(y >= 2048) {
-		dstbase = ivideo.video_linelength * y;
+		dstbase = ivideo->video_linelength * y;
 		y = 0;
 	}
 	SiS310SetupDSTBase(dstbase)
@@ -327,23 +291,23 @@
 
 /* The exported routines */
 
-int sisfb_initaccel(void)
+int sisfb_initaccel(struct sis_video_info *ivideo)
 {
 #ifdef SISFB_USE_SPINLOCKS
-    spin_lock_init(&ivideo.lockaccel);
+    spin_lock_init(&ivideo->lockaccel);
 #endif
     return(0);
 }
 
-void sisfb_syncaccel(void)
+void sisfb_syncaccel(struct sis_video_info *ivideo)
 {
-    if(sisvga_engine == SIS_300_VGA) {
+    if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-    	SiS300Sync();
+    	SiS300Sync(ivideo);
 #endif
     } else {
 #ifdef CONFIG_FB_SIS_315
-    	SiS310Sync();
+    	SiS310Sync(ivideo);
 #endif
     }
 }
@@ -352,18 +316,19 @@
 
 int fbcon_sis_sync(struct fb_info *info)
 {
+   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
    CRITFLAGS
 
-   if(!ivideo.accel)
+   if(!ivideo->accel)
    	return 0;
 
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-      SiS300Sync();
+      SiS300Sync(ivideo);
 #endif
    } else {
 #ifdef CONFIG_FB_SIS_315
-      SiS310Sync();
+      SiS310Sync(ivideo);
 #endif
    }
    CRITEND
@@ -372,42 +337,53 @@
 
 void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-   int col=0;
+   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+   u32 col = 0;
+   u32 vxres = info->var.xres_virtual;
+   u32 vyres = info->var.yres_virtual;
+   int width, height;
    CRITFLAGS
 
-   TWDEBUG("Inside sis_fillrect");
-   if(!rect->width || !rect->height)
-   	return;
+   if(info->state != FBINFO_STATE_RUNNING) {
+	return;
+   }
 
-   if(!ivideo.accel) {
+   if(!ivideo->accel) {
 	cfb_fillrect(info, rect);
 	return;
    }
    
+   if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) {
+	return;
+   }
+
+   /* Clipping */
+   width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
+   height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
+
    switch(info->var.bits_per_pixel) {
 	case 8:  col = rect->color;
 		 break;
-	case 16: col = ((u32 *)(info->pseudo_palette))[rect->color];
-		 break;
+	case 16:
 	case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
 		 break;
    }
 
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
       CRITBEGIN
-      SiS300SetupForSolidFill(col, myrops[rect->rop], 0);
-      SiS300SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
+      SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+      SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
       CRITEND
-      SiS300Sync();
+      SiS300Sync(ivideo);
 #endif
    } else {
 #ifdef CONFIG_FB_SIS_315
       CRITBEGIN
-      SiS310SetupForSolidFill(col, myrops[rect->rop], 0);
-      SiS310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
+      SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+      SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
       CRITEND
-      SiS310Sync();
+      SiS310Sync(ivideo);
 #endif
    }
 
@@ -415,38 +391,58 @@
 
 void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
-   int xdir, ydir;
+   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+   u32 vxres = info->var.xres_virtual;
+   u32 vyres = info->var.yres_virtual;
+   int width = area->width;
+   int height = area->height;
    CRITFLAGS
 
-   TWDEBUG("Inside sis_copyarea");
-   if(!ivideo.accel) {
+   if(info->state != FBINFO_STATE_RUNNING) {
+	return;
+   }
+
+   if(!ivideo->accel) {
    	cfb_copyarea(info, area);
 	return;
    }
 
-   if(!area->width || !area->height)
+   if(!width || !height ||
+      area->sx >= vxres || area->sy >= vyres ||
+      area->dx >= vxres || area->dy >= vyres) {
    	return;
+   }
 
-   if(area->sx < area->dx) xdir = 0;
-   else                    xdir = 1;
-   if(area->sy < area->dy) ydir = 0;
-   else                    ydir = 1;
+   /* Clipping */
+   if((area->sx + width) > vxres) width = vxres - area->sx;
+   if((area->dx + width) > vxres) width = vxres - area->dx;
+   if((area->sy + height) > vyres) height = vyres - area->sy;
+   if((area->dy + height) > vyres) height = vyres - area->dy;
 
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
+      int xdir, ydir;
+
+      if(area->sx < area->dx) xdir = 0;
+      else                    xdir = 1;
+      if(area->sy < area->dy) ydir = 0;
+      else                    ydir = 1;
+
       CRITBEGIN
-      SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-      SiS300SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
+      SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+      SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
+      					 width, height);
       CRITEND
-      SiS300Sync();
+      SiS300Sync(ivideo);
 #endif
    } else {
 #ifdef CONFIG_FB_SIS_315
       CRITBEGIN
-      SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-      SiS310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
+      SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+      SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
+      					 width, height);
       CRITEND
-      SiS310Sync();
+      SiS310Sync(ivideo);
 #endif
    }
 }
@@ -458,11 +454,12 @@
 void fbcon_sis_bmove(struct display *p, int srcy, int srcx,
 			    int dsty, int dstx, int height, int width)
 {
-        int xdir, ydir;
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
+
 	CRITFLAGS
 
-	if(!ivideo.accel) {
-	    switch(ivideo.video_bpp) {
+	if(!ivideo->accel) {
+	    switch(ivideo->video_bpp) {
 	    case 8:
 #ifdef FBCON_HAS_CFB8
 	       fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
@@ -489,30 +486,28 @@
 	width *= fontwidth(p);
 	height *= fontheight(p);
 
-	if(srcx < dstx) xdir = 0;
-	else            xdir = 1;
-	if(srcy < dsty) ydir = 0;
-	else            ydir = 1;
-
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
+	   int xdir, ydir;
+
+	   if(srcx < dstx) xdir = 0;
+	   else            xdir = 1;
+	   if(srcy < dsty) ydir = 0;
+	   else            ydir = 1;
+
 	   CRITBEGIN
-	   SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-	   SiS300SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
+	   SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+	   SiS300SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
 	   CRITEND
-	   SiS300Sync();
+	   SiS300Sync(ivideo);
 #endif
 	} else {
 #ifdef CONFIG_FB_SIS_315
 	   CRITBEGIN
-	   SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-	   SiS310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
+	   SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+	   SiS310SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
 	   CRITEND
-	   SiS310Sync();
-#if 0
-	   printk(KERN_INFO "sis_bmove sx %d sy %d dx %d dy %d w %d h %d\n",
-		srcx, srcy, dstx, dsty, width, height);
-#endif
+	   SiS310Sync(ivideo);
 #endif
 	}
 }
@@ -520,6 +515,7 @@
 static void fbcon_sis_clear(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width, int color)
 {
+        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	CRITFLAGS
 
 	srcx *= fontwidth(p);
@@ -527,21 +523,21 @@
 	width *= fontwidth(p);
 	height *= fontheight(p);
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
-	   SiS300SetupForSolidFill(color, 3, 0);
-	   SiS300SubsequentSolidFillRect(srcx, srcy, width, height);
+	   SiS300SetupForSolidFill(ivideo, color, 3);
+	   SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
 	   CRITEND
-	   SiS300Sync();
+	   SiS300Sync(ivideo);
 #endif
 	} else {
 #ifdef CONFIG_FB_SIS_315
 	   CRITBEGIN
-	   SiS310SetupForSolidFill(color, 3, 0);
-	   SiS310SubsequentSolidFillRect(srcx, srcy, width, height);
+	   SiS310SetupForSolidFill(ivideo, color, 3);
+	   SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
 	   CRITEND
-	   SiS310Sync();
+	   SiS310Sync(ivideo);
 #endif
 	}
 }
@@ -549,9 +545,10 @@
 void fbcon_sis_clear8(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	u32 bgx;
 
-	if(!ivideo.accel) {
+	if(!ivideo->accel) {
 #ifdef FBCON_HAS_CFB8
 	    fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
 #endif
@@ -565,8 +562,10 @@
 void fbcon_sis_clear16(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width)
 {
+        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	u32 bgx;
-	if(!ivideo.accel) {
+
+	if(!ivideo->accel) {
 #ifdef FBCON_HAS_CFB16
 	    fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
 #endif
@@ -580,9 +579,10 @@
 void fbcon_sis_clear32(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	u32 bgx;
 
-	if(!ivideo.accel) {
+	if(!ivideo->accel) {
 #ifdef FBCON_HAS_CFB32
 	    fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
 #endif
@@ -595,10 +595,11 @@
 
 void fbcon_sis_revc(struct display *p, int srcx, int srcy)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	CRITFLAGS
 
-	if(!ivideo.accel) {
-	    switch(ivideo.video_bpp) {
+	if(!ivideo->accel) {
+	    switch(ivideo->video_bpp) {
 	    case 16:
 #ifdef FBCON_HAS_CFB16
 	       fbcon_cfb16_revc(p, srcx, srcy);
@@ -616,59 +617,59 @@
 	srcx *= fontwidth(p);
 	srcy *= fontheight(p);
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
-	   SiS300SetupForSolidFill(0, 0x0a, 0);
-	   SiS300SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
+	   SiS300SetupForSolidFill(ivideo, 0, 0x0a);
+	   SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
 	   CRITEND
-	   SiS300Sync();
+	   SiS300Sync(ivideo);
 #endif
 	} else {
 #ifdef CONFIG_FB_SIS_315
 	   CRITBEGIN
-	   SiS310SetupForSolidFill(0, 0x0a, 0);
-	   SiS310SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
+	   SiS310SetupForSolidFill(ivideo, 0, 0x0a);
+	   SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
 	   CRITEND
-	   SiS310Sync();
+	   SiS310Sync(ivideo);
 #endif
 	}
 }
 
 #ifdef FBCON_HAS_CFB8
 struct display_switch fbcon_sis8 = {
-	.setup			= fbcon_cfb8_setup,
-	.bmove			= fbcon_sis_bmove,
-	.clear			= fbcon_sis_clear8,
-	.putc			= fbcon_cfb8_putc,
-	.putcs			= fbcon_cfb8_putcs,
-	.revc			= fbcon_cfb8_revc,
-	.clear_margins		= fbcon_cfb8_clear_margins,
-	.fontwidthmask		= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+	.setup		= fbcon_cfb8_setup,
+	.bmove		= fbcon_sis_bmove,
+	.clear		= fbcon_sis_clear8,
+	.putc		= fbcon_cfb8_putc,
+	.putcs		= fbcon_cfb8_putcs,
+	.revc		= fbcon_cfb8_revc,
+	.clear_margins	= fbcon_cfb8_clear_margins,
+	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 #ifdef FBCON_HAS_CFB16
 struct display_switch fbcon_sis16 = {
-	.setup			= fbcon_cfb16_setup,
-	.bmove			= fbcon_sis_bmove,
-	.clear			= fbcon_sis_clear16,
-	.putc			= fbcon_cfb16_putc,
-	.putcs			= fbcon_cfb16_putcs,
-	.revc			= fbcon_sis_revc,
-	.clear_margins		= fbcon_cfb16_clear_margins,
-	.fontwidthmask		= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+	.setup		= fbcon_cfb16_setup,
+	.bmove		= fbcon_sis_bmove,
+	.clear		= fbcon_sis_clear16,
+	.putc		= fbcon_cfb16_putc,
+	.putcs		= fbcon_cfb16_putcs,
+	.revc		= fbcon_sis_revc,
+	.clear_margins	= fbcon_cfb16_clear_margins,
+	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 #ifdef FBCON_HAS_CFB32
 struct display_switch fbcon_sis32 = {
-	.setup			= fbcon_cfb32_setup,
-	.bmove			= fbcon_sis_bmove,
-	.clear			= fbcon_sis_clear32,
-	.putc			= fbcon_cfb32_putc,
-	.putcs			= fbcon_cfb32_putcs,
-	.revc			= fbcon_sis_revc,
-	.clear_margins		= fbcon_cfb32_clear_margins,
-	.fontwidthmask		= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+	.setup		= fbcon_cfb32_setup,
+	.bmove		= fbcon_sis_bmove,
+	.clear		= fbcon_sis_clear32,
+	.putc		= fbcon_cfb32_putc,
+	.putcs		= fbcon_cfb32_putcs,
+	.revc		= fbcon_sis_revc,
+	.clear_margins	= fbcon_cfb32_clear_margins,
+	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 
diff -Nru a/drivers/video/sis/sis_accel.h b/drivers/video/sis/sis_accel.h
--- a/drivers/video/sis/sis_accel.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/sis/sis_accel.h	2004-06-23 19:04:26 -07:00
@@ -36,8 +36,8 @@
 
 #ifdef SISFB_USE_SPINLOCKS
 #include <linux/spinlock.h>
-#define CRITBEGIN  spin_lock_irqsave(&ivideo.lockaccel), critflags);
-#define CRITEND	   spin_unlock_irqrestore(&ivideo.lockaccel), critflags);
+#define CRITBEGIN  spin_lock_irqsave(&ivideo->lockaccel, critflags);
+#define CRITEND	   spin_unlock_irqrestore(&ivideo->lockaccel, critflags);
 #define CRITFLAGS  unsigned long critflags;
 #else
 #define CRITBEGIN
@@ -65,7 +65,6 @@
 #define A3D_FUNCTION		0x00000008  /* 3D command ? */
 #define	CLEAR_Z_BUFFER		0x00000009  /* ? */
 #define GRADIENT_FILL		0x0000000A  /* Gradient fill */
-#define STRETCH_BITBLT		0x0000000B  /* Stretched Blit */
 
 /* source select */
 #define SRCVIDEO                0x00000000  /* source is video RAM */
@@ -98,11 +97,6 @@
 #define DSTAGP                  0x02000000
 #define DSTVIDEO                0x02000000
 
-/* Line */
-#define LINE_STYLE              0x00800000
-#define NO_RESET_COUNTER        0x00400000
-#define NO_LAST_PIXEL           0x00200000
-
 /* Subfunctions for Color/Enhanced Color Expansion (315 only) */
 #define COLOR_TO_MONO		0x00100000
 #define AA_TEXT			0x00200000
@@ -134,212 +128,142 @@
 
 #define PATTERN_REG		0x8300  /* 384 bytes pattern buffer */
 
-/* Line registers */
-#define LINE_X0			SRC_Y
-#define LINE_X1			DST_Y
-#define LINE_Y0			SRC_X
-#define LINE_Y1			DST_X
-#define LINE_COUNT		RECT_WIDTH
-#define LINE_STYLE_PERIOD	RECT_HEIGHT
-#define LINE_STYLE_0		MONO_MASK
-#define LINE_STYLE_1		0x8230
-#define LINE_XN			PATTERN_REG
-#define LINE_YN			PATTERN_REG+2
-
 /* Transparent bitblit registers */
 #define TRANS_DST_KEY_HIGH	PAT_FGCOLOR
 #define TRANS_DST_KEY_LOW	PAT_BGCOLOR
 #define TRANS_SRC_KEY_HIGH	SRC_FGCOLOR
 #define TRANS_SRC_KEY_LOW	SRC_BGCOLOR
 
-/* Queue */
-#define Q_BASE_ADDR		0x85C0  /* Base address of software queue (?) */
-#define Q_WRITE_PTR		0x85C4  /* Current write pointer (?) */
-#define Q_READ_PTR		0x85C8  /* Current read pointer (?) */
-#define Q_STATUS		0x85CC  /* queue status */
-
-
-#define MMIO_IN8(base, offset) \
-	*(volatile u8 *)(((u8*)(base)) + (offset))
-#define MMIO_IN16(base, offset) \
-	*(volatile u16 *)(void *)(((u8*)(base)) + (offset))
-#define MMIO_IN32(base, offset) \
-	*(volatile u32 *)(void *)(((u8*)(base)) + (offset))
-#define MMIO_OUT8(base, offset, val) \
-	*(volatile u8 *)(((u8*)(base)) + (offset)) = (val)
-#define MMIO_OUT16(base, offset, val) \
-	*(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val)
-#define MMIO_OUT32(base, offset, val) \
-	*(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val)
+/* Store queue length in par */
+#define CmdQueLen ivideo->cmdqueuelength
 
 /* ------------- SiS 300 series -------------- */
 
-/* Macros to do useful things with the SIS BitBLT engine */
-
-/* BR(16) (0x8420):
+/* BR(16) (0x8240):
 
    bit 31 2D engine: 1 is idle,
    bit 30 3D engine: 1 is idle,
    bit 29 Command queue: 1 is empty
-
    bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0]
-
    bits 15:0:  Current command queue length
 
 */
 
-/* TW: BR(16)+2 = 0x8242 */
-
-int     CmdQueLen;
-
 #define SiS300Idle \
   { \
-  while( (MMIO_IN16(ivideo.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  while( (MMIO_IN16(ivideo.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  while( (MMIO_IN16(ivideo.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  CmdQueLen=MMIO_IN16(ivideo.mmio_vbase, 0x8240); \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	CmdQueLen = MMIO_IN16(ivideo->mmio_vbase, 0x8240); \
   }
-/* TW: (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
+/* (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
 
 #define SiS300SetupSRCBase(base) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(0), base);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(0), base);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCPitch(pitch) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(1), pitch);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, BR(1), pitch);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCXY(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(2), (x)<<16 | (y) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(2), (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS300SetupDSTBase(base) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(4), base);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(4), base);\
+	CmdQueLen--;
 
 #define SiS300SetupDSTXY(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(3), (x)<<16 | (y) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(3), (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS300SetupDSTRect(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(5), (y)<<16 | (x) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(5), (y)<<16 | (x) );\
+	CmdQueLen--;
 
 #define SiS300SetupDSTColorDepth(bpp) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(1)+2, bpp);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, BR(1)+2, bpp);\
+	CmdQueLen--;
 
 #define SiS300SetupRect(w,h) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(6), (h)<<16 | (w) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(6), (h)<<16 | (w) );\
+	CmdQueLen--;
 
 #define SiS300SetupPATFG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(7), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(7), color);\
+	CmdQueLen--;
 
 #define SiS300SetupPATBG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(8), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(8), color);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCFG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(9), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(9), color);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCBG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(10), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(10), color);\
+	CmdQueLen--;
 
 /* 0x8224 src colorkey high */
 /* 0x8228 src colorkey low */
 /* 0x821c dest colorkey high */
 /* 0x8220 dest colorkey low */
 #define SiS300SetupSRCTrans(color) \
-                if (CmdQueLen <= 1)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, 0x8224, color);\
-		MMIO_OUT32(ivideo.mmio_vbase, 0x8228, color);\
-		CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8224, color);\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8228, color);\
+	CmdQueLen -= 2;
 
 #define SiS300SetupDSTTrans(color) \
-		if (CmdQueLen <= 1)  SiS300Idle;\
-		MMIO_OUT32(ivideo.mmio_vbase, 0x821C, color); \
-		MMIO_OUT32(ivideo.mmio_vbase, 0x8220, color); \
-                CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x821C, color); \
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8220, color); \
+	CmdQueLen -= 2;
 
 #define SiS300SetupMONOPAT(p0,p1) \
-                if (CmdQueLen <= 1)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(11), p0);\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(12), p1);\
-                CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(11), p0);\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(12), p1);\
+	CmdQueLen -= 2;
 
 #define SiS300SetupClipLT(left,top) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
-                CmdQueLen--;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
+	CmdQueLen--;
 
 #define SiS300SetupClipRB(right,bottom) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
-                CmdQueLen--;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
+	CmdQueLen--;
 
 /* General */
 #define SiS300SetupROP(rop) \
-                ivideo.CommandReg = (rop) << 8;
+	ivideo->CommandReg = (rop) << 8;
 
 #define SiS300SetupCMDFlag(flags) \
-                ivideo.CommandReg |= (flags);
+	ivideo->CommandReg |= (flags);
 
 #define SiS300DoCMD \
-                if (CmdQueLen <= 1)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(15), ivideo.CommandReg); \
-                MMIO_OUT32(ivideo.mmio_vbase, BR(16), 0);\
-                CmdQueLen -= 2;
-
-/* Line */
-#define SiS300SetupX0Y0(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(2), (y)<<16 | (x) );\
-                CmdQueLen--;
-
-#define SiS300SetupX1Y1(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(3), (y)<<16 | (x) );\
-                CmdQueLen--;
-
-#define SiS300SetupLineCount(c) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(6), c);\
-                CmdQueLen--;
-
-#define SiS300SetupStylePeriod(p) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(6)+2, p);\
-                CmdQueLen--;
-
-#define SiS300SetupStyleLow(ls) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(11), ls);\
-                CmdQueLen--;
-
-#define SiS300SetupStyleHigh(ls) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(12), ls);\
-                CmdQueLen--;
-
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(15), ivideo->CommandReg); \
+	MMIO_OUT32(ivideo->mmio_vbase, BR(16), 0);\
+	CmdQueLen -= 2;
 
-
-/* -------------- SiS 315 series --------------- */
+/* -------------- SiS 315/330 series --------------- */
 
 /* Q_STATUS:
    bit 31 = 1: All engines idle and all queues empty
@@ -353,179 +277,131 @@
    bits 23:16: 2D counter 3
    bits 15:8:  2D counter 2
    bits 7:0:   2D counter 1
-
-   Where is the command queue length (current amount of commands the queue
-   can accept) on the 315 series?
 */
 
-/* TW: FIXME: CmdQueLen is... where....? */
-/* We assume a length of 4 bytes per command; since 512K of
- * of RAM are allocated, the number of commands is easily
- * calculated (assuming that there is no 3D support yet)
- * We calculate it very cautiously (128K only) and let the
- * rest to the (never?)-to-come (?) 3D engine. (The 3D engine
- * can use a similar technique, using the remaining 384K,
- * hence a queue overflow is avoided)
- * UPDATE: This technique causes a terrible system latency
- * on integrated chipsets. Disable the queue handling for
- * now.
- */
 #define SiS310Idle \
   { \
-  while( (MMIO_IN16(ivideo.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-  while( (MMIO_IN16(ivideo.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-  CmdQueLen = 0; \
-  /*CmdQueLen = ((128 * 1024) / 4) - 64; */ \
+  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  	CmdQueLen = 0; \
   }
 
 #define SiS310SetupSRCBase(base) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_ADDR, base);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_ADDR, base);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCPitch(pitch) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, SRC_PITCH, pitch);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, SRC_PITCH, pitch);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCXY(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_Y, (x)<<16 | (y) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_Y, (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS310SetupDSTBase(base) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, DST_ADDR, base);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_ADDR, base);\
+	CmdQueLen--;
 
 #define SiS310SetupDSTXY(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, DST_Y, (x)<<16 | (y) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_Y, (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS310SetupDSTRect(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
+	CmdQueLen--;
 
 #define SiS310SetupDSTColorDepth(bpp) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, AGP_BASE, bpp);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, AGP_BASE, bpp);\
+	CmdQueLen--;
 
 #define SiS310SetupRect(w,h) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
+	CmdQueLen--;
 
 #define SiS310SetupPATFG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, PAT_FGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, PAT_FGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupPATBG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, PAT_BGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, PAT_BGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCFG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_FGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_FGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCBG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_BGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_BGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCTrans(color) \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_SRC_KEY_LOW, color);\
-      CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_LOW, color);\
+	CmdQueLen -= 2;
 
 #define SiS310SetupDSTTrans(color) \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_DST_KEY_HIGH, color); \
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_DST_KEY_LOW, color); \
-      CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_HIGH, color); \
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_LOW, color); \
+	CmdQueLen -= 2;
 
 #define SiS310SetupMONOPAT(p0,p1) \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, MONO_MASK, p0);\
-      MMIO_OUT32(ivideo.mmio_vbase, MONO_MASK+4, p1);\
-      CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK, p0);\
+	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK+4, p1);\
+	CmdQueLen -= 2;
 
 #define SiS310SetupClipLT(left,top) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
+	CmdQueLen--;
 
 #define SiS310SetupClipRB(right,bottom) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
+	CmdQueLen--;
 
 #define SiS310SetupROP(rop) \
-      ivideo.CommandReg = (rop) << 8;
+	ivideo->CommandReg = (rop) << 8;
 
 #define SiS310SetupCMDFlag(flags) \
-      ivideo.CommandReg |= (flags);
+	ivideo->CommandReg |= (flags);
 
 #define SiS310DoCMD \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, COMMAND_READY, ivideo.CommandReg); \
-      MMIO_OUT32(ivideo.mmio_vbase, FIRE_TRIGGER, 0); \
-      CmdQueLen -= 2;
-
-#define SiS310SetupX0Y0(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_X0, (y)<<16 | (x) );\
-      CmdQueLen--;
-
-#define SiS310SetupX1Y1(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_X1, (y)<<16 | (x) );\
-      CmdQueLen--;
-
-#define SiS310SetupLineCount(c) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, LINE_COUNT, c);\
-      CmdQueLen--;
-
-#define SiS310SetupStylePeriod(p) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, LINE_STYLE_PERIOD, p);\
-      CmdQueLen--;
-
-#define SiS310SetupStyleLow(ls) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_STYLE_0, ls);\
-      CmdQueLen--;
-
-#define SiS310SetupStyleHigh(ls) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_STYLE_1, ls);\
-      CmdQueLen--;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, COMMAND_READY, ivideo->CommandReg); \
+	MMIO_OUT32(ivideo->mmio_vbase, FIRE_TRIGGER, 0); \
+	CmdQueLen -= 2;
 
-int  sisfb_initaccel(void);
-void sisfb_syncaccel(void);
 
-extern struct video_info ivideo;
+int  sisfb_initaccel(struct sis_video_info *ivideo);
+void sisfb_syncaccel(struct sis_video_info *ivideo);
 
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
 void fbcon_sis_bmove(struct display *p, int srcy, int srcx, int dsty,
-                     int dstx, int height, int width);
+			int dstx, int height, int width);
 void fbcon_sis_revc(struct display *p, int srcy, int srcx);
 void fbcon_sis_clear8(struct vc_data *conp, struct display *p, int srcy,
-                      int srcx, int height, int width);
+			int srcx, int height, int width);
 void fbcon_sis_clear16(struct vc_data *conp, struct display *p, int srcy,
-                       int srcx, int height, int width);
+			int srcx, int height, int width);
 void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy,
-                       int srcx, int height, int width);
+			int srcx, int height, int width);
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
-extern int sisfb_accel;
 void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
 void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area);
 #endif
diff -Nru a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
--- a/drivers/video/sis/sis_main.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/sis/sis_main.c	2004-06-23 19:04:27 -07:00
@@ -1,6 +1,7 @@
 /*
- * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/M741/330/760
- * frame buffer driver for Linux kernels 2.4.x and 2.5.x
+ * SiS 300/305/540/630(S)/730(S)
+ * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
  *
  * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
  *
@@ -20,8 +21,8 @@
  *
  * Author:   	Thomas Winischhofer <thomas@winischhofer.net>
  *
- * Author of code base:
- *		SiS (www.sis.com.tw)
+ * Author of (practically wiped) code base:
+ *		SiS (www.sis.com)
  *	 	Copyright (C) 1999 Silicon Integrated Systems, Inc.
  *
  * See http://www.winischhofer.net/ for more information and updates
@@ -34,7 +35,11 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <linux/moduleparam.h>
+#endif
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -47,28 +52,12 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 #include <linux/vmalloc.h>
-#endif
 #include <linux/vt_kern.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/agp_backend.h>
 #include <linux/types.h>
 #include <asm/uaccess.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#include <linux/spinlock.h>
-#endif
-
-#include "osdef.h"
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#include <video/sisfb.h>
-#else
-#include <linux/sisfb.h>
-#endif
-
 #include <asm/io.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
@@ -82,32 +71,16 @@
 #include <video/fbcon-cfb32.h>
 #endif
 
-#include "vgatypes.h"
-#include "sis_main.h"
 #include "sis.h"
+#include "sis_main.h"
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#error "This version of sisfb requires at least 2.6.0"
-#else
-#if 0
-#define NEWFBDEV		/* Define this as soon as new fvdev code has been merged */
-#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3)
+#error "This version of sisfb requires at least 2.6.3"
 #endif
 #endif
 
-/* -------------------- Macro definitions ---------------------------- */
-
-#undef SISFBDEBUG 	/* TW: no debugging */
-
-#ifdef SISFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#ifdef SISFBACCEL
 #ifdef FBCON_HAS_CFB8
 extern struct display_switch fbcon_sis8;
 #endif
@@ -118,174 +91,289 @@
 extern struct display_switch fbcon_sis32;
 #endif
 #endif
-#endif
 
-/* --------------- Hardware Access Routines -------------------------- */
+/* ------------------ Internal helper routines ----------------- */
 
-void sisfb_set_reg4(u16 port, unsigned long data)
+static void __init
+sisfb_setdefaultparms(void)
 {
-	outl((u32) (data & 0xffffffff), port);
+	sisfb_off 		= 0;
+	sisfb_parm_mem 		= 0;
+	sisfb_accel 		= -1;
+	sisfb_ypan      	= -1;
+	sisfb_max 		= -1;
+	sisfb_userom    	= -1;
+        sisfb_useoem    	= -1;
+#ifdef MODULE
+	/* Module: "None" for 2.4, default mode for 2.5+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	sisfb_mode_idx 		= -1;
+#else
+	sisfb_mode_idx  	= MODE_INDEX_NONE;
+#endif
+#else
+	/* Static: Default mode */
+	sisfb_mode_idx  	= -1;
+#endif
+	sisfb_parm_rate 	= -1;
+	sisfb_crt1off 		= 0;
+	sisfb_forcecrt1 	= -1;
+	sisfb_crt2type  	= -1;
+	sisfb_crt2flags 	= 0;
+	sisfb_pdc 		= 0xff;
+	sisfb_pdca 		= 0xff;
+	sisfb_scalelcd  	= -1;
+	sisfb_specialtiming 	= CUT_NONE;
+	sisfb_lvdshl 		= -1;
+	sisfb_dstn     		= 0;
+	sisfb_fstn 		= 0;
+	sisfb_tvplug    	= -1;
+	sisfb_tvstd     	= -1;
+	sisfb_tvxposoffset 	= 0;
+	sisfb_tvyposoffset 	= 0;
+	sisfb_filter 		= -1;
+	sisfb_nocrt2rate 	= 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	sisfb_inverse   	= 0;
+	sisfb_fontname[0] 	= 0;
+#endif
+#if !defined(__i386__) && !defined(__x86_64__)
+	sisfb_resetcard 	= 0;
+	sisfb_videoram  	= 0;
+#endif
 }
 
-u32 sisfb_get_reg3(u16 port)
+static void __init
+sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
 {
-	u32 data;
+	int i = 0, j = 0;
 
-	data = inl(port);
-	return (data);
-}
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(vesamode == 0) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+		sisfb_mode_idx = MODE_INDEX_NONE;
+#else
+		if(!quiet) {
+		   printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
+		}
+		sisfb_mode_idx = DEFAULT_MODE;
+#endif
+		return;
+	}
 
-/* ------------ Interface for init & mode switching code ------------- */
+	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
 
-BOOLEAN
-sisfb_query_VGA_config_space(PSIS_HW_INFO psishw_ext,
-	unsigned long offset, unsigned long set, unsigned long *value)
+	while(sisbios_mode[i++].mode_no[0] != 0) {
+		if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
+		    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
+		    if(sisfb_fstn) {
+		       if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+		          sisbios_mode[i-1].mode_no[1] == 0x56 ||
+		          sisbios_mode[i-1].mode_no[1] == 0x53) continue;
+	            } else {
+		       if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+		          sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
+		    }
+		    sisfb_mode_idx = i - 1;
+		    j = 1;
+		    break;
+		}
+	}
+	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
+}
+
+static void
+sisfb_search_mode(char *name, BOOLEAN quiet)
 {
-	static struct pci_dev *pdev = NULL;
-	static unsigned char init = 0, valid_pdev = 0;
+	int i = 0;
+	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
+	char strbuf[16], strbuf1[20];
+	char *nameptr = name;
 
-	if (!set)
-		DPRINTK("sisfb: Get VGA offset 0x%lx\n", offset);
-	else
-		DPRINTK("sisfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
 
-	if (!init) {
-		init = TRUE;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-		pci_for_each_dev(pdev) {
-#else
-		while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-			DPRINTK("sisfb: Current: 0x%x, target: 0x%x\n",
-			         pdev->device, ivideo.chip_id);
-			if ((pdev->vendor == PCI_VENDOR_ID_SI)
-			           && (pdev->device == ivideo.chip_id)) {
-				valid_pdev = TRUE;
-				break;
-			}
-		}
+	if(name == NULL) {
+	   if(!quiet) {
+	      printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
+	   }
+	   sisfb_mode_idx = DEFAULT_MODE;
+	   return;
 	}
 
-	if (!valid_pdev) {
-		printk(KERN_DEBUG "sisfb: Can't find SiS %d VGA device.\n",
-				ivideo.chip_id);
-		return FALSE;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+        if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
+	   if(!quiet) {
+	      printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
+	   }
+	   sisfb_mode_idx = DEFAULT_MODE;
+	   return;
 	}
+#endif
+	if(strlen(name) <= 19) {
+	   strcpy(strbuf1, name);
+	   for(i=0; i<strlen(strbuf1); i++) {
+	      if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
+	   }
 
-	if (set == 0)
-		pci_read_config_dword(pdev, offset, (u32 *)value);
-	else
-		pci_write_config_dword(pdev, offset, (u32)(*value));
+	   /* This does some fuzzy mode naming detection */
+	   if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
+	      if((rate <= 32) || (depth > 32)) {
+	         j = rate; rate = depth; depth = j;
+	      }
+	      sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+	      nameptr = strbuf;
+	      sisfb_parm_rate = rate;
+	   } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
+	      sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+	      nameptr = strbuf;
+	   } else {
+	      xres = 0;
+	      if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
+	         sprintf(strbuf, "%ux%ux8", xres, yres);
+	         nameptr = strbuf;
+	      } else {
+	         sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
+	         return;
+	      }
+	   }
+	}
 
-	return TRUE;
+	i = 0; j = 0;
+	while(sisbios_mode[i].mode_no[0] != 0) {
+		if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
+		   	if(sisfb_fstn) {
+		      		if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+		         	   sisbios_mode[i-1].mode_no[1] == 0x56 ||
+		         	   sisbios_mode[i-1].mode_no[1] == 0x53) continue;
+	           	} else {
+		      		if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+		         	   sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
+		   	}
+		   	sisfb_mode_idx = i - 1;
+		   	j = 1;
+		   	break;
+		}
+	}
+	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
 }
 
-BOOLEAN sisfb_query_north_bridge_space(PSIS_HW_INFO psishw_ext,
-	unsigned long offset, unsigned long set, unsigned long *value)
+#ifndef MODULE
+static void __devinit
+sisfb_get_vga_mode_from_kernel(void)
 {
-	static struct pci_dev *pdev = NULL;
-	static unsigned char init = 0, valid_pdev = 0;
-	u16 nbridge_id = 0;
-
-	if (!init) {
-		init = TRUE;
-		switch (ivideo.chip) {
-#ifdef CONFIG_FB_SIS_300
-		case SIS_540:
-			nbridge_id = PCI_DEVICE_ID_SI_540;
-			break;
-		case SIS_630:
-			nbridge_id = PCI_DEVICE_ID_SI_630;
-			break;
-		case SIS_730:
-			nbridge_id = PCI_DEVICE_ID_SI_730;
-			break;
+#if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT)
+   	char mymode[32];
+	int  mydepth = screen_info.lfb_depth;
+
+	if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
+
+	if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
+	    (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
+	    (mydepth >= 8) && (mydepth <= 32) ) {
+
+	    if(mydepth == 24) mydepth = 32;
+
+	    sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
+	    				screen_info.lfb_height,
+					mydepth);
+
+	    printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode);
+
+	    sisfb_search_mode(mymode, TRUE);
+	}
 #endif
-#ifdef CONFIG_FB_SIS_315
-		case SIS_550:
-			nbridge_id = PCI_DEVICE_ID_SI_550;
-			break;
-		case SIS_650:
-			nbridge_id = PCI_DEVICE_ID_SI_650;
-			break;
-		case SIS_740:
-			nbridge_id = PCI_DEVICE_ID_SI_740;
-			break;
-		case SIS_661:
-			nbridge_id = PCI_DEVICE_ID_SI_660;
-			break;
-		case SIS_741:
-			nbridge_id = PCI_DEVICE_ID_SI_741;
-			break;
-		case SIS_660:
-			nbridge_id = PCI_DEVICE_ID_SI_660;
-			break;
-		case SIS_760:
-			nbridge_id = PCI_DEVICE_ID_SI_760;
-			break;
+	return;
+}
 #endif
-		default:
-			nbridge_id = 0;
-			break;
-		}
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-		pci_for_each_dev(pdev) {
-#else
-		while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-			DPRINTK("Current: 0x%x, target: 0x%x\n",
-					pdev->device, ivideo.chip_id);
-			if ((pdev->vendor == PCI_VENDOR_ID_SI)
-					&& (pdev->device == nbridge_id)) {
-				valid_pdev = TRUE;
-				break;
-			}
-		}
-	}
+static void __init
+sisfb_search_crt2type(const char *name)
+{
+	int i = 0;
+
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
 
-	if (!valid_pdev) {
-		printk(KERN_DEBUG "sisfb: Can't find SiS %d North Bridge device.\n",
-				nbridge_id);
-		return FALSE;
+	if(name == NULL) return;
+
+	while(sis_crt2type[i].type_no != -1) {
+	   	if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+	      		sisfb_crt2type = sis_crt2type[i].type_no;
+	      		sisfb_tvplug = sis_crt2type[i].tvplug_no;
+	      		sisfb_crt2flags = sis_crt2type[i].flags;
+	      		break;
+	   	}
+	   	i++;
 	}
 
-	if (set == 0)
-		pci_read_config_dword(pdev, offset, (u32 *)value);
-	else
-		pci_write_config_dword(pdev, offset, (u32)(*value));
+	sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
+	sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
 
-	return TRUE;
+	if(sisfb_crt2type < 0) {
+		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
+	}
 }
 
-/* ------------------ Internal helper routines ----------------- */
-
-static BOOLEAN sisfb_verify_rate(struct sisfb_monitor *monitor, int mode_idx, int rate_idx, int rate)
+static void __init
+sisfb_search_tvstd(const char *name)
 {
-	int htotal, vtotal;
-	unsigned int dclock, hsync;
+	int i = 0;
 
-	if(!monitor->datavalid) return TRUE;
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
 
-	if(mode_idx < 0) return FALSE;
+	if(name == NULL) return;
 
-	if(rate < (monitor->vmin - 1)) return FALSE;
-	if(rate > (monitor->vmax + 1)) return FALSE;
-
-	if(sisfb_gettotalfrommode(&SiS_Pr, &sishw_ext, sisbios_mode[mode_idx].mode_no,
-	                          &htotal, &vtotal, rate_idx)) {
-		dclock = (htotal * vtotal * rate) / 1000;
-		if(dclock > (monitor->dclockmax + 1000)) return FALSE;
-		hsync = dclock / htotal;
-		if(hsync < (monitor->hmin - 1)) return FALSE;
-		if(hsync > (monitor->hmax + 1)) return FALSE;
-        } else {
-	  	return FALSE;
+	while(sis_tvtype[i].type_no != -1) {
+	   	if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+	      		sisfb_tvstd = sis_tvtype[i].type_no;
+	      		break;
+	   	}
+	   	i++;
 	}
-	return TRUE;
-};
+}
+
+static void __init
+sisfb_search_specialtiming(const char *name)
+{
+	int i = 0;
+	BOOLEAN found = FALSE;
+
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) return;
+
+	if(!strnicmp(name, "none", 4)) {
+	        sisfb_specialtiming = CUT_FORCENONE;
+		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
+	} else {
+	   while(mycustomttable[i].chipID != 0) {
+	      if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
+		 sisfb_specialtiming = mycustomttable[i].SpecialID;
+		 found = TRUE;
+		 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
+		 	mycustomttable[i].vendorName, mycustomttable[i].cardName,
+		 	mycustomttable[i].optionName);
+		 break;
+	      }
+	      i++;
+	   }
+	   if(!found) {
+	      printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
+	      printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
+	      i = 0;
+	      while(mycustomttable[i].chipID != 0) {
+		 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
+		     mycustomttable[i].optionName,
+		     mycustomttable[i].vendorName,
+		     mycustomttable[i].cardName);
+		 i++;
+	      }
+           }
+ 	}
+}
 
-static BOOLEAN sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
+static BOOLEAN __devinit
+sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
 {
 	int i, j, xres, yres, refresh, index;
 	u32 emodes;
@@ -385,7 +473,8 @@
  	return(monitor->datavalid);
 }
 
-static void sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno)
+static void __devinit
+sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
 {
 	USHORT  temp, i, realcrtno = crtno;
    	u8      buffer[256];
@@ -393,14 +482,15 @@
 	monitor->datavalid = FALSE;
 
 	if(crtno) {
-       	   if(ivideo.vbflags & CRT2_LCD)      realcrtno = 1;
-      	   else if(ivideo.vbflags & CRT2_VGA) realcrtno = 2;
+       	   if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
+      	   else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
       	   else return;
    	}
 
-	if((sisfb_crt1off) && (!crtno)) return;
+	if((ivideo->sisfb_crt1off) && (!crtno)) return;
 
-    	temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine, realcrtno, 0, &buffer[0]);
+    	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+				realcrtno, 0, &buffer[0]);
    	if((!temp) || (temp == 0xffff)) {
       	   printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
 	   return;
@@ -415,7 +505,7 @@
       	   if(temp & 0x02) {
 	      i = 3;  /* Number of retrys */
 	      do {
-	    	 temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine,
+	    	 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
 				     realcrtno, 1, &buffer[0]);
 	      } while((temp) && i--);
               if(!temp) {
@@ -435,194 +525,117 @@
 	}
 }
 
-static void sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
+static BOOLEAN
+sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
+		int mode_idx, int rate_idx, int rate)
 {
-	int i = 0, j = 0;
-
-	if(vesamode == 0) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		sisfb_mode_idx = MODE_INDEX_NONE;
-#else
-		if(!quiet)
-		   printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
-		sisfb_mode_idx = DEFAULT_MODE;
-#endif
-		return;
-	}
-
-	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
-
-	while(sisbios_mode[i++].mode_no != 0) {
-		if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
-		    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
-		    if(sisfb_fstn) {
-		       if(sisbios_mode[i-1].mode_no == 0x50 ||
-		          sisbios_mode[i-1].mode_no == 0x56 ||
-		          sisbios_mode[i-1].mode_no == 0x53) continue;
-	            } else {
-		       if(sisbios_mode[i-1].mode_no == 0x5a ||
-		          sisbios_mode[i-1].mode_no == 0x5b) continue;
-		    }
-		    sisfb_mode_idx = i - 1;
-		    j = 1;
-		    break;
-		}
-	}
-	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
-}
+	int htotal, vtotal;
+	unsigned int dclock, hsync;
 
-static void sisfb_search_mode(char *name, BOOLEAN quiet)
-{
-	int i = 0;
-	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
-	char strbuf[16], strbuf1[20];
-	char *nameptr = name;
+	if(!monitor->datavalid) return TRUE;
 
-	if(name == NULL) {
-	   if(!quiet)
-	      printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
-	   sisfb_mode_idx = DEFAULT_MODE;
-	   return;
-	}
+	if(mode_idx < 0) return FALSE;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-        if (!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
-	   if(!quiet)
-	      printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
-	   sisfb_mode_idx = DEFAULT_MODE;
-	   return;
-	}
+	/* Skip for 320x200, 320x240, 640x400 */
+    	switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
+    	case 0x59:
+    	case 0x41:
+    	case 0x4f:
+    	case 0x50:
+    	case 0x56:
+    	case 0x53:
+    	case 0x2f:
+    	case 0x5d:
+    	case 0x5e:
+    		return TRUE;
+#ifdef CONFIG_FB_SIS_315
+	case 0x5a:
+	case 0x5b:
+		if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE;
 #endif
-	if(strlen(name) <= 19) {
-	   strcpy(strbuf1, name);
-	   for(i=0; i<strlen(strbuf1); i++) {
-	      if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
-	   }
+    	}
 
-	   /* This does some fuzzy mode naming detection */
-	   if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
-	      if((rate <= 32) || (depth > 32)) {
-	         j = rate; rate = depth; depth = j;
-	      }
-	      sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
-	      nameptr = strbuf;
-	      ivideo.refresh_rate = sisfb_parm_rate = rate;
-	   } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
-	      sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
-	      nameptr = strbuf;
-	   } else {
-	      xres = 0;
-	      if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
-	         sprintf(strbuf, "%ux%ux8", xres, yres);
-	         nameptr = strbuf;
-	      } else {
-	         sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
-	         return;
-	      }
-	   }
-	}
+	if(rate < (monitor->vmin - 1)) return FALSE;
+	if(rate > (monitor->vmax + 1)) return FALSE;
 
-	i = 0; j = 0;
-	while(sisbios_mode[i].mode_no != 0) {
-		if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
-		   if(sisfb_fstn) {
-		      if(sisbios_mode[i-1].mode_no == 0x50 ||
-		         sisbios_mode[i-1].mode_no == 0x56 ||
-		         sisbios_mode[i-1].mode_no == 0x53) continue;
-	           } else {
-		      if(sisbios_mode[i-1].mode_no == 0x5a ||
-		         sisbios_mode[i-1].mode_no == 0x5b) continue;
-		   }
-		   sisfb_mode_idx = i - 1;
-		   j = 1;
-		   break;
-		}
+	if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+				  sisbios_mode[mode_idx].mode_no[ivideo->mni],
+	                          &htotal, &vtotal, rate_idx)) {
+		dclock = (htotal * vtotal * rate) / 1000;
+		if(dclock > (monitor->dclockmax + 1000)) return FALSE;
+		hsync = dclock / htotal;
+		if(hsync < (monitor->hmin - 1)) return FALSE;
+		if(hsync > (monitor->hmax + 1)) return FALSE;
+        } else {
+	  	return FALSE;
 	}
-	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
-
+	return TRUE;
 }
 
-static int sisfb_validate_mode(int myindex, unsigned long vbflags)
+static int
+sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
 {
-   u16 xres, yres, myres;
+   u16 xres=0, yres, myres;
 
 #ifdef CONFIG_FB_SIS_300
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
       if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1);
    }
 #endif
 #ifdef CONFIG_FB_SIS_315
-   if(sisvga_engine == SIS_315_VGA) {
+   if(ivideo->sisvga_engine == SIS_315_VGA) {
       if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
    }
 #endif
 
    myres = sisbios_mode[myindex].yres;
 
-   switch (vbflags & VB_DISPTYPE_DISP2) {
+   switch(vbflags & VB_DISPTYPE_DISP2) {
+
      case CRT2_LCD:
-	switch (sishw_ext.ulCRT2LCDType) {
-	case LCD_640x480:  xres =  640; yres =  480;  break;
-	case LCD_800x600:  xres =  800; yres =  600;  break;
-        case LCD_1024x600: xres = 1024; yres =  600;  break;
-	case LCD_1024x768: xres = 1024; yres =  768;  break;
-	case LCD_1152x768: xres = 1152; yres =  768;  break;
-	case LCD_1280x960: xres = 1280; yres =  960;  break;
-	case LCD_1280x768: xres = 1280; yres =  768;  break;
-	case LCD_1280x1024:xres = 1280; yres = 1024;  break;
-	case LCD_1400x1050:xres = 1400; yres = 1050;  break;
-	case LCD_1600x1200:xres = 1600; yres = 1200;  break;
-	case LCD_320x480:  xres =  320; yres =  480;  break; /* FSTN (old) */
-	case LCD_640x480_2:
-	case LCD_640x480_3:xres =  640; yres =  480;  break; /* FSTN (new) */
-	default:           xres =    0; yres =    0;  break;
-	}
 
-	if(SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
-	   xres = 1360; yres = 1024;
-	}
+        xres = ivideo->lcdxres; yres = ivideo->lcdyres;
 
-	if(SiS_Pr.SiS_CustomT == CUT_PANEL848) {
-	   xres = 848;  yres =  480;
-	} else {
-	   if(sisbios_mode[myindex].xres > xres) return(-1);
-           if(myres > yres) return(-1);
+	if(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) {
+	   	if(sisbios_mode[myindex].xres > xres) return(-1);
+           	if(myres > yres) return(-1);
 	}
 
 	if(vbflags & (VB_LVDS | VB_30xBDH)) {
 	   if(sisbios_mode[myindex].xres == 320) {
 	      if((myres == 240) || (myres == 480)) {
-		 if(!sisfb_fstn) {
-		    if(sisbios_mode[myindex].mode_no == 0x5a ||
-		       sisbios_mode[myindex].mode_no == 0x5b)
+		 if(!ivideo->sisfb_fstn) {
+		    if(sisbios_mode[myindex].mode_no[1] == 0x5a ||
+		       sisbios_mode[myindex].mode_no[1] == 0x5b)
 		       return(-1);
 		 } else {
-		    if(sisbios_mode[myindex].mode_no == 0x50 ||
-		       sisbios_mode[myindex].mode_no == 0x56 ||
-		       sisbios_mode[myindex].mode_no == 0x53)
+		    if(sisbios_mode[myindex].mode_no[1] == 0x50 ||
+		       sisbios_mode[myindex].mode_no[1] == 0x56 ||
+		       sisbios_mode[myindex].mode_no[1] == 0x53)
 		       return(-1);
 		 }
 	      }
 	   }
 	}
 
-	if(SiS_GetModeID_LCD(sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres,
-	                     0, sisfb_fstn, SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
-	   return(-1);
+	if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+			     sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
+			     ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
+	   	return(-1);
 	}
 	break;
 
      case CRT2_TV:
-	if(SiS_GetModeID_TV(sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+	if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 	                    sisbios_mode[myindex].yres, 0) < 0x14) {
-	   return(-1);
+	   	return(-1);
 	}
 	break;
 
      case CRT2_VGA:
-        if(SiS_GetModeID_VGA2(sisvga_engine, vbflags, sisbios_mode[myindex].xres,
-	                    sisbios_mode[myindex].yres, 0) < 0x14) {
-	   return(-1);
+        if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+	                      sisbios_mode[myindex].yres, 0) < 0x14) {
+	   	return(-1);
 	}
 	break;
      }
@@ -630,49 +643,8 @@
      return(myindex);
 }
 
-static void sisfb_search_crt2type(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while(sis_crt2type[i].type_no != -1) {
-		if (!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
-			sisfb_crt2type = sis_crt2type[i].type_no;
-			sisfb_tvplug = sis_crt2type[i].tvplug_no;
-			sisfb_dstn = (sis_crt2type[i].flags & FL_550_DSTN) ? 1 : 0;
-			sisfb_fstn = (sis_crt2type[i].flags & FL_550_FSTN) ? 1 : 0;
-			break;
-		}
-		i++;
-	}
-	if(sisfb_crt2type < 0)
-		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
-        if(ivideo.chip != SIS_550) {
-	   sisfb_dstn = sisfb_fstn = 0;
-	}
-}
-
-static void sisfb_search_queuemode(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while (sis_queuemode[i].type_no != -1) {
-		if (!strnicmp(name, sis_queuemode[i].name, strlen(sis_queuemode[i].name))) {
-			sisfb_queuemode = sis_queuemode[i].type_no;
-			break;
-		}
-		i++;
-	}
-	if (sisfb_queuemode < 0)
-		printk(KERN_ERR "sisfb: Invalid queuemode type: %s\n", name);
-}
-
-static u8 sisfb_search_refresh_rate(unsigned int rate, int mode_idx)
+static u8
+sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
 {
 	u16 xres, yres;
 	int i = 0;
@@ -680,116 +652,64 @@
 	xres = sisbios_mode[mode_idx].xres;
 	yres = sisbios_mode[mode_idx].yres;
 
-	sisfb_rate_idx = 0;
-	while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
-		if ((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
-			if (sisfb_vrate[i].refresh == rate) {
-				sisfb_rate_idx = sisfb_vrate[i].idx;
+	ivideo->rate_idx = 0;
+	while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
+		if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
+			if(sisfb_vrate[i].refresh == rate) {
+				ivideo->rate_idx = sisfb_vrate[i].idx;
 				break;
-			} else if (sisfb_vrate[i].refresh > rate) {
-				if ((sisfb_vrate[i].refresh - rate) <= 3) {
+			} else if(sisfb_vrate[i].refresh > rate) {
+				if((sisfb_vrate[i].refresh - rate) <= 3) {
 					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
 						rate, sisfb_vrate[i].refresh);
-					sisfb_rate_idx = sisfb_vrate[i].idx;
-					ivideo.refresh_rate = sisfb_vrate[i].refresh;
-				} else if (((rate - sisfb_vrate[i-1].refresh) <= 2)
+					ivideo->rate_idx = sisfb_vrate[i].idx;
+					ivideo->refresh_rate = sisfb_vrate[i].refresh;
+				} else if(((rate - sisfb_vrate[i-1].refresh) <= 2)
 						&& (sisfb_vrate[i].idx != 1)) {
 					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 						rate, sisfb_vrate[i-1].refresh);
-					sisfb_rate_idx = sisfb_vrate[i-1].idx;
-					ivideo.refresh_rate = sisfb_vrate[i-1].refresh;
+					ivideo->rate_idx = sisfb_vrate[i-1].idx;
+					ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
 				} 
 				break;
 			} else if((rate - sisfb_vrate[i].refresh) <= 2) {
 				DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 						rate, sisfb_vrate[i].refresh);
-	           		sisfb_rate_idx = sisfb_vrate[i].idx;
+	           		ivideo->rate_idx = sisfb_vrate[i].idx;
 		   		break;
 	       		}
 		}
 		i++;
 	}
-	if (sisfb_rate_idx > 0) {
-		return sisfb_rate_idx;
+	if(ivideo->rate_idx > 0) {
+		return ivideo->rate_idx;
 	} else {
-		printk(KERN_INFO
-			"sisfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
+		printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
+				rate, xres, yres);
 		return 0;
 	}
 }
 
-static void sisfb_search_tvstd(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while (sis_tvtype[i].type_no != -1) {
-		if (!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
-			ivideo.vbflags |= sis_tvtype[i].type_no;
-			break;
-		}
-		i++;
-	}
-}
-
-static void sisfb_search_specialtiming(const char *name)
-{
-	int i = 0;
-	BOOLEAN found = FALSE;
-
-	if(name == NULL)
-		return;
-
-	if(!strnicmp(name, "none", 4)) {
-	        SiS_Pr.SiS_CustomT = CUT_FORCENONE;
-		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
-	} else {
-	   while(mycustomttable[i].chipID != 0) {
-	      if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
-		 SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
-		 found = TRUE;
-		 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
-		 	mycustomttable[i].vendorName, mycustomttable[i].cardName,
-		 	mycustomttable[i].optionName);
-		 break;
-	      }
-	      i++;
-	   }
-	   if(!found) {
-	      printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
-	      printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
-	      i = 0;
-	      while(mycustomttable[i].chipID != 0) {
-		 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
-		     mycustomttable[i].optionName,
-		     mycustomttable[i].vendorName,
-		     mycustomttable[i].cardName);
-		 i++;
-	      }
-           }
- 	}
-}
-
-static BOOLEAN sisfb_bridgeisslave(void)
+static BOOLEAN
+sisfb_bridgeisslave(struct sis_video_info *ivideo)
 {
    unsigned char P1_00;
 
-   if(!(ivideo.vbflags & VB_VIDEOBRIDGE)) return FALSE;
+   if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE;
 
    inSISIDXREG(SISPART1,0x00,P1_00);
-   if( ((sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
-       ((sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
+   if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
+       ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
 	   return TRUE;
    } else {
            return FALSE;
    }
 }
 
-static BOOLEAN sisfballowretracecrt1(void)
+static BOOLEAN
+sisfballowretracecrt1(struct sis_video_info *ivideo)
 {
-   unsigned char temp;
+   u8 temp;
 
    inSISIDXREG(SISCR,0x17,temp);
    if(!(temp & 0x80)) return FALSE;
@@ -800,20 +720,21 @@
    return TRUE;
 }
 
-static BOOLEAN sisfbcheckvretracecrt1(void)
+static BOOLEAN
+sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
 {
-
-   if(!sisfballowretracecrt1()) return FALSE;
+   if(!sisfballowretracecrt1(ivideo)) return FALSE;
 
    if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
    else 			   return FALSE;
 }
 
-static void sisfbwaitretracecrt1(void)
+static void
+sisfbwaitretracecrt1(struct sis_video_info *ivideo)
 {
    int watchdog;
 
-   if(!sisfballowretracecrt1()) return;
+   if(!sisfballowretracecrt1(ivideo)) return;
 
    watchdog = 65536;
    while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
@@ -821,19 +742,15 @@
    while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
 }
 
-static BOOLEAN sisfbcheckvretracecrt2(void)
+static BOOLEAN
+sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
 {
    unsigned char temp, reg;
 
-   switch(sisvga_engine) {
-   case SIS_300_VGA:
-   	reg = 0x25;
-	break;
-   case SIS_315_VGA:
-   	reg = 0x30;
-	break;
-   default:
-        return FALSE;
+   switch(ivideo->sisvga_engine) {
+   case SIS_300_VGA: reg = 0x25; break;
+   case SIS_315_VGA: reg = 0x30; break;
+   default:          return FALSE;
    }
 
    inSISIDXREG(SISPART1, reg, temp);
@@ -841,19 +758,67 @@
    else 	   return TRUE;
 }
 
-static BOOLEAN sisfb_CheckVBRetrace(void)
+static BOOLEAN
+sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
 {
-   if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
-      if(sisfb_bridgeisslave()) {
-         return(sisfbcheckvretracecrt1());
+   if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+      if(sisfb_bridgeisslave(ivideo)) {
+         return(sisfbcheckvretracecrt1(ivideo));
       } else {
-         return(sisfbcheckvretracecrt2());
+         return(sisfbcheckvretracecrt2(ivideo));
       }
    } 
-   return(sisfbcheckvretracecrt1());
+   return(sisfbcheckvretracecrt1(ivideo));
 }
 
-static int sisfb_myblank(int blank)
+static u32
+sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
+{
+   u8 idx, reg1, reg2, reg3, reg4;
+   u32 ret = 0;
+
+   (*vcount) = (*hcount) = 0;
+
+   if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
+      ret |= (FB_VBLANK_HAVE_VSYNC  |
+      	      FB_VBLANK_HAVE_HBLANK |
+              FB_VBLANK_HAVE_VBLANK |
+	      FB_VBLANK_HAVE_VCOUNT |
+	      FB_VBLANK_HAVE_HCOUNT);
+      switch(ivideo->sisvga_engine) {
+         case SIS_300_VGA: idx = 0x25; break;
+	 default:
+         case SIS_315_VGA: idx = 0x30; break;
+      }
+      inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
+      inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
+      inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
+      inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
+      if(!(reg1 & 0x01)) ret |= FB_VBLANK_VBLANKING;
+      if(!(reg1 & 0x02)) ret |= FB_VBLANK_VSYNCING;
+      if(!(reg4 & 0x80)) ret |= FB_VBLANK_HBLANKING;
+      (*vcount) = reg3 | ((reg4 & 0x70) << 4);
+      (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
+   } else if(sisfballowretracecrt1(ivideo)) {
+      ret |= (FB_VBLANK_HAVE_VSYNC  |
+              FB_VBLANK_HAVE_VBLANK |
+	      FB_VBLANK_HAVE_VCOUNT |
+	      FB_VBLANK_HAVE_HCOUNT);
+      reg1 = inSISREG(SISINPSTAT);
+      if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
+      if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+      inSISIDXREG(SISCR,0x20,reg1);
+      inSISIDXREG(SISCR,0x1b,reg1);
+      inSISIDXREG(SISCR,0x1c,reg2);
+      inSISIDXREG(SISCR,0x1d,reg3);
+      (*vcount) = reg2 | ((reg3 & 0x07) << 8);
+      (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
+   }
+   return ret;
+}
+
+static int
+sisfb_myblank(struct sis_video_info *ivideo, int blank)
 {
    u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
    BOOLEAN backlight = TRUE;
@@ -908,63 +873,64 @@
       return 1;
    }
 
-   if(ivideo.currentvbflags & VB_DISPTYPE_CRT1) {
+   if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
 
-      setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
+      if( (!ivideo->sisfb_thismonitor.datavalid) ||
+          ((ivideo->sisfb_thismonitor.datavalid) &&
+           (ivideo->sisfb_thismonitor.feature & 0xe0))) {
 
-      if( (!sisfb_thismonitor.datavalid) ||
-          ((sisfb_thismonitor.datavalid) &&
-           (sisfb_thismonitor.feature & 0xe0))) {
-
-	 if(sisvga_engine == SIS_315_VGA) {
-	    setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, 0xbf, cr63);
+	 if(ivideo->sisvga_engine == SIS_315_VGA) {
+	    setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
 	 }
 
-	 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+	 if(!(sisfb_bridgeisslave(ivideo))) {
+	    setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
+	    setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+	 }
       }
 
    }
 
-   if(ivideo.currentvbflags & CRT2_LCD) {
+   if(ivideo->currentvbflags & CRT2_LCD) {
 
-      if(ivideo.vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+      if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
 	 if(backlight) {
-	    SiS_SiS30xBLOn(&SiS_Pr, &sishw_ext);
+	    SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext);
 	 } else {
-	    SiS_SiS30xBLOff(&SiS_Pr, &sishw_ext);
+	    SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext);
 	 }
-      } else if(sisvga_engine == SIS_315_VGA) {
-	 if(ivideo.vbflags & VB_CHRONTEL) {
+      } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+	 if(ivideo->vbflags & VB_CHRONTEL) {
 	    if(backlight) {
-	       SiS_Chrontel701xBLOn(&SiS_Pr,&sishw_ext);
+	       SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext);
 	    } else {
-	       SiS_Chrontel701xBLOff(&SiS_Pr);
+	       SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
 	    }
 	 }
       }
 
-      if(((sisvga_engine == SIS_300_VGA) &&
-          (ivideo.vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
-         ((sisvga_engine == SIS_315_VGA) &&
-          ((ivideo.vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
+      if(((ivideo->sisvga_engine == SIS_300_VGA) &&
+          (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
+         ((ivideo->sisvga_engine == SIS_315_VGA) &&
+          ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
           setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
       }
 
-      if(sisvga_engine == SIS_300_VGA) {
-         if((ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) &&
-            (!(ivideo.vbflags & VB_30xBDH))) {
+      if(ivideo->sisvga_engine == SIS_300_VGA) {
+         if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
+            (!(ivideo->vbflags & VB_30xBDH))) {
 	    setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
 	 }
-      } else if(sisvga_engine == SIS_315_VGA) {
-         if((ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) &&
-            (!(ivideo.vbflags & VB_30xBDH))) {
+      } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+         if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
+            (!(ivideo->vbflags & VB_30xBDH))) {
 	    setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
 	 }
       }
 
-   } else if(ivideo.currentvbflags & CRT2_VGA) {
+   } else if(ivideo->currentvbflags & CRT2_VGA) {
 
-      if(ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) {
+      if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) {
          setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
       }
 
@@ -975,35 +941,122 @@
 
 /* ----------- FBDev related routines for all series ----------- */
 
-static void sisfb_set_vparms(void)
+static int
+sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
 {
-   switch(ivideo.video_bpp) {
-   case 8:
-       	ivideo.DstColor = 0x0000;
-	ivideo.SiS310_AccelDepth = 0x00000000;
-	ivideo.video_cmap_len = 256;
-       	break;
-   case 16:
-       	ivideo.DstColor = 0x8000;
-       	ivideo.SiS310_AccelDepth = 0x00010000;
-	ivideo.video_cmap_len = 16;
-       	break;
-   case 32:
-       	ivideo.DstColor = 0xC000;
-	ivideo.SiS310_AccelDepth = 0x00020000;
-	ivideo.video_cmap_len = 16;
-       	break;
-   default:
- 	ivideo.video_cmap_len = 16;
-	printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo.video_bpp);
-	ivideo.accel = 0;
-	break;
-   }
+	return (var->bits_per_pixel == 8) ? 256 : 16;
+}
+
+static void
+sisfb_set_vparms(struct sis_video_info *ivideo)
+{
+   	switch(ivideo->video_bpp) {
+	case 8:
+		ivideo->DstColor = 0x0000;
+		ivideo->SiS310_AccelDepth = 0x00000000;
+		ivideo->video_cmap_len = 256;
+		break;
+	case 16:
+		ivideo->DstColor = 0x8000;
+		ivideo->SiS310_AccelDepth = 0x00010000;
+		ivideo->video_cmap_len = 16;
+		break;
+	case 32:
+		ivideo->DstColor = 0xC000;
+		ivideo->SiS310_AccelDepth = 0x00020000;
+		ivideo->video_cmap_len = 16;
+		break;
+	default:
+		ivideo->video_cmap_len = 16;
+		printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
+		ivideo->accel = 0;
+		break;
+   	}
+}
+
+static int
+sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+{
+	int maxyres = ivideo->heapstart / (var->xres_virtual * (var->bits_per_pixel >> 3));
+
+	if(maxyres > 32767) maxyres = 32767;
+
+	return maxyres;
+}
+
+static void
+sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+{
+	ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
+	ivideo->scrnpitchCRT1 = ivideo->video_linelength;
+	if(!(ivideo->currentvbflags & CRT1_LCDA)) {
+		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+			ivideo->scrnpitchCRT1 <<= 1;
+		}
+	}
+
 }
 
-static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
-		      struct fb_info *info)
+static void
+sisfb_set_pitch(struct sis_video_info *ivideo)
 {
+   	BOOLEAN isslavemode = FALSE;
+	unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
+	unsigned short HDisplay2 = ivideo->video_linelength >> 3;
+
+   	if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
+
+   	/* We need to set pitch for CRT1 if bridge is in slave mode, too */
+   	if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
+   		outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
+   		setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
+	}
+
+   	/* We must not set the pitch for CRT2 if bridge is in slave mode */
+   	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
+		orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
+   		outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
+   		setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
+   	}
+}
+
+static void
+sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+{
+	ivideo->video_cmap_len = sisfb_get_cmap_len(var);
+
+	switch(var->bits_per_pixel) {
+	case 8:
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 6;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+}
+
+static int
+sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	unsigned int htotal = 0, vtotal = 0;
 	unsigned int drate = 0, hrate = 0;
 	int found_mode = 0;
@@ -1033,52 +1086,51 @@
 	}
 
 	if(pixclock && htotal && vtotal) {
-	   drate = 1000000000 / pixclock;
-	   hrate = (drate * 1000) / htotal;
-	   ivideo.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else ivideo.refresh_rate = 60;
-
-#if 0
-	printk(KERN_DEBUG "sisfb: Change mode to %dx%dx%d-%dHz\n",
-		var->xres,var->yres,var->bits_per_pixel,ivideo.refresh_rate);
-#endif
+	   	drate = 1000000000 / pixclock;
+	   	hrate = (drate * 1000) / htotal;
+	   	ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+	} else {
+	   	ivideo->refresh_rate = 60;
+	}
 
-	old_mode = sisfb_mode_idx;
-	sisfb_mode_idx = 0;
+	old_mode = ivideo->sisfb_mode_idx;
+	ivideo->sisfb_mode_idx = 0;
 
-	while( (sisbios_mode[sisfb_mode_idx].mode_no != 0) &&
-	       (sisbios_mode[sisfb_mode_idx].xres <= var->xres) ) {
-		if( (sisbios_mode[sisfb_mode_idx].xres == var->xres) &&
-		    (sisbios_mode[sisfb_mode_idx].yres == var->yres) &&
-		    (sisbios_mode[sisfb_mode_idx].bpp == var->bits_per_pixel)) {
-			sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+	while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
+	       (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
+		if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
+		    (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
+		    (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
+			ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
 			found_mode = 1;
 			break;
 		}
-		sisfb_mode_idx++;
+		ivideo->sisfb_mode_idx++;
 	}
 
-	if(found_mode)
-		sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
-	else
-		sisfb_mode_idx = -1;
+	if(found_mode) {
+		ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
+				ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+	} else {
+		ivideo->sisfb_mode_idx = -1;
+	}
 
-       	if(sisfb_mode_idx < 0) {
+       	if(ivideo->sisfb_mode_idx < 0) {
 		printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
 		       var->yres, var->bits_per_pixel);
-		sisfb_mode_idx = old_mode;
+		ivideo->sisfb_mode_idx = old_mode;
 		return -EINVAL;
 	}
 
-	if(sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx) == 0) {
-		sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
-		ivideo.refresh_rate = 60;
+	if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
+		ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
+		ivideo->refresh_rate = 60;
 	}
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	if(sisfb_thismonitor.datavalid) {
-	   if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
-	                         sisfb_rate_idx, ivideo.refresh_rate)) {
+	if(ivideo->sisfb_thismonitor.datavalid) {
+	   if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
+	                         ivideo->rate_idx, ivideo->refresh_rate)) {
 	      printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 	   }
 	}
@@ -1089,64 +1141,77 @@
 #else
 	if(isactive) {
 #endif
-		sisfb_pre_setmode();
+		sisfb_pre_setmode(ivideo);
 
-		if(SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {
-			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", sisfb_mode_no);
+		if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
+			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
 			return -EINVAL;
 		}
 
 		outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-		ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
-		ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
-		ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
-		ivideo.org_x = ivideo.org_y = 0;
-		ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
-		ivideo.accel = 0;
-		if(sisfb_accel) {
-		   ivideo.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
-		}
-
-		sisfb_set_vparms();
-
-		ivideo.current_width = ivideo.video_width;
-		ivideo.current_height = ivideo.video_height;
-		ivideo.current_bpp = ivideo.video_bpp;
-		ivideo.current_htotal = htotal;
-		ivideo.current_vtotal = vtotal;
-		ivideo.current_pixclock = var->pixclock;
-		ivideo.current_refresh_rate = ivideo.refresh_rate;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-                sisfb_lastrates[sisfb_mode_no] = ivideo.refresh_rate;
+		sisfb_post_setmode(ivideo);
+
+		ivideo->video_bpp    = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+		ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+
+		sisfb_calc_pitch(ivideo, var);
+		sisfb_set_pitch(ivideo);
+
+		ivideo->accel = 0;
+#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
+#ifdef STUPID_ACCELF_TEXT_SHIT
+		if(var->accel_flags & FB_ACCELF_TEXT) {
+			info->flags &= ~FBINFO_HWACCEL_DISABLED;
+		} else {
+			info->flags |= FBINFO_HWACCEL_DISABLED;
+		}
+#endif
+		if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
+#else
+		if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
 #endif
 
-		sisfb_post_setmode();
+		sisfb_set_vparms(ivideo);
 
+		ivideo->current_width = ivideo->video_width;
+		ivideo->current_height = ivideo->video_height;
+		ivideo->current_bpp = ivideo->video_bpp;
+		ivideo->current_htotal = htotal;
+		ivideo->current_vtotal = vtotal;
+		ivideo->current_linelength = ivideo->video_linelength;
+		ivideo->current_pixclock = var->pixclock;
+		ivideo->current_refresh_rate = ivideo->refresh_rate;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+                ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
+#endif
 	}
+
 	return 0;
 }
 
-static int sisfb_pan_var(struct fb_var_screeninfo *var)
+static int
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
 {
 	unsigned int base;
 
-	if (var->xoffset > (var->xres_virtual - var->xres)) {
+	if(var->xoffset > (var->xres_virtual - var->xres)) {
 		return -EINVAL;
 	}
 	if(var->yoffset > (var->yres_virtual - var->yres)) {
 		return -EINVAL;
 	}
 
-	base = var->yoffset * var->xres_virtual + var->xoffset;
+	base = (var->yoffset * var->xres_virtual) + var->xoffset;
 
         /* calculate base bpp dep. */
         switch(var->bits_per_pixel) {
+	case 32:
+            	break;
         case 16:
         	base >>= 1;
         	break;
-	case 32:
-            	break;
 	case 8:
         default:
         	base >>= 2;
@@ -1158,81 +1223,27 @@
         outSISIDXREG(SISCR, 0x0D, base & 0xFF);
 	outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
 	outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
-	if(sisvga_engine == SIS_315_VGA) {
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
 		setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
 	}
-        if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
-		orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);
+        if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+		orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
         	outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
         	outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
         	outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
-		if(sisvga_engine == SIS_315_VGA) {
+		if(ivideo->sisvga_engine == SIS_315_VGA) {
 			setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
 		}
         }
 	return 0;
 }
 
-static void sisfb_bpp_to_var(struct fb_var_screeninfo *var)
-{
-	switch(var->bits_per_pixel) {
-	   case 8:
-	   	var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = 6;
-		ivideo.video_cmap_len = 256;
-		break;
-	   case 16:
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		ivideo.video_cmap_len = 16;
-		break;
-	   case 32:
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		ivideo.video_cmap_len = 16;
-		break;
-	}
-}
-
-void sis_dispinfo(struct ap_data *rec)
-{
-	rec->minfo.bpp      = ivideo.video_bpp;
-	rec->minfo.xres     = ivideo.video_width;
-	rec->minfo.yres     = ivideo.video_height;
-	rec->minfo.v_xres   = ivideo.video_vwidth;
-	rec->minfo.v_yres   = ivideo.video_vheight;
-	rec->minfo.org_x    = ivideo.org_x;
-	rec->minfo.org_y    = ivideo.org_y;
-	rec->minfo.vrate    = ivideo.refresh_rate;
-	rec->iobase         = ivideo.vga_base - 0x30;
-	rec->mem_size       = ivideo.video_size;
-	rec->disp_state     = ivideo.disp_state;
-	rec->version        = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
-	rec->hasVB          = ivideo.hasVB;
-	rec->TV_type        = ivideo.TV_type;
-	rec->TV_plug        = ivideo.TV_plug;
-	rec->chip           = ivideo.chip;
-	rec->vbflags	    = ivideo.vbflags;
-	rec->currentvbflags = ivideo.currentvbflags;
-}
-
 /* ------------ FBDev related routines for 2.4 series ----------- */
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 
-static void sisfb_crtc_to_var(struct fb_var_screeninfo *var)
+static void
+sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
 {
 	u16 VRE, VBE, VRS, VBS, VDE, VT;
 	u16 HRE, HBE, HRS, HBS, HDE, HT;
@@ -1247,50 +1258,55 @@
 	else
 	   var->vmode = FB_VMODE_NONINTERLACED;
 
-	switch ((sr_data & 0x1C) >> 2) {
-	   case SIS_8BPP_COLOR_MODE:
+	switch((sr_data & 0x1C) >> 2) {
+	case SIS_8BPP_COLOR_MODE:
 		var->bits_per_pixel = 8;
 		break;
-	   case SIS_16BPP_COLOR_MODE:
+	case SIS_16BPP_COLOR_MODE:
 		var->bits_per_pixel = 16;
 		break;
-	   case SIS_32BPP_COLOR_MODE:
+	case SIS_32BPP_COLOR_MODE:
 		var->bits_per_pixel = 32;
 		break;
 	}
 
-	sisfb_bpp_to_var(var);
+	sisfb_bpp_to_var(ivideo, var);
 	
 	inSISIDXREG(SISSR, 0x0A, sr_data);
-
         inSISIDXREG(SISCR, 0x06, cr_data);
-
         inSISIDXREG(SISCR, 0x07, cr_data2);
 
-	VT = (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |
-	     ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10);
+	VT = (cr_data & 0xFF) |
+	     ((u16) (cr_data2 & 0x01) << 8) |
+	     ((u16) (cr_data2 & 0x20) << 4) |
+	     ((u16) (sr_data  & 0x01) << 10);
 	A = VT + 2;
 
 	inSISIDXREG(SISCR, 0x12, cr_data);
 
-	VDE = (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |
-	      ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);
+	VDE = (cr_data & 0xff) |
+	      ((u16) (cr_data2 & 0x02) << 7) |
+	      ((u16) (cr_data2 & 0x40) << 3) |
+	      ((u16) (sr_data  & 0x02) << 9);
 	E = VDE + 1;
 
 	inSISIDXREG(SISCR, 0x10, cr_data);
 
-	VRS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |
-	      ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);
+	VRS = (cr_data & 0xff) |
+	      ((u16) (cr_data2 & 0x04) << 6) |
+	      ((u16) (cr_data2 & 0x80) << 2) |
+	      ((u16) (sr_data  & 0x08) << 7);
 	F = VRS + 1 - E;
 
 	inSISIDXREG(SISCR, 0x15, cr_data);
-
 	inSISIDXREG(SISCR, 0x09, cr_data3);
 
 	if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE;
 
-	VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |
-	      ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);
+	VBS = (cr_data & 0xff) |
+	      ((u16) (cr_data2 & 0x08) << 5) |
+	      ((u16) (cr_data3 & 0x20) << 4) |
+	      ((u16) (sr_data & 0x04) << 8);
 
 	inSISIDXREG(SISCR, 0x16, cr_data);
 
@@ -1324,7 +1340,6 @@
 	}
 
 	inSISIDXREG(SISSR, 0x0b, sr_data);
-
 	inSISIDXREG(SISCR, 0x00, cr_data);
 
 	HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
@@ -1345,13 +1360,12 @@
 	HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
 
 	inSISIDXREG(SISSR, 0x0c, sr_data);
-
 	inSISIDXREG(SISCR, 0x03, cr_data);
-
 	inSISIDXREG(SISCR, 0x05, cr_data2);
 
-	HBE = (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |
-	      ((u16) (sr_data & 0x03) << 6);
+	HBE = (cr_data & 0x1f) |
+	      ((u16) (cr_data2 & 0x80) >> 2) |
+	      ((u16) (sr_data  & 0x03) << 6);
 	HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
 
 	temp = HBE - ((E - 1) & 255);
@@ -1362,7 +1376,10 @@
 
 	D = B - F - C;
 
-	var->xres = var->xres_virtual = E * 8;
+	var->xres = E * 8;
+	if(var->xres_virtual < var->xres) {
+		var->xres_virtual = var->xres;
+	}
 
 	if((var->xres == 320) &&
 	   (var->yres == 200 || var->yres == 240)) {
@@ -1399,14 +1416,13 @@
 	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
 	   VT <<= 1;
 	}
-	hrate = ivideo.refresh_rate * VT / 2;
+	hrate = ivideo->refresh_rate * VT / 2;
 	drate = (hrate * HT) / 1000;
 	var->pixclock = (u32) (1000000000 / drate);
 
-	if(sisfb_ypan) {
-	   maxyres = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
-	   if(maxyres > 32767) maxyres = 32767;
-	   if(sisfb_max) {
+	if(ivideo->sisfb_ypan) {
+	   maxyres = sisfb_calc_maxyres(ivideo, var);
+	   if(ivideo->sisfb_max) {
 	      var->yres_virtual = maxyres;
 	   } else {
 	      if(var->yres_virtual > maxyres) {
@@ -1416,42 +1432,48 @@
 	   if(var->yres_virtual <= var->yres) {
 	      var->yres_virtual = var->yres;
 	   }
-	} else
+	} else {
 	   var->yres_virtual = var->yres;
+	}
 
 }
 
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
-			 unsigned *transp, struct fb_info *fb_info)
+static int
+sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
+			 unsigned *transp, struct fb_info *info)
 {
-	if (regno >= ivideo.video_cmap_len)
-		return 1;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 
-	*red = sis_palette[regno].red;
-	*green = sis_palette[regno].green;
-	*blue = sis_palette[regno].blue;
+	if(regno >= ivideo->video_cmap_len) return 1;
+
+	*red   = ivideo->sis_palette[regno].red;
+	*green = ivideo->sis_palette[regno].green;
+	*blue  = ivideo->sis_palette[regno].blue;
 	*transp = 0;
+
 	return 0;
 }
 
-static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-                           unsigned transp, struct fb_info *fb_info)
+static int
+sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+                           unsigned transp, struct fb_info *info)
 {
-	if (regno >= ivideo.video_cmap_len)
-		return 1;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+
+	if(regno >= ivideo->video_cmap_len) return 1;
 
-	sis_palette[regno].red = red;
-	sis_palette[regno].green = green;
-	sis_palette[regno].blue = blue;
+	ivideo->sis_palette[regno].red   = red;
+	ivideo->sis_palette[regno].green = green;
+	ivideo->sis_palette[regno].blue  = blue;
 
-	switch (ivideo.video_bpp) {
+	switch(ivideo->video_bpp) {
 #ifdef FBCON_HAS_CFB8
 	case 8:
 	        outSISREG(SISDACA, regno);
 		outSISREG(SISDACD, (red >> 10));
 		outSISREG(SISDACD, (green >> 10));
 		outSISREG(SISDACD, (blue >> 10));
-		if (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 		        outSISREG(SISDAC2A, regno);
 			outSISREG(SISDAC2D, (red >> 8));
 			outSISREG(SISDAC2D, (green >> 8));
@@ -1461,317 +1483,250 @@
 #endif
 #ifdef FBCON_HAS_CFB16
 	case 16:
-		sis_fbcon_cmap.cfb16[regno] =
+		ivideo->sis_fbcon_cmap.cfb16[regno] =
 		    ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
 	case 32:
-		red >>= 8;
+		red   >>= 8;
 		green >>= 8;
-		blue >>= 8;
-		sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
+		blue  >>= 8;
+		ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
 		break;
 #endif
 	}
+
 	return 0;
 }
 
-static void sisfb_set_disp(int con, struct fb_var_screeninfo *var,
-                           struct fb_info *info)
+static void
+sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct sis_video_info    *ivideo = (struct sis_video_info *)info->par;
+	struct display           *display;
+	struct display_switch    *sw;
 	struct fb_fix_screeninfo fix;
 	long   flags;
-	struct display *display;
-	struct display_switch *sw;
 
-	if(con >= 0)
-		display = &fb_display[con];
-	else
-		display = &sis_disp;
+	display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
 
-	sisfb_get_fix(&fix, con, 0);
+	sisfb_get_fix(&fix, con, info);
 
-	display->screen_base = ivideo.video_vbase;
+	display->var = *var;
+	display->screen_base = (char *)ivideo->video_vbase;
 	display->visual = fix.visual;
 	display->type = fix.type;
 	display->type_aux = fix.type_aux;
 	display->ypanstep = fix.ypanstep;
 	display->ywrapstep = fix.ywrapstep;
 	display->line_length = fix.line_length;
-	display->next_line = fix.line_length;
 	display->can_soft_blank = 1;
-	display->inverse = sisfb_inverse;
-	display->var = *var;
+	display->inverse = ivideo->sisfb_inverse;
+	display->next_line = fix.line_length;
 
 	save_flags(flags);
 
-	switch (ivideo.video_bpp) {
+	switch(ivideo->video_bpp) {
 #ifdef FBCON_HAS_CFB8
-	   case 8:
-#ifdef SISFBACCEL
-		sw = ivideo.accel ? &fbcon_sis8 : &fbcon_cfb8;
-#else
-		sw = &fbcon_cfb8;
-#endif
+	case 8:	sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB16
-	   case 16:
-#ifdef SISFBACCEL
-		sw = ivideo.accel ? &fbcon_sis16 : &fbcon_cfb16;
-#else
-		sw = &fbcon_cfb16;
-#endif
-		display->dispsw_data = sis_fbcon_cmap.cfb16;
+	case 16:sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16;
+		display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
-	   case 32:
-#ifdef SISFBACCEL
-		sw = ivideo.accel ? &fbcon_sis32 : &fbcon_cfb32;
-#else
-		sw = &fbcon_cfb32;
-#endif
-		display->dispsw_data = sis_fbcon_cmap.cfb32;
+	case 32:sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32;
+		display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32;
 		break;
 #endif
-	   default:
-		sw = &fbcon_dummy;
-		return;
+	default:sw = &fbcon_dummy;
+		break;
 	}
-	memcpy(&sisfb_sw, sw, sizeof(*sw));
-	display->dispsw = &sisfb_sw;
+	memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw));
+	display->dispsw = &ivideo->sisfb_sw;
+
 	restore_flags(flags);
 
-        if(sisfb_ypan) {
+        if(ivideo->sisfb_ypan) {
   	    /* display->scrollmode = 0;  */
 	} else {
 	    display->scrollmode = SCROLL_YREDRAW;
-	    sisfb_sw.bmove = fbcon_redraw_bmove;
+	    ivideo->sisfb_sw.bmove = fbcon_redraw_bmove;
 	}
 }
 
-static void sisfb_do_install_cmap(int con, struct fb_info *info)
+static void
+sisfb_do_install_cmap(int con, struct fb_info *info)
 {
-        if (con != currcon)
-		return;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+
+        if(con != ivideo->currcon) return;
 
-        if (fb_display[con].cmap.len)
+        if(fb_display[con].cmap.len) {
 		fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
-        else
-		fb_set_cmap(fb_default_cmap(ivideo.video_cmap_len), 1,
-			    sisfb_setcolreg, info);
+        } else {
+		int size = sisfb_get_cmap_len(&fb_display[con].var);
+		fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info);
+	}
 }
 
-
-static int sisfb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+static int
+sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
-	if(con == -1)
-		memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
-	else
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+
+	if(con == -1) {
+		memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo));
+	} else {
 		*var = fb_display[con].var;
+	}
 
-	if(sisfb_fstn) {
-	   if (var->xres == 320 && var->yres == 480)
-		var->yres = 240;
+	if(ivideo->sisfb_fstn) {
+	   	if(var->xres == 320 && var->yres == 480) var->yres = 240;
         }
 
 	return 0;
 }
 
-static int sisfb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+static int
+sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int err;
-	unsigned int cols, rows;
 
 	fb_display[con].var.activate = FB_ACTIVATE_NOW;
-        if(sisfb_do_set_var(var, con == currcon, info)) {
-		sisfb_crtc_to_var(var);
+
+        if(sisfb_do_set_var(var, con == ivideo->currcon, info)) {
+		sisfb_crtc_to_var(ivideo, var);
 		return -EINVAL;
 	}
 
-	sisfb_crtc_to_var(var);
+	sisfb_crtc_to_var(ivideo, var);
 
 	sisfb_set_disp(con, var, info);
 
-	if(info->changevar)
-		(*info->changevar) (con);
+	if(info->changevar) {
+		(*info->changevar)(con);
+	}
 
-	if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
+	if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) {
 		return err;
+	}
 
 	sisfb_do_install_cmap(con, info);
 
-	cols = sisbios_mode[sisfb_mode_idx].cols;
-	rows = sisbios_mode[sisfb_mode_idx].rows;
-#if 0
-	/* Why was this called here? */
+#if 0	/* Why was this called here? */
+	unsigned int cols, rows;
+	cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
+	rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
  	vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
 #endif
-
 	return 0;
 }
 
-static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+static int
+sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
 {
-        if (con == currcon)
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	struct display *display;
+
+	display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
+
+        if(con == ivideo->currcon) {
+
 		return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
 
-	else if (fb_display[con].cmap.len)
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(ivideo.video_cmap_len), cmap, kspc ? 0 : 2);
+	} else if(display->cmap.len) {
+
+		fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2);
+
+	} else {
+
+		int size = sisfb_get_cmap_len(&display->var);
+		fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+
+	}
 
 	return 0;
 }
 
-static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+static int
+sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
 {
-	int err;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	struct display *display;
+	int err, size;
+
+	display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
 
-	if (!fb_display[con].cmap.len) {
-		err = fb_alloc_cmap(&fb_display[con].cmap, ivideo.video_cmap_len, 0);
-		if (err)
-			return err;
+	size = sisfb_get_cmap_len(&display->var);
+	if(display->cmap.len != size) {
+		err = fb_alloc_cmap(&display->cmap, size, 0);
+		if(err)	return err;
 	}
         
-	if (con == currcon)
+	if(con == ivideo->currcon) {
 		return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
-
-	else
-		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+	} else {
+		fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1);
+	}
 
 	return 0;
 }
 
-static int sisfb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info* info)
+static int
+sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int err;
 
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
-			return -EINVAL;
-	} else {
-		if (var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
-		    var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
-			return -EINVAL;
+	if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
+
+	if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) ||
+	   (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) {
+		return -EINVAL;
 	}
 
-        if(con == currcon) {
-	   if((err = sisfb_pan_var(var)) < 0) return err;
+        if(con == ivideo->currcon) {
+	   	if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
 	}
 
 	fb_display[con].var.xoffset = var->xoffset;
 	fb_display[con].var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		fb_display[con].var.vmode |= FB_VMODE_YWRAP;
-	else
-		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
-
-	return 0;
-}
-
-static int sisfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma)
-{
-	struct fb_var_screeninfo var;
-	unsigned long start;
-	unsigned long off;
-	u32 len, mmio_off;
-
-	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	start = (unsigned long) ivideo.video_base;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
-#if 0
-	if (off >= len) {
-		off -= len;
-#endif
-	/* By Jake Page: Treat mmap request with offset beyond heapstart
-	 *               as request for mapping the mmio area 
-	 */
-	mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.heapstart);
-	if(off >= mmio_off) {
-		off -= mmio_off;		
-		sisfb_get_var(&var, currcon, info);
-		if(var.accel_flags) return -EINVAL;
-
-		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + sisfb_mmio_size);
-	}
-
-	start &= PAGE_MASK;
-	if((vma->vm_end - vma->vm_start + off) > len)	return -EINVAL;
-
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-	vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
-
-#if defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#endif
-        /* RedHat requires vma as the first paramater to the following call */
-	if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,
-				vma->vm_page_prot))
-		return -EAGAIN;
 
 	return 0;
 }
 
-static void sis_get_glyph(struct fb_info *info, SIS_GLYINFO *gly)
+static int
+sisfb_update_var(int con, struct fb_info *info)
 {
-	struct display *p = &fb_display[currcon];
-	u16 c;
-	u8 *cdat;
-	int widthb;
-	u8 *gbuf = gly->gmask;
-	int size;
-
-	gly->fontheight = fontheight(p);
-	gly->fontwidth = fontwidth(p);
-	widthb = (fontwidth(p) + 7) / 8;
-
-	c = gly->ch & p->charmask;
-	if (fontwidth(p) <= 8)
-		cdat = p->fontdata + c * fontheight(p);
-	else
-		cdat = p->fontdata + (c * fontheight(p) << 1);
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 
-	size = fontheight(p) * widthb;
-	memcpy(gbuf, cdat, size);
-	gly->ngmask = size;
+        return(sisfb_pan_var(ivideo, &fb_display[con].var));
 }
 
-static int sisfb_update_var(int con, struct fb_info *info)
-{
-        return(sisfb_pan_var(&fb_display[con].var));
-}
-
-static int sisfb_switch(int con, struct fb_info *info)
+static int
+sisfb_switch(int con, struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int cols, rows;
 
-        if(fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info);
+        if(fb_display[ivideo->currcon].cmap.len) {
+		fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info);
+	}
 
 	fb_display[con].var.activate = FB_ACTIVATE_NOW;
 
-	if(!memcmp(&fb_display[con].var, &fb_display[currcon].var,
-	                           sizeof(struct fb_var_screeninfo))) {
-		currcon = con;
+	if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var,
+	                           	sizeof(struct fb_var_screeninfo))) {
+		ivideo->currcon = con;
 		return 1;
 	}
 
-	currcon = con;
+	ivideo->currcon = con;
 
 	sisfb_do_set_var(&fb_display[con].var, 1, info);
 
@@ -1779,8 +1734,8 @@
 
 	sisfb_do_install_cmap(con, info);
 
-	cols = sisbios_mode[sisfb_mode_idx].cols;
-	rows = sisbios_mode[sisfb_mode_idx].rows;
+	cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
+	rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
 	vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
 
 	sisfb_update_var(con, info);
@@ -1788,55 +1743,46 @@
 	return 1;
 }
 
-static void sisfb_blank(int blank, struct fb_info *info)
+static void
+sisfb_blank(int blank, struct fb_info *info)
 {
-	sisfb_myblank(blank);
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+
+	sisfb_myblank(ivideo, blank);
 }
 #endif
 
-/* ------------ FBDev related routines for 2.5 series ----------- */
+/* ------------ FBDev related routines for 2.6 series ----------- */
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 
-static int sisfb_open(struct fb_info *info, int user)
+static int
+sisfb_open(struct fb_info *info, int user)
 {
-    return 0;
+    	return 0;
 }
 
-static int sisfb_release(struct fb_info *info, int user)
+static int
+sisfb_release(struct fb_info *info, int user)
 {
-    return 0;
+    	return 0;
 }
 
-static int sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
+static int
+sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+		unsigned transp, struct fb_info *info)
 {
-	int rc = 16;		
-
-	switch(var->bits_per_pixel) {
-	case 8:
-		rc = 256;	
-		break;
-	case 16:
-	case 32:
-		rc = 16;
-		break;
-	}
-	return rc;
-}
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 
-static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-                           unsigned transp, struct fb_info *info)
-{
-	if (regno >= sisfb_get_cmap_len(&info->var))
-		return 1;
+	if(regno >= sisfb_get_cmap_len(&info->var)) return 1;
 
-	switch (info->var.bits_per_pixel) {
+	switch(info->var.bits_per_pixel) {
 	case 8:
 	        outSISREG(SISDACA, regno);
 		outSISREG(SISDACD, (red >> 10));
 		outSISREG(SISDACD, (green >> 10));
 		outSISREG(SISDACD, (blue >> 10));
-		if (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 		        outSISREG(SISDAC2A, regno);
 			outSISREG(SISDAC2D, (red >> 8));
 			outSISREG(SISDAC2D, (green >> 8));
@@ -1851,28 +1797,31 @@
 		red >>= 8;
 		green >>= 8;
 		blue >>= 8;
-		((u32 *) (info->pseudo_palette))[regno] =
-			(red << 16) | (green << 8) | (blue);
+		((u32 *)(info->pseudo_palette))[regno] =
+				(red << 16) | (green << 8) | (blue);
 		break;
 	}
 	return 0;
 }
 
-static int sisfb_set_par(struct fb_info *info)
+static int
+sisfb_set_par(struct fb_info *info)
 {
 	int err;
 
-        if((err = sisfb_do_set_var(&info->var, 1, info)))
+        if((err = sisfb_do_set_var(&info->var, 1, info))) {
 		return err;
+	}
 
 	sisfb_get_fix(&info->fix, info->currcon, info);
 
 	return 0;
 }
 
-static int sisfb_check_var(struct fb_var_screeninfo *var,
-                           struct fb_info *info)
+static int
+sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
 	unsigned int drate = 0, hrate = 0, maxyres;
 	int found_mode = 0;
@@ -1902,12 +1851,12 @@
 	}
 
 	search_idx = 0;
-	while( (sisbios_mode[search_idx].mode_no != 0) &&
+	while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
 	       (sisbios_mode[search_idx].xres <= var->xres) ) {
 		if( (sisbios_mode[search_idx].xres == var->xres) &&
 		    (sisbios_mode[search_idx].yres == var->yres) &&
 		    (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
-		        if(sisfb_validate_mode(search_idx, ivideo.currentvbflags) > 0) {
+		        if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) {
 			   found_mode = 1;
 			   break;
 			}
@@ -1916,13 +1865,12 @@
 	}
 
 	if(!found_mode) {
-
                 search_idx = 0;
-		while(sisbios_mode[search_idx].mode_no != 0) {
+		while(sisbios_mode[search_idx].mode_no[0] != 0) {
 		   if( (var->xres <= sisbios_mode[search_idx].xres) &&
 		       (var->yres <= sisbios_mode[search_idx].yres) &&
 		       (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
-		          if(sisfb_validate_mode(search_idx, ivideo.currentvbflags) > 0) {
+		          if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) {
 			     found_mode = 1;
 			     break;
 			  }
@@ -1946,24 +1894,25 @@
 		}
 	}
 
-	if( ((ivideo.vbflags & VB_LVDS) ||			/* Slave modes on LVDS and 301B-DH */
-	     ((ivideo.vbflags & VB_30xBDH) && (ivideo.currentvbflags & CRT2_LCD))) &&
+	if( ((ivideo->vbflags & VB_LVDS) ||			/* Slave modes on LVDS and 301B-DH */
+	     ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
 	    (var->bits_per_pixel == 8) ) {
 	    	refresh_rate = 60;
 		recalc_clock = TRUE;
-	} else if( (ivideo.current_htotal == htotal) &&		/* x=x & y=y & c=c -> assume depth change */
-	    	   (ivideo.current_vtotal == vtotal) &&
-	    	   (ivideo.current_pixclock == pixclock) ) {
+	} else if( (ivideo->current_htotal == htotal) &&	/* x=x & y=y & c=c -> assume depth change */
+	    	   (ivideo->current_vtotal == vtotal) &&
+	    	   (ivideo->current_pixclock == pixclock) ) {
 		drate = 1000000000 / pixclock;
 	        hrate = (drate * 1000) / htotal;
 	        refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else if( ( (ivideo.current_htotal != htotal) ||	/* x!=x | y!=y & c=c -> invalid pixclock */
-	    	     (ivideo.current_vtotal != vtotal) ) &&
-	    	   (ivideo.current_pixclock == var->pixclock) ) {
-		if(sisfb_lastrates[sisbios_mode[search_idx].mode_no]) {
-			refresh_rate = sisfb_lastrates[sisbios_mode[search_idx].mode_no];
-		} else if(sisfb_parm_rate != -1) {
-			refresh_rate = sisfb_parm_rate;
+	} else if( ( (ivideo->current_htotal != htotal) ||	/* x!=x | y!=y & c=c -> invalid pixclock */
+	    	     (ivideo->current_vtotal != vtotal) ) &&
+	    	   (ivideo->current_pixclock == var->pixclock) ) {
+		if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
+			refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
+		} else if(ivideo->sisfb_parm_rate != -1) {
+			/* Sic, sisfb_parm_rate - want to know originally desired rate here */
+			refresh_rate = ivideo->sisfb_parm_rate;
 		} else {
 			refresh_rate = 60;
 		}
@@ -1972,56 +1921,51 @@
 		drate = 1000000000 / pixclock;
 	   	hrate = (drate * 1000) / htotal;
 	   	refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else if(ivideo.current_refresh_rate) {
-		refresh_rate = ivideo.current_refresh_rate;
+	} else if(ivideo->current_refresh_rate) {
+		refresh_rate = ivideo->current_refresh_rate;
 		recalc_clock = TRUE;
 	} else {
 		refresh_rate = 60;
 		recalc_clock = TRUE;
 	}
 
-	myrateindex = sisfb_search_refresh_rate(refresh_rate, search_idx);
+	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
 
 	/* Eventually recalculate timing and clock */
 	if(recalc_clock) {
 	   if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
-	   var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
-						sisbios_mode[search_idx].mode_no, myrateindex));
-	   sisfb_mode_rate_to_ddata(&SiS_Pr, &sishw_ext,
-		 			sisbios_mode[search_idx].mode_no, myrateindex,
-		 			&var->left_margin, &var->right_margin,
-		 			&var->upper_margin, &var->lower_margin,
-		 			&var->hsync_len, &var->vsync_len,
-		 			&var->sync, &var->vmode);
+	   var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
+	   					&ivideo->sishw_ext,
+						sisbios_mode[search_idx].mode_no[ivideo->mni],
+						myrateindex));
+	   sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+		 		    sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex,	var);
 	   if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-		var->pixclock <<= 1;
+	      var->pixclock <<= 1;
 	   }
 	}
 
-	if(sisfb_thismonitor.datavalid) {
-	   if(!sisfb_verify_rate(&sisfb_thismonitor, search_idx,
+	if(ivideo->sisfb_thismonitor.datavalid) {
+	   if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
 	                         myrateindex, refresh_rate)) {
 	      printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 	   }
 	}
 
 	/* Adapt RGB settings */
-	sisfb_bpp_to_var(var);	
+	sisfb_bpp_to_var(ivideo, var);
 	
 	/* Sanity check for offsets */
-	if (var->xoffset < 0)
-		var->xoffset = 0;
-	if (var->yoffset < 0)
-		var->yoffset = 0;
+	if(var->xoffset < 0) var->xoffset = 0;
+	if(var->yoffset < 0) var->yoffset = 0;
 
-	/* Horiz-panning not supported */
-	if(var->xres != var->xres_virtual)
-		var->xres_virtual = var->xres;
+	if(var->xres > var->xres_virtual) {
+	   var->xres_virtual = var->xres;
+	}
 
-	if(sisfb_ypan) {
-	   maxyres = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
-	   if(maxyres > 32767) maxyres = 32767;
-	   if(sisfb_max) {
+	if(ivideo->sisfb_ypan) {
+	   maxyres = sisfb_calc_maxyres(ivideo, var);
+	   if(ivideo->sisfb_max) {
 	      var->yres_virtual = maxyres;
 	   } else {
 	      if(var->yres_virtual > maxyres) {
@@ -2040,310 +1984,241 @@
 	}
 	
 	/* Truncate offsets to maximum if too high */
-	if(var->xoffset > var->xres_virtual - var->xres)
-		var->xoffset = var->xres_virtual - var->xres - 1;
+	if(var->xoffset > var->xres_virtual - var->xres) {
+	   var->xoffset = var->xres_virtual - var->xres - 1;
+	}
 
-	if(var->yoffset > var->yres_virtual - var->yres)
-		var->yoffset = var->yres_virtual - var->yres - 1;
+	if(var->yoffset > var->yres_virtual - var->yres) {
+	   var->yoffset = var->yres_virtual - var->yres - 1;
+	}
 	
 	/* Set everything else to 0 */
 	var->red.msb_right = 
-	    var->green.msb_right =
-	    var->blue.msb_right =
-	    var->transp.offset = var->transp.length = var->transp.msb_right = 0;		
+	var->green.msb_right =
+	var->blue.msb_right =
+	var->transp.offset =
+	var->transp.length =
+	var->transp.msb_right = 0;
 
 	return 0;
 }
 
-static int sisfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info* info)
+static int
+sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int err;
 
-	if (var->xoffset > (var->xres_virtual - var->xres))
+	if(var->xoffset > (var->xres_virtual - var->xres)) {
 		return -EINVAL;
-	if (var->yoffset > (var->yres_virtual - var->yres))
+	}
+	if(var->yoffset > (var->yres_virtual - var->yres)) {
 		return -EINVAL;
-
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0 ||
-		    var->yoffset >= info->var.yres_virtual ||
-		    var->xoffset)
-		    	return -EINVAL;
-	} else {
-		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-		    var->yoffset + info->var.yres > info->var.yres_virtual)
-			return -EINVAL;
 	}
-    
-	if((err = sisfb_pan_var(var)) < 0) return err;
 
-	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;
+	if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
 
-	return 0;
-}
-
-static int sisfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma)
-{
-	unsigned long start;
-	unsigned long off;
-	u32 len, mmio_off;
-
-	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	start = (unsigned long) ivideo.video_base;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
-#if 0
-	if (off >= len) {
-		off -= len;
-#endif
-	/* By Jake Page: Treat mmap request with offset beyond heapstart
-	 *               as request for mapping the mmio area 
-	 */
-	mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.heapstart);
-	if(off >= mmio_off) {
-		off -= mmio_off;		
-		if(info->var.accel_flags) return -EINVAL;
-
-		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + sisfb_mmio_size);
+	if(var->xoffset + info->var.xres > info->var.xres_virtual ||
+	   var->yoffset + info->var.yres > info->var.yres_virtual) {
+		return -EINVAL;
 	}
 
-	start &= PAGE_MASK;
-	if((vma->vm_end - vma->vm_start + off) > len)	return -EINVAL;
+	if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
 
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-	vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
-
-#if defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#endif
-	if (io_remap_page_range(vma, vma->vm_start, off, vma->vm_end - vma->vm_start,
-				vma->vm_page_prot))
-		return -EAGAIN;
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
 
 	return 0;
 }
 
-static int sisfb_blank(int blank, struct fb_info *info)
+static int
+sisfb_blank(int blank, struct fb_info *info)
 {
-	return(sisfb_myblank(blank));
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+
+	return(sisfb_myblank(ivideo, blank));
 }
 
 #endif
 
 /* ----------- FBDev related routines for all series ---------- */
 
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int sisfb_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg,
-		       struct fb_info *info)
-#else
-static int sisfb_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg, int con,
-		       struct fb_info *info)
-#endif
-{
-	struct sis_memreq sismemreq;
-	struct ap_data sisapdata;
-	unsigned long sismembase = 0;
+static int
+sisfb_ioctl(struct inode *inode, struct file *file,
+            unsigned int cmd, unsigned long arg,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	SIS_GLYINFO sisglyinfo;
+	    int con,
 #endif
+	    struct fb_info *info)
+{
+	struct sis_video_info 	*ivideo = (struct sis_video_info *)info->par;
+	struct sis_memreq 	sismemreq;
+	struct fb_vblank  	sisvbblank;
+	sisfb_info        	x;
+	u32			gpu32 = 0;
+	static int 		count = 0;
+	u32 __user		*argp = (u32 __user *) arg;
 
 	switch (cmd) {
 	   case FBIO_ALLOC:
-		if(!capable(CAP_SYS_RAWIO))
+		if(!capable(CAP_SYS_RAWIO)) {
 			return -EPERM;
-		if(copy_from_user(&sismemreq, (void *)arg, sizeof(sismemreq)))
+		}
+		if(copy_from_user(&sismemreq, argp, sizeof(sismemreq))) {
 		   	return -EFAULT;
+		}
         	sis_malloc(&sismemreq);
-		if(copy_to_user((void *)arg, &sismemreq, sizeof(sismemreq))) {
-			sis_free(sismemreq.offset);
+		if(copy_to_user(argp, &sismemreq, sizeof(sismemreq))) {
+			sis_free((u32)sismemreq.offset);
 		    	return -EFAULT;
 		}
 		break;
+
 	   case FBIO_FREE:
-		if(!capable(CAP_SYS_RAWIO))
+		if(!capable(CAP_SYS_RAWIO)) {
 			return -EPERM;
-		if(get_user(sismembase, (unsigned long *) arg))
+		}
+		if(get_user(gpu32, argp)) {
 			return -EFAULT;
-		sis_free(sismembase);
+		}
+		sis_free(gpu32);
 		break;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	   case FBIOGET_GLYPH:
-	        if(copy_from_user(&sisglyinfo, (void *)arg, sizeof(sisglyinfo)))
+
+	   case FBIOGET_VBLANK:
+		sisvbblank.count = 0;
+		sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
+		if(copy_to_user(argp, &sisvbblank, sizeof(sisvbblank))) {
 			return -EFAULT;
-                sis_get_glyph(info, &sisglyinfo);
+		}
 		break;
-	   case FBIOPUT_MODEINFO:
-		{
-			struct mode_info x;
 
-			if(copy_from_user(&x, (void *)arg, sizeof(x)))
-				return -EFAULT;
+	   case SISFB_GET_INFO_SIZE:
+	        return put_user(sizeof(sisfb_info), argp);
 
-			ivideo.video_bpp        = x.bpp;
-			ivideo.video_width      = x.xres;
-			ivideo.video_height     = x.yres;
-			ivideo.video_vwidth     = x.v_xres;
-			ivideo.video_vheight    = x.v_yres;
-			ivideo.org_x            = x.org_x;
-			ivideo.org_y            = x.org_y;
-			ivideo.refresh_rate     = x.vrate;
-			ivideo.video_linelength = ivideo.video_vwidth * (ivideo.video_bpp >> 3);
-			sisfb_set_vparms();
-			break;
+	   case SISFB_GET_INFO_OLD:
+	        if(++count < 50) {
+	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
-#endif
-	   case FBIOGET_HWCINFO:
-		{
-			unsigned long myhwcoffset = 0;
-
-			if(sisfb_caps & HW_CURSOR_CAP)
-				myhwcoffset = sisfb_hwcursor_vbase -
-				    (unsigned long) ivideo.video_vbase;
-
-			return put_user(myhwcoffset, (unsigned long *)arg);
-
-			break;
+	   case SISFB_GET_INFO:  /* For communication with X driver */
+		x.sisfb_id         = SISFB_ID;
+		x.sisfb_version    = VER_MAJOR;
+		x.sisfb_revision   = VER_MINOR;
+		x.sisfb_patchlevel = VER_LEVEL;
+		x.chip_id = ivideo->chip_id;
+		x.memory = ivideo->video_size / 1024;
+		x.heapstart = ivideo->heapstart / 1024;
+		if(ivideo->modechanged) {
+		   x.fbvidmode = ivideo->mode_no;
+		} else {
+		   x.fbvidmode = ivideo->modeprechange;
 		}
-	   case FBIOGET_DISPINFO:
-	   	sis_dispinfo(&sisapdata);
-		if(copy_to_user((void *)arg, &sisapdata, sizeof(sisapdata)))
+		x.sisfb_caps = ivideo->caps;
+		x.sisfb_tqlen = 512; /* yet fixed */
+		x.sisfb_pcibus = ivideo->pcibus;
+		x.sisfb_pcislot = ivideo->pcislot;
+		x.sisfb_pcifunc = ivideo->pcifunc;
+		x.sisfb_lcdpdc = ivideo->detectedpdc;
+		x.sisfb_lcdpdca = ivideo->detectedpdca;
+		x.sisfb_lcda = ivideo->detectedlcda;
+		x.sisfb_vbflags = ivideo->vbflags;
+		x.sisfb_currentvbflags = ivideo->currentvbflags;
+		x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
+		x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
+		x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
+		x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
+		x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
+		x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
+		x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
+		x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
+		x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
+		x.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
+
+		if(copy_to_user(argp, &x, sizeof(x))) {
 			return -EFAULT;
-		break;
-	   case SISFB_GET_INFO:  /* For communication with X driver */
-	        {
-			sisfb_info x;
+		}
+	        break;
 
-			x.sisfb_id = SISFB_ID;
-			x.sisfb_version = VER_MAJOR;
-			x.sisfb_revision = VER_MINOR;
-			x.sisfb_patchlevel = VER_LEVEL;
-			x.chip_id = ivideo.chip_id;
-			x.memory = ivideo.video_size / 1024;
-			x.heapstart = ivideo.heapstart / 1024;
-			x.fbvidmode = sisfb_mode_no;
-			x.sisfb_caps = sisfb_caps;
-			x.sisfb_tqlen = 512; /* yet fixed */
-			x.sisfb_pcibus = ivideo.pcibus;
-			x.sisfb_pcislot = ivideo.pcislot;
-			x.sisfb_pcifunc = ivideo.pcifunc;
-			x.sisfb_lcdpdc = sisfb_detectedpdc;
-			x.sisfb_lcda = sisfb_detectedlcda;
-			x.sisfb_vbflags = ivideo.vbflags;
-			x.sisfb_currentvbflags = ivideo.currentvbflags;
-			x.sisfb_scalelcd = SiS_Pr.UsePanelScaler;
-			x.sisfb_specialtiming = SiS_Pr.SiS_CustomT;
-			x.sisfb_haveemi = SiS_Pr.HaveEMI ? 1 : 0;
-			x.sisfb_haveemilcd = SiS_Pr.HaveEMILCD ? 1 : 0;
-			x.sisfb_emi30 = SiS_Pr.EMI_30;
-			x.sisfb_emi31 = SiS_Pr.EMI_31;
-			x.sisfb_emi32 = SiS_Pr.EMI_32;
-			x.sisfb_emi33 = SiS_Pr.EMI_33;
-			if(copy_to_user((void *)arg, &x, sizeof(x)))
-				return -EFAULT;
-	                break;
+	   case SISFB_GET_VBRSTATUS_OLD:
+	   	if(++count < 50) {
+	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
 	   case SISFB_GET_VBRSTATUS:
-	        {
-			if(sisfb_CheckVBRetrace())
-				return put_user(1UL, (unsigned long *) arg);
-			else
-				return put_user(0UL, (unsigned long *) arg);
-			break;
+	        if(sisfb_CheckVBRetrace(ivideo)) {
+			return put_user((u32)1, argp);
+		} else {
+			return put_user((u32)0, argp);
+		}
+
+	   case SISFB_GET_AUTOMAXIMIZE_OLD:
+	   	if(++count < 50) {
+	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
 	   case SISFB_GET_AUTOMAXIMIZE:
-	        {
-			if(sisfb_max)
-				return put_user(1UL, (unsigned long *) arg);
-			else
-				return put_user(0UL, (unsigned long *) arg);
-			break;
+	        if(ivideo->sisfb_max) return put_user((u32)1, argp);
+		else 	              return put_user((u32)0, argp);
+
+	   case SISFB_SET_AUTOMAXIMIZE_OLD:
+	   	if(++count < 50) {
+		   printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
 	   case SISFB_SET_AUTOMAXIMIZE:
-	        {
-			unsigned long newmax;
+		if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+			return -EFAULT;
+		}
+		ivideo->sisfb_max = (gpu32) ? 1 : 0;
+		break;
 
-			if(copy_from_user(&newmax, (unsigned long *)arg, sizeof(newmax)))
-				return -EFAULT;
+	   case SISFB_SET_TVPOSOFFSET:
+		if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+			return -EFAULT;
+		}
+		sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
+		sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
+		break;
 
-			if(newmax) sisfb_max = 1;
-			else	   sisfb_max = 0;
-			break;
+	   case SISFB_GET_TVPOSOFFSET:
+	        return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)), argp);
+
+	   case SISFB_SET_LOCK:
+		if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+			return -EFAULT;
 		}
+		ivideo->sisfblocked = (gpu32) ? 1 : 0;
+		break;
+
 	   default:
 		return -EINVAL;
 	}
 	return 0;
 }
 
-
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info)
+static int
+sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
 {
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
-	strcpy(fix->id, sis_fb_info->modename);
-#else
-	strcpy(fix->id, myid);
-#endif	
-
-	fix->smem_start = ivideo.video_base;
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
-        if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
-	    if(sisvga_engine == SIS_300_VGA) {
-	       if(ivideo.video_size > 0x1000000) {
-	          	fix->smem_len = 0xc00000;
-	       } else if(ivideo.video_size > 0x800000)
-		  	fix->smem_len = 0x800000;
-	       else
-		  	fix->smem_len = 0x400000;
-            } else {
-	       	fix->smem_len = ivideo.video_size - 0x100000;
-	    }
-        } else
-		fix->smem_len = sisfb_mem * 1024;
+	strcpy(fix->id, ivideo->myid);
 
+	fix->smem_start  = ivideo->video_base;
+	fix->smem_len    = ivideo->sisfb_mem;
 	fix->type        = FB_TYPE_PACKED_PIXELS;
 	fix->type_aux    = 0;
-	if(ivideo.video_bpp == 8)
-	   fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-	   fix->visual = FB_VISUAL_TRUECOLOR;
-	fix->xpanstep    = 0;
-
-        if(sisfb_ypan) 	 fix->ypanstep = 1;
-
+	fix->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	fix->xpanstep    = 1;
+	fix->ypanstep 	 = (ivideo->sisfb_ypan) ? 1 : 0;
 	fix->ywrapstep   = 0;
-	fix->line_length = ivideo.video_linelength;
-	fix->mmio_start  = ivideo.mmio_base;
-	fix->mmio_len    = sisfb_mmio_size;
-	if(sisvga_engine == SIS_300_VGA) 
+	fix->line_length = ivideo->video_linelength;
+	fix->mmio_start  = ivideo->mmio_base;
+	fix->mmio_len    = ivideo->mmio_size;
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 	   fix->accel    = FB_ACCEL_SIS_GLAMOUR;
-	else if((ivideo.chip == SIS_330) || (ivideo.chip == SIS_760))
+	} else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) {
 	   fix->accel    = FB_ACCEL_SIS_XABRE;
-	else
+	} else {
 	   fix->accel    = FB_ACCEL_SIS_GLAMOUR_2;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	fix->reserved[0] = ivideo.video_size & 0xFFFF;
-	fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
-	fix->reserved[2] = sisfb_caps;
-#endif
+	}
 
 	return 0;
 }
@@ -2359,458 +2234,416 @@
 	.fb_get_cmap	= sisfb_get_cmap,
 	.fb_set_cmap	= sisfb_set_cmap,
         .fb_pan_display = sisfb_pan_display,
-	.fb_ioctl	= sisfb_ioctl,
-	.fb_mmap	= sisfb_mmap,
+	.fb_ioctl	= sisfb_ioctl
 };
 #endif
 
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 static struct fb_ops sisfb_ops = {
-	.owner        =	THIS_MODULE,
-	.fb_open      = sisfb_open,
-	.fb_release   = sisfb_release,
-	.fb_check_var = sisfb_check_var,
-	.fb_set_par   = sisfb_set_par,
-	.fb_setcolreg = sisfb_setcolreg,
+	.owner          = THIS_MODULE,
+	.fb_open        = sisfb_open,
+	.fb_release     = sisfb_release,
+	.fb_check_var   = sisfb_check_var,
+	.fb_set_par     = sisfb_set_par,
+	.fb_setcolreg   = sisfb_setcolreg,
         .fb_pan_display = sisfb_pan_display,
-        .fb_blank     = sisfb_blank,
-	.fb_fillrect  = fbcon_sis_fillrect,
-	.fb_copyarea  = fbcon_sis_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_cursor    = soft_cursor,	
-	.fb_sync      = fbcon_sis_sync,
-	.fb_ioctl     =	sisfb_ioctl,
-	.fb_mmap      =	sisfb_mmap,
+        .fb_blank       = sisfb_blank,
+	.fb_fillrect    = fbcon_sis_fillrect,
+	.fb_copyarea    = fbcon_sis_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+	.fb_cursor      = soft_cursor,
+	.fb_sync        = fbcon_sis_sync,
+	.fb_ioctl       = sisfb_ioctl
 };
 #endif
 
-
 /* ---------------- Chip generation dependent routines ---------------- */
 
-#ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */
-
-static int sisfb_get_dram_size_300(void)
+static struct pci_dev * sisfb_get_northbridge(int basechipid)
 {
 	struct pci_dev *pdev = NULL;
-	int pdev_valid = 0;
-	u8  pci_data, reg;
-	u16 nbridge_id;
-
-	switch (ivideo.chip) {
-	   case SIS_540:
-		nbridge_id = PCI_DEVICE_ID_SI_540;
-		break;
-	   case SIS_630:
-		nbridge_id = PCI_DEVICE_ID_SI_630;
-		break;
-	   case SIS_730:
-		nbridge_id = PCI_DEVICE_ID_SI_730;
-		break;
-	   default:
-		nbridge_id = 0;
-		break;
-	}
-
-	if (nbridge_id == 0) {  /* 300 */
-
-	        inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE,reg);
-		ivideo.video_size =
-		        ((unsigned int) ((reg & SIS_DRAM_SIZE_MASK) + 1) << 20);
+	int nbridgenum, nbridgeidx, i;
+	const unsigned short nbridgeids[] = {
+		PCI_DEVICE_ID_SI_540,	/* for SiS 540 VGA */
+		PCI_DEVICE_ID_SI_630,	/* for SiS 630/730 VGA */
+		PCI_DEVICE_ID_SI_730,
+		PCI_DEVICE_ID_SI_550,   /* for SiS 550 VGA */
+		PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */
+		PCI_DEVICE_ID_SI_651,
+		PCI_DEVICE_ID_SI_740,
+		PCI_DEVICE_ID_SI_661,	/* for SiS 661/741/660/760 VGA */
+		PCI_DEVICE_ID_SI_741,
+		PCI_DEVICE_ID_SI_660,
+		PCI_DEVICE_ID_SI_760
+	};
 
-	} else {		/* 540, 630, 730 */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-		pci_for_each_dev(pdev) {
-#else
-		while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
+    	switch(basechipid) {
+#ifdef CONFIG_FB_SIS_300
+	case SIS_540:	nbridgeidx = 0; nbridgenum = 1; break;
+	case SIS_630:	nbridgeidx = 1; nbridgenum = 2; break;
 #endif
-			if ((pdev->vendor == PCI_VENDOR_ID_SI)
-				       && (pdev->device == nbridge_id)) {
-				pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS, &pci_data);
-				pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
-				ivideo.video_size = (unsigned int)(1 << (pci_data+21));
-				pdev_valid = 1;
-
-				reg = SIS_DATA_BUS_64 << 6;
-				switch (pci_data) {
-				   case BRI_DRAM_SIZE_2MB:
-					reg |= SIS_DRAM_SIZE_2MB;
-					break;
-				   case BRI_DRAM_SIZE_4MB:
-					reg |= SIS_DRAM_SIZE_4MB;
-					break;
-				   case BRI_DRAM_SIZE_8MB:
-					reg |= SIS_DRAM_SIZE_8MB;
-					break;
-				   case BRI_DRAM_SIZE_16MB:
-					reg |= SIS_DRAM_SIZE_16MB;
-					break;
-				   case BRI_DRAM_SIZE_32MB:
-					reg |= SIS_DRAM_SIZE_32MB;
-					break;
-				   case BRI_DRAM_SIZE_64MB:
-					reg |= SIS_DRAM_SIZE_64MB;
-					break;
-				}
-				outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
-				break;
-			}  
-		}
-	
-		if (!pdev_valid)  return -1;
+#ifdef CONFIG_FB_SIS_315
+	case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;
+	case SIS_650:	nbridgeidx = 4; nbridgenum = 3; break;
+	case SIS_660:	nbridgeidx = 7; nbridgenum = 4; break;
+#endif
+	default:	return NULL;
 	}
-	return 0;
+	for(i = 0; i < nbridgenum; i++) {
+		if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break;
+	}
+	return pdev;
 }
 
-#endif  /* CONFIG_FB_SIS_300 */
-
-
-#ifdef CONFIG_FB_SIS_315    /* for SiS 315/550/650/740/330/661/741/760 */
-
-static int sisfb_get_dram_size_315(void)
+static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
 {
-	u8  reg = 0;
-
-	if(ivideo.chip == SIS_550 ||
-	   ivideo.chip == SIS_650 ||
-	   ivideo.chip == SIS_740) {
-
-                inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
-		reg &= 0x3f;
-		reg++;
-		reg <<= 2;
-		ivideo.video_size = reg << 20;
-		return 0;
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+	u8 reg;
+#endif
 
-	} else if(ivideo.chip == SIS_661 ||
-	          ivideo.chip == SIS_741 ||
-		  ivideo.chip == SIS_660 ||
-		  ivideo.chip == SIS_760) {
+	ivideo->video_size = 0;
 
+	switch(ivideo->chip) {
+#ifdef CONFIG_FB_SIS_300
+	case SIS_300:
+	        inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = ((reg & 0x3F) + 1) << 20;
+		break;
+	case SIS_540:
+	case SIS_630:
+	case SIS_730:
+	   	if(!ivideo->nbridge) return -1;
+	   	pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
+		ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
+		break;
+#endif
+#ifdef CONFIG_FB_SIS_315
+	case SIS_315H:
+	case SIS_315PRO:
+	case SIS_315:
+	   	inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		switch((reg >> 2) & 0x03) {
+		case 0x01:
+		case 0x03:
+		   ivideo->video_size <<= 1;
+		   break;
+		case 0x02:
+		   ivideo->video_size += (ivideo->video_size/2);
+		}
+	   	break;
+	case SIS_330:
+	   	inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		if(reg & 0x0c) ivideo->video_size <<= 1;
+	   	break;
+	case SIS_550:
+	case SIS_650:
+	case SIS_740:
+	    	inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
+		break;
+	case SIS_661:
+	case SIS_741:
+	     	inSISIDXREG(SISCR, 0x79, reg);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+	   	break;
+	case SIS_660:
+	case SIS_760:
 		inSISIDXREG(SISCR, 0x79, reg);
-		reg &= 0xf0;
-		reg >>= 4;
-		ivideo.video_size = (1 << reg) << 20;
-		return 0;
-
-	} else {	/* 315, 330 */
-
-	        inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
-		ivideo.video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
-
-		reg &= SIS315_DUAL_CHANNEL_MASK;
-		reg >>= 2;
-
-		if(ivideo.chip == SIS_330) {
-
-		   if(reg) ivideo.video_size <<= 1;
-		
-		} else {
-		   
-		   switch (reg) {
-		      case SIS315_SINGLE_CHANNEL_2_RANK:
-			   ivideo.video_size <<= 1;
-			   break;
-		      case SIS315_DUAL_CHANNEL_1_RANK:
-			   ivideo.video_size <<= 1;
-			   break;
-		      case SIS315_ASYM_DDR:		/* TW: DDR asymetric */
-			   ivideo.video_size += (ivideo.video_size/2);
-			   break;
-		   }
+		reg = (reg & 0xf0) >> 4;
+		if(reg)	ivideo->video_size = (1 << reg) << 20;
+		inSISIDXREG(SISCR, 0x78, reg);
+		reg &= 0x30;
+		if(reg) {
+		   if(reg == 0x10) ivideo->video_size += (32 << 20);
+		   else		   ivideo->video_size += (64 << 20);
 		}
-
-		return 0;
+	   	break;
+#endif
+	default:
+		return -1;
 	}
-	
-	return -1;
-	
+	return 0;
 }
 
-#endif   /* CONFIG_FB_SIS_315 */
-
-
-/* -------------- video bridge detection --------------- */
+/* -------------- video bridge device detection --------------- */
 
-static void sisfb_detect_VB_connect()
+static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
 {
-	u8 sr16, sr17, cr32, temp;
+	u8 cr32, temp;
 
-	if(sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		inSISIDXREG(SISSR, 0x17, temp);
+		if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
+			/* PAL/NTSC is stored on SR16 on such machines */
+			if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
+		   		inSISIDXREG(SISSR, 0x16, temp);
+				if(temp & 0x20)
+					ivideo->vbflags |= TV_PAL;
+				else
+					ivideo->vbflags |= TV_NTSC;
+			}
+		}
+	}
+#endif
 
-		inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
+	inSISIDXREG(SISCR, 0x32, cr32);
 
-		if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
+	if(cr32 & SIS_CRT1) {
+		ivideo->sisfb_crt1off = 0;
+	} else {
+		ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
+	}
 
-			/* Old BIOSes store the detected CRT2 type in SR17
-		 	 * instead of CR32. However, since our detection
-			 * routines store their results to CR32, we now copy
-			 * the remaining bits (for LCD and VGA) to CR32 for
-			 * unified usage.
-			 * SR17[0] CRT1    [1] LCD     [2] TV    [3] VGA2
-			 *     [4] AVIDEO  [5] SVIDEO
-			 */
+	ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
 
-#if 0
-			if (sr17 & 0x01) orSISIDXREG(SISCR, 0x32, SIS_CRT1);
-			else		 andSISIDXREG(SISCR, 0x32, ~SIS_CRT1);
+	if(cr32 & SIS_VB_TV)   ivideo->vbflags |= CRT2_TV;
+	if(cr32 & SIS_VB_LCD)  ivideo->vbflags |= CRT2_LCD;
+	if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
 
-			if (sr17 & 0x02) orSISIDXREG(SISCR, 0x32, SIS_VB_LCD);
-			else		 andSISIDXREG(SISCR, 0x32, ~SIS_VB_LCD);
+	/* Check given parms for hardware compatibility.
+	 * (Cannot do this in the search_xx routines since we don't
+	 * know what hardware we are running on then)
+	 */
 
-			/* no HiVision and no DVI connector here */
-			andSISIDXREG(SISCR, 0x32, ~0xc0);
-#endif
+	if(ivideo->chip != SIS_550) {
+	   ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
+	}
 
-			/* PAL/NTSC is stored on SR16 on such machines */
-			if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) {
-		   		inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_16, sr16);
-				if (sr16 & 0x20)
-					ivideo.vbflags |= TV_PAL;
-				else
-					ivideo.vbflags |= TV_NTSC;
-			}
+	if(ivideo->sisfb_tvplug != -1) {
+	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
+	       (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) {
+	      if(ivideo->sisfb_tvplug & TV_YPBPR) {
+	         ivideo->sisfb_tvplug = -1;
+		 printk(KERN_ERR "sisfb: YPbPr not supported\n");
+	      }
+	   }
+	}
+	if(ivideo->sisfb_tvplug != -1) {
+	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
+	       (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) {
+	      if(ivideo->sisfb_tvplug & TV_HIVISION) {
+	         ivideo->sisfb_tvplug = -1;
+		 printk(KERN_ERR "sisfb: HiVision not supported\n");
+	      }
+	   }
+	}
+	if(ivideo->sisfb_tvstd != -1) {
+	   if( (!(ivideo->vbflags & VB_SISBRIDGE)) &&
+	       (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) {
+	      if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
+	         ivideo->sisfb_tvstd = -1;
+	         printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
+	      }
+	   }
+	}
 
+	/* Detect/set TV plug & type */
+	if(ivideo->sisfb_tvplug != -1) {
+		ivideo->vbflags |= ivideo->sisfb_tvplug;
+	} else {
+		if(cr32 & SIS_VB_YPBPR)     	 ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
+		else if(cr32 & SIS_VB_HIVISION)  ivideo->vbflags |= TV_HIVISION;
+		else if(cr32 & SIS_VB_SCART)     ivideo->vbflags |= TV_SCART;
+	 	else {
+			if(cr32 & SIS_VB_SVIDEO)    ivideo->vbflags |= TV_SVIDEO;
+			if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
 		}
-
 	}
 
-	inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);
-
-	if (cr32 & SIS_CRT1)
-		sisfb_crt1off = 0;
-	else {
-		if (cr32 & 0x5F)
-			sisfb_crt1off = 1;
-		else
-			sisfb_crt1off = 0;
-	}
-
-	ivideo.vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
-
-	if (cr32 & SIS_VB_TV)
-		ivideo.vbflags |= CRT2_TV;
-	if (cr32 & SIS_VB_LCD)
-		ivideo.vbflags |= CRT2_LCD;
-	if (cr32 & SIS_VB_CRT2)
-		ivideo.vbflags |= CRT2_VGA;
-
-	/* TW: Detect/set TV plug & type */
-	if(sisfb_tvplug != -1)
-	        ivideo.vbflags |= sisfb_tvplug;
-
-	if (cr32 & SIS_VB_SVIDEO)
-		ivideo.vbflags |= TV_SVIDEO;
-	else if (cr32 & SIS_VB_COMPOSITE)
-		ivideo.vbflags |= TV_AVIDEO;
-	else if (cr32 & SIS_VB_SCART)
-		ivideo.vbflags |= TV_SCART;
-
-	if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) {
-		if(sisvga_engine == SIS_300_VGA) {
-	        	inSISIDXREG(SISSR, IND_SIS_POWER_ON_TRAP, temp);
-			if (temp & 0x01)
-				ivideo.vbflags |= TV_PAL;
-			else
-				ivideo.vbflags |= TV_NTSC;
-		} else if((ivideo.chip <= SIS_315PRO) || (ivideo.chip >= SIS_330)) {
-
+	if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
+	    if(ivideo->sisfb_tvstd != -1) {
+	       ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
+	       ivideo->vbflags |= ivideo->sisfb_tvstd;
+	    }
+	    if(ivideo->vbflags & TV_SCART) {
+	       ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
+	       ivideo->vbflags |= TV_PAL;
+	    }
+	    if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+	        	inSISIDXREG(SISSR, 0x38, temp);
+			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
+		} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
                 	inSISIDXREG(SISSR, 0x38, temp);
-			if(temp & 0x01)
-				ivideo.vbflags |= TV_PAL;
-			else
-				ivideo.vbflags |= TV_NTSC;
-
+			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
 	    	} else {
-
 	        	inSISIDXREG(SISCR, 0x79, temp);
-			if(temp & 0x20)
-				ivideo.vbflags |= TV_PAL;
-			else
-				ivideo.vbflags |= TV_NTSC;
+			if(temp & 0x20)	ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
 	    	}
+	    }
 	}
 
-	/* TW: Copy forceCRT1 option to CRT1off if option is given */
-    	if (sisfb_forcecrt1 != -1) {
-    		if(sisfb_forcecrt1) sisfb_crt1off = 0;
-		else                sisfb_crt1off = 1;
+	/* Copy forceCRT1 option to CRT1off if option is given */
+    	if(ivideo->sisfb_forcecrt1 != -1) {
+    	   ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
     	}
-
 }
 
-static void sisfb_get_VB_type(void)
+static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo)
 {
-	u8 vb_chipid;
-	u8 reg;
 	char stdstr[]    = "sisfb: Detected";
 	char bridgestr[] = "video bridge";
-	char lvdsstr[]   = "LVDS transmitter";
-  	char chrstr[]    = "Chrontel TV encoder";
-
-	ivideo.hasVB = HASVB_NONE;
-	sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
-	sishw_ext.Is301BDH = FALSE;
-	sishw_ext.usExternalChip = 0;
+	u8 vb_chipid;
+	u8 reg;
 
 	inSISIDXREG(SISPART4, 0x00, vb_chipid);
-	switch (vb_chipid) {
-	   case 0x01:
-		ivideo.hasVB = HASVB_301;
+	switch(vb_chipid) {
+	case 0x01:
 		inSISIDXREG(SISPART4, 0x01, reg);
 		if(reg < 0xb0) {
-			ivideo.vbflags |= VB_301;
-			sishw_ext.ujVBChipID = VB_CHIP_301;
+			ivideo->vbflags |= VB_301;
 			printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
 		} else if(reg < 0xc0) {
-		 	ivideo.vbflags |= VB_301B;
-			sishw_ext.ujVBChipID = VB_CHIP_301B;
+		 	ivideo->vbflags |= VB_301B;
 			inSISIDXREG(SISPART4,0x23,reg);
 			if(!(reg & 0x02)) {
-			   sishw_ext.Is301BDH = TRUE;
-			   ivideo.vbflags |= VB_30xBDH;
+			   ivideo->vbflags |= VB_30xBDH;
 			   printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
 			} else {
 			   printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
 			}
 		} else if(reg < 0xd0) {
-		 	ivideo.vbflags |= VB_301C;
-			sishw_ext.ujVBChipID = VB_CHIP_301C;
+		 	ivideo->vbflags |= VB_301C;
 			printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
 		} else if(reg < 0xe0) {
-			ivideo.vbflags |= VB_301LV;
-			sishw_ext.ujVBChipID = VB_CHIP_301LV;
+			ivideo->vbflags |= VB_301LV;
 			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
 		} else if(reg <= 0xe1) {
 		        inSISIDXREG(SISPART4,0x39,reg);
 			if(reg == 0xff) {
-			   ivideo.vbflags |= VB_302LV;
-			   sishw_ext.ujVBChipID = VB_CHIP_302LV;
+			   ivideo->vbflags |= VB_302LV;
 			   printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
 			} else {
-			   ivideo.vbflags |= VB_302ELV;
-			   sishw_ext.ujVBChipID = VB_CHIP_302ELV;
+			   ivideo->vbflags |= VB_301C;
+			   printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
+#if 0
+			   ivideo->vbflags |= VB_302ELV;
 			   printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
+#endif
 			}
 		}
 		break;
-	   case 0x02:
-		ivideo.hasVB = HASVB_302;
-		inSISIDXREG(SISPART4, 0x01, reg);
-		if(reg < 0xd0) {
-			ivideo.vbflags |= VB_302B;
-			sishw_ext.ujVBChipID = VB_CHIP_302B;
-			inSISIDXREG(SISPART4,0x23,reg);
-		  	if(!(reg & 0x02)) {
-			   sishw_ext.Is301BDH = TRUE;
-			   ivideo.vbflags |= VB_30xBDH;
-			   printk(KERN_INFO "%s SiS302B-DH %s\n", stdstr, bridgestr);
-			} else {
-			   printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
-			}
-		} else if(reg < 0xe0) {
-		 	ivideo.vbflags |= VB_301LV;
-			sishw_ext.ujVBChipID = VB_CHIP_301LV;
-			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
-		} else if(reg <= 0xe1) {
-			ivideo.vbflags |= VB_302LV;
-			sishw_ext.ujVBChipID = VB_CHIP_302LV;
-			printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
-		}
+	case 0x02:
+		ivideo->vbflags |= VB_302B;
+		printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
 		break;
 	}
 
-	if((!(ivideo.vbflags & VB_VIDEOBRIDGE)) && (ivideo.chip != SIS_300)) {
-		inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
+	if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
+		inSISIDXREG(SISCR, 0x37, reg);
 		reg &= SIS_EXTERNAL_CHIP_MASK;
 		reg >>= 1;
-		if(sisvga_engine == SIS_300_VGA) {
-			switch (reg) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
+			switch(reg) {
 			   case SIS_EXTERNAL_CHIP_LVDS:
-				ivideo.hasVB = HASVB_LVDS;
-				ivideo.vbflags |= VB_LVDS;
-				sishw_ext.usExternalChip = 0x01;
-				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
+				ivideo->vbflags |= VB_LVDS;
 				break;
 			   case SIS_EXTERNAL_CHIP_TRUMPION:
-				ivideo.hasVB = HASVB_TRUMPION;
-				sishw_ext.usExternalChip = 0x02;
-				printk(KERN_INFO "%s Trumpion LCD scaler\n", stdstr);
+				ivideo->vbflags |= VB_TRUMPION;
 				break;
 			   case SIS_EXTERNAL_CHIP_CHRONTEL:
-				ivideo.hasVB = HASVB_CHRONTEL;
-				ivideo.vbflags |= VB_CHRONTEL;
-				sishw_ext.usExternalChip = 0x04;
-				printk(KERN_INFO "%s %s\n", stdstr, chrstr);
+				ivideo->vbflags |= VB_CHRONTEL;
 				break;
 			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
-				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
-				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				sishw_ext.usExternalChip = 0x05;
-				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
 				break;
 			}
-		} else if(ivideo.chip < SIS_661) {
+			if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1;
+#endif
+		} else if(ivideo->chip < SIS_661) {
+#ifdef CONFIG_FB_SIS_315
 			switch (reg) {
 	 	   	   case SIS310_EXTERNAL_CHIP_LVDS:
-				ivideo.hasVB = HASVB_LVDS;
-				ivideo.vbflags |= VB_LVDS;
-				sishw_ext.usExternalChip = 0x01;
-				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
+				ivideo->vbflags |= VB_LVDS;
 				break;
 		   	   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
-				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
-				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				sishw_ext.usExternalChip = 0x05;
-				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
+				break;
+			}
+			if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+		} else if(ivideo->chip >= SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+			inSISIDXREG(SISCR, 0x38, reg);
+			reg >>= 5;
+			switch(reg) {
+			   case 0x02:
+				ivideo->vbflags |= VB_LVDS;
+				break;
+			   case 0x03:
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
+				break;
+			   case 0x04:
+				ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);
 				break;
 			}
+			if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+		}
+		if(ivideo->vbflags & VB_LVDS) {
+		   printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
+		}
+		if(ivideo->vbflags & VB_TRUMPION) {
+		   printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
+		}
+		if(ivideo->vbflags & VB_CHRONTEL) {
+		   printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
+		}
+		if(ivideo->vbflags & VB_CONEXANT) {
+		   printk(KERN_INFO "%s Conexant external device\n", stdstr);
 		}
-
 	}
 
-	if(ivideo.vbflags & VB_SISBRIDGE) {
-		SiS_Sense30x();
-	} else if(ivideo.vbflags & VB_CHRONTEL) {
-		SiS_SenseCh();
+	if(ivideo->vbflags & VB_SISBRIDGE) {
+		SiS_Sense30x(ivideo);
+	} else if(ivideo->vbflags & VB_CHRONTEL) {
+		SiS_SenseCh(ivideo);
 	}
-
 }
 
 /* ------------------ Sensing routines ------------------ */
 
-static BOOLEAN
-sisfb_test_DDC1(void)
+static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo)
 {
     unsigned short old;
     int count = 48;
 
-    old = SiS_ReadDDC1Bit(&SiS_Pr);
+    old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
     do {
-       if(old != SiS_ReadDDC1Bit(&SiS_Pr)) break;
+       	if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
     } while(count--);
     return (count == -1) ? FALSE : TRUE;
 }
 
-static void
-sisfb_sense_crt1(void)
+static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
 {
-    unsigned char SR1F, CR63=0, CR17;
-    unsigned short temp = 0xffff;
-    int i;
     BOOLEAN mustwait = FALSE;
+    u8  SR1F, CR17;
+#ifdef CONFIG_FB_SIS_315
+    u8  CR63=0;
+#endif
+    u16 temp = 0xffff;
+    int i;
 
     inSISIDXREG(SISSR,0x1F,SR1F);
     orSISIDXREG(SISSR,0x1F,0x04);
     andSISIDXREG(SISSR,0x1F,0x3F);
     if(SR1F & 0xc0) mustwait = TRUE;
 
-    if(sisvga_engine == SIS_315_VGA) {
-       inSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,CR63);
+#ifdef CONFIG_FB_SIS_315
+    if(ivideo->sisvga_engine == SIS_315_VGA) {
+       inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,CR63);
        CR63 &= 0x40;
-       andSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF);
+       andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
     }
+#endif
 
     inSISIDXREG(SISCR,0x17,CR17);
     CR17 &= 0x80;
@@ -2822,25 +2655,46 @@
     }
 
     if(mustwait) {
-       for(i=0; i < 10; i++) sisfbwaitretracecrt1();
+       for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
     }
 
-    i = 3;
-    do {
-       temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine, 0, 0, NULL);
-    } while(((temp == 0) || (temp == 0xffff)) && i--);
+#ifdef CONFIG_FB_SIS_315
+    if(ivideo->chip >= SIS_330) {
+       andSISIDXREG(SISCR,0x32,~0x20);
+       if(ivideo->chip >= SIS_340) {
+          outSISIDXREG(SISCR, 0x57, 0x4a);
+       } else {
+          outSISIDXREG(SISCR, 0x57, 0x5f);
+       }
+       orSISIDXREG(SISCR, 0x53, 0x02);
+       while((inSISREG(SISINPSTAT)) & 0x01)    break;
+       while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
+       if((inSISREG(SISMISCW)) & 0x10) temp = 1;
+       andSISIDXREG(SISCR, 0x53, 0xfd);
+       andSISIDXREG(SISCR, 0x57, 0x00);
+    }
+#endif
 
-    if((temp == 0) || (temp == 0xffff)) {
-       if(sisfb_test_DDC1()) temp = 1;
+    if(temp == 0xffff) {
+       i = 3;
+       do {
+          temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL);
+       } while(((temp == 0) || (temp == 0xffff)) && i--);
+
+       if((temp == 0) || (temp == 0xffff)) {
+          if(sisfb_test_DDC1(ivideo)) temp = 1;
+       }
     }
 
     if((temp) && (temp != 0xffff)) {
        orSISIDXREG(SISCR,0x32,0x20);
     }
 
-    if(sisvga_engine == SIS_315_VGA) {
-       setSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF,CR63);
+#ifdef CONFIG_FB_SIS_315
+    if(ivideo->sisvga_engine == SIS_315_VGA) {
+       setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,CR63);
     }
+#endif
 
     setSISIDXREG(SISCR,0x17,0x7F,CR17);
 
@@ -2848,225 +2702,207 @@
 }
 
 /* Determine and detect attached devices on SiS30x */
-static int
-SISDoSense(int tempbl, int tempbh, int tempcl, int tempch)
+static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
 {
-    int temp;
+    int temp, mytest, result, i, j;
 
-    outSISIDXREG(SISPART4,0x11,tempbl);
-    temp = tempbh | tempcl;
-    setSISIDXREG(SISPART4,0x10,0xe0,temp);
-    SiS_DDC2Delay(&SiS_Pr, 0x1000);
-    tempch &= 0x7f;
-    inSISIDXREG(SISPART4,0x03,temp);
-    temp ^= 0x0e;
-    temp &= tempch;
-    return((temp == tempch));
+    for(j = 0; j < 10; j++) {
+       result = 0;
+       for(i = 0; i < 3; i++) {
+          mytest = test;
+          outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
+          temp = (type >> 8) | (mytest & 0x00ff);
+          setSISIDXREG(SISPART4,0x10,0xe0,temp);
+          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
+          mytest >>= 8;
+          mytest &= 0x7f;
+          inSISIDXREG(SISPART4,0x03,temp);
+          temp ^= 0x0e;
+          temp &= mytest;
+          if(temp == mytest) result++;
+#if 1
+	  outSISIDXREG(SISPART4,0x11,0x00);
+	  andSISIDXREG(SISPART4,0x10,0xe0);
+	  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
+#endif
+       }
+       if((result == 0) || (result >= 2)) break;
+    }
+    return(result);
 }
 
-static void
-SiS_Sense30x(void)
+static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
 {
-  u8 backupP4_0d,backupP2_00;
-  u8 svhs_bl, svhs_bh;
-  u8 svhs_cl, svhs_ch;
-  u8 cvbs_bl, cvbs_bh;
-  u8 cvbs_cl, cvbs_ch;
-  u8 vga2_bl, vga2_bh;
-  u8 vga2_cl, vga2_ch;
-  int myflag, result, haveresult, i, j;
-  char stdstr[] = "sisfb: Detected";
-  char tvstr[]  = "TV connected to";
-
-  inSISIDXREG(SISPART4,0x0d,backupP4_0d);
-  if(!(ivideo.vbflags & (VB_301C|VB_302ELV))) {
-     outSISIDXREG(SISPART4,0x0d,(backupP4_0d | 0x04));
-  }
-
-  inSISIDXREG(SISPART2,0x00,backupP2_00);
-  outSISIDXREG(SISPART2,0x00,(backupP2_00 | 0x1c));
-
-  if(sisvga_engine == SIS_300_VGA) {
-
-	if(ivideo.vbflags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV)) {
-	   	vga2_bh = 0x01; vga2_bl = 0x90;
-	   	svhs_bh = 0x01; svhs_bl = 0x6b;
-	   	cvbs_bh = 0x01; cvbs_bl = 0x74;
-	} else {
-		vga2_bh = 0x00; vga2_bl = 0xd1;
-        	svhs_bh = 0x00; svhs_bl = 0xb9;
-		cvbs_bh = 0x00; cvbs_bl = 0xb3;
-	}
-	inSISIDXREG(SISPART4,0x01,myflag);
-	if(myflag & 0x04) {
-	   vga2_bh = 0x00; vga2_bl = 0xfd;
-	   svhs_bh = 0x00; svhs_bl = 0xdd;
-	   cvbs_bh = 0x00; cvbs_bl = 0xee;
-	}
-	vga2_ch = 0x0e;	vga2_cl = 0x08;
-	svhs_ch = 0x04;	svhs_cl = 0x04;
-	cvbs_ch = 0x08; cvbs_cl = 0x04;
-	if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
-	   	vga2_bh = 0x00; vga2_bl = 0x00;
-	   	vga2_ch = 0x00; vga2_cl = 0x00;
-	 }
-	if(ivideo.chip == SIS_300) {
-	   inSISIDXREG(SISSR,0x3b,myflag);
-	   if(!(myflag & 0x01)) {
-	      	vga2_bh = 0x00; vga2_bl = 0x00;
-	      	vga2_ch = 0x00; vga2_cl = 0x00;
-	   }
-	}
+    u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
+    u16 svhs=0, svhs_c=0;
+    u16 cvbs=0, cvbs_c=0;
+    u16 vga2=0, vga2_c=0;
+    int myflag, result;
+    char stdstr[] = "sisfb: Detected";
+    char tvstr[]  = "TV connected to";
+
+    if(ivideo->vbflags & VB_301) {
+       svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
+       inSISIDXREG(SISPART4,0x01,myflag);
+       if(myflag & 0x04) {
+	  svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
+       }
+    } else if(ivideo->vbflags & (VB_301B | VB_302B)) {
+       svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
+    } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) {
+       svhs = 0x0200; cvbs = 0x0100;
+    } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) {
+       svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
+    } else return;
+
+    vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
+    if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+       svhs_c = 0x0408; cvbs_c = 0x0808;
+    }
+    biosflag = 2;
 
-  } else {
-
-	if(ivideo.vbflags & (VB_301B|VB_302B)) {
-		vga2_bh = 0x01; vga2_bl = 0x90;
-		svhs_bh = 0x01; svhs_bl = 0x6b;
-		cvbs_bh = 0x01; cvbs_bl = 0x74;
-	} else if(ivideo.vbflags & (VB_301C|VB_302ELV)) {
-	      	vga2_bh = 0x01; vga2_bl = 0x90;
-	      	svhs_bh = 0x01; svhs_bl = 0x6b;
-	      	cvbs_bh = 0x01; cvbs_bl = 0x10;
-	} else if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
-	      	vga2_bh = 0x00; vga2_bl = 0x00;
-	      	svhs_bh = 0x02; svhs_bl = 0x00;
-	      	cvbs_bh = 0x01; cvbs_bl = 0x00;
-	} else {
-		vga2_bh = 0x00; vga2_bl = 0xd1;
-        	svhs_bh = 0x00; svhs_bl = 0xb9;
-		cvbs_bh = 0x00; cvbs_bl = 0xb3;
-		inSISIDXREG(SISPART4,0x01,myflag);
-	        if(myflag & 0x04) {
-	           vga2_bh = 0x00; vga2_bl = 0xfd;
-	           svhs_bh = 0x00; svhs_bl = 0xdd;
-	           cvbs_bh = 0x00; cvbs_bl = 0xee;
-	        }
-	}
+    if(ivideo->chip == SIS_300) {
+       inSISIDXREG(SISSR,0x3b,myflag);
+       if(!(myflag & 0x01)) vga2 = vga2_c = 0;
+    }
 
-	if(ivideo.vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
-	   vga2_bh = 0x00; vga2_bl = 0x00;
-	   vga2_ch = 0x00; vga2_cl = 0x00;
-	   svhs_ch = 0x04; svhs_cl = 0x08;
-	   cvbs_ch = 0x08; cvbs_cl = 0x08;
-	} else {
-	   vga2_ch = 0x0e; vga2_cl = 0x08;
-	   svhs_ch = 0x04; svhs_cl = 0x04;
-	   cvbs_ch = 0x08; cvbs_cl = 0x04;
-	}
-    } 
-
-    if(vga2_ch || vga2_cl || vga2_bh || vga2_bl) {
-       haveresult = 0;
-       for(j = 0; j < 10; j++) {
-          result = 0;
-          for(i = 0; i < 3; i++) {
-             if(SISDoSense(vga2_bl, vga2_bh, vga2_cl, vga2_ch))
-	        result++;
-          }
-	  if((result == 0) || (result >= 2)) break;
-       }
-       if(result) {
-          printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
-	  orSISIDXREG(SISCR, 0x32, 0x10);
-       } else {
-	  andSISIDXREG(SISCR, 0x32, ~0x10);
+    inSISIDXREG(SISSR,0x1e,backupSR_1e);
+    orSISIDXREG(SISSR,0x1e,0x20);
+
+    inSISIDXREG(SISPART4,0x0d,backupP4_0d);
+    if(ivideo->vbflags & VB_301C) {
+       setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
+    } else {
+       orSISIDXREG(SISPART4,0x0d,0x04);
+    }
+    SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
+
+    inSISIDXREG(SISPART2,0x00,backupP2_00);
+    outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
+
+    inSISIDXREG(SISPART2,0x4d,backupP2_4d);
+    if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) {
+       outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
+    }
+
+    if(!(ivideo->vbflags & VB_301C)) {
+       SISDoSense(ivideo, 0, 0);
+    }
+
+    andSISIDXREG(SISCR, 0x32, ~0x14);
+
+    if(vga2_c || vga2) {
+       if(SISDoSense(ivideo, vga2, vga2_c)) {
+          if(biosflag & 0x01) {
+	     printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
+	     orSISIDXREG(SISCR, 0x32, 0x04);
+	  } else {
+	     printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
+	     orSISIDXREG(SISCR, 0x32, 0x10);
+	  }
        }
     }
 
-    if(ivideo.vbflags & (VB_301C|VB_302ELV)) {
+    andSISIDXREG(SISCR, 0x32, 0x3f);
+
+    if(ivideo->vbflags & VB_301C) {
        orSISIDXREG(SISPART4,0x0d,0x04);
     }
 
-    haveresult = 0;
-    for(j = 0; j < 10; j++) {
-       result = 0;
-       for(i = 0; i < 3; i++) {
-          if(SISDoSense(svhs_bl, svhs_bh, svhs_cl, svhs_ch))
-	        result++;
+    if((ivideo->sisvga_engine == SIS_315_VGA) &&
+       (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) {
+       outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
+       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
+       if((result = SISDoSense(ivideo, svhs, 0x0604))) {
+          if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
+	     printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
+	     orSISIDXREG(SISCR,0x32,0x80);
+	  }
        }
-       if((result == 0) || (result >= 2)) break;
-    }
-    if(result) {
-        printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
-	ivideo.vbflags |= TV_SVIDEO;
-	orSISIDXREG(SISCR, 0x32, 0x02);
-	andSISIDXREG(SISCR, 0x32, ~0x05);
+       outSISIDXREG(SISPART2,0x4d,backupP2_4d);
     }
 
-    if(!result) {
+    andSISIDXREG(SISCR, 0x32, ~0x03);
 
-	haveresult = 0;
-       	for(j = 0; j < 10; j++) {
-           result = 0;
-           for(i = 0; i < 3; i++) {
-              if(SISDoSense(cvbs_bl, cvbs_bh, cvbs_cl, cvbs_ch))
-	        result++;
-           }
-           if((result == 0) || (result >= 2)) break;
-        }
-	if(result) {
-	    printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
-	    ivideo.vbflags |= TV_AVIDEO;
-	    orSISIDXREG(SISCR, 0x32, 0x01);
-	    andSISIDXREG(SISCR, 0x32, ~0x06);
-	} else {
-	    andSISIDXREG(SISCR, 0x32, ~0x07);
-	}
+    if(!(ivideo->vbflags & TV_YPBPR)) {
+       if((result = SISDoSense(ivideo, svhs, svhs_c))) {
+          printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
+          orSISIDXREG(SISCR, 0x32, 0x02);
+       }
+       if((biosflag & 0x02) || (!result)) {
+          if(SISDoSense(ivideo, cvbs, cvbs_c)) {
+	     printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
+	     orSISIDXREG(SISCR, 0x32, 0x01);
+          }
+       }
     }
-    SISDoSense(0, 0, 0, 0);
+
+    SISDoSense(ivideo, 0, 0);
 
     outSISIDXREG(SISPART2,0x00,backupP2_00);
     outSISIDXREG(SISPART4,0x0d,backupP4_0d);
+    outSISIDXREG(SISSR,0x1e,backupSR_1e);
+
+    if(ivideo->vbflags & VB_301C) {
+       inSISIDXREG(SISPART2,0x00,biosflag);
+       if(biosflag & 0x20) {
+          for(myflag = 2; myflag > 0; myflag--) {
+	     biosflag ^= 0x20;
+	     outSISIDXREG(SISPART2,0x00,biosflag);
+	  }
+       }
+    }
+
+    outSISIDXREG(SISPART2,0x00,backupP2_00);
 }
 
 /* Determine and detect attached TV's on Chrontel */
-static void
-SiS_SenseCh(void)
+static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
 {
-
-   u8 temp1, temp2;
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+    u8 temp1, temp2;
+    char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
+#endif
 #ifdef CONFIG_FB_SIS_300
-   unsigned char test[3];
-   int i;
+    unsigned char test[3];
+    int i;
 #endif
-   char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
 
-   if(ivideo.chip < SIS_315H) {
+    if(ivideo->chip < SIS_315H) {
 
 #ifdef CONFIG_FB_SIS_300
-       SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* Chrontel 700x */
-       SiS_SetChrontelGPIO(&SiS_Pr, 0x9c);	/* Set general purpose IO for Chrontel communication */
-       SiS_DDC2Delay(&SiS_Pr, 1000);
-       temp1 = SiS_GetCH700x(&SiS_Pr, 0x25);
+       ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* Chrontel 700x */
+       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c);	/* Set general purpose IO for Chrontel communication */
+       SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
+       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
        /* See Chrontel TB31 for explanation */
-       temp2 = SiS_GetCH700x(&SiS_Pr, 0x0e);
+       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
        if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
-	  SiS_SetCH700x(&SiS_Pr, 0x0b0e);
-	  SiS_DDC2Delay(&SiS_Pr, 300);
+	  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e);
+	  SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
        }
-       temp2 = SiS_GetCH700x(&SiS_Pr, 0x25);
+       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
        if(temp2 != temp1) temp1 = temp2;
 
        if((temp1 >= 0x22) && (temp1 <= 0x50)) {
 	   /* Read power status */
-	   temp1 = SiS_GetCH700x(&SiS_Pr, 0x0e);
+	   temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
 	   if((temp1 & 0x03) != 0x03) {
      	        /* Power all outputs */
-		SiS_SetCH700x(&SiS_Pr, 0x0B0E);
-		SiS_DDC2Delay(&SiS_Pr, 300);
+		SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E);
+		SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
 	   }
 	   /* Sense connected TV devices */
 	   for(i = 0; i < 3; i++) {
-	       SiS_SetCH700x(&SiS_Pr, 0x0110);
-	       SiS_DDC2Delay(&SiS_Pr, 0x96);
-	       SiS_SetCH700x(&SiS_Pr, 0x0010);
-	       SiS_DDC2Delay(&SiS_Pr, 0x96);
-	       temp1 = SiS_GetCH700x(&SiS_Pr, 0x10);
+	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
 	       if(!(temp1 & 0x08))       test[i] = 0x02;
 	       else if(!(temp1 & 0x02))  test[i] = 0x01;
 	       else                      test[i] = 0;
-	       SiS_DDC2Delay(&SiS_Pr, 0x96);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
 	   }
 
 	   if(test[0] == test[1])      temp1 = test[0];
@@ -3079,42 +2915,42 @@
 	   }
 	   if(temp1 == 0x02) {
 		printk(KERN_INFO "%s SVIDEO output\n", stdstr);
-		ivideo.vbflags |= TV_SVIDEO;
+		ivideo->vbflags |= TV_SVIDEO;
 		orSISIDXREG(SISCR, 0x32, 0x02);
 		andSISIDXREG(SISCR, 0x32, ~0x05);
 	   } else if (temp1 == 0x01) {
 		printk(KERN_INFO "%s CVBS output\n", stdstr);
-		ivideo.vbflags |= TV_AVIDEO;
+		ivideo->vbflags |= TV_AVIDEO;
 		orSISIDXREG(SISCR, 0x32, 0x01);
 		andSISIDXREG(SISCR, 0x32, ~0x06);
 	   } else {
- 		SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
+ 		SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
 		andSISIDXREG(SISCR, 0x32, ~0x07);
 	   }
        } else if(temp1 == 0) {
-	  SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
+	  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
 	  andSISIDXREG(SISCR, 0x32, ~0x07);
        }
        /* Set general purpose IO for Chrontel communication */
-       SiS_SetChrontelGPIO(&SiS_Pr, 0x00);
+       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
 #endif
 
-   } else {
+    } else {
 
 #ifdef CONFIG_FB_SIS_315
-	SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* Chrontel 7019 */
-        temp1 = SiS_GetCH701x(&SiS_Pr, 0x49);
-	SiS_SetCH701x(&SiS_Pr, 0x2049);
-	SiS_DDC2Delay(&SiS_Pr, 0x96);
-	temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);
+	ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* Chrontel 7019 */
+        temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
+	SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
 	temp2 |= 0x01;
-	SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);
-	SiS_DDC2Delay(&SiS_Pr, 0x96);
+	SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
 	temp2 ^= 0x01;
-	SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);
-	SiS_DDC2Delay(&SiS_Pr, 0x96);
-	temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);
-	SiS_SetCH701x(&SiS_Pr, (temp1 << 8) | 0x49);
+	SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
+	SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49);
         temp1 = 0;
 	if(temp2 & 0x02) temp1 |= 0x01;
 	if(temp2 & 0x10) temp1 |= 0x01;
@@ -3123,13 +2959,13 @@
 	switch(temp1) {
 	case 0x01:
 	     printk(KERN_INFO "%s CVBS output\n", stdstr);
-	     ivideo.vbflags |= TV_AVIDEO;
+	     ivideo->vbflags |= TV_AVIDEO;
 	     orSISIDXREG(SISCR, 0x32, 0x01);
 	     andSISIDXREG(SISCR, 0x32, ~0x06);
              break;
 	case 0x02:
 	     printk(KERN_INFO "%s SVIDEO output\n", stdstr);
-	     ivideo.vbflags |= TV_SVIDEO;
+	     ivideo->vbflags |= TV_SVIDEO;
 	     orSISIDXREG(SISCR, 0x32, 0x02);
 	     andSISIDXREG(SISCR, 0x32, ~0x05);
              break;
@@ -3142,336 +2978,171 @@
 	     andSISIDXREG(SISCR, 0x32, ~0x07);
 	}
 #endif
-
-   }
+    }
 }
 
-
 /* ------------------------ Heap routines -------------------------- */
 
-static int sisfb_heap_init(void)
+static u32 __devinit
+sisfb_getheapstart(struct sis_video_info *ivideo)
 {
-	SIS_OH *poh;
-	u8 temp=0;
-#ifdef CONFIG_FB_SIS_315
-	int            agp_enabled = 1;
-	u32            agp_size;
-	unsigned long *cmdq_baseport = 0;
-	unsigned long *read_port = 0;
-	unsigned long *write_port = 0;
-	SIS_CMDTYPE    cmd_type;
-#ifndef AGPOFF
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-	struct agp_kern_info  *agp_info;
-	struct agp_memory     *agp;
-#else
-	agp_kern_info  *agp_info;
-	agp_memory     *agp;
-#endif
-	u32            agp_phys;
-#endif
-#endif
-/*     The heap start is either set manually using the "mem" parameter, or
- *     defaults as follows:
- *     -) If more than 16MB videoRAM available, let our heap start at 12MB.
- *     -) If more than  8MB videoRAM available, let our heap start at  8MB.
- *     -) If 4MB or less is available, let it start at 4MB.
- *     This is for avoiding a clash with X driver which uses the beginning
- *     of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
- *     in XF86Config-4.
- *     The heap start can also be specified by parameter "mem" when starting the sisfb
- *     driver. sisfb mem=1024 lets heap starts at 1MB, etc.
- *
- *     On the 315 and Xabre series, the default is a 1MB heap since DRI is not
- *     supported there.
- */
-     if ((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
-        if(sisvga_engine == SIS_300_VGA) {
-           if (ivideo.video_size > 0x1000000) {
-	        ivideo.heapstart = 0xc00000;
-	   } else if (ivideo.video_size > 0x800000) {
-	        ivideo.heapstart = 0x800000;
-	   } else {
-		ivideo.heapstart = 0x400000;
-	   }
-	} else {
-	   ivideo.heapstart = ivideo.video_size - 0x100000;
-	}
-     } else {
-           ivideo.heapstart = sisfb_mem * 1024;
-     }
-     sisfb_heap_start = (unsigned long) (ivideo.video_vbase + ivideo.heapstart);
-     printk(KERN_INFO "sisfb: Memory heap starting at %dK\n",
-     					(int)(ivideo.heapstart / 1024));
+	u32 ret = ivideo->sisfb_parm_mem * 1024;
+	u32 max = ivideo->video_size - ivideo->hwcursor_size;
+	u32 def;
 
-     sisfb_heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
-     sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
-
-#ifdef CONFIG_FB_SIS_315
-     if (sisvga_engine == SIS_315_VGA) {
-        /* Now initialize the 315/330 series' command queue mode.
-	 * On 315, there are three queue modes available which
-	 * are chosen by setting bits 7:5 in SR26:
-	 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
-	 *    track of the queue, the FIFO, command parsing and so
-	 *    on. This is the one comparable to the 300 series.
-	 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
-	 *    have to do queue management himself. Register 0x85c4 will
-	 *    hold the location of the next free queue slot, 0x85c8
-	 *    is the "queue read pointer" whose way of working is
-	 *    unknown to me. Anyway, this mode would require a
-	 *    translation of the MMIO commands to some kind of
-	 *    accelerator assembly and writing these commands
-	 *    to the memory location pointed to by 0x85c4.
-	 *    We will not use this, as nobody knows how this
-	 *    "assembly" works, and as it would require a complete
-	 *    re-write of the accelerator code.
-	 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
-	 *    queue in AGP memory space.
+	/* Calculate heap start = end of memory for console
 	 *
-	 * SR26 bit 4 is called "Bypass H/W queue".
-	 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
-	 * SR26 bit 0 resets the queue
-	 * Size of queue memory is encoded in bits 3:2 like this:
-	 *    00  (0x00)  512K
-	 *    01  (0x04)  1M
-	 *    10  (0x08)  2M
-	 *    11  (0x0C)  4M
-	 * The queue location is to be written to 0x85C0.
+	 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
+	 * C = console, D = heap, H = HWCursor, Q = cmd-queue
 	 *
-         */
-	cmdq_baseport = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE);
-	write_port    = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT);
-	read_port     = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_READPORT);
-
-	DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
-
-	agp_size  = COMMAND_QUEUE_AREA_SIZE;
-
-#ifndef AGPOFF
-	if (sisfb_queuemode == AGP_CMD_QUEUE) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-		agp_info = vmalloc(sizeof(*agp_info));
-		memset((void*)agp_info, 0x00, sizeof(*agp_info));
-#else
-		agp_info = vmalloc(sizeof(agp_kern_info));
-		memset((void*)agp_info, 0x00, sizeof(agp_kern_info));
-#endif
-		agp_copy_info(agp_info);
-
-		agp_backend_acquire();
-
-		agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
-					  AGP_NORMAL_MEMORY);
-		if (agp == NULL) {
-			DPRINTK("sisfb: Allocating AGP buffer failed.\n");
-			agp_enabled = 0;
-		} else {
-			if (agp_bind_memory(agp, agp->pg_start) != 0) {
-				DPRINTK("sisfb: AGP: Failed to bind memory\n");
-				/* TODO: Free AGP memory here */
-				agp_enabled = 0;
-			} else {
-				agp_enable(0);
-			}
-		}
-	}
-#else
-	agp_enabled = 0;
-#endif
-
-	/* Now select the queue mode */
+	 * Basically given by "mem" parameter
+	 *
+	 * maximum = videosize - cmd_queue - hwcursor
+	 *           (results in a heap of size 0)
+	 * default = SiS 300: depends on videosize
+	 *           SiS 315/330: 32k below max
+	 */
 
-	if ((agp_enabled) && (sisfb_queuemode == AGP_CMD_QUEUE)) {
-		cmd_type = AGP_CMD_QUEUE;
-		printk(KERN_INFO "sisfb: Using AGP queue mode\n");
-/*	} else if (sisfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)  */
-        } else if (sisfb_queuemode == VM_CMD_QUEUE) {
-		cmd_type = VM_CMD_QUEUE;
-		printk(KERN_INFO "sisfb: Using VRAM queue mode\n");
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   max -= TURBO_QUEUE_AREA_SIZE;
+	   if(ivideo->video_size > 0x1000000) {
+	      def = 0xc00000;
+	   } else if(ivideo->video_size > 0x800000) {
+	      def = 0x800000;
+	   } else {
+	      def = 0x400000;
+	   }
 	} else {
-		printk(KERN_INFO "sisfb: Using MMIO queue mode\n");
-		cmd_type = MMIO_CMD;
+	   max -= COMMAND_QUEUE_AREA_SIZE;
+	   def = max - 0x8000;
 	}
 
-	switch (agp_size) {
-	   case 0x80000:
-		temp = SIS_CMD_QUEUE_SIZE_512k;
-		break;
-	   case 0x100000:
-		temp = SIS_CMD_QUEUE_SIZE_1M;
-		break;
-	   case 0x200000:
-		temp = SIS_CMD_QUEUE_SIZE_2M;
-		break;
-	   case 0x400000:
-		temp = SIS_CMD_QUEUE_SIZE_4M;
-		break;
-	}
+        if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) {
+	   ret = def;
+        }
 
-	switch (cmd_type) {
-	   case AGP_CMD_QUEUE:
-#ifndef AGPOFF
-		DPRINTK("sisfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
-			agp_info->aper_base, agp->physical, agp_size/1024);
+	return ret;
+}
 
-		agp_phys = agp_info->aper_base + agp->physical;
+static int __devinit
+sisfb_heap_init(struct sis_video_info *ivideo)
+{
+     SIS_OH *poh;
 
-		outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, 0);
-		outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, SIS_AGP_2X);
+     ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo);
 
-                outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+     ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
+     ivideo->sisfb_heap_end   = ivideo->video_vbase + ivideo->video_size;
 
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+     /* Initialize command queue (We use MMIO only) */
 
-		*write_port = *read_port;
+#ifdef CONFIG_FB_SIS_315
+     if(ivideo->sisvga_engine == SIS_315_VGA) {
+        u32 tempq = 0;
+	u8  temp = 0;
 
-		temp |= SIS_AGP_CMDQUEUE_ENABLE;
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+        ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
 
-		*cmdq_baseport = agp_phys;
+	outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+	outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
 
-		sisfb_caps |= AGP_CMD_QUEUE_CAP;
-#endif
-		break;
+	tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
+	MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
 
-	   case VM_CMD_QUEUE:
-		sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
-		sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
+	temp = SIS_CMD_QUEUE_SIZE_512k;
+	temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
+	outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
 
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+	tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE);
+	MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
 
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+	ivideo->caps |= MMIO_CMD_QUEUE_CAP;
+     }
+#endif
 
-		*write_port = *read_port;
+#ifdef CONFIG_FB_SIS_300
+     if(ivideo->sisvga_engine == SIS_300_VGA) {
+     	unsigned long tqueue_pos;
+	u8 tq_state;
 
-		temp |= SIS_VRAM_CMDQUEUE_ENABLE;
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+	ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
 
-		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
+	tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
 
-		sisfb_caps |= VM_CMD_QUEUE_CAP;
+	inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+	tq_state |= 0xf0;
+	tq_state &= 0xfc;
+	tq_state |= (u8)(tqueue_pos >> 8);
+	outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
 
-		DPRINTK("sisfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
-			*cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
-		break;
+	outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
 
-	   default:  /* MMIO */
-	   	sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
-		sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
+	ivideo->caps |= TURBO_QUEUE_CAP;
+     }
+#endif
 
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+     /* Reserve memory for the HWCursor */
+     ivideo->sisfb_heap_end -= ivideo->hwcursor_size;
+     ivideo->hwcursor_vbase = ivideo->sisfb_heap_end;
+     ivideo->caps |= HW_CURSOR_CAP;
 
-		*write_port = *read_port;
+     ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start;
 
-		/* Set Auto_Correction bit */
-		temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+     if(ivideo->cardnumber == 0) {
 
-		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
+     	printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
+     		(int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
 
-		sisfb_caps |= MMIO_CMD_QUEUE_CAP;
+	sisfb_heap.vinfo = ivideo;
 
-		DPRINTK("sisfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
-			*cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
-		break;
-	}
-     } /* sisvga_engine = 315 */
-#endif
+     	sisfb_heap.poha_chain = NULL;
+     	sisfb_heap.poh_freelist = NULL;
 
-#ifdef CONFIG_FB_SIS_300
-     if (sisvga_engine == SIS_300_VGA) {
-  	    /* Now initialize TurboQueue. TB is always located at the very
-	     * top of the video RAM. */
-	    if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) {
-		unsigned int  tqueue_pos;
-		u8 tq_state;
-
-		tqueue_pos = (ivideo.video_size -
-		       TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
-
-		temp = (u8) (tqueue_pos & 0xff);
-
-		inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
-		tq_state |= 0xf0;
-		tq_state &= 0xfc;
-		tq_state |= (u8) (tqueue_pos >> 8);
-		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
-
-		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, temp);
-
-		sisfb_caps |= TURBO_QUEUE_CAP;
-
-		sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
-		sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
-		DPRINTK("sisfb: TurboQueue start at 0x%lx, size is %dK\n",
-			sisfb_heap_end, TURBO_QUEUE_AREA_SIZE/1024);
-	    }
-     }
-#endif
-     /* Now reserve memory for the HWCursor. It is always located at the very
-        top of the videoRAM, right below the TB memory area (if used). */
-     if (sisfb_heap_size >= sisfb_hwcursor_size) {
-		sisfb_heap_end -= sisfb_hwcursor_size;
-		sisfb_heap_size -= sisfb_hwcursor_size;
-		sisfb_hwcursor_vbase = sisfb_heap_end;
+     	poh = sisfb_poh_new_node();
+     	if(poh == NULL) return 1;
 
-		sisfb_caps |= HW_CURSOR_CAP;
+     	poh->poh_next = &sisfb_heap.oh_free;
+     	poh->poh_prev = &sisfb_heap.oh_free;
+     	poh->size = ivideo->sisfb_heap_size;
+     	poh->offset = ivideo->heapstart;
 
-		DPRINTK("sisfb: Hardware Cursor start at 0x%lx, size is %dK\n",
-			sisfb_heap_end, sisfb_hwcursor_size/1024);
-     }
+     	sisfb_heap.oh_free.poh_next = poh;
+     	sisfb_heap.oh_free.poh_prev = poh;
+     	sisfb_heap.oh_free.size = 0;
+     	sisfb_heap.max_freesize = poh->size;
 
-     sisfb_heap.poha_chain = NULL;
-     sisfb_heap.poh_freelist = NULL;
+     	sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
+     	sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
+     	sisfb_heap.oh_used.size = SENTINEL;
 
-     poh = sisfb_poh_new_node();
+     } else {
 
-     if(poh == NULL)  return 1;
-	
-     poh->poh_next = &sisfb_heap.oh_free;
-     poh->poh_prev = &sisfb_heap.oh_free;
-     poh->size = sisfb_heap_end - sisfb_heap_start + 1;
-     poh->offset = sisfb_heap_start - (unsigned long) ivideo.video_vbase;
-
-     DPRINTK("sisfb: Heap start:0x%p, end:0x%p, len=%dk\n",
-		(char *) sisfb_heap_start, (char *) sisfb_heap_end,
-		(unsigned int) poh->size / 1024);
-
-     DPRINTK("sisfb: First Node offset:0x%x, size:%dk\n",
-		(unsigned int) poh->offset, (unsigned int) poh->size / 1024);
-
-     sisfb_heap.oh_free.poh_next = poh;
-     sisfb_heap.oh_free.poh_prev = poh;
-     sisfb_heap.oh_free.size = 0;
-     sisfb_heap.max_freesize = poh->size;
-
-     sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
-     sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
-     sisfb_heap.oh_used.size = SENTINEL;
+        printk(KERN_INFO "Skipped heap initialization for secondary cards\n");
+
+     }
 
      return 0;
 }
 
-static SIS_OH *sisfb_poh_new_node(void)
+static SIS_OH *
+sisfb_poh_new_node(void)
 {
 	int           i;
 	unsigned long cOhs;
 	SIS_OHALLOC   *poha;
 	SIS_OH        *poh;
 
-	if (sisfb_heap.poh_freelist == NULL) {
-		poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
+	if(sisfb_heap.poh_freelist == NULL) {
+		poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
 		if(!poha) return NULL;
 
 		poha->poha_next = sisfb_heap.poha_chain;
 		sisfb_heap.poha_chain = poha;
 
-		cOhs = (OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
+		cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
 
 		poh = &poha->aoh[0];
-		for (i = cOhs - 1; i != 0; i--) {
+		for(i = cOhs - 1; i != 0; i--) {
 			poh->poh_next = poh + 1;
 			poh = poh + 1;
 		}
@@ -3486,21 +3157,22 @@
 	return (poh);
 }
 
-static SIS_OH *sisfb_poh_allocate(unsigned long size)
+static SIS_OH *
+sisfb_poh_allocate(u32 size)
 {
 	SIS_OH *pohThis;
 	SIS_OH *pohRoot;
 	int     bAllocated = 0;
 
-	if (size > sisfb_heap.max_freesize) {
-		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
+	if(size > sisfb_heap.max_freesize) {
+		DPRINTK("sisfb: Can't allocate %dk video memory\n",
 			(unsigned int) size / 1024);
 		return (NULL);
 	}
 
 	pohThis = sisfb_heap.oh_free.poh_next;
 
-	while (pohThis != &sisfb_heap.oh_free) {
+	while(pohThis != &sisfb_heap.oh_free) {
 		if (size <= pohThis->size) {
 			bAllocated = 1;
 			break;
@@ -3508,19 +3180,19 @@
 		pohThis = pohThis->poh_next;
 	}
 
-	if (!bAllocated) {
-		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
+	if(!bAllocated) {
+		DPRINTK("sisfb: Can't allocate %dk video memory\n",
 			(unsigned int) size / 1024);
 		return (NULL);
 	}
 
-	if (size == pohThis->size) {
+	if(size == pohThis->size) {
 		pohRoot = pohThis;
 		sisfb_delete_node(pohThis);
 	} else {
 		pohRoot = sisfb_poh_new_node();
 
-		if (pohRoot == NULL) {
+		if(pohRoot == NULL) {
 			return (NULL);
 		}
 
@@ -3539,7 +3211,8 @@
 	return (pohRoot);
 }
 
-static void sisfb_delete_node(SIS_OH *poh)
+static void
+sisfb_delete_node(SIS_OH *poh)
 {
 	SIS_OH *poh_prev;
 	SIS_OH *poh_next;
@@ -3549,10 +3222,10 @@
 
 	poh_prev->poh_next = poh_next;
 	poh_next->poh_prev = poh_prev;
-
 }
 
-static void sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
+static void
+sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
 {
 	SIS_OH *pohTemp;
 
@@ -3565,15 +3238,16 @@
 	poh->poh_next = pohTemp;
 }
 
-static SIS_OH *sisfb_poh_free(unsigned long base)
+static SIS_OH *
+sisfb_poh_free(u32 base)
 {
 	SIS_OH *pohThis;
 	SIS_OH *poh_freed;
 	SIS_OH *poh_prev;
 	SIS_OH *poh_next;
-	unsigned long ulUpper;
-	unsigned long ulLower;
-	int foundNode = 0;
+	u32     ulUpper;
+	u32     ulLower;
+	int     foundNode = 0;
 
 	poh_freed = sisfb_heap.oh_used.poh_next;
 
@@ -3586,7 +3260,7 @@
 		poh_freed = poh_freed->poh_next;
 	}
 
-	if (!foundNode)  return (NULL);
+	if(!foundNode) return(NULL);
 
 	sisfb_heap.max_freesize += poh_freed->size;
 
@@ -3596,12 +3270,10 @@
 
 	pohThis = sisfb_heap.oh_free.poh_next;
 
-	while (pohThis != &sisfb_heap.oh_free) {
-		if (pohThis->offset == ulUpper) {
+	while(pohThis != &sisfb_heap.oh_free) {
+		if(pohThis->offset == ulUpper) {
 			poh_next = pohThis;
-		}
-			else if ((pohThis->offset + pohThis->size) ==
-				 ulLower) {
+		} else if((pohThis->offset + pohThis->size) == ulLower) {
 			poh_prev = pohThis;
 		}
 		pohThis = pohThis->poh_next;
@@ -3609,65 +3281,73 @@
 
 	sisfb_delete_node(poh_freed);
 
-	if (poh_prev && poh_next) {
+	if(poh_prev && poh_next) {
 		poh_prev->size += (poh_freed->size + poh_next->size);
 		sisfb_delete_node(poh_next);
 		sisfb_free_node(poh_freed);
 		sisfb_free_node(poh_next);
-		return (poh_prev);
+		return(poh_prev);
 	}
 
-	if (poh_prev) {
+	if(poh_prev) {
 		poh_prev->size += poh_freed->size;
 		sisfb_free_node(poh_freed);
-		return (poh_prev);
+		return(poh_prev);
 	}
 
-	if (poh_next) {
+	if(poh_next) {
 		poh_next->size += poh_freed->size;
 		poh_next->offset = poh_freed->offset;
 		sisfb_free_node(poh_freed);
-		return (poh_next);
+		return(poh_next);
 	}
 
 	sisfb_insert_node(&sisfb_heap.oh_free, poh_freed);
 
-	return (poh_freed);
+	return(poh_freed);
 }
 
-static void sisfb_free_node(SIS_OH *poh)
+static void
+sisfb_free_node(SIS_OH *poh)
 {
 	if(poh == NULL) return;
 
 	poh->poh_next = sisfb_heap.poh_freelist;
 	sisfb_heap.poh_freelist = poh;
-
 }
 
-void sis_malloc(struct sis_memreq *req)
+void
+sis_malloc(struct sis_memreq *req)
 {
-	SIS_OH *poh;
+	struct sis_video_info *ivideo = sisfb_heap.vinfo;
+	SIS_OH *poh = NULL;
 
-	poh = sisfb_poh_allocate(req->size);
+	if((ivideo) && (!ivideo->havenoheap)) {
+	   poh = sisfb_poh_allocate((u32)req->size);
+	}
 
 	if(poh == NULL) {
-		req->offset = 0;
-		req->size = 0;
-		DPRINTK("sisfb: Video RAM allocation failed\n");
+	   req->offset = req->size = 0;
+	   DPRINTK("sisfb: Video RAM allocation failed\n");
 	} else {
-		DPRINTK("sisfb: Video RAM allocation succeeded: 0x%p\n",
-			(char *) (poh->offset + (unsigned long) ivideo.video_vbase));
-
-		req->offset = poh->offset;
-		req->size = poh->size;
+	   req->offset = poh->offset;
+	   req->size = poh->size;
+	   DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
+	   	    (poh->offset + ivideo->video_vbase));
 	}
 }
 
-void sis_free(unsigned long base)
+/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
+
+void
+sis_free(u32 base)
 {
+	struct sis_video_info *ivideo = sisfb_heap.vinfo;
 	SIS_OH *poh;
 
-	poh = sisfb_poh_free(base);
+	if((!ivideo) || (ivideo->havenoheap)) return;
+
+	poh = sisfb_poh_free((u32)base);
 
 	if(poh == NULL) {
 		DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
@@ -3677,125 +3357,313 @@
 
 /* --------------------- SetMode routines ------------------------- */
 
-static void sisfb_pre_setmode(void)
+static void
+sisfb_pre_setmode(struct sis_video_info *ivideo)
 {
-	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0;
+	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
+	int tvregnum = 0;
 
-	ivideo.currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
+	ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
 
 	inSISIDXREG(SISCR, 0x31, cr31);
 	cr31 &= ~0x60;
 	cr31 |= 0x04;
 
-	cr33 = sisfb_rate_idx & 0x0F;
+	cr33 = ivideo->rate_idx & 0x0F;
+
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if(ivideo->chip >= SIS_661) {
+	      inSISIDXREG(SISCR, 0x38, cr38);
+	      cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
+	   } else {
+	      tvregnum = 0x38;
+	      inSISIDXREG(SISCR, tvregnum, cr38);
+	      cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
+	   }
+	}
+#endif
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   tvregnum = 0x35;
+	   inSISIDXREG(SISCR, tvregnum, cr38);
+	}
+#endif
+
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
 
-	SiS_SetEnableDstn(&SiS_Pr, FALSE);
-	SiS_SetEnableFstn(&SiS_Pr, FALSE);
+	switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 
-	switch (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
 	   case CRT2_TV:
-		ivideo.disp_state = DISPTYPE_TV;
-		if (ivideo.vbflags & TV_SVIDEO) {
-			cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
-			ivideo.currentvbflags |= TV_SVIDEO;
-			ivideo.TV_plug = TVPLUG_SVIDEO;
-		} else if (ivideo.vbflags & TV_AVIDEO) {
-			cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
-			ivideo.currentvbflags |= TV_AVIDEO;
-			ivideo.TV_plug = TVPLUG_COMPOSITE;
-		} else if (ivideo.vbflags & TV_SCART) {
-			cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
-			ivideo.currentvbflags |= TV_SCART;
-			ivideo.TV_plug = TVPLUG_SCART;
-		}
-		cr31 |= SIS_DRIVER_MODE;
-
-		if(!(ivideo.vbflags & TV_HIVISION)) {
-	        	if (ivideo.vbflags & TV_PAL) {
-		 		cr31 |= 0x01;
-				cr35 |= 0x01;
-				ivideo.currentvbflags |= TV_PAL;
-				ivideo.TV_type = TVMODE_PAL;
-                	} else {
-		       		cr31 &= ~0x01;
-				cr35 &= ~0x01;
-				ivideo.currentvbflags |= TV_NTSC;
-				ivideo.TV_type = TVMODE_NTSC;
-			}
-		}
-		break;
+	      cr38 &= ~0xc0;   /* Clear PAL-M / PAL-N bits */
+	      if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) {
+#ifdef CONFIG_FB_SIS_315
+	         if(ivideo->chip >= SIS_661) {
+	            cr38 |= 0x04;
+	            if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
+		    else if(ivideo->vbflags & TV_YPBPR750P)  cr35 |= 0x40;
+		    else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
+		    cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
+		    cr35 &= ~0x01;
+		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
+	         } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+	            cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    cr38 |= 0x08;
+	            if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
+		    else if(ivideo->vbflags & TV_YPBPR750P)  cr38 |= 0x20;
+		    else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
+		    cr31 &= ~0x01;
+		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
+	         }
+#endif
+	      } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) {
+	         if(ivideo->chip >= SIS_661) {
+	            cr38 |= 0x04;
+	            cr35 |= 0x60;
+	         } else {
+	            cr30 |= 0x80;
+	         }
+		 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
+	         cr31 |= 0x01;
+	         cr35 |= 0x01;
+		 ivideo->currentvbflags |= TV_HIVISION;
+	      } else if(ivideo->vbflags & TV_SCART) {
+		 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		 cr31 |= 0x01;
+		 cr35 |= 0x01;
+		 ivideo->currentvbflags |= TV_SCART;
+	      } else {
+		 if(ivideo->vbflags & TV_SVIDEO) {
+		    cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    ivideo->currentvbflags |= TV_SVIDEO;
+		 }
+		 if(ivideo->vbflags & TV_AVIDEO) {
+		    cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    ivideo->currentvbflags |= TV_AVIDEO;
+		 }
+	      }
+	      cr31 |= SIS_DRIVER_MODE;
+
+	      if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) {
+	         if(ivideo->vbflags & TV_PAL) {
+		    cr31 |= 0x01; cr35 |= 0x01;
+		    ivideo->currentvbflags |= TV_PAL;
+		    if(ivideo->vbflags & TV_PALM) {
+		       cr38 |= 0x40; cr35 |= 0x04;
+		       ivideo->currentvbflags |= TV_PALM;
+		    } else if(ivideo->vbflags & TV_PALN) {
+		       cr38 |= 0x80; cr35 |= 0x08;
+		       ivideo->currentvbflags |= TV_PALN;
+	  	    }
+                 } else {
+		    cr31 &= ~0x01; cr35 &= ~0x01;
+		    ivideo->currentvbflags |= TV_NTSC;
+		    if(ivideo->vbflags & TV_NTSCJ) {
+		       cr38 |= 0x40; cr35 |= 0x02;
+		       ivideo->currentvbflags |= TV_NTSCJ;
+	 	    }
+		 }
+	      }
+	      break;
+
 	   case CRT2_LCD:
-		ivideo.disp_state = DISPTYPE_LCD;
-		cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
-		cr31 |= SIS_DRIVER_MODE;
-		SiS_SetEnableDstn(&SiS_Pr, sisfb_dstn);
-	        SiS_SetEnableFstn(&SiS_Pr, sisfb_fstn);
-		break;
+	      cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
+	      cr31 |= SIS_DRIVER_MODE;
+	      SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
+	      SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
+	      break;
+
 	   case CRT2_VGA:
-		ivideo.disp_state = DISPTYPE_CRT2;
-		cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
-		cr31 |= SIS_DRIVER_MODE;
-		if(sisfb_nocrt2rate) {
-			cr33 |= (sisbios_mode[sisfb_mode_idx].rate_idx << 4);
-		} else {
-			cr33 |= ((sisfb_rate_idx & 0x0F) << 4);
-		}
-		break;
+	      cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+	      cr31 |= SIS_DRIVER_MODE;
+	      if(ivideo->sisfb_nocrt2rate) {
+		 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
+	      } else {
+		 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
+	      }
+	      break;
+
 	   default:	/* disable CRT2 */
-		cr30 = 0x00;
-		cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
+	      cr30 = 0x00;
+	      cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
 	}
 
-	if(ivideo.chip >= SIS_661) {
-	   cr31 &= ~0x01;
-	   /* Leave overscan bit alone */
-	   setSISIDXREG(SISCR, 0x35, ~0x10, cr35);
-	}
-	outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR30, cr30);
-	outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR31, cr31);
-	outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR33, cr33);
+	outSISIDXREG(SISCR, 0x30, cr30);
+	outSISIDXREG(SISCR, 0x33, cr33);
 
+	if(ivideo->chip >= SIS_661) {
 #ifdef CONFIG_FB_SIS_315
-        if(sisvga_engine == SIS_315_VGA) {
-	   /* Clear LCDA and PAL-N/M bits */
-	   andSISIDXREG(SISCR,0x38,~0x03);
-	   if(ivideo.chip < SIS_661) {
-	      andSISIDXREG(SISCR,0x38,~0xc0);
-	   }
+	   cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
+	   setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
+	   cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
+	   setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
+#endif
+	} else if(ivideo->chip != SIS_300) {
+	   outSISIDXREG(SISCR, tvregnum, cr38);
 	}
+	outSISIDXREG(SISCR, 0x31, cr31);
+
+	if(ivideo->accel) sisfb_syncaccel(ivideo);
+
+	ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
+}
+
+/* Fix SR11 for 661 and later */
+#ifdef CONFIG_FB_SIS_315
+static void
+sisfb_fixup_SR11(struct sis_video_info *ivideo)
+{
+    u8  tmpreg;
+
+    if(ivideo->chip >= SIS_661) {
+       inSISIDXREG(SISSR,0x11,tmpreg);
+       if(tmpreg & 0x20) {
+          inSISIDXREG(SISSR,0x3e,tmpreg);
+	  tmpreg = (tmpreg + 1) & 0xff;
+	  outSISIDXREG(SISSR,0x3e,tmpreg);
+	  inSISIDXREG(SISSR,0x11,tmpreg);
+       }
+       if(tmpreg & 0xf0) {
+          andSISIDXREG(SISSR,0x11,0x0f);
+       }
+    }
+}
 #endif
 
-	if(ivideo.accel) sisfb_syncaccel();
+static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
+{
+   if(val > 32) val = 32;
+   if(val < -32) val = -32;
+   ivideo->tvxpos = val;
+
+   if(ivideo->sisfblocked) return;
+   if(!ivideo->modechanged) return;
+
+   if(ivideo->currentvbflags & CRT2_TV) {
+
+      if(ivideo->vbflags & VB_CHRONTEL) {
+
+	 int x = ivideo->tvx;
+
+	 switch(ivideo->chronteltype) {
+	 case 1:
+	     x += val;
+	     if(x < 0) x = 0;
+	     outSISIDXREG(SISSR,0x05,0x86);
+	     SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a));
+	     SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD);
+	     break;
+	 case 2:
+	     /* Not supported by hardware */
+	     break;
+	 }
+
+      } else if(ivideo->vbflags & VB_SISBRIDGE) {
 
-	SiS_Pr.SiS_UseOEM = sisfb_useoem;
+	 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
+	 unsigned short temp;
+
+	 p2_1f = ivideo->p2_1f;
+	 p2_20 = ivideo->p2_20;
+	 p2_2b = ivideo->p2_2b;
+	 p2_42 = ivideo->p2_42;
+	 p2_43 = ivideo->p2_43;
+
+	 temp = p2_1f | ((p2_20 & 0xf0) << 4);
+	 temp += (val * 2);
+	 p2_1f = temp & 0xff;
+	 p2_20 = (temp & 0xf00) >> 4;
+	 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
+	 temp = p2_43 | ((p2_42 & 0xf0) << 4);
+	 temp += (val * 2);
+	 p2_43 = temp & 0xff;
+	 p2_42 = (temp & 0xf00) >> 4;
+	 outSISIDXREG(SISPART2,0x1f,p2_1f);
+	 setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
+	 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
+	 setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
+	 outSISIDXREG(SISPART2,0x43,p2_43);
+      }
+   }
 }
 
-static void sisfb_post_setmode(void)
+static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
+{
+   if(val > 32) val = 32;
+   if(val < -32) val = -32;
+   ivideo->tvypos = val;
+
+   if(ivideo->sisfblocked) return;
+   if(!ivideo->modechanged) return;
+
+   if(ivideo->currentvbflags & CRT2_TV) {
+
+      if(ivideo->vbflags & VB_CHRONTEL) {
+
+	 int y = ivideo->tvy;
+
+	 switch(ivideo->chronteltype) {
+	 case 1:
+	    y -= val;
+	    if(y < 0) y = 0;
+	    outSISIDXREG(SISSR,0x05,0x86);
+	    SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b));
+	    SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE);
+	    break;
+	 case 2:
+	    /* Not supported by hardware */
+	    break;
+	 }
+
+      } else if(ivideo->vbflags & VB_SISBRIDGE) {
+
+	 char p2_01, p2_02;
+	 val /= 2;
+	 p2_01 = ivideo->p2_01;
+	 p2_02 = ivideo->p2_02;
+
+	 p2_01 += val;
+	 p2_02 += val;
+	 while((p2_01 <= 0) || (p2_02 <= 0)) {
+	    p2_01 += 2;
+	    p2_02 += 2;
+	 }
+	 outSISIDXREG(SISPART2,0x01,p2_01);
+	 outSISIDXREG(SISPART2,0x02,p2_02);
+      }
+   }
+}
+
+static void
+sisfb_post_setmode(struct sis_video_info *ivideo)
 {
-	u8 reg;
 	BOOLEAN crt1isoff = FALSE;
+	BOOLEAN doit = TRUE;
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+	u8 reg;
+#endif
 #ifdef CONFIG_FB_SIS_315
 	u8 reg1;
 #endif
-#ifdef CONFIG_FB_SIS_300
-	BOOLEAN doit = TRUE;
-#endif
-	/* We can't switch off CRT1 if bridge is in slave mode */
-	if(ivideo.vbflags & VB_VIDEOBRIDGE) {
-#ifdef CONFIG_FB_SIS_300
-		if(sisvga_engine == SIS_300_VGA) {
-			inSISIDXREG(SISPART1, 0x00, reg);
-			if((reg & 0xa0) == 0x20) {
-				doit = FALSE;
-			}
-		}
+
+	outSISIDXREG(SISSR,0x05,0x86);
+
+#ifdef CONFIG_FB_SIS_315
+	sisfb_fixup_SR11(ivideo);
 #endif
-	} else sisfb_crt1off = 0;
 
-	if(sisvga_engine == SIS_300_VGA) {
+	/* Now we actually HAVE changed the display mode */
+        ivideo->modechanged = 1;
+
+	/* We can't switch off CRT1 if bridge is in slave mode */
+	if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+		if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
+	} else ivideo->sisfb_crt1off = 0;
 
 #ifdef CONFIG_FB_SIS_300
-	   if((sisfb_crt1off) && (doit)) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   if((ivideo->sisfb_crt1off) && (doit)) {
 	        crt1isoff = TRUE;
 		reg = 0x00;
 	   } else {
@@ -3803,12 +3671,11 @@
 		reg = 0x80;
 	   }
 	   setSISIDXREG(SISCR, 0x17, 0x7f, reg);
+	}
 #endif
-
-	} else {
-
 #ifdef CONFIG_FB_SIS_315
-	   if(sisfb_crt1off) {
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if((ivideo->sisfb_crt1off) && (doit)) {
 	        crt1isoff = TRUE;
 		reg  = 0x40;
 		reg1 = 0xc0;
@@ -3818,66 +3685,89 @@
 		reg1 = 0x00;
 
 	   }
-	   setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, ~0x40, reg);
+	   setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
 	   setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
-#endif
-
 	}
+#endif
 
 	if(crt1isoff) {
-	   ivideo.currentvbflags &= ~VB_DISPTYPE_CRT1;
-	   ivideo.currentvbflags |= VB_SINGLE_MODE;
-	   ivideo.disp_state |= DISPMODE_SINGLE;
+	   ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
+	   ivideo->currentvbflags |= VB_SINGLE_MODE;
 	} else {
-	   ivideo.currentvbflags |= VB_DISPTYPE_CRT1;
-	   ivideo.disp_state |= DISPTYPE_CRT1;
-	   if(ivideo.currentvbflags & VB_DISPTYPE_CRT2) {
-	  	ivideo.currentvbflags |= VB_MIRROR_MODE;
-		ivideo.disp_state |= DISPMODE_MIRROR;
+	   ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
+	   if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
+	  	ivideo->currentvbflags |= VB_MIRROR_MODE;
 	   } else {
-	 	ivideo.currentvbflags |= VB_SINGLE_MODE;
-		ivideo.disp_state |= DISPMODE_SINGLE;
+	 	ivideo->currentvbflags |= VB_SINGLE_MODE;
 	   }
 	}
 
         andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
 
-	if((ivideo.currentvbflags & CRT2_TV) && (ivideo.vbflags & VB_301)) {  /* Set filter for SiS301 */
+	if(ivideo->currentvbflags & CRT2_TV) {
+	   if(ivideo->vbflags & VB_SISBRIDGE) {
+	      inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
+	      inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
+	      inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
+	      inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
+	      inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
+	      inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
+	      inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
+	   } else if(ivideo->vbflags & VB_CHRONTEL) {
+	      if(ivideo->chronteltype == 1) {
+	         ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
+	         ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
+	         ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
+	         ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
+ 	      }
+	   }
+	}
+
+	if(ivideo->tvxpos) {
+   	   sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
+	}
+	if(ivideo->tvypos) {
+   	   sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
+	}
+
+	if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) {  /* Set filter for SiS301 */
 
-		switch (ivideo.video_width) {
+	   	unsigned char filter_tb = 0;
+
+		switch (ivideo->video_width) {
 		   case 320:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 4 : 12;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12;
 			break;
 		   case 640:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 5 : 13;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13;
 			break;
 		   case 720:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 6 : 14;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14;
 			break;
 		   case 400:
 		   case 800:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 7 : 15;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15;
 			break;
 		   default:
-			filter = -1;
+			ivideo->sisfb_filter = -1;
 			break;
 		}
 
-		orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);
+		orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
 
-		if(ivideo.vbflags & TV_NTSC) {
+		if(ivideo->vbflags & TV_NTSC) {
 
 		        andSISIDXREG(SISPART2, 0x3a, 0x1f);
 
-			if (ivideo.vbflags & TV_SVIDEO) {
+			if (ivideo->vbflags & TV_SVIDEO) {
 
 			        andSISIDXREG(SISPART2, 0x30, 0xdf);
 
-			} else if (ivideo.vbflags & TV_AVIDEO) {
+			} else if (ivideo->vbflags & TV_AVIDEO) {
 
 			        orSISIDXREG(SISPART2, 0x30, 0x20);
 
-				switch (ivideo.video_width) {
+				switch (ivideo->video_width) {
 				case 640:
 				        outSISIDXREG(SISPART2, 0x35, 0xEB);
 					outSISIDXREG(SISPART2, 0x36, 0x04);
@@ -3900,19 +3790,19 @@
 				}
 			}
 
-		} else if(ivideo.vbflags & TV_PAL) {
+		} else if(ivideo->vbflags & TV_PAL) {
 
 			andSISIDXREG(SISPART2, 0x3A, 0x1F);
 
-			if (ivideo.vbflags & TV_SVIDEO) {
+			if (ivideo->vbflags & TV_SVIDEO) {
 
 			        andSISIDXREG(SISPART2, 0x30, 0xDF);
 
-			} else if (ivideo.vbflags & TV_AVIDEO) {
+			} else if (ivideo->vbflags & TV_AVIDEO) {
 
 			        orSISIDXREG(SISPART2, 0x30, 0x20);
 
-				switch (ivideo.video_width) {
+				switch (ivideo->video_width) {
 				case 640:
 					outSISIDXREG(SISPART2, 0x35, 0xF1);
 					outSISIDXREG(SISPART2, 0x36, 0xF7);
@@ -3936,129 +3826,137 @@
 			}
 		}
 
-		if ((filter >= 0) && (filter <= 7)) {
-			DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
-				sis_TV_filter[filter_tb].filter[filter][0],
-				sis_TV_filter[filter_tb].filter[filter][1],
-				sis_TV_filter[filter_tb].filter[filter][2],
-				sis_TV_filter[filter_tb].filter[filter][3]
-			);
-			outSISIDXREG(SISPART2, 0x35, (sis_TV_filter[filter_tb].filter[filter][0]));
-			outSISIDXREG(SISPART2, 0x36, (sis_TV_filter[filter_tb].filter[filter][1]));
-			outSISIDXREG(SISPART2, 0x37, (sis_TV_filter[filter_tb].filter[filter][2]));
-			outSISIDXREG(SISPART2, 0x38, (sis_TV_filter[filter_tb].filter[filter][3]));
+		if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) {
+		   outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0]));
+		   outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1]));
+		   outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2]));
+		   outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3]));
 		}
 	  
 	}
-
 }
 
 #ifndef MODULE
-int sisfb_setup(char *options)
+int __init sisfb_setup(char *options)
 {
 	char *this_opt;
 	
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	sisfb_fontname[0] = '\0';
-#endif
-
-	ivideo.refresh_rate = 0;
-	SiS_Pr.SiS_CustomT = CUT_NONE;
-	SiS_Pr.UsePanelScaler = -1;
-	SiS_Pr.LVDSHL = -1;
+	sisfb_setdefaultparms();
 
         printk(KERN_DEBUG "sisfb: Options %s\n", options);
 
-	if (!options || !*options)
+	if(!options || !(*options)) {
 		return 0;
+	}
 
 	while((this_opt = strsep(&options, ",")) != NULL) {
 
-		if (!*this_opt)	continue;
+		if(!(*this_opt)) continue;
 
-		if (!strnicmp(this_opt, "mode:", 5)) {
+		if(!strnicmp(this_opt, "off", 3)) {
+			sisfb_off = 1;
+		} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
+			/* Need to check crt2 type first for fstn/dstn */
+			sisfb_search_crt2type(this_opt + 14);
+		} else if(!strnicmp(this_opt, "tvmode:",7)) {
+		        sisfb_search_tvstd(this_opt + 7);
+                } else if(!strnicmp(this_opt, "tvstandard:",11)) {
+			sisfb_search_tvstd(this_opt + 7);
+		} else if(!strnicmp(this_opt, "mode:", 5)) {
 			sisfb_search_mode(this_opt + 5, FALSE);
-		} else if (!strnicmp(this_opt, "vesa:", 5)) {
+		} else if(!strnicmp(this_opt, "vesa:", 5)) {
 			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		} else if (!strnicmp(this_opt, "inverse", 7)) {
+		} else if(!strnicmp(this_opt, "inverse", 7)) {
 			sisfb_inverse = 1;
 			/* fb_invert_cmaps(); */
-		} else if (!strnicmp(this_opt, "font:", 5)) {
-			strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
-			sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
-#endif
-		} else if (!strnicmp(this_opt, "vrate:", 6)) {
-			ivideo.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
-			sisfb_parm_rate = ivideo.refresh_rate;
-		} else if (!strnicmp(this_opt, "rate:", 5)) {
-			ivideo.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
-			sisfb_parm_rate = ivideo.refresh_rate;
-		} else if (!strnicmp(this_opt, "off", 3)) {
-			sisfb_off = 1;
-		} else if (!strnicmp(this_opt, "crt1off", 7)) {
-			sisfb_crt1off = 1;
-		} else if (!strnicmp(this_opt, "filter:", 7)) {
-			filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if (!strnicmp(this_opt, "forcecrt2type:", 14)) {
-			sisfb_search_crt2type(this_opt + 14);
-		} else if (!strnicmp(this_opt, "forcecrt1:", 10)) {
+		} else if(!strnicmp(this_opt, "font:", 5)) {
+		        if(strlen(this_opt + 5) < 40) {
+			   strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
+			   sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
+			}
+#endif
+		} else if(!strnicmp(this_opt, "rate:", 5)) {
+			sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
+		} else if(!strnicmp(this_opt, "filter:", 7)) {
+			sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
+		} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
 			sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
-                } else if (!strnicmp(this_opt, "tvmode:",7)) {
-		        sisfb_search_tvstd(this_opt + 7);
-                } else if (!strnicmp(this_opt, "tvstandard:",11)) {
-			sisfb_search_tvstd(this_opt + 7);
-                } else if (!strnicmp(this_opt, "mem:",4)) {
-		        sisfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if (!strnicmp(this_opt, "queuemode:", 10)) {
-			sisfb_search_queuemode(this_opt + 10);
-		} else if (!strnicmp(this_opt, "pdc:", 4)) {
+                } else if(!strnicmp(this_opt, "mem:",4)) {
+		        sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
+		} else if(!strnicmp(this_opt, "pdc:", 4)) {
 		        sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if (!strnicmp(this_opt, "noaccel", 7)) {
+		} else if(!strnicmp(this_opt, "pdc1:", 5)) {
+		        sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
+		} else if(!strnicmp(this_opt, "noaccel", 7)) {
 			sisfb_accel = 0;
-		} else if (!strnicmp(this_opt, "noypan", 6)) {
+		} else if(!strnicmp(this_opt, "accel", 5)) {
+			sisfb_accel = -1;
+		} else if(!strnicmp(this_opt, "noypan", 6)) {
 		        sisfb_ypan = 0;
-		} else if (!strnicmp(this_opt, "nomax", 5)) {
+		} else if(!strnicmp(this_opt, "ypan", 4)) {
+		        sisfb_ypan = -1;
+		} else if(!strnicmp(this_opt, "nomax", 5)) {
 		        sisfb_max = 0;
-		} else if (!strnicmp(this_opt, "userom:", 7)) {
+		} else if(!strnicmp(this_opt, "max", 3)) {
+		        sisfb_max = -1;
+		} else if(!strnicmp(this_opt, "userom:", 7)) {
 			sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if (!strnicmp(this_opt, "useoem:", 7)) {
+		} else if(!strnicmp(this_opt, "useoem:", 7)) {
 			sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if (!strnicmp(this_opt, "nocrt2rate", 10)) {
+		} else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
 			sisfb_nocrt2rate = 1;
-	 	} else if (!strnicmp(this_opt, "scalelcd:", 9)) {
+	 	} else if(!strnicmp(this_opt, "scalelcd:", 9)) {
 		        unsigned long temp = 2;
 		        temp = simple_strtoul(this_opt + 9, NULL, 0);
 		        if((temp == 0) || (temp == 1)) {
-			   SiS_Pr.UsePanelScaler = temp ^ 1;
+			   sisfb_scalelcd = temp ^ 1;
 		        }
-		} else if (!strnicmp(this_opt, "specialtiming:", 14)) {
+		} else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
+		        int temp = 0;
+		        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+		        if((temp >= -32) && (temp <= 32)) {
+			   sisfb_tvxposoffset = temp;
+		        }
+		} else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
+		        int temp = 0;
+		        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+		        if((temp >= -32) && (temp <= 32)) {
+			   sisfb_tvyposoffset = temp;
+		        }
+		} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
 			sisfb_search_specialtiming(this_opt + 14);
-		} else if (!strnicmp(this_opt, "lvdshl:", 7)) {
-		        unsigned long temp = 4;
+		} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
+		        int temp = 4;
 		        temp = simple_strtoul(this_opt + 7, NULL, 0);
 		        if((temp >= 0) && (temp <= 3)) {
-			   SiS_Pr.LVDSHL = temp;
+			   sisfb_lvdshl = temp;
 		        }
 		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
 			sisfb_search_mode(this_opt, TRUE);
+#if !defined(__i386__) && !defined(__x86_64__)
+	        } else if(!strnicmp(this_opt, "resetcard", 9)) {
+		  	sisfb_resetcard = 1;
+	        } else if(!strnicmp(this_opt, "videoram:", 9)) {
+		  	sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
+#endif
 		} else {
 			printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
 		}
 
-		/* TW: Acceleration only with MMIO mode */
-		if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
-			sisfb_accel = 0;
-		}
-
 	}
+
+
+
 	return 0;
 }
 #endif
 
-static char *sis_find_rom(void)
+static char * __devinit sis_find_rom(struct pci_dev *pdev)
 {
-#if defined(__i386__)
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+
+#if defined(__i386__) || defined(__x86_64__)
         u32  segstart;
         unsigned char *rom_base, *rom;
         int  romptr;
@@ -4066,292 +3964,972 @@
 
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
 
-                rom_base = (char *)ioremap(segstart, 0x10000);
-		if(!rom_base) continue;
+            rom_base = (unsigned char *)ioremap(segstart, 0x10000);
+	    if(!rom_base) continue;
 
-                if((*rom_base != 0x55) || (*(rom_base + 1) != 0xaa)) {
-                   iounmap(rom_base);
-                   continue;
-                }
+	    if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
+	       iounmap(rom_base);
+               continue;
+	    }
 
-		romptr = (unsigned short)(*(rom_base + 0x18) | (*(rom_base + 0x19) << 8));
-		if(romptr > (0x10000 - 8)) {
-		   iounmap(rom_base);
-		   continue;
-		}
+	    romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+	    if(romptr > (0x10000 - 8)) {
+	       iounmap(rom_base);
+	       continue;
+	    }
 
-		rom = rom_base + romptr;
+	    rom = rom_base + romptr;
 
-		if((*rom != 'P') || (*(rom + 1) != 'C') || (*(rom + 2) != 'I') || (*(rom + 3) != 'R')) {
-		   iounmap(rom_base);
-		   continue;
-		}
+	    if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
+	       (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
+	       iounmap(rom_base);
+	       continue;
+	    }
 
-		pciid = (*(rom + 4)) | ((*(rom + 5)) << 8);
-		if(pciid != 0x1039) {
-		   iounmap(rom_base);
-		   continue;
-		}
+	    pciid = readb(rom + 4) | (readb(rom + 5) << 8);
+	    if(pciid != 0x1039) {
+	       iounmap(rom_base);
+	       continue;
+	    }
 
-		pciid = (*(rom + 6)) | ((*(rom + 7)) << 8);
-		if(pciid == ivideo.chip_id) return rom_base;
+	    pciid = readb(rom + 6) | (readb(rom + 7) << 8);
+	    if(pciid == ivideo->chip_id) return rom_base;
 
-		iounmap(rom_base);
+	    iounmap(rom_base);
         }
+#else
+	unsigned char *rom_base, *rom, *myrombase = NULL;
+        int  romptr;
+	unsigned short pciid;
+	u32 backup;
+
+	pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &backup);
+	pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
+			(ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
+
+	rom_base = ioremap(ivideo->video_base, 65536);
+	if(rom_base) {
+	   if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) {
+	      romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+	      if(romptr <= (0x10000 - 8)) {
+	         rom = rom_base + romptr;
+		 if((readb(rom)     == 'P') && (readb(rom + 1) == 'C') &&
+		    (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) {
+		    pciid = readb(rom + 4) | (readb(rom + 5) << 8);
+		    if(pciid == 0x1039) {
+		       pciid = readb(rom + 6) | (readb(rom + 7) << 8);
+		       if(pciid == ivideo->chip_id) {
+		          if((myrombase = vmalloc(65536))) {
+			     memcpy_fromio(myrombase, rom_base, 65536);
+			  }
+		       }
+		    }
+		 }
+	      }
+	   }
+	   iounmap(rom_base);
+	}
+        pci_write_config_dword(pdev, PCI_ROM_ADDRESS, backup);
+	if(myrombase) return myrombase;
 #endif
         return NULL;
 }
 
+#ifdef CONFIG_FB_SIS_300
+static int __devinit
+sisfb_chkbuswidth300(struct pci_dev *pdev, ULONG FBAddress)
+{
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	int i, j;
+	USHORT temp;
+	UCHAR reg;
+
+	andSISIDXREG(SISSR,0x15,0xFB);
+	orSISIDXREG(SISSR,0x15,0x04);
+   	outSISIDXREG(SISSR,0x13,0x00);
+   	outSISIDXREG(SISSR,0x14,0xBF);
+
+	for(i=0; i<2; i++) {
+	   temp = 0x1234;
+	   for(j=0; j<4; j++) {
+	      writew(temp, FBAddress);
+	      if(readw(FBAddress) == temp) break;
+	      orSISIDXREG(SISSR,0x3c,0x01);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      andSISIDXREG(SISSR,0x3c,0xfe);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      temp++;
+	   }
+	}
 
+	writel(0x01234567L, FBAddress);
+	writel(0x456789ABL, (FBAddress+4));
+	writel(0x89ABCDEFL, (FBAddress+8));
+	writel(0xCDEF0123L, (FBAddress+12));
+	inSISIDXREG(SISSR,0x3b,reg);
+	if(reg & 0x01) {
+	   if(readl((FBAddress+12)) == 0xCDEF0123L) return(4);  /* Channel A 128bit */
+	}
+	if(readl((FBAddress+4)) == 0x456789ABL)     return(2);  /* Channel B 64bit */
+	return(1);						/* 32bit */
+}
+
+static void __devinit
+sisfb_setramsize300(struct pci_dev *pdev)
+{
+	struct  sis_video_info *ivideo = pci_get_drvdata(pdev);
+  	ULONG 	FBAddr = (ULONG)ivideo->sishw_ext.pjVideoMemoryAddress, Addr;
+	USHORT 	SR13, SR14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
+	int     PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
+   	int     RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
+   	int     PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k;
+	const 	USHORT SiS_DRAMType[17][5] = {
+			{0x0C,0x0A,0x02,0x40,0x39},
+			{0x0D,0x0A,0x01,0x40,0x48},
+			{0x0C,0x09,0x02,0x20,0x35},
+			{0x0D,0x09,0x01,0x20,0x44},
+			{0x0C,0x08,0x02,0x10,0x31},
+			{0x0D,0x08,0x01,0x10,0x40},
+			{0x0C,0x0A,0x01,0x20,0x34},
+			{0x0C,0x09,0x01,0x08,0x32},
+			{0x0B,0x08,0x02,0x08,0x21},
+			{0x0C,0x08,0x01,0x08,0x30},
+			{0x0A,0x08,0x02,0x04,0x11},
+			{0x0B,0x0A,0x01,0x10,0x28},
+			{0x09,0x08,0x02,0x02,0x01},
+			{0x0B,0x09,0x01,0x08,0x24},
+			{0x0B,0x08,0x01,0x04,0x20},
+			{0x0A,0x08,0x01,0x02,0x10},
+			{0x09,0x08,0x01,0x01,0x00}
+		};
+
+        buswidth = sisfb_chkbuswidth300(pdev, FBAddr);
+
+   	MB2Bank = 16;
+   	Done = 0;
+   	for(i = 6; i >= 0; i--) {
+      	   if(Done) break;
+      	   PseudoRankCapacity = 1 << i;
+      	   for(j = 4; j >= 1; j--) {
+              if(Done) break;
+              PseudoTotalCapacity = PseudoRankCapacity * j;
+              PseudoAdrPinCount = 15 - j;
+              if(PseudoTotalCapacity <= 64) {
+                 for(k = 0; k <= 16; k++) {
+                    if(Done) break;
+                    RankCapacity = buswidth * SiS_DRAMType[k][3];
+                    AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0];
+                    if(RankCapacity == PseudoRankCapacity)
+                       if(AdrPinCount <= PseudoAdrPinCount) {
+                          if(j == 3) {             /* Rank No */
+                             BankNumHigh = RankCapacity * MB2Bank * 3 - 1;
+                             BankNumMid  = RankCapacity * MB2Bank * 1 - 1;
+                          } else {
+                             BankNumHigh = RankCapacity * MB2Bank * j - 1;
+                             BankNumMid  = RankCapacity * MB2Bank * j / 2 - 1;
+                          }
+                          PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
+                          PhysicalAdrHigh = BankNumHigh;
+                          PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
+                          PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
+                          /* Write data */
+                          andSISIDXREG(SISSR,0x15,0xFB); /* Test */
+                          orSISIDXREG(SISSR,0x15,0x04);  /* Test */
+                          TotalCapacity = SiS_DRAMType[k][3] * buswidth;
+                          SR13 = SiS_DRAMType[k][4];
+                          if(buswidth == 4) SR14 = (TotalCapacity - 1) | 0x80;
+                          if(buswidth == 2) SR14 = (TotalCapacity - 1) | 0x40;
+                          if(buswidth == 1) SR14 = (TotalCapacity - 1) | 0x00;
+                          outSISIDXREG(SISSR,0x13,SR13);
+                          outSISIDXREG(SISSR,0x14,SR14);
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
+                          /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */
+			  writew(((USHORT)PhysicalAdrHigh), Addr);
+                          Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh;
+                          /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */
+			  writew(((USHORT)BankNumMid), Addr);
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage;
+                          /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */
+			  writew(((USHORT)PhysicalAdrHalfPage), Addr);
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage;
+                          /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */
+			  writew(((USHORT)PhysicalAdrOtherPage), Addr);
+                          /* Read data */
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
+                          data = readw(Addr); /* *((USHORT *)(Addr)); */
+                          if(data == PhysicalAdrHigh) Done = 1;
+                       }  /* if */
+                 }  /* for k */
+              }  /* if */
+      	   }  /* for j */
+   	}  /* for i */
+}
+
+static void __devinit sisfb_post_sis300(struct pci_dev *pdev)
+{
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
+	u16 index, rindex, memtype = 0;
+
+	outSISIDXREG(SISSR,0x05,0x86);
+
+	if(ivideo->sishw_ext.UseROM) {
+	   if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
+	      memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
+ 	   } else {
+	      inSISIDXREG(SISSR,0x3a,memtype);
+	   }
+	   memtype &= 0x07;
+	}
 
-int __init sisfb_init(void)
+	if(ivideo->revision_id <= 0x13) {
+	   v1 = 0x44; v2 = 0x42; v3 = 0x80;
+	   v4 = 0x44; v5 = 0x42; v6 = 0x80;
+	} else {
+	   v1 = 0x68; v2 = 0x43; v3 = 0x80;  /* Assume 125Mhz MCLK */
+	   v4 = 0x68; v5 = 0x43; v6 = 0x80;  /* Assume 125Mhz ECLK */
+	   if(ivideo->sishw_ext.UseROM) {
+	      index = memtype * 5;
+	      rindex = index + 0x54;
+	      v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      rindex = index + 0x7c;
+	      v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	   }
+	}
+	outSISIDXREG(SISSR,0x28,v1);
+	outSISIDXREG(SISSR,0x29,v2);
+	outSISIDXREG(SISSR,0x2a,v3);
+	outSISIDXREG(SISSR,0x2e,v4);
+	outSISIDXREG(SISSR,0x2f,v5);
+	outSISIDXREG(SISSR,0x30,v6);
+	v1 = 0x10;
+	if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4];
+	outSISIDXREG(SISSR,0x07,v1);       /* DAC speed */
+	outSISIDXREG(SISSR,0x11,0x0f);     /* DDC, power save */
+	v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
+	v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
+	if(ivideo->sishw_ext.UseROM) {
+	   memtype += 0xa5;
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16];
+	   v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24];
+	   v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32];
+	   v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40];
+	   v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48];
+	   v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56];
+	}
+	if(ivideo->revision_id >= 0x80) v3 &= 0xfd;
+	outSISIDXREG(SISSR,0x15,v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
+	outSISIDXREG(SISSR,0x16,v2);
+	outSISIDXREG(SISSR,0x17,v3);
+	outSISIDXREG(SISSR,0x18,v4);
+	outSISIDXREG(SISSR,0x19,v5);
+	outSISIDXREG(SISSR,0x1a,v6);
+	outSISIDXREG(SISSR,0x1b,v7);
+	outSISIDXREG(SISSR,0x1c,v8);	   /* ---- */
+	andSISIDXREG(SISSR,0x15,0xfb);
+	orSISIDXREG(SISSR,0x15,0x04);
+	if(ivideo->sishw_ext.UseROM) {
+	   if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
+	      orSISIDXREG(SISSR,0x19,0x20);
+	   }
+	}
+	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
+	if(ivideo->revision_id >= 0x80) v1 |= 0x01;
+	outSISIDXREG(SISSR,0x1f,v1);
+	outSISIDXREG(SISSR,0x20,0xa0);     /* linear & relocated io */
+	v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea];
+	}
+	outSISIDXREG(SISSR,0x23,v1);
+	outSISIDXREG(SISSR,0x24,v2);
+	outSISIDXREG(SISSR,0x25,v3);
+	outSISIDXREG(SISSR,0x21,0x84);
+	outSISIDXREG(SISSR,0x22,0x00);
+	outSISIDXREG(SISCR,0x37,0x00);
+	orSISIDXREG(SISPART1,0x24,0x01);   /* unlock crt2 */
+	outSISIDXREG(SISPART1,0x00,0x00);
+	v1 = 0x40; v2 = 0x11;
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb];
+	}
+	outSISIDXREG(SISPART1,0x02,v1);
+	if(ivideo->revision_id >= 0x80) v2 &= ~0x01;
+	inSISIDXREG(SISPART4,0x00,reg);
+	if((reg == 1) || (reg == 2)) {
+	   outSISIDXREG(SISCR,0x37,0x02);
+	   outSISIDXREG(SISPART2,0x00,0x1c);
+	   v4 = 0x00; v5 = 0x00; v6 = 0x10;
+	   if(ivideo->sishw_ext.UseROM) {
+	      v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5];
+	      v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6];
+	      v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7];
+	   }
+	   outSISIDXREG(SISPART4,0x0d,v4);
+	   outSISIDXREG(SISPART4,0x0e,v5);
+	   outSISIDXREG(SISPART4,0x10,v6);
+	   outSISIDXREG(SISPART4,0x0f,0x3f);
+	   inSISIDXREG(SISPART4,0x01,reg);
+	   if(reg >= 0xb0) {
+	      inSISIDXREG(SISPART4,0x23,reg);
+	      reg &= 0x20;
+	      reg <<= 1;
+	      outSISIDXREG(SISPART4,0x23,reg);
+	   }
+	} else {
+	   v2 &= ~0x10;
+	}
+	outSISIDXREG(SISSR,0x32,v2);
+	andSISIDXREG(SISPART1,0x24,0xfe);  /* Lock CRT2 */
+	inSISIDXREG(SISSR,0x16,reg);
+	reg &= 0xc3;
+	outSISIDXREG(SISCR,0x35,reg);
+	outSISIDXREG(SISCR,0x83,0x00);
+#if !defined(__i386__) && !defined(__x86_64__)
+	if(sisfb_videoram) {
+	   outSISIDXREG(SISSR,0x13,0x28);  /* ? */
+	   reg = ((sisfb_videoram >> 10) - 1) | 0x40;
+	   outSISIDXREG(SISSR,0x14,reg);
+	} else {
+#endif
+	   /* Need to map max FB size for finding out about RAM size */
+	   ivideo->sishw_ext.pjVideoMemoryAddress = ioremap(ivideo->video_base, 0x4000000);
+	   if(ivideo->sishw_ext.pjVideoMemoryAddress) {
+	      sisfb_setramsize300(pdev);
+	      iounmap(ivideo->sishw_ext.pjVideoMemoryAddress);
+	   } else {
+	      printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
+	      outSISIDXREG(SISSR,0x13,0x28);  /* ? */
+	      outSISIDXREG(SISSR,0x14,0x47);  /* 8MB, 64bit default */
+	   }
+#if !defined(__i386__) && !defined(__x86_64__)
+	}
+#endif
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7];
+	} else {
+	   inSISIDXREG(SISSR,0x3a,reg);
+	   if((reg & 0x30) == 0x30) {
+	      v1 = 0x04; /* PCI */
+	      v2 = 0x92;
+	   } else {
+	      v1 = 0x14; /* AGP */
+	      v2 = 0xb2;
+	   }
+	}
+	outSISIDXREG(SISSR,0x21,v1);
+	outSISIDXREG(SISSR,0x22,v2);
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static void __devinit sisfb_post_sis315330(struct pci_dev *pdev)
 {
-	struct pci_dev *pdev = NULL;
-	struct board *b;
-	int pdev_valid = 0;
-	u32 reg32;
-	u16 reg16;
-	u8  reg;
+#ifdef YET_TO_BE_DONE
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
+	u16 index, rindex, memtype = 0;
+	u32 reg1_32, reg2_32, reg3_32;
+	int i;
+
+	/* Unlock */
+	/* outSISIDXREG(0x3c4,0x05,0x86); */
+	outSISIDXREG(SISSR,0x05,0x86);
+
+	/* Enable relocated i/o ports */
+	/* setSISIDXREG(0x3c4,0x20,~0x10,0x20); */
+	setSISIDXREG(SISSR,0x20,~0x10,0x20);
+
+	/* Clear regs */
+	for(i = 0; i < 0x22; i++) {
+	   outSISIDXREG(SISSR,(0x06 + i),0x00);
+	}
+	v1 = 0x0d;
+	if( is 330) v1 = 0x0b;
+	for(i = 0; i < v1; i++) {
+	   outSISIDXREG(SISSR,(0x31 + i),0x00);
+	}
+	for(i = 0; i < 0x10; i++) {
+	   outSISIDXREG(SISCR,(0x30 + i),0x00);
+	}
+
+	/* Reset clocks */
+	reg = inSISREG(SISMISCR);
+	outSISIDXREG(SISSR,0x28,0x81);
+	outSISIDXREG(SISSR,0x2A,0x00);
+	outSISIDXREG(SISSR,0x29,0xE1);
+	outSISREG(SISMISCW,(reg | 0x0c));
+	outSISIDXREG(SISSR,0x2B,0x81);
+	outSISIDXREG(SISSR,0x2D,0x00);
+	outSISIDXREG(SISSR,0x2C,0xE1);
+	outSISIDXREG(SISSR,0x2E,0x81);
+	outSISIDXREG(SISSR,0x30,0x00);
+	outSISIDXREG(SISSR,0x2F,0xE1);
+	SiS_DDC2Delay(....);
+	outSISREG(SISMISCW,reg);
+
+	/* Get memory type */
+	if(ivideo->sishw_ext.UseROM) {
+	   if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80)) {
+	      memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
+ 	   } else {
+	      inSISIDXREG(SISSR,0x3a,memtype);
+	   }
+	   memtype &= 0x03;
+	   if( is 330 ) {
+	      if(memtype <= 1) memtype = 0;
+	      else {
+	         inSISIDXREG(SISCR,0x5F,reg);
+		 reg &= 0x30;
+		 switch(reg) {
+		 case 0x00: memtype = 1; break;
+		 case 0x10: memtype = 3; break;
+		 case 0x20: memtype = 3; break;
+		 default:   memtype = 2;
+		 }
+	      }
+	   }
+	}
 
-#if 0
-	/* for DOC VB */
-	sisfb_set_reg4(0xcf8,0x800000e0);
-	reg32 = sisfb_get_reg3(0xcfc);
-	reg32 = reg32 | 0x00001000;
-	sisfb_set_reg4(0xcfc,reg32);
+	/* Set clocks */
+	v1 = 0x3b; v2 = 0x22; v3 = 0x01;  /* Assume 143Mhz MCLK */
+	v4 = 0x5c; v5 = 0x23; v6 = 0x01;  /* Assume 166Mhz ECLK */
+	if(ivideo->sishw_ext.UseROM) {
+	   index = memtype * 5;
+	   rindex = index + 0x54;
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	   rindex = index + 0x68;
+	   v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	   v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	   v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	}
+	outSISIDXREG(SISSR,0x28,v1);
+	outSISIDXREG(SISSR,0x29,v2);
+	outSISIDXREG(SISSR,0x2a,v3);
+	if( is 330 ) {
+	   inSISIDXREG(SISSR,0x3a,reg);
+	   reg &= 0x03;
+	   if(reg >= 2) {
+	      ...
+	   }
 	}
-#endif
+	outSISIDXREG(SISSR,0x2e,v4);
+	outSISIDXREG(SISSR,0x2f,v5);
+	outSISIDXREG(SISSR,0x30,v6);
+
+	/* End of comp with 330 */
+
+	v1 = 0x18;
+	if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0x7c];
+	outSISIDXREG(SISSR,0x07,v1);
+	outSISIDXREG(SISSR,0x11,0x0f);
+
+	v1 = 0x00; v2 = 0x0f; v3 = 0xba; v4 = 0xa9;
+	v5 = 0xa0; v6 = 0x00; v7 = 0x30;
+	if(ivideo->sishw_ext.UseROM) {
+	   index = memtype + 0x7d;
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
+	   v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
+	   v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
+	   v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
+	   v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
+	}
+	outSISIDXREG(SISSR,0x15,v1);       /* Ram type (assuming 0, BIOS 0x7d step 4) */
+	outSISIDXREG(SISSR,0x16,v2);
+	outSISIDXREG(SISSR,0x17,v3);
+	outSISIDXREG(SISSR,0x18,v4);
+	outSISIDXREG(SISSR,0x19,v5);
+	outSISIDXREG(SISSR,0x1a,v6);
+	outSISIDXREG(SISSR,0x1b,v7);
+	outSISIDXREG(SISSR,0x1c,v8);	   /* ---- */
+
+	v1 = 0x77; v2 = 0x77; v3 = 0x00; v4 = 0x5b; v5 = 0x00;
+	if(ivideo->sishw_ext.UseROM) {
+	   index = memtype + 0xa2;
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
+	   v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
+	   v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
+	}
+	outSISIDXREG(SISCR,0x40,v1);
+	outSISIDXREG(SISCR,0x41,v2);
+	outSISIDXREG(SISCR,0x42,v3);
+	outSISIDXREG(SISCR,0x43,v4);
+	outSISIDXREG(SISCR,0x44,v5);
+
+	if( is 330 ) {
+
+	   v1 = 0x;
+	   if(ivideo->sishw_ext.UseROM) {
+	      v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
+	   }
+	   outSISIDXREG(SISCR,0x59,v1);
 
-	if (sisfb_off)
-		return -ENXIO;
+	   v1 = 0x; v2 = 0x; v3 = 0x; v4 = 0x;
+	   v5 = 0x; v6 = 0x; v7 = 0x; v8 = 0x;
+	   if(ivideo->sishw_ext.UseROM) {
+	      index = memtype + 0xbe;
+	      v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
+	      v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
+	      v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
+	      v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
+	      v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
+	      v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
+	      v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
+	      v8 = ivideo->sishw_ext.pjVirtualRomBase[index + 28];
+	   }
+	   outSISIDXREG(SISCR,0x68,v1);
+	   outSISIDXREG(SISCR,0x69,v2);
+	   outSISIDXREG(SISCR,0x6a,v3);
+	   outSISIDXREG(SISCR,0x6b,v4);
+	   outSISIDXREG(SISCR,0x6c,v5);
+	   outSISIDXREG(SISCR,0x6d,v6);
+	   outSISIDXREG(SISCR,0x6e,v7);
+	   outSISIDXREG(SISCR,0x6f,v8);
+
+	   v1 = 0x20;
+	   inSISIDXREG(SISSR,0x3b,reg);
+
+	   if(!(reg & 0x04)) {
+	      inSISIDXREG(SISCR,0x5F,reg);
+	      reg &= 0x30;
+	      if(reg) v1 = 0x23;
+	   }
+	   outSISIDXREG(SISCR,0x48,v1);
+	   outSISIDXREG(SISCR,0x4c,0x20);
 
-	sisfb_registered = 0;
-	sisfb_thismonitor.datavalid = FALSE;
+	   xx= xxx();
+	   if(xx >= 1) {
+	      v1 = 0x;
+	      if(ivideo->sishw_ext.UseROM) {
+	         v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
+	      }
+	      outSISIDXREG(SISCR,0x59,v1);
+	   }
 
-	memset(&sishw_ext, 0, sizeof(sishw_ext));
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-        memset(&sisfb_lastrates[0], 0, 128);
+
+	} else {
+
+	   outSISIDXREG(SISCR,0x48,0x23);
+
+	   andSISIDXREG(SISSR,0x16,0x0f);
+	   if(memtype <= 1) {
+	      orSISIDXREG(SISSR,0x16,0x80);
+	   } else {
+	      v1 = 0x0f;
+	      if(ivideo->sishw_ext.UseROM) {
+	         v1 = ivideo->sishw_ext.pjVirtualRomBase[0x81 + memtype];
+	      }
+	      if(!(v1 & 0x10)) v2 = 0xc0;
+	      else             v2 = 0xd0;
+	      orSISIDXREG(SISSR,0x16,v2);
+	      andSISIDXREG(SISSR,0x16,0x0f);
+	      if(!(v1 & 0x10)) v2 = 0x80;
+	      else             v2 = 0xA0;
+	      orSISIDXREG(SISSR,0x16,v2);
+ 	   }
+
+	   if(memtype >= 2) {
+	      const u8 sr3cseq1[] = { 0xc0,0xe0,0xf0,0xe0,0xf0,0xa0,0xb0,0xa0,0xb0,0x90,0xd0 };
+	      const u8 sr3cseq2[] = { 0xc0,0xa0,0xb0,0xa0,0xb0,0xe0,0xf0,0xa0,0xb0,0x90,0xd0 };
+	      for(i = 0; i < 11; i++) {
+	         outSISIDXREG(SISSR,0x3c,sr3cseq1[i]);
+	      }
+	      outSISIDXREG(SISSR,0x3d,0x00);
+	      outSISIDXREG(SISSR,0x3d,0x04);
+	      SiS_DDC2Delay(0x200);
+	      v1 = inSISIDXREG(SISCR,0xEC);
+	      v2 = inSISIDXREG(SISCR,0xED);
+	      reg1_32 = (v2 << 8) | v1;
+	      outSISIDXREG(SISSR,0x3D,0x00);
+	      for(i = 0; i < 11; i++) {
+	         outSISIDXREG(SISSR,0x3c,sr3cseq2[i]);
+	      }
+	      outSISIDXREG(SISSR,0x3d,0x00);
+	      outSISIDXREG(SISSR,0x3d,0x04);
+	      SiS_DDC2Delay(0x200);
+	      v1 = inSISIDXREG(SISCR,0xEC);
+	      v2 = inSISIDXREG(SISCR,0xED);
+	      reg2_32 = (v2 << 8) | v1;
+	      outSISIDXREG(SISSR,0x3D,0x00);
+	      reg3_32 = reg2_32 << 1;
+	      reg2_32 >>= 1;
+	      reg3_32 += reg2_32;
+	      v1 = 0x40;
+	      if(reg3_32 > reg1_32) v1 = 0x10;
+	         outSISIDXREG(SISCR,0x59,v1);
+	   }
+
+	}
+
+	v1 = 0x00;
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0x99];
+	}
+	outSISIDXREG(SISSR,0x1f,v1);
+
+	outSISIDXREG(SISSR,0x20,0x20);
+
+	v1 = 0xf6; v2 = 0x0d; v3 = 0x33;
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9c];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9d];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[0x9e];
+	}
+	outSISIDXREG(SISSR,0x23,v1);
+	outSISIDXREG(SISSR,0x24,v2);
+	outSISIDXREG(SISSR,0x25,v3);
+
+	outSISIDXREG(SISSR,0x21,0x84);
+	outSISIDXREG(SISSR,0x22,0x00);
+	outSISIDXREG(SISSR,0x27,0x1f);
+
+	v1 = 0x00; v2 = 0x00;
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9F];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xA1];
+	}
+	outSISIDXREG(SISSR,0x31,v1);
+	outSISIDXREG(SISSR,0x33,v2);
+
+	v1 = 0x11;
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xA0];
+	}
+	v2 = inSISIDXREG(SISPART4,0x00);
+	if((v2 != 1) && (v2 != 2)) v1 &= 0xef;
+	outSISIDXREG(SISSR,0x32,v1);
+
+	/* AGP */
+	pci_read_config_long(pdev, 0x50, &reg1_32);
+	reg1_32 >>= 20;
+	reg1_32 &= 0x0f;
+	if(reg1_32 == 1) {
+	   v1 = 0xAA; v2 = 0x33;
+	   if(ivideo->sishw_ext.UseROM) {
+	      v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF7];
+	      v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9E];
+	   }
+	} else {
+	   v1 = 0x88; v2 = 0x03;
+	   if(ivideo->sishw_ext.UseROM) {
+	      v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF8];
+	      v2 = ivideo->sishw_ext.pjVirtualRomBase[0xF6];
+	   }
+	}
+	outSISIDXREG(SISCR,0x49,v1);
+	outSISIDXREG(SISSR,0x25,v2);
+
+	v1 = inSISIDXREG(SISPART4,0x00);
+	if((v1 == 1) || (v1 == 2)) {
+	   orSISIDXREG(SISPART1,0x2F,0x01);  /* Unlock CRT2 */
+	   outSISIDXREG(SISPART1,0x00,0x00);
+	   v1 = 0x00;
+	   if(ivideo->sishw_ext.UseROM) {
+	      v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb6];
+	   }
+	   outSISIDXREG(SISPART1,0x02,v1);
+	   outSISIDXREG(SISPART1,0x2E,0x08);
+	   outSISIDXREG(SISPART2,0x00,0x1c);
+	   v1 = 0x40; v2 = 0x00; v3 = 0x80;
+	   if(ivideo->sishw_ext.UseROM) {
+	      v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb7];
+	      v2 = ivideo->sishw_ext.pjVirtualRomBase[0xb8];
+	      v3 = ivideo->sishw_ext.pjVirtualRomBase[0xbb];
+	   }
+	   outSISIDXREG(SISPART4,0x0d,v1);
+	   outSISIDXREG(SISPART4,0x0e,v2);
+	   outSISIDXREG(SISPART4,0x10,v3);
+	   outSISIDXREG(SISPART4,0x0F,0x3F);
+
+	   inSISIDXREG(SISPART4,0x01,reg);
+	   if(reg >= 0xb0) {
+	      inSISIDXREG(SISPART4,0x23,reg);
+	      reg &= 0x20;
+	      reg <<= 1;
+	      outSISIDXREG(SISPART4,0x23,reg);
+	   }
+	}
+	outSISIDXREG(SISCR,0x37,0x02); /* Why? */
+
+	outSISIDXREG(SISCR,0x83,0x00);
+	outSISIDXREG(SISCR,0x90,0x00);
+	andSISIDXREG(SISSR,0x5B,0xDF);
+	outSISIDXREG(SISVID,0x00,0x86);
+	outSISIDXREG(SISVID,0x32,0x00);
+	outSISIDXREG(SISVID,0x30,0x00);
+	outSISIDXREG(SISVID,0x32,0x01);
+	outSISIDXREG(SISVID,0x30,0x00);
+	orSISIDXREG(SISCR,0x63,0x80);
+	/* End of Init1 */
+
+	/* Set Mode 0x2e */
+
+	/* Ramsize */
+	orSISIDXREG(SISSR,0x16,0x0f);
+	orSISIDXREG(SISSR,0x18,0xA9);
+	orSISIDXREG(SISSR,0x19,0xA0);
+	orSISIDXREG(SISSR,0x1B,0x30);
+	andSISIDXREG(SISSR,0x17,0xF8);
+	orSISIDXREG(SISSR,0x19,0x03);
+	andSIDIDXREG(SISSR,0x13,0x00);
+
+	/* Need to map max FB size for finding out about RAM size */
+	ivideo->sishw_ext.pjVideoMemoryAddress = ioremap(ivideo->video_base, 0x4000000);
+	if(ivideo->sishw_ext.pjVideoMemoryAddress) {
+	   /* Find out about bus width */
+	   if(memtype <= 1) {
+	      outSISIDXREG(SISSR,0x14,0x02);
+	      andSISIDXREG(SISSR,0x16,0x0F);
+	      orSISIDXREG(SISSR,0x16,0x80);
+
+	      ...
+
+	   } else {
+
+	      ...
+
+	   }
+
+	   /* Find out about size */
+
+
+	   iounmap(ivideo->sishw_ext.pjVideoMemoryAddress);
+	} else {
+	   printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
+	   outSISIDXREG(SISSR,0x14,0x??);  /* 8MB, 64bit default */
+	}
+
+	/* AGP (Missing: Checks for VIA and AMD hosts) */
+	v1 = 0xA5; v2 = 0xFB;
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9A];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9B];
+	}
+	outSISIDXREG(SISSR,0x21,v1);
+	outSISIDXREG(SISSR,0x22,v2);
+
 #endif
-	
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
-	memset(&sis_disp, 0, sizeof(sis_disp));
+	return;
+}
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-	pci_for_each_dev(pdev) {
+
+int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct sisfb_chip_info 	*chipinfo = &sisfb_chip_info[ent->driver_data];
+	struct sis_video_info 	*ivideo = NULL;
+	struct fb_info 		*sis_fb_info = NULL;
+	u16 reg16;
+	u8  reg;
+	int sisvga_enabled = 0, i;
+
+	if(sisfb_off) return -ENXIO;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+	sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
+	if(!sis_fb_info) return -ENOMEM;
 #else
-	while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
+	sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL);
+	if(!sis_fb_info) return -ENOMEM;
+	memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo));
+	sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info));
 #endif
-		for (b = sisdev_list; b->vendor; b++) {
-			if ((b->vendor == pdev->vendor)
-			    && (b->device == pdev->device)) {
-				pdev_valid = 1;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(NEWFBDEV)
-				sis_fb_info = framebuffer_alloc(0, &pdev->dev);
-#else
-				sis_fb_info = kmalloc(sizeof(*sis_fb_info), GFP_KERNEL);
+
+	ivideo = (struct sis_video_info *)sis_fb_info->par;
+	ivideo->memyselfandi = sis_fb_info;
+
+	if(card_list == NULL) {
+	   ivideo->cardnumber = 0;
+	} else {
+	   struct sis_video_info *countvideo = card_list;
+	   ivideo->cardnumber = 1;
+	   while ((countvideo = countvideo->next) != NULL) ivideo->cardnumber++;
+	}
+
+	strncpy(ivideo->myid, chipinfo->chip_name, 30);
+
+	ivideo->chip_id = pdev->device;
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
+	ivideo->sishw_ext.jChipRevision = ivideo->revision_id;
+	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
+	sisvga_enabled = reg16 & 0x01;
+	ivideo->pcibus = pdev->bus->number;
+	ivideo->pcislot = PCI_SLOT(pdev->devfn);
+	ivideo->pcifunc = PCI_FUNC(pdev->devfn);
+	ivideo->subsysvendor = pdev->subsystem_vendor;
+	ivideo->subsysdevice = pdev->subsystem_device;
+#ifdef SIS_CONFIG_COMPAT
+	ivideo->ioctl32registered = 0;
+	ivideo->ioctl32vblankregistered = 0;
 #endif
-				if(!sis_fb_info) return -ENOMEM;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || (!(defined(NEWFBDEV)))
-				memset(sis_fb_info, 0, sizeof(*sis_fb_info));
+
+#ifndef MODULE
+	if(sisfb_mode_idx == -1) {
+		sisfb_get_vga_mode_from_kernel();
+	}
 #endif
+
+	ivideo->chip = chipinfo->chip;
+	ivideo->sisvga_engine = chipinfo->vgaengine;
+	ivideo->hwcursor_size = chipinfo->hwcursor_size;
+	ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
+	ivideo->mni = chipinfo->mni;
+
+	ivideo->detectedpdc  = 0xff;
+	ivideo->detectedpdca = 0xff;
+	ivideo->detectedlcda = 0xff;
+
+	ivideo->sisfb_thismonitor.datavalid = FALSE;
+
+	ivideo->sisfb_parm_mem = sisfb_parm_mem;
+	ivideo->sisfb_accel = sisfb_accel;
+	ivideo->sisfb_ypan = sisfb_ypan;
+	ivideo->sisfb_max = sisfb_max;
+	ivideo->sisfb_userom = sisfb_userom;
+	ivideo->sisfb_useoem = sisfb_useoem;
+	ivideo->sisfb_mode_idx = sisfb_mode_idx;
+	ivideo->sisfb_parm_rate = sisfb_parm_rate;
+	ivideo->sisfb_crt1off = sisfb_crt1off;
+	ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
+	ivideo->sisfb_crt2type = sisfb_crt2type;
+	ivideo->sisfb_crt2flags = sisfb_crt2flags;
+	/* pdc(a), scalelcd, special timing, lvdshl handled below */
+	ivideo->sisfb_dstn = sisfb_dstn;
+	ivideo->sisfb_fstn = sisfb_fstn;
+	ivideo->sisfb_tvplug = sisfb_tvplug;
+	ivideo->sisfb_tvstd = sisfb_tvstd;
+	ivideo->tvxpos = sisfb_tvxposoffset;
+	ivideo->tvypos = sisfb_tvyposoffset;
+	ivideo->sisfb_filter = sisfb_filter;
+	ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, b->name);
-#else				
-				strcpy(myid, b->name);
-#endif				
-				ivideo.chip_id = pdev->device;
-				pci_read_config_byte(pdev, PCI_REVISION_ID,
-				                     &ivideo.revision_id);
-				pci_read_config_word(pdev, PCI_COMMAND, &reg16);
-				sishw_ext.jChipRevision = ivideo.revision_id;
-				sisvga_enabled = reg16 & 0x01;
-				ivideo.pcibus = pdev->bus->number;
-				ivideo.pcislot = PCI_SLOT(pdev->devfn);
-				ivideo.pcifunc = PCI_FUNC(pdev->devfn);
-				ivideo.subsysvendor = pdev->subsystem_vendor;
-				ivideo.subsysdevice = pdev->subsystem_device;
-				break;
-			}
-		}
+	ivideo->sisfb_inverse = sisfb_inverse;
+#endif
 
-		if (pdev_valid)
-			break;
+	ivideo->refresh_rate = 0;
+	if(ivideo->sisfb_parm_rate != -1) {
+	   ivideo->refresh_rate = ivideo->sisfb_parm_rate;
+	}
+
+	ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
+	ivideo->SiS_Pr.CenterScreen = -1;
+	ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
+	ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
+
+	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
+        ivideo->SiS_Pr.SiS_CHOverScan = -1;
+        ivideo->SiS_Pr.SiS_ChSW = FALSE;
+	ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
+	ivideo->SiS_Pr.HaveEMI = FALSE;
+	ivideo->SiS_Pr.HaveEMILCD = FALSE;
+	ivideo->SiS_Pr.OverruleEMI = FALSE;
+	ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE;
+	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
+	ivideo->SiS_Pr.PDC  = -1;
+	ivideo->SiS_Pr.PDCA = -1;
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->chip >= SIS_330) {
+	   ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
+	   if(ivideo->chip >= SIS_661) {
+	      ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
+	   }
 	}
+#endif
 
-	if (!pdev_valid)
-		return -ENODEV;
+	memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
 
-	switch (ivideo.chip_id) {
+	pci_set_drvdata(pdev, ivideo);
+
+	/* Patch special cases */
+	if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
+		switch(ivideo->nbridge->device) {
 #ifdef CONFIG_FB_SIS_300
-	   case PCI_DEVICE_ID_SI_300:
-		ivideo.chip = SIS_300;
-		sisvga_engine = SIS_300_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;  /* New X driver uses 2 buffers */
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
-		break;
-	   case PCI_DEVICE_ID_SI_630_VGA:
-		{
-			ivideo.chip = SIS_630;
-			sisfb_set_reg4(0xCF8, 0x80000000);
-			reg32 = sisfb_get_reg3(0xCFC);
-			if(reg32 == 0x07301039) {
-				ivideo.chip = SIS_730;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 730");
-#else
-				strcpy(myid, "SIS 730");
-#endif
-			}
-			sisvga_engine = SIS_300_VGA;
-			sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;
-			sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
-			break;
-		}
-	   case PCI_DEVICE_ID_SI_540_VGA:
-		ivideo.chip = SIS_540;
-		sisvga_engine = SIS_300_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
-		break;
+		case PCI_DEVICE_ID_SI_730:
+		   	ivideo->chip = SIS_730;
+			strcpy(ivideo->myid, "SiS 730");
+		   	break;
 #endif
 #ifdef CONFIG_FB_SIS_315
-	   case PCI_DEVICE_ID_SI_315H:
-		ivideo.chip = SIS_315H;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_315:
-		ivideo.chip = SIS_315;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_315PRO:
-		ivideo.chip = SIS_315PRO;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_550_VGA:
-		ivideo.chip = SIS_550;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_650_VGA:
-	   	{
-			ivideo.chip = SIS_650;  
-			sisfb_set_reg4(0xCF8, 0x80000000);
-			reg32 = sisfb_get_reg3(0xCFC);
-			if(reg32 == 0x07401039) {
-				ivideo.chip = SIS_740;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 740");
-#else
-				strcpy(myid, "SIS 740");
-#endif
-			}
-			sisvga_engine = SIS_315_VGA;
-			sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-			sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
+		case PCI_DEVICE_ID_SI_651:
+			/* ivideo->chip is ok */
+			strcpy(ivideo->myid, "SiS 651");
 			break;
-		}
-	   case PCI_DEVICE_ID_SI_330:
-		ivideo.chip = SIS_330;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_660_VGA:
-	   	{
-			sisfb_set_reg4(0xCF8, 0x80000000);
-			reg32 = sisfb_get_reg3(0xCFC);
-			if(reg32 == 0x07601039) {
-				ivideo.chip = SIS_760;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 760");
-#else
-				strcpy(myid, "SIS 760");
-#endif
-			} else if(reg32 == 0x06601039) {
-				ivideo.chip = SIS_660;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 660");
-#else
-				strcpy(myid, "SIS 660");
-#endif
-			} else if(reg32 == 0x07411039) {
-				ivideo.chip = SIS_741;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 741");
-#else
-				strcpy(myid, "SIS 741");
-#endif
-			} else {
-				ivideo.chip = SIS_661;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 661");
-#else
-				strcpy(myid, "SIS 661");
-#endif
-			}
-			sisvga_engine = SIS_315_VGA;
-			sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-			sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
+		case PCI_DEVICE_ID_SI_740:
+		   	ivideo->chip = SIS_740;
+			strcpy(ivideo->myid, "SiS 740");
+			break;
+		case PCI_DEVICE_ID_SI_661:
+		   	ivideo->chip = SIS_661;
+			strcpy(ivideo->myid, "SiS 661");
+			break;
+		case PCI_DEVICE_ID_SI_741:
+		   	ivideo->chip = SIS_741;
+			strcpy(ivideo->myid, "SiS 741");
+			break;
+		case PCI_DEVICE_ID_SI_760:
+		   	ivideo->chip = SIS_760;
+			strcpy(ivideo->myid, "SiS 760");
 			break;
-		}
 #endif
-           default:
-	   	kfree(sis_fb_info);
-	        return -ENODEV;
+		}
 	}
-	sishw_ext.jChipType = ivideo.chip;
 
-	/* for Debug */
-	if( (sishw_ext.jChipType == SIS_315PRO) ||
-	    (sishw_ext.jChipType == SIS_315) )
-		sishw_ext.jChipType = SIS_315H;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	strcpy(sis_fb_info->modename, ivideo->myid);
+#endif
+
+	ivideo->sishw_ext.jChipType = ivideo->chip;
 
-	ivideo.video_base = pci_resource_start(pdev, 0);
-	ivideo.mmio_base = pci_resource_start(pdev, 1);
-	sishw_ext.ulIOAddress = SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
-	ivideo.vga_base = (unsigned short) sishw_ext.ulIOAddress;
+#ifdef CONFIG_FB_SIS_315
+	if((ivideo->sishw_ext.jChipType == SIS_315PRO) ||
+	   (ivideo->sishw_ext.jChipType == SIS_315)) {
+		ivideo->sishw_ext.jChipType = SIS_315H;
+	}
+#endif
 
-	sisfb_mmio_size =  pci_resource_len(pdev, 1);
+	ivideo->video_base = pci_resource_start(pdev, 0);
+	ivideo->mmio_base  = pci_resource_start(pdev, 1);
+	ivideo->mmio_size  = pci_resource_len(pdev, 1);
+	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
+	ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
 
 	if(!sisvga_enabled) {
-	   if(pci_enable_device(pdev)) {
-	      kfree(sis_fb_info);
-	      return -EIO;
-	   }
+	   	if(pci_enable_device(pdev)) {
+	      		pci_set_drvdata(pdev, NULL);
+	      		kfree(sis_fb_info);
+	      		return -EIO;
+	   	}
 	}
 
-	SiS_Pr.SiS_Backup70xx = 0xff;
-        SiS_Pr.SiS_CHOverScan = -1;
-        SiS_Pr.SiS_ChSW = FALSE;
-	SiS_Pr.SiS_UseLCDA = FALSE;
-	SiS_Pr.HaveEMI = FALSE;
-	SiS_Pr.HaveEMILCD = FALSE;
-	SiS_Pr.OverruleEMI = FALSE;
-	SiS_Pr.SiS_SensibleSR11 = FALSE;
-	SiS_Pr.SiS_MyCR63 = 0x63;
-	if(ivideo.chip >= SIS_661) {
-	   SiS_Pr.SiS_SensibleSR11 = TRUE;
-	   SiS_Pr.SiS_MyCR63 = 0x53;
-	}
-	SiSRegInit(&SiS_Pr, sishw_ext.ulIOAddress);
+	SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress);
 
 #ifdef CONFIG_FB_SIS_300
-	/* TW: Find PCI systems for Chrontel/GPIO communication setup */
-	if(ivideo.chip == SIS_630) {
-	   int i=0;
+	/* Find PCI systems for Chrontel/GPIO communication setup */
+	if(ivideo->chip == SIS_630) {
+	   i=0;
            do {
-	      if(mychswtable[i].subsysVendor == ivideo.subsysvendor &&
-	         mychswtable[i].subsysCard   == ivideo.subsysdevice) {
-		 SiS_Pr.SiS_ChSW = TRUE;
+	      if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
+	         mychswtable[i].subsysCard   == ivideo->subsysdevice) {
+		 ivideo->SiS_Pr.SiS_ChSW = TRUE;
 		 printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n",
 		        mychswtable[i].vendorName, mychswtable[i].cardName);
 		 break;
@@ -4361,14 +4939,41 @@
 	}
 #endif
 
-        outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+        outSISIDXREG(SISSR, 0x05, 0x86);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		
-#ifdef MODULE
+	if( (!sisvga_enabled)
+#if !defined(__i386__) && !defined(__x86_64__)
+		  	      || (sisfb_resetcard)
+#endif
+			      			   ) {
+	   	for(i = 0x30; i <= 0x3f; i++) {
+	      		outSISIDXREG(SISCR,i,0x00);
+	   	}
+	}
+
+	/* Find out about current video mode */
 	inSISIDXREG(SISCR,0x34,reg);
+	if(reg & 0x7f) {
+		ivideo->modeprechange = reg & 0x7f;
+	} else {
+		ivideo->modeprechange = 0x03;
+#if defined(__i386__) || defined(__x86_64__)
+		{
+			unsigned char *tt = ioremap(0, 0x1000);
+			if(tt) {
+			   	ivideo->modeprechange = tt[0x449];
+			   	iounmap(tt);
+			}
+		}
+#endif
+	}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#ifdef MODULE
 	if((reg & 0x80) && (reg != 0xff)) {
-	   if((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {
+	   if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) {
 	      printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
+	      pci_set_drvdata(pdev, NULL);
 	      kfree(sis_fb_info);
 	      return -EBUSY;
 	   }
@@ -4376,96 +4981,82 @@
 #endif	
 #endif
 
-	if (sisvga_engine == SIS_315_VGA) {
-		switch (ivideo.chip) {
-		   case SIS_315H:
-		   case SIS_315:
-		   case SIS_330:
-			sishw_ext.bIntegratedMMEnabled = TRUE;
-			break;
-		   case SIS_550:
-		   case SIS_650:
-		   case SIS_740:
-		   case SIS_661:
-		   case SIS_741:
-		   case SIS_660:
-		   case SIS_760:
-			sishw_ext.bIntegratedMMEnabled = TRUE;
-			break;
-		   default:
-			break;
-		}
-	} else if (sisvga_engine == SIS_300_VGA) {
-		if (ivideo.chip == SIS_300) {
-			sishw_ext.bIntegratedMMEnabled = TRUE;
-		} else {
-		        inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_1A, reg);
-			if (reg & SIS_SCRATCH_REG_1A_MASK)
-				sishw_ext.bIntegratedMMEnabled = TRUE;
-			else
-				sishw_ext.bIntegratedMMEnabled = FALSE;
-		}
+	ivideo->sishw_ext.bIntegratedMMEnabled = TRUE;
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   if(ivideo->chip != SIS_300) {
+	      inSISIDXREG(SISSR, 0x1a, reg);
+	      if(!(reg & 0x10)) {
+		 ivideo->sishw_ext.bIntegratedMMEnabled = FALSE;
+	      }
+	   }
 	}
+#endif
 
-	if(sisfb_userom) {
-	    sishw_ext.pjVirtualRomBase = sis_find_rom();
-	    if(sishw_ext.pjVirtualRomBase) {
-		printk(KERN_INFO "sisfb: Video ROM found and mapped to %p\n",
-		        sishw_ext.pjVirtualRomBase);
-		sishw_ext.UseROM = TRUE;
+	ivideo->bios_vbase = ivideo->bios_abase = NULL;
+	if(ivideo->sisfb_userom) {
+	    ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
+#if defined(__i386__) || defined(__x86_64__)
+	    ivideo->bios_vbase = ivideo->sishw_ext.pjVirtualRomBase;	/* mapped */
+#else
+	    ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase;	/* allocated */
+#endif
+	    if(ivideo->sishw_ext.pjVirtualRomBase) {
+		printk(KERN_INFO "sisfb: Video ROM found and %s to 0x%p\n",
+			ivideo->bios_vbase ? "mapped" : "copied",
+		        ivideo->sishw_ext.pjVirtualRomBase);
+		ivideo->sishw_ext.UseROM = TRUE;
 	    } else {
-	        sishw_ext.UseROM = FALSE;
+	        ivideo->sishw_ext.UseROM = FALSE;
 	        printk(KERN_INFO "sisfb: Video ROM not found\n");
 	    }
 	} else {
-	    sishw_ext.pjVirtualRomBase = NULL;
-	    sishw_ext.UseROM = FALSE;
+	    ivideo->sishw_ext.pjVirtualRomBase = NULL;
+	    ivideo->sishw_ext.UseROM = FALSE;
 	    printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
 	}
-	sishw_ext.bSkipDramSizing = 0;
-	sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;
-	sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
 
         /* Find systems for special custom timing */
-	if(SiS_Pr.SiS_CustomT == CUT_NONE) {
-	   int i=0, j;
+	if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
+	   int j;
 	   unsigned char *biosver = NULL;
            unsigned char *biosdate = NULL;
 	   BOOLEAN footprint;
-	   unsigned long chksum = 0;
+	   u32 chksum = 0;
 
-	   if(sishw_ext.UseROM) {
-	      biosver = sishw_ext.pjVirtualRomBase + 0x06;
-	      biosdate = sishw_ext.pjVirtualRomBase + 0x2c;
-              for(i=0; i<32768; i++) chksum += sishw_ext.pjVirtualRomBase[i];
+	   if(ivideo->sishw_ext.UseROM) {
+	      biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06;
+	      biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c;
+              for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i];
 	   }
 
 	   i=0;
            do {
-	      if( (mycustomttable[i].chipID == ivideo.chip) &&
+	      if( (mycustomttable[i].chipID == ivideo->chip) &&
 	          ((!strlen(mycustomttable[i].biosversion)) ||
-		   (sishw_ext.UseROM &&
+		   (ivideo->sishw_ext.UseROM &&
 		   (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) &&
 	          ((!strlen(mycustomttable[i].biosdate)) ||
-		   (sishw_ext.UseROM &&
+		   (ivideo->sishw_ext.UseROM &&
 		   (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) &&
 		  ((!mycustomttable[i].bioschksum) ||
-		   (sishw_ext.UseROM &&
+		   (ivideo->sishw_ext.UseROM &&
 	           (mycustomttable[i].bioschksum == chksum)))	&&
-		  (mycustomttable[i].pcisubsysvendor == ivideo.subsysvendor) &&
-		  (mycustomttable[i].pcisubsyscard == ivideo.subsysdevice) ) {
+		  (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
+		  (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
 		 footprint = TRUE;
-	         for(j=0; j<5; j++) {
+	         for(j = 0; j < 5; j++) {
 	            if(mycustomttable[i].biosFootprintAddr[j]) {
-		       if(sishw_ext.UseROM) {
-	                  if(sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
-		      		mycustomttable[i].biosFootprintData[j])
-		          footprint = FALSE;
+		       if(ivideo->sishw_ext.UseROM) {
+	                  if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
+		      		mycustomttable[i].biosFootprintData[j]) {
+		             footprint = FALSE;
+			  }
 		       } else footprint = FALSE;
 		    }
 	         }
 	         if(footprint) {
-	 	    SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
+	 	    ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
 		    printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
 		        mycustomttable[i].vendorName,
 			mycustomttable[i].cardName);
@@ -4479,466 +5070,502 @@
 	}
 
 #ifdef CONFIG_FB_SIS_300
-	/* Mode numbers for 1280x768 are different for 300 and 315 series */
-	if(sisvga_engine == SIS_300_VGA) {
-		sisbios_mode[MODEINDEX_1280x768].mode_no = 0x55;
-		sisbios_mode[MODEINDEX_1280x768+1].mode_no = 0x5a;
-		sisbios_mode[MODEINDEX_1280x768+2].mode_no = 0x5b;
-		sisbios_mode[MODEINDEX_1280x768+3].mode_no = 0x5b;
-	}
-#endif
-
-	sishw_ext.pSR = vmalloc(sizeof(SIS_DSReg) * SR_BUFFER_SIZE);
-	if (sishw_ext.pSR == NULL) {
-		printk(KERN_ERR "sisfb: Fatal error: Allocating SRReg space failed.\n");
-		kfree(sis_fb_info);
-		return -ENODEV;
-	}
-	sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
-
-	sishw_ext.pCR = vmalloc(sizeof(SIS_DSReg) * CR_BUFFER_SIZE);
-	if (sishw_ext.pCR == NULL) {
-	        vfree(sishw_ext.pSR);
-		printk(KERN_ERR "sisfb: Fatal error: Allocating CRReg space failed.\n");
-		kfree(sis_fb_info);
-		return -ENODEV;
-	}
-	sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;
-
-#ifdef CONFIG_FB_SIS_300
-	if(sisvga_engine == SIS_300_VGA) {
-		if(!sisvga_enabled) {
-		        /* Mapping Max FB Size for 300 Init */
-			sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, 0x4000000);
-			if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
-				outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		if( (!sisvga_enabled)
+#if !defined(__i386__) && !defined(__x86_64__)
+		    		      || (sisfb_resetcard)
+#endif
+		  					   ) {
+			if(ivideo->chip == SIS_300) {
+				sisfb_post_sis300(pdev);
 			}
 		}
-		if(sisfb_get_dram_size_300()) {
-		        vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			printk(KERN_ERR "sisfb: Fatal error: Unable to determine RAM size\n");
-			kfree(sis_fb_info);
-			return -ENODEV;
-		}
 	}
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-	if (sisvga_engine == SIS_315_VGA) {
-		if (!sisvga_enabled) {
-			/* Mapping Max FB Size for 315 Init */
-			sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, 0x8000000);
-			if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
-				outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-				sishw_ext.bSkipDramSizing = TRUE;
-				sishw_ext.pSR[0].jIdx = 0x13;
-				sishw_ext.pSR[1].jIdx = 0x14;
-				sishw_ext.pSR[2].jIdx = 0xFF;
-				inSISIDXREG(SISSR, 0x13, sishw_ext.pSR[0].jVal);
-				inSISIDXREG(SISSR, 0x14, sishw_ext.pSR[1].jVal);
-				sishw_ext.pSR[2].jVal = 0xFF;
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+		if( (!sisvga_enabled)
+#if !defined(__i386__) && !defined(__x86_64__)
+		    		     || (sisfb_resetcard)
+#endif
+		  					  ) {
+			if((ivideo->chip == SIS_315H)   ||
+			   (ivideo->chip == SIS_315)    ||
+			   (ivideo->chip == SIS_315PRO) ||
+			   (ivideo->chip == SIS_330)) {
+				sisfb_post_sis315330(pdev);
 			}
 		}
-		if(sisfb_get_dram_size_315()) {
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
-			kfree(sis_fb_info);
-			return -ENODEV;
-		}
 	}
 #endif
 
-	if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) { 
+	if(sisfb_get_dram_size(ivideo)) {
+		printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		pci_set_drvdata(pdev, NULL);
+		kfree(sis_fb_info);
+		return -ENODEV;
+	}
 
+	if((ivideo->sisfb_mode_idx < 0) ||
+	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
 	        /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
 	        orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
-
                 /* Enable 2D accelerator engine */
 	        orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
-
 	}
 
-	sishw_ext.ulVideoMemorySize = ivideo.video_size;
-
-	if(sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
-	if(sisfb_pdc) {
-	    SiS_Pr.PDC = sisfb_pdc;
-	} else {
-	    SiS_Pr.PDC = 0;
+	if(sisfb_pdc != 0xff) {
+	   if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
+	   else				            sisfb_pdc &= 0x1f;
+	   ivideo->SiS_Pr.PDC = sisfb_pdc;
+	}
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
 	}
+#endif
 
-	if(!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) {
+	if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n");
 		printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
-		vfree(sishw_ext.pSR);
-		vfree(sishw_ext.pCR);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 
-	if(!request_mem_region(ivideo.mmio_base, sisfb_mmio_size, "sisfb MMIO")) {
+	if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
-		release_mem_region(ivideo.video_base, ivideo.video_size);
-		vfree(sishw_ext.pSR);
-		vfree(sishw_ext.pCR);
+		release_mem_region(ivideo->video_base, ivideo->video_size);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 
-	ivideo.video_vbase = sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, ivideo.video_size);
-	if(!ivideo.video_vbase) {
+	ivideo->video_vbase = (unsigned long)ioremap(ivideo->video_base, ivideo->video_size);
+	ivideo->sishw_ext.pjVideoMemoryAddress = (unsigned char *)ivideo->video_vbase;
+	if(!ivideo->video_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
-	   	release_mem_region(ivideo.video_base, ivideo.video_size);
-	   	release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
-	   	vfree(sishw_ext.pSR);
-	   	vfree(sishw_ext.pCR);
+	   	release_mem_region(ivideo->video_base, ivideo->video_size);
+	   	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 	   	kfree(sis_fb_info);
 	   	return -ENODEV;
 	}
 
-	ivideo.mmio_vbase = ioremap(ivideo.mmio_base, sisfb_mmio_size);
-	if(!ivideo.mmio_vbase) {
+	ivideo->mmio_vbase = (unsigned long)ioremap(ivideo->mmio_base, ivideo->mmio_size);
+	if(!ivideo->mmio_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
-	   	iounmap(ivideo.video_vbase);
-	   	release_mem_region(ivideo.video_base, ivideo.video_size);
-	   	release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
-	   	vfree(sishw_ext.pSR);
-	   	vfree(sishw_ext.pCR);
+	   	iounmap((void *)ivideo->video_vbase);
+	   	release_mem_region(ivideo->video_base, ivideo->video_size);
+	   	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 	   	kfree(sis_fb_info);
 	   	return -ENODEV;
 	}
 
-	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
-	       	ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024);
+	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	       	ivideo->video_base, ivideo->video_vbase, ivideo->video_size / 1024);
 
-	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
-	       	ivideo.mmio_base, ivideo.mmio_vbase, sisfb_mmio_size / 1024);
+	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	       	ivideo->mmio_base, ivideo->mmio_vbase, ivideo->mmio_size / 1024);
 
-	if(sisfb_heap_init()) {
+	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
 		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
 	}
 
-	ivideo.mtrr = (unsigned int) 0;
+	/* Used for clearing the screen only, therefore respect our mem limit */
+	ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem;
 
-	ivideo.vbflags = 0;
+	ivideo->mtrr = 0;
 
-	if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
+	ivideo->vbflags = 0;
+	ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
+	ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
+	ivideo->defmodeidx    = DEFAULT_MODE;
 
-		sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
-		sishw_ext.Is301BDH = FALSE;
-		sishw_ext.usExternalChip = 0;
+	ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext);
 
-		sisfb_sense_crt1();
+	if((ivideo->sisfb_mode_idx < 0) ||
+	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
 
-		sisfb_get_VB_type();
+		sisfb_sense_crt1(ivideo);
 
-		if(ivideo.vbflags & VB_VIDEOBRIDGE) {
-			sisfb_detect_VB_connect();
+		sisfb_get_VB_type(ivideo);
+
+		if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+			sisfb_detect_VB_connect(ivideo);
 		}
 
-		ivideo.currentvbflags = ivideo.vbflags & VB_VIDEOBRIDGE;
+		ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
 
-		if(ivideo.vbflags & VB_VIDEOBRIDGE) {
-		   if(sisfb_crt2type != -1) {
-		      if((sisfb_crt2type == CRT2_LCD) && (ivideo.vbflags & CRT2_LCD)) {
-		         ivideo.currentvbflags |= CRT2_LCD;
-		      } else if(sisfb_crt2type != CRT2_LCD) {
-		         ivideo.currentvbflags |= sisfb_crt2type;
+		if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+		   if(ivideo->sisfb_crt2type != -1) {
+		      if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) {
+		         ivideo->currentvbflags |= CRT2_LCD;
+		      } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
+		         ivideo->currentvbflags |= ivideo->sisfb_crt2type;
 		      }
 		   } else {
 		      /* Chrontel 700x TV detection often unreliable, therefore use a
 		       * different default order on such machines
 		       */
-		      if((sisvga_engine == SIS_300_VGA) && (ivideo.vbflags & VB_CHRONTEL)) {
-		         if(ivideo.vbflags & CRT2_LCD)      ivideo.currentvbflags |= CRT2_LCD;
-		         else if(ivideo.vbflags & CRT2_TV)  ivideo.currentvbflags |= CRT2_TV;
-		         else if(ivideo.vbflags & CRT2_VGA) ivideo.currentvbflags |= CRT2_VGA;
+		      if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags & VB_CHRONTEL)) {
+		         if(ivideo->vbflags & CRT2_LCD)      ivideo->currentvbflags |= CRT2_LCD;
+		         else if(ivideo->vbflags & CRT2_TV)  ivideo->currentvbflags |= CRT2_TV;
+		         else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
 		      } else {
-		         if(ivideo.vbflags & CRT2_TV)       ivideo.currentvbflags |= CRT2_TV;
-		         else if(ivideo.vbflags & CRT2_LCD) ivideo.currentvbflags |= CRT2_LCD;
-		         else if(ivideo.vbflags & CRT2_VGA) ivideo.currentvbflags |= CRT2_VGA;
+		         if(ivideo->vbflags & CRT2_TV)       ivideo->currentvbflags |= CRT2_TV;
+		         else if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD;
+		         else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
 		      }
 		   }
 		}
 
-		if(ivideo.vbflags & CRT2_LCD) {
-		   inSISIDXREG(SISCR, IND_SIS_LCD_PANEL, reg);
+		if(ivideo->vbflags & CRT2_LCD) {
+		   inSISIDXREG(SISCR, 0x36, reg);
 		   reg &= 0x0f;
-		   if(sisvga_engine == SIS_300_VGA) {
-		      sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
+		   if(ivideo->sisvga_engine == SIS_300_VGA) {
+		      ivideo->sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
+		   } else if(ivideo->chip >= SIS_661) {
+		      ivideo->sishw_ext.ulCRT2LCDType = sis661paneltype[reg];
 		   } else {
-		      sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
+		      ivideo->sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
+		      if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
+		         if((ivideo->sishw_ext.ulCRT2LCDType != LCD_640x480_2) &&
+			    (ivideo->sishw_ext.ulCRT2LCDType != LCD_640x480_3)) {
+		      	    ivideo->sishw_ext.ulCRT2LCDType = LCD_320x480;
+			 }
+		      }
+		   }
+		   if(ivideo->sishw_ext.ulCRT2LCDType == LCD_UNKNOWN) {
+		      ivideo->sishw_ext.ulCRT2LCDType = LCD_1024x768;
+		      printk(KERN_DEBUG "sisfb: Illegal panel ID (%02x), assuming 1024x768\n", reg);
 		   }
+		   for(i = 0; i < SIS_LCD_NUMBER; i++) {
+		      if(ivideo->sishw_ext.ulCRT2LCDType == sis_lcd_data[i].lcdtype) {
+		         ivideo->lcdxres = sis_lcd_data[i].xres;
+			 ivideo->lcdyres = sis_lcd_data[i].yres;
+			 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
+			 break;
+		      }
+		   }
+		   if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
+	   		ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99;
+		   } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
+	   		ivideo->lcdxres =  848; ivideo->lcdyres =  480; ivideo->lcddefmodeidx = 47;
+		   }
+		   printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
+		   		ivideo->lcdxres, ivideo->lcdyres);
 		}
-		
-		sisfb_detectedpdc = 0;
 
 #ifdef CONFIG_FB_SIS_300
                 /* Save the current PanelDelayCompensation if the LCD is currently used */
-		if(sisvga_engine == SIS_300_VGA) {
-	           if(ivideo.vbflags & (VB_LVDS | VB_30xBDH)) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+	           if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) {
 		       int tmp;
 		       inSISIDXREG(SISCR,0x30,tmp);
 		       if(tmp & 0x20) {
 		          /* Currently on LCD? If yes, read current pdc */
-		          inSISIDXREG(SISPART1,0x13,sisfb_detectedpdc);
-			  sisfb_detectedpdc &= 0x3c;
-			  if(SiS_Pr.PDC == 0) {
+		          inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
+			  ivideo->detectedpdc &= 0x3c;
+			  if(ivideo->SiS_Pr.PDC == -1) {
 			     /* Let option override detection */
-			     SiS_Pr.PDC = sisfb_detectedpdc;
+			     ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
 			  }
-			  printk(KERN_INFO
-			         "sisfb: Detected LCD PanelDelayCompensation %d\n",
-  			         sisfb_detectedpdc);
+			  printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
+  			         ivideo->detectedpdc);
 		       }
-		       if((SiS_Pr.PDC) && (SiS_Pr.PDC != sisfb_detectedpdc)) {
-		          printk(KERN_INFO
-			         "sisfb: Using LCD PanelDelayCompensation %d\n",
-				 SiS_Pr.PDC);
+		       if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+		          printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
+				 ivideo->SiS_Pr.PDC);
 		       }
 	           }
 		}
 #endif
 
-	        sisfb_detectedlcda = 0xff;
-
 #ifdef CONFIG_FB_SIS_315
+		if(ivideo->sisvga_engine == SIS_315_VGA) {
+
+		   /* Try to find about LCDA */
+		   if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
+		      int tmp;
+		      inSISIDXREG(SISPART1,0x13,tmp);
+		      if(tmp & 0x04) {
+		         ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
+		         ivideo->detectedlcda = 0x03;
+		      }
+	           }
 
-		if(sisvga_engine == SIS_315_VGA) {
 		   /* Save PDC */
-		   if(ivideo.vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
+		   if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
 		      int tmp;
 		      inSISIDXREG(SISCR,0x30,tmp);
-		      if(tmp & 0x20) {
+		      if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
 		         /* Currently on LCD? If yes, read current pdc */
-		         inSISIDXREG(SISPART1,0x2D,sisfb_detectedpdc);
-			 if(SiS_Pr.PDC == 0) {
-			    /* Let option override detection */
-			    SiS_Pr.PDC = sisfb_detectedpdc;
+			 u8 pdc;
+		         inSISIDXREG(SISPART1,0x2D,pdc);
+			 ivideo->detectedpdc  = (pdc & 0x0f) << 1;
+			 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
+			 inSISIDXREG(SISPART1,0x35,pdc);
+			 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
+			 inSISIDXREG(SISPART1,0x20,pdc);
+			 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
+			 if(ivideo->newrom) {
+			    /* New ROM invalidates other PDC resp. */
+			    if(ivideo->detectedlcda != 0xff) {
+			       ivideo->detectedpdc = 0xff;
+			    } else {
+			       ivideo->detectedpdca = 0xff;
+			    }
+			 }
+			 if(ivideo->SiS_Pr.PDC == -1) {
+			    if(ivideo->detectedpdc != 0xff) {
+			       ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
+			    }
+			 }
+			 if(ivideo->SiS_Pr.PDCA == -1) {
+			    if(ivideo->detectedpdca != 0xff) {
+			       ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
+			    }
+			 }
+			 if(ivideo->detectedpdc != 0xff) {
+			    printk(KERN_INFO
+			         "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
+  			          ivideo->detectedpdc);
+			 }
+			 if(ivideo->detectedpdca != 0xff) {
+			    printk(KERN_INFO
+			         "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
+  			          ivideo->detectedpdca);
 			 }
-			 printk(KERN_INFO
-			        "sisfb: Detected LCD PanelDelayCompensation %d\n",
-  			         sisfb_detectedpdc);
-		      }
-		      if((SiS_Pr.PDC) && (SiS_Pr.PDC != sisfb_detectedpdc)) {
-		         printk(KERN_INFO
-			         "sisfb: Using LCD PanelDelayCompensation %d\n",
-				 SiS_Pr.PDC);
 		      }
+
 		      /* Save EMI */
-		      if(ivideo.vbflags & (VB_302LV | VB_302ELV)) {
-		         inSISIDXREG(SISPART4,0x30,SiS_Pr.EMI_30);
-			 inSISIDXREG(SISPART4,0x31,SiS_Pr.EMI_31);
-			 inSISIDXREG(SISPART4,0x32,SiS_Pr.EMI_32);
-			 inSISIDXREG(SISPART4,0x33,SiS_Pr.EMI_33);
-			 SiS_Pr.HaveEMI = TRUE;
-			 if(tmp & 0x20) SiS_Pr.HaveEMILCD = TRUE;
+		      if(ivideo->vbflags & (VB_302LV | VB_302ELV)) {
+		         inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
+			 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
+			 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
+			 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
+			 ivideo->SiS_Pr.HaveEMI = TRUE;
+			 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+			  	ivideo->SiS_Pr.HaveEMILCD = TRUE;
+			 }
 		      }
 		   }
 
-		   /* Try to find about LCDA */
-		   if(ivideo.vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
-		      int tmp;
-		      inSISIDXREG(SISCR,0x34,tmp);
-		      if((tmp <= 0x13) || (tmp == 0xff)) {
-		         /* Currently on LCDA? (Some BIOSes leave CR38) */
-		         inSISIDXREG(SISCR,0x38,tmp);
-			 if((tmp & 0x03) == 0x03)  SiS_Pr.SiS_UseLCDA = TRUE;
-			 else {
-			    /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
-			    inSISIDXREG(SISCR,0x35,tmp);
-			    if(tmp & 0x01) SiS_Pr.SiS_UseLCDA = TRUE;
-			    else {
-			       /* Currently on LCD? If so, we can find out
-			        * by peeking the mode register
-				*/
-			       inSISIDXREG(SISCR,0x30,tmp);
-			       if(tmp & 0x20) {
-			          inSISIDXREG(SISPART1,0x13,tmp);
-				  if(tmp & 0x04) SiS_Pr.SiS_UseLCDA = TRUE;
-			       }
-			    }
-			 }
+		   /* Let user override detected PDCs (all bridges) */
+		   if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
+		      if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+		         printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
+				 ivideo->SiS_Pr.PDC);
 		      }
-		      if(SiS_Pr.SiS_UseLCDA) {
-		         sisfb_detectedlcda = 0x03;
-		         printk(KERN_DEBUG
-			        "sisfb: Bridge uses LCDA for low resolution and text modes\n");
+		      if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
+		         printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
+				 ivideo->SiS_Pr.PDCA);
 		      }
-	          }
+		   }
+
 		}
 #endif
 
-		if (!sisfb_crt1off) {
-		   	sisfb_handle_ddc(&sisfb_thismonitor, 0);
+		if(!ivideo->sisfb_crt1off) {
+		   	sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
 		} else {
-		   	if ((ivideo.vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
-		      	    (ivideo.vbflags & (CRT2_VGA | CRT2_LCD))) {
-		      		sisfb_handle_ddc(&sisfb_thismonitor, 1);
+		   	if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
+		      	   (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
+		      		sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
 		   	}
 		}
 
-		if (sisfb_mode_idx >= 0)
-			sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
+		if(ivideo->sisfb_mode_idx >= 0) {
+			int bu = ivideo->sisfb_mode_idx;
+			ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
+					ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+			if(bu != ivideo->sisfb_mode_idx) {
+				printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
+					sisbios_mode[bu].xres,
+					sisbios_mode[bu].yres,
+					sisbios_mode[bu].bpp);
+			}
+		}
 
-		if (sisfb_mode_idx < 0) {
-			switch (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo->sisfb_mode_idx < 0) {
+			switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 			   case CRT2_LCD:
-				sisfb_mode_idx = DEFAULT_LCDMODE;
+				ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
 				break;
 			   case CRT2_TV:
-				sisfb_mode_idx = DEFAULT_TVMODE;
+				ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
 				break;
 			   default:
-				sisfb_mode_idx = DEFAULT_MODE;
+				ivideo->sisfb_mode_idx = ivideo->defmodeidx;
 				break;
 			}
 		}
 
-		sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+		ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
 
-		if (ivideo.refresh_rate != 0)
-			sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx);
+		if(ivideo->refresh_rate != 0) {
+			sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx);
+		}
 
-		if (sisfb_rate_idx == 0) {
-			sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
-			ivideo.refresh_rate = 60;
+		if(ivideo->rate_idx == 0) {
+			ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
+			ivideo->refresh_rate = 60;
 		}
 
-		if (sisfb_thismonitor.datavalid) {
-			if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
-			                      sisfb_rate_idx, ivideo.refresh_rate)) {
+		if(ivideo->sisfb_thismonitor.datavalid) {
+			if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
+			                      ivideo->rate_idx, ivideo->refresh_rate)) {
 				printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 			}
 		}
 
-		ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
-		ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
-		ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
-		ivideo.org_x = ivideo.org_y = 0;
-		ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
+		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+		ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
 
-		sisfb_set_vparms();
+		sisfb_set_vparms(ivideo);
 		
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
 
 		/* ---------------- For 2.4: Now switch the mode ------------------ */		
 		
 		printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n",
-	       		ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
-			ivideo.refresh_rate);
+	       		ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+			ivideo->refresh_rate);
 
-		sisfb_pre_setmode();
+		sisfb_pre_setmode(ivideo);
 
-		if (SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {
+		if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
 			printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
-				sisfb_mode_no);
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			release_mem_region(ivideo.video_base, ivideo.video_size);
-			release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
+									ivideo->mode_no);
+			iounmap((void *)ivideo->video_vbase);
+			iounmap((void *)ivideo->mmio_vbase);
+			release_mem_region(ivideo->video_base, ivideo->video_size);
+			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+			if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+			pci_set_drvdata(pdev, NULL);
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
 
 		outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-		sisfb_post_setmode();
-
-		ivideo.accel = 0;
-		if(sisfb_accel) {
-		   ivideo.accel = -1;
-		   default_var.accel_flags |= FB_ACCELF_TEXT;
-		   sisfb_initaccel();
-		}
+		sisfb_post_setmode(ivideo);
 
 		/* Maximize regardless of sisfb_max at startup */
-		default_var.yres_virtual = 32767;
-		sisfb_crtc_to_var(&default_var);
+		ivideo->default_var.yres_virtual = 32767;
+
+		/* Force reset of x virtual in crtc_to_var */
+		ivideo->default_var.xres_virtual = 0;
+
+		sisfb_crtc_to_var(ivideo, &ivideo->default_var);
+
+		sisfb_calc_pitch(ivideo, &ivideo->default_var);
+		sisfb_set_pitch(ivideo);
+
+		ivideo->accel = 0;
+		if(ivideo->sisfb_accel) {
+		   ivideo->accel = -1;
+		   ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+		}
+		sisfb_initaccel(ivideo);
 		
-		sis_fb_info->node = -1;
+		sis_fb_info->node  = -1;
 		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
-		sis_fb_info->blank = &sisfb_blank;
 		sis_fb_info->fbops = &sisfb_ops;
+		sis_fb_info->disp  = &ivideo->sis_disp;
+		sis_fb_info->blank = &sisfb_blank;
 		sis_fb_info->switch_con = &sisfb_switch;
-		sis_fb_info->updatevar = &sisfb_update_var;
-		sis_fb_info->changevar = NULL;
-		sis_fb_info->disp = &sis_disp;
+		sis_fb_info->updatevar  = &sisfb_update_var;
+		sis_fb_info->changevar  = NULL;
 		strcpy(sis_fb_info->fontname, sisfb_fontname);
 
-		sisfb_set_disp(-1, &default_var, sis_fb_info);
+		sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info);
 
-#else		/* --------- For 2.5: Setup a somewhat sane default var ------------ */
+#else		/* --------- For 2.6: Setup a somewhat sane default var ------------ */
 
 		printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
-	       		ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
-			ivideo.refresh_rate);
+	       		ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+			ivideo->refresh_rate);
 
-		default_var.xres = default_var.xres_virtual = ivideo.video_width;
-		default_var.yres = default_var.yres_virtual = ivideo.video_height;
-		default_var.bits_per_pixel = ivideo.video_bpp;
+		ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
+		ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
+		ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
 
-		sisfb_bpp_to_var(&default_var);
+		sisfb_bpp_to_var(ivideo, &ivideo->default_var);
 		
-		default_var.pixclock = (u32) (1000000000 /
-				sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
-						sisfb_mode_no, sisfb_rate_idx));
+		ivideo->default_var.pixclock = (u32) (1000000000 /
+				sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+						ivideo->mode_no, ivideo->rate_idx));
 						
-		if(sisfb_mode_rate_to_ddata(&SiS_Pr, &sishw_ext,
-			 sisfb_mode_no, sisfb_rate_idx,
-			 &default_var.left_margin, &default_var.right_margin, 
-			 &default_var.upper_margin, &default_var.lower_margin,
-			 &default_var.hsync_len, &default_var.vsync_len,
-			 &default_var.sync, &default_var.vmode)) {
-		   if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-		      default_var.pixclock <<= 1;
+		if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+			 	ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) {
+		   if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		      ivideo->default_var.pixclock <<= 1;
 	   	   }
 	        }
 
-		ivideo.accel = 0;
-		if(sisfb_accel) {
-		   ivideo.accel = -1;
-		   default_var.accel_flags |= FB_ACCELF_TEXT;
-		   sisfb_initaccel();
-		}
-
-		if(sisfb_ypan) {
+		if(ivideo->sisfb_ypan) {
 		   /* Maximize regardless of sisfb_max at startup */
-	    	   default_var.yres_virtual =
-				ivideo.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
-		   if(default_var.yres_virtual > 32767) default_var.yres_virtual = 32767;
-	    	   if(default_var.yres_virtual <= default_var.yres) {
-	              default_var.yres_virtual = default_var.yres;
+	    	   ivideo->default_var.yres_virtual = sisfb_calc_maxyres(ivideo, &ivideo->default_var);
+	    	   if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
+	              ivideo->default_var.yres_virtual = ivideo->default_var.yres;
 	    	   }
 		}
 
+		sisfb_calc_pitch(ivideo, &ivideo->default_var);
+
+		ivideo->accel = 0;
+		if(ivideo->sisfb_accel) {
+		   ivideo->accel = -1;
+#ifdef STUPID_ACCELF_TEXT_SHIT
+		   ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+#endif
+		}
+		sisfb_initaccel(ivideo);
+
+#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
+		sis_fb_info->flags = FBINFO_DEFAULT 		|
+				     FBINFO_HWACCEL_YPAN 	|
+				     FBINFO_HWACCEL_XPAN 	|
+				     FBINFO_HWACCEL_COPYAREA 	|
+				     FBINFO_HWACCEL_FILLRECT 	|
+				     ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
+#else
 		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
-		sis_fb_info->var = default_var;
-		sis_fb_info->fix = sisfb_fix;
-		sis_fb_info->par = &ivideo;
-		sis_fb_info->screen_base = ivideo.video_vbase;
-		sis_fb_info->fbops = &sisfb_ops;
-#ifdef NEWFBDEV
-		sis_fb_info->class_dev.dev = &pdev->dev;
 #endif
+		sis_fb_info->var = ivideo->default_var;
+		sis_fb_info->fix = ivideo->sisfb_fix;
+		sis_fb_info->screen_base = (char *)ivideo->video_vbase;
+		sis_fb_info->fbops = &sisfb_ops;
+
 		sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
-		sis_fb_info->pseudo_palette = pseudo_palette;
+		sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
 		
 		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
-#endif
+#endif		/* 2.6 */
 
-		printk(KERN_INFO "sisfb: Initial vbflags 0x%lx\n", ivideo.vbflags);
+		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags);
 
 #ifdef CONFIG_MTRR
-		ivideo.mtrr = mtrr_add((unsigned int) ivideo.video_base,
-				(unsigned int) ivideo.video_size,
-				MTRR_TYPE_WRCOMB, 1);
-		if(ivideo.mtrr) {
-			printk(KERN_INFO "sisfb: Added MTRRs\n");
+		ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
+					MTRR_TYPE_WRCOMB, 1);
+		if(!ivideo->mtrr) {
+			printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
 		}
-
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -4946,39 +5573,157 @@
 #endif
 
 		if(register_framebuffer(sis_fb_info) < 0) {
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			release_mem_region(ivideo.video_base, ivideo.video_size);
-			release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
 			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
+			iounmap((void *)ivideo->video_vbase);
+			iounmap((void *)ivideo->mmio_vbase);
+			release_mem_region(ivideo->video_base, ivideo->video_size);
+			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+			if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+			pci_set_drvdata(pdev, NULL);
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
 
-		sisfb_registered = 1;			
+		ivideo->registered = 1;
 
-		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_INFO ioctl (%x)\n", SISFB_GET_INFO);
-		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_VBRSTATUS ioctl (%x)\n", SISFB_GET_VBRSTATUS);
-		
-		printk(KERN_INFO "sisfb: 2D acceleration is %s, scrolling mode %s\n",
-		     sisfb_accel ? "enabled" : "disabled",
-		     sisfb_ypan  ? (sisfb_max ? "ypan (auto-max)" : "ypan (no auto-max)") : "redraw");
+		/* Enlist us */
+		ivideo->next = card_list;
+		card_list = ivideo;
+
+#ifdef SIS_CONFIG_COMPAT
+		{
+		int ret;
+		/* Our ioctls are all "32/64bit compatible" */
+		if(register_ioctl32_conversion(FBIOGET_VBLANK, NULL)) {
+		   printk(KERN_ERR "sisfb: Error registering FBIOGET_VBLANK ioctl32 translation\n");
+		} else {
+		   ivideo->ioctl32vblankregistered = 1;
+		}
+		ret =  register_ioctl32_conversion(FBIO_ALLOC,             NULL);
+		ret |= register_ioctl32_conversion(FBIO_FREE,              NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE,    NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_INFO,         NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET,  NULL);
+		ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET,  NULL);
+		ret |= register_ioctl32_conversion(SISFB_SET_LOCK,         NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS,    NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
+		ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
+		if(ret)	printk(KERN_ERR "sisfb: Error registering ioctl32 translations\n");
+		else    ivideo->ioctl32registered = 1;
+		}
+#endif
+
+		printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
+		     ivideo->sisfb_accel ? "enabled" : "disabled",
+		     ivideo->sisfb_ypan  ?
+		     	(ivideo->sisfb_max ? "enabled (auto-max)" : "enabled (no auto-max)") : "disabled");
 
+
+		printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%d\n",
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
-	       		GET_FB_IDX(sis_fb_info->node), sis_fb_info->modename, VER_MAJOR, VER_MINOR,
-	       		VER_LEVEL);		     
+	       		GET_FB_IDX(sis_fb_info->node),
 #else
-		printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
-	       		sis_fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
+	       		sis_fb_info->node,
 #endif
+			ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
 
 		printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n");
 
 	}	/* if mode = "none" */
+
 	return 0;
 }
 
+/*****************************************************/
+/*                PCI DEVICE HANDLING                */
+/*****************************************************/
+
+static void __devexit sisfb_remove(struct pci_dev *pdev)
+{
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	struct fb_info        *sis_fb_info = ivideo->memyselfandi;
+	int                   registered = ivideo->registered;
+
+#ifdef SIS_CONFIG_COMPAT
+	if(ivideo->ioctl32vblankregistered) {
+		if(unregister_ioctl32_conversion(FBIOGET_VBLANK)) {
+			printk(KERN_ERR "sisfb: Error unregistering FBIOGET_VBLANK ioctl32 translation\n");
+		}
+	}
+	if(ivideo->ioctl32registered) {
+		int ret;
+		ret =  unregister_ioctl32_conversion(FBIO_ALLOC);
+		ret |= unregister_ioctl32_conversion(FBIO_FREE);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
+		ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
+		ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
+		ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
+		if(ret)	printk(KERN_ERR "sisfb: Error unregistering ioctl32 translations\n");
+	}
+#endif
+
+	/* Unmap */
+	iounmap((void *)ivideo->video_vbase);
+	iounmap((void *)ivideo->mmio_vbase);
+	if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+	if(ivideo->bios_abase)    vfree(ivideo->bios_abase);
+
+	/* Release mem regions */
+	release_mem_region(ivideo->video_base, ivideo->video_size);
+	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+
+#ifdef CONFIG_MTRR
+	/* Release MTRR region */
+	if(ivideo->mtrr) {
+		mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
+	}
+#endif
+
+	/* Unregister the framebuffer */
+	if(ivideo->registered) {
+		unregister_framebuffer(sis_fb_info);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+		framebuffer_release(sis_fb_info);
+#else
+		kfree(sis_fb_info);
+#endif
+	}
+
+	pci_set_drvdata(pdev, NULL);
+
+	/* TODO: Restore the initial mode
+	 * This sounds easy but is as good as impossible
+	 * on many machines with SiS chip and video bridge
+	 * since text modes are always set up differently
+	 * from machine to machine. Depends on the type
+	 * of integration between chipset and bridge.
+	 */
+	if(registered) {
+	   printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n");
+	}
+};
+
+static struct pci_driver sisfb_driver = {
+	.name		= "sisfb",
+	.id_table 	= sisfb_pci_table,
+	.probe 		= sisfb_probe,
+	.remove 	= __devexit_p(sisfb_remove)
+};
+
+int __init sisfb_init(void)
+{
+	return(pci_module_init(&sisfb_driver));
+}
+
+/*****************************************************/
+/*                      MODULE                       */
+/*****************************************************/
 
 #ifdef MODULE
 
@@ -4989,202 +5734,240 @@
 static unsigned int mem = 0;
 static char         *forcecrt2type = NULL;
 static int          forcecrt1 = -1;
-static char         *queuemode = NULL;
-static int          pdc = 0;
+static int          pdc = -1;
+static int          pdc1 = -1;
 static int          noaccel = -1;
 static int          noypan  = -1;
 static int	    nomax = -1;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static int          inverse = 0;
 #endif
-static int          userom = 1;
+static int          userom = -1;
 static int          useoem = -1;
 static char         *tvstandard = NULL;
 static int	    nocrt2rate = 0;
 static int          scalelcd = -1;
 static char	    *specialtiming = NULL;
 static int	    lvdshl = -1;
+static int	    tvxposoffset = 0, tvyposoffset = 0;
+static int	    filter = -1;
+#if !defined(__i386__) && !defined(__x86_64__)
+static int	    resetcard = 0;
+static int	    videoram = 0;
+#endif
 
-MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/650/651/661/740/741/330/760 framebuffer driver");
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver");
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>; SiS; Various others");
+MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+MODULE_PARM(mem, "i");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM(noypan, "i");
+MODULE_PARM(nomax, "i");
+MODULE_PARM(userom, "i");
+MODULE_PARM(useoem, "i");
 MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode,
-       "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
-         "1024x768x16. Other formats supported include XxY-Depth and\n"
-	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
-	 "number, it will be interpreted as a VESA mode number. (default: none if\n"
-	 "sisfb is a module; this leaves the console untouched and the driver will\n"
-	 "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
-	 "is in the kernel)");
+MODULE_PARM(vesa, "i");
+MODULE_PARM(rate, "i");
+MODULE_PARM(forcecrt1, "i");
+MODULE_PARM(forcecrt2type, "s");
+MODULE_PARM(scalelcd, "i");
+MODULE_PARM(pdc, "i");
+MODULE_PARM(pdc1, "i");
+MODULE_PARM(specialtiming, "s");
+MODULE_PARM(lvdshl, "i");
+MODULE_PARM(tvstandard, "s");
+MODULE_PARM(tvxposoffset, "i");
+MODULE_PARM(tvyposoffset, "i");
+MODULE_PARM(filter, "i");
+MODULE_PARM(nocrt2rate, "i");
+MODULE_PARM(inverse, "i");
+#if !defined(__i386__) && !defined(__x86_64__)
+MODULE_PARM(resetcard, "i");
+MODULE_PARM(videoram, "i");
+#endif
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+module_param(mem, int, 0);
+module_param(noaccel, int, 0);
+module_param(noypan, int, 0);
+module_param(nomax, int, 0);
+module_param(userom, int, 0);
+module_param(useoem, int, 0);
+module_param(mode, charp, 0);
+module_param(vesa, int, 0);
+module_param(rate, int, 0);
+module_param(forcecrt1, int, 0);
+module_param(forcecrt2type, charp, 0);
+module_param(scalelcd, int, 0);
+module_param(pdc, int, 0);
+module_param(pdc1, int, 0);
+module_param(specialtiming, charp, 0);
+module_param(lvdshl, int, 0);
+module_param(tvstandard, charp, 0);
+module_param(tvxposoffset, int, 0);
+module_param(tvyposoffset, int, 0);
+module_param(filter, int, 0);
+module_param(nocrt2rate, int, 0);
+#if !defined(__i386__) && !defined(__x86_64__)
+module_param(resetcard, int, 0);
+module_param(videoram, int, 0);
 #endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)	 
-MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode,
-       "\nSelects the desired default display mode in the format XxYxDepth,\n"
-         "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
-	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
-	 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)");
 #endif
 
+MODULE_PARM_DESC(mem,
+	"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
+	  "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
+	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
+	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
+	  "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
+	  "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
+	  "for XFree86 4.x/X.org 6.7 and later.\n");
+
+MODULE_PARM_DESC(noaccel,
+        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+	  "(default: 0)\n");
+
+MODULE_PARM_DESC(noypan,
+        "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
+ 	  "will be performed by redrawing the screen. (default: 0)\n");
+
+MODULE_PARM_DESC(nomax,
+        "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
+	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
+	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
+	  "enable the user to positively specify a virtual Y size of the screen using\n"
+	  "fbset. (default: 0)\n");
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-MODULE_PARM(vesa, "i");
+MODULE_PARM_DESC(mode,
+        "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
+          "1024x768x16. Other formats supported include XxY-Depth and\n"
+ 	  "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
+	  "number, it will be interpreted as a VESA mode number. (default: none if\n"
+	  "sisfb is a module; this leaves the console untouched and the driver will\n"
+	  "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
+	  "is in the kernel)\n");
 MODULE_PARM_DESC(vesa,
-       "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
-         "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
-	 "and the driver will only do the video memory management for eg. DRM/DRI;\n"
-	 "0x0103 if sisfb is in the kernel)");
+        "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
+          "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
+	  "and the driver will only do the video memory management for eg. DRM/DRI;\n"
+	  "0x0103 if sisfb is in the kernel)\n");
 #endif
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-MODULE_PARM(vesa, "i");
+MODULE_PARM_DESC(mode,
+       "\nSelects the desired default display mode in the format XxYxDepth,\n"
+         "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
+	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
+	 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
+
 MODULE_PARM_DESC(vesa,
        "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
-         "0x117 (default: 0x0103)");
+         "0x117 (default: 0x0103)\n");
 #endif
 
-MODULE_PARM(rate, "i");
 MODULE_PARM_DESC(rate,
 	"\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
 	  "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
-	  "will be ignored (default: 60)");
-
-MODULE_PARM(crt1off,   "i");
-MODULE_PARM_DESC(crt1off,
-	"(Deprecated, please use forcecrt1)");
+	  "will be ignored (default: 60)\n");
 
-MODULE_PARM(filter, "i");
-MODULE_PARM_DESC(filter,
-	"\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
-	  "(Possible values 0-7, default: [no filter])");
-
-MODULE_PARM(queuemode,   "s");
-MODULE_PARM_DESC(queuemode,
-	"\nSelects the queue mode on 315/550/65x/74x/330/760. Possible choices are AGP, VRAM,\n"
-  	  "MMIO. AGP is only available if the kernel has AGP support. The queue mode is\n"
-	  "important to programs using the 2D/3D accelerator of the SiS chip. The modes\n"
-	  "require a totally different way of programming the engines. If any mode than\n"
-	  "MMIO is selected, sisfb will disable its own 2D acceleration. On\n"
-	  "300/540/630/730, this option is ignored. (default: MMIO)");
-
-/* TW: "Import" the options from the X driver */
-MODULE_PARM(mem,    "i");
-MODULE_PARM_DESC(mem,
-	"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
-	  "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
-	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
-	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
-	  "otherwise at 12288KB. On 315 and Xabre series, the heap is 1MB by default. The\n"
-	  "value is to be specified without 'KB' and should match the MaxXFBMem setting for\n"
-	  "XFree 4.x (x>=2).");
+MODULE_PARM_DESC(forcecrt1,
+	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
+	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
+	  "0=CRT1 OFF) (default: [autodetected])\n");
 
-MODULE_PARM(forcecrt2type, "s");
 MODULE_PARM_DESC(forcecrt2type,
 	"\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
 	  "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
 	  "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
-	  "On systems with a 301(B/LV) bridge, parameters SVIDEO, COMPOSITE or SCART can be\n"
-	  "used instead of TV to override the TV detection. (default: [autodetected])");
+	  "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
+	  "be used instead of TV to override the TV detection. Furthermore, on systems\n"
+	  "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
+	  "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
+	  "depends on the very hardware in use. (default: [autodetected])\n");
 
-MODULE_PARM(forcecrt1, "i");
-MODULE_PARM_DESC(forcecrt1,
-	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
-	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
-	  " 0=CRT1 off) (default: [autodetected])");
+MODULE_PARM_DESC(scalelcd,
+	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
+	  "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
+	  "show black bars around the image, TMDS panels will probably do the scaling\n"
+	  "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
 
-MODULE_PARM(pdc, "i");
 MODULE_PARM_DESC(pdc,
         "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
 	  "should detect this correctly in most cases; however, sometimes this is not\n"
 	  "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
-	  "on a 300 series chipset; 3 or 51 on a 315 series chipset. If the problem persists,\n"
+	  "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
 	  "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
-	  "and value from 0 to 255). (default: [autodetected])");
-
-MODULE_PARM(noaccel, "i");
-MODULE_PARM_DESC(noaccel,
-        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
-	  "(default: 0)");
+	  "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
 
-MODULE_PARM(noypan, "i");
-MODULE_PARM_DESC(noypan,
-        "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
- 	  "will be performed by redrawing the screen. (default: 0)");
-
-MODULE_PARM(nomax, "i");
-MODULE_PARM_DESC(nomax,
-        "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
-	  "memory for the virtual screen in order to optimize scrolling performance. If this\n"
-	  "is set to anything other than 0, sisfb will not do this and thereby enable the user\n"
-	  "to positively specify a virtual Y size of the screen using fbset. (default: 0)\n");
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
-MODULE_PARM(inverse, "i");
-MODULE_PARM_DESC(inverse,
-        "\nSetting this to anything but 0 should invert the display colors, but this\n"
-	  "does not seem to work. (default: 0)");
-#endif	
+#ifdef CONFIG_FB_SIS_315
+MODULE_PARM_DESC(pdc1,
+        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
+	  "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
+	  "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
+	  "implemented yet.\n");
+#endif
 
-MODULE_PARM(userom, "i");
-MODULE_PARM_DESC(userom,
-        "\nSetting this to 0 keeps sisfb from using the video BIOS data which is needed\n"
-	  "for some LCD and TV setup. (default: 1)");
+MODULE_PARM_DESC(specialtiming,
+	"\nPlease refer to documentation for more information on this option.\n");
 
-MODULE_PARM(useoem, "i");
-MODULE_PARM_DESC(useoem,
-        "\nSetting this to 0 keeps sisfb from using its internel OEM data for some LCD\n"
-	  "panels and TV connector types. (default: [auto])");
+MODULE_PARM_DESC(lvdshl,
+	"\nPlease refer to documentation for more information on this option.\n");
 
-MODULE_PARM(tvstandard, "s");
 MODULE_PARM_DESC(tvstandard,
 	"\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
-	  "pal and ntsc. (default: [auto])");
+	  "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
+
+MODULE_PARM_DESC(tvxposoffset,
+	"\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
+	  "Default: 0\n");
+
+MODULE_PARM_DESC(tvyposoffset,
+	"\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
+	  "Default: 0\n");
+
+MODULE_PARM_DESC(filter,
+	"\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
+	  "(Possible values 0-7, default: [no filter])\n");
 
-MODULE_PARM(nocrt2rate, "i");
 MODULE_PARM_DESC(nocrt2rate,
 	"\nSetting this to 1 will force the driver to use the default refresh rate for\n"
-	  "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)");
-
-MODULE_PARM(scalelcd, "i");
-MODULE_PARM_DESC(scalelcd,
-	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
-	  "native resolution. Setting it to 0 will disable scaling; if the panel can scale\n"
-	  "by itself, it will probably do this, otherwise you will see a black bar around\n"
-	  "the screen image. Default: [autodetect if panel can scale]");
+	  "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
 
-MODULE_PARM(specialtiming, "s");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+MODULE_PARM_DESC(inverse,
+        "\nSetting this to anything but 0 should invert the display colors, but this\n"
+	  "does not seem to work. (default: 0)\n");
+#endif
 
-MODULE_PARM(lvdshl, "i");
+#if !defined(__i386__) && !defined(__x86_64__)
+#ifdef CONFIG_FB_SIS_300
+MODULE_PARM_DESC(resetcard,
+	"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
+	  "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n"
+	  "Default: 0\n");
 
+MODULE_PARM_DESC(videoram,
+	"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
+	  "some non-x86 architectures where the memory auto detection fails. Only\n"
+	  "relevant if resetcard is set, too. Default: [auto-detect]\n");
+#endif
+#endif
 
-int init_module(void)
+int __init sisfb_init_module(void)
 {
-	int err;
-
-	SiS_Pr.UsePanelScaler = -1;
-	SiS_Pr.SiS_CustomT = CUT_NONE;
-	SiS_Pr.LVDSHL = -1;
+	sisfb_setdefaultparms();
 
-	ivideo.refresh_rate = sisfb_parm_rate = rate;
+	if(rate) sisfb_parm_rate = rate;
 
 	if((scalelcd == 0) || (scalelcd == 1)) {
-	   SiS_Pr.UsePanelScaler = scalelcd ^ 1;
+	   sisfb_scalelcd = scalelcd ^ 1;
 	}
 
-	if(mode)
-		sisfb_search_mode(mode, FALSE);
-	else if(vesa != -1)
-		sisfb_search_vesamode(vesa, FALSE);
-	else
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		/* For 2.4, set mode=none if no mode is given  */
-		sisfb_mode_idx = MODE_INDEX_NONE;
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-		/* For 2.5, we don't need this "mode=none" stuff anymore */
-		sisfb_mode_idx = DEFAULT_MODE;
-#endif
+	/* Need to check crt2 type first for fstn/dstn */
 
 	if(forcecrt2type)
 		sisfb_search_crt2type(forcecrt2type);
@@ -5192,16 +5975,16 @@
 	if(tvstandard)
 		sisfb_search_tvstd(tvstandard);
 
-	if(crt1off == 0)
-		sisfb_crt1off = 1;
-	else
-		sisfb_crt1off = 0;
+	if(mode)
+		sisfb_search_mode(mode, FALSE);
+	else if(vesa != -1)
+		sisfb_search_vesamode(vesa, FALSE);
+
+	sisfb_crt1off = (crt1off == 0) ? 1 : 0;
 
 	sisfb_forcecrt1 = forcecrt1;
-	if(forcecrt1 == 1)
-		sisfb_crt1off = 0;
-	else if(forcecrt1 == 0)
-		sisfb_crt1off = 1;
+	if(forcecrt1 == 1)      sisfb_crt1off = 0;
+	else if(forcecrt1 == 0) sisfb_crt1off = 1;
 
 	if(noaccel == 1)      sisfb_accel = 0;
 	else if(noaccel == 0) sisfb_accel = 1;
@@ -5214,84 +5997,48 @@
 	
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	if(inverse)           sisfb_inverse = 1;
-	sisfb_fontname[0] = '\0';
 #endif
 
-	if(mem)		      sisfb_mem = mem;
-
-	sisfb_userom = userom;
+	if(mem)		      sisfb_parm_mem = mem;
 
-	sisfb_useoem = useoem;
-
-	if (queuemode)        sisfb_search_queuemode(queuemode);
-	
-	/* If other queuemode than MMIO, disable 2D accel and ypan */
-	if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
-	        sisfb_accel = 0;
-	}
+	if(userom != -1)      sisfb_userom = userom;
+	if(useoem != -1)      sisfb_useoem = useoem;
 
-        if(pdc) sisfb_pdc = pdc & 0x3c;
+        if(pdc != -1)  sisfb_pdc  = (pdc  & 0x7f);
+	if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
 
 	sisfb_nocrt2rate = nocrt2rate;
 
 	if(specialtiming)
 		sisfb_search_specialtiming(specialtiming);
 
-	if((lvdshl >= 0) && (lvdshl <= 3)) SiS_Pr.LVDSHL = lvdshl;
+	if((lvdshl >= 0) && (lvdshl <= 3))  sisfb_lvdshl = lvdshl;
 
-	if((err = sisfb_init()) < 0) return err;
+	if(filter != -1) sisfb_filter = filter;
 
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	/* Unmap */
-	iounmap(ivideo.video_vbase);
-	iounmap(ivideo.mmio_vbase);
+	sisfb_tvxposoffset = tvxposoffset;
+	sisfb_tvyposoffset = tvyposoffset;
 
-	/* Release mem regions */
-	release_mem_region(ivideo.video_base, ivideo.video_size);
-	release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
-
-#ifdef CONFIG_MTRR
-	/* Release MTRR region */
-	if(ivideo.mtrr) {
-		mtrr_del(ivideo.mtrr,
-		      (unsigned int)ivideo.video_base,
-	              (unsigned int)ivideo.video_size);
-	}
+#if !defined(__i386__) && !defined(__x86_64__)
+ 	sisfb_resetcard = (resetcard) ? 1 : 0;
+	if(videoram)    sisfb_videoram = videoram;
 #endif
 
-	/* Unregister the framebuffer */
-	if(sisfb_registered) {
-		unregister_framebuffer(sis_fb_info);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (defined(NEWFBDEV))
-		framebuffer_release(sis_fb_info);
-#else
-		kfree(sis_fb_info);
-#endif
-	}
+        return(sisfb_init());
+}
 
-	if(sishw_ext.pSR) vfree(sishw_ext.pSR);
-	if(sishw_ext.pCR) vfree(sishw_ext.pCR);
-	
-	/* TODO: Restore the initial mode
-	 * This sounds easy but is as good as impossible
-	 * on many machines with SiS chip and video bridge
-	 * since text modes are always set up differently
-	 * from machine to machine. Depends on the type
-	 * of integration between chipset and bridge.
-	 */
-	
-	printk(KERN_INFO "sisfb: Module unloaded\n");
+static void __exit sisfb_remove_module(void)
+{
+	pci_unregister_driver(&sisfb_driver);
+	printk(KERN_DEBUG "sisfb: Module unloaded\n");
 }
 
-#endif
+module_init(sisfb_init_module);
+module_exit(sisfb_remove_module);
+
+#endif 	   /*  /MODULE  */
 
 EXPORT_SYMBOL(sis_malloc);
 EXPORT_SYMBOL(sis_free);
-EXPORT_SYMBOL(sis_dispinfo);
 
-EXPORT_SYMBOL(ivideo);
-                                                                                           
+
diff -Nru a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
--- a/drivers/video/sis/sis_main.h	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/sis/sis_main.h	2004-06-23 19:04:26 -07:00
@@ -1,6 +1,7 @@
 /*
- * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/330/760
- * frame buffer driver for Linux kernels 2.4.x and 2.5.x
+ * SiS 300/305/540/630(S)/730(S)
+ * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
  *
  * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
  *
@@ -22,304 +23,15 @@
 #ifndef _SISFB_MAIN
 #define _SISFB_MAIN
 
-#include "vstruct.h"
-
-/* ------------------- Constant Definitions ------------------------- */
-
-#define AGPOFF     /* default is turn off AGP */
-
-#define SISFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
-
-#define VER_MAJOR                 1
-#define VER_MINOR                 6
-#define VER_LEVEL                 25
+#include <linux/spinlock.h>
 
+#include "vstruct.h"
 #include "sis.h"
 
-/* To be included in pci_ids.h */
-#ifndef PCI_DEVICE_ID_SI_650_VGA
-#define PCI_DEVICE_ID_SI_650_VGA  0x6325
-#endif
-#ifndef PCI_DEVICE_ID_SI_650
-#define PCI_DEVICE_ID_SI_650      0x0650
-#endif
-#ifndef PCI_DEVICE_ID_SI_740
-#define PCI_DEVICE_ID_SI_740      0x0740
-#endif
-#ifndef PCI_DEVICE_ID_SI_330
-#define PCI_DEVICE_ID_SI_330      0x0330
-#endif
-#ifndef PCI_DEVICE_ID_SI_660_VGA
-#define PCI_DEVICE_ID_SI_660_VGA  0x6330
-#endif
-#ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660      0x0661
-#endif
-#ifndef PCI_DEVICE_ID_SI_741
-#define PCI_DEVICE_ID_SI_741      0x0741
-#endif
-#ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660      0x0660
-#endif
-#ifndef PCI_DEVICE_ID_SI_760
-#define PCI_DEVICE_ID_SI_760      0x0760
-#endif
-
-/* To be included in fb.h */
-#ifndef FB_ACCEL_SIS_GLAMOUR_2
-#define FB_ACCEL_SIS_GLAMOUR_2  40	/* SiS 315, 65x, 740, 661, 741  */
-#endif
-#ifndef FB_ACCEL_SIS_XABRE
-#define FB_ACCEL_SIS_XABRE      41	/* SiS 330 ("Xabre"), 760 	*/
-#endif
-
-#define MAX_ROM_SCAN              0x10000
-
-#define HW_CURSOR_CAP             0x80
-#define TURBO_QUEUE_CAP           0x40
-#define AGP_CMD_QUEUE_CAP         0x20
-#define VM_CMD_QUEUE_CAP          0x10
-#define MMIO_CMD_QUEUE_CAP        0x08
-
-/* For 300 series */
-#ifdef CONFIG_FB_SIS_300
-#define TURBO_QUEUE_AREA_SIZE     0x80000 /* 512K */
-#endif
-
-/* For 315/Xabre series */
-#ifdef CONFIG_FB_SIS_315
-#define COMMAND_QUEUE_AREA_SIZE   0x80000 /* 512K */
-#define COMMAND_QUEUE_THRESHOLD   0x1F
-#endif
-
-#define HW_CURSOR_AREA_SIZE_315   0x4000  /* 16K */
-#define HW_CURSOR_AREA_SIZE_300   0x1000  /* 4K */
-
-#define OH_ALLOC_SIZE             4000
-#define SENTINEL                  0x7fffffff
-
-#define SEQ_ADR                   0x14
-#define SEQ_DATA                  0x15
-#define DAC_ADR                   0x18
-#define DAC_DATA                  0x19
-#define CRTC_ADR                  0x24
-#define CRTC_DATA                 0x25
-#define DAC2_ADR                  (0x16-0x30)
-#define DAC2_DATA                 (0x17-0x30)
-#define VB_PART1_ADR              (0x04-0x30)
-#define VB_PART1_DATA             (0x05-0x30)
-#define VB_PART2_ADR              (0x10-0x30)
-#define VB_PART2_DATA             (0x11-0x30)
-#define VB_PART3_ADR              (0x12-0x30)
-#define VB_PART3_DATA             (0x13-0x30)
-#define VB_PART4_ADR              (0x14-0x30)
-#define VB_PART4_DATA             (0x15-0x30)
-
-#define SISSR			  SiS_Pr.SiS_P3c4
-#define SISCR                     SiS_Pr.SiS_P3d4
-#define SISDACA                   SiS_Pr.SiS_P3c8
-#define SISDACD                   SiS_Pr.SiS_P3c9
-#define SISPART1                  SiS_Pr.SiS_Part1Port
-#define SISPART2                  SiS_Pr.SiS_Part2Port
-#define SISPART3                  SiS_Pr.SiS_Part3Port
-#define SISPART4                  SiS_Pr.SiS_Part4Port
-#define SISPART5                  SiS_Pr.SiS_Part5Port
-#define SISDAC2A                  SISPART5
-#define SISDAC2D                  (SISPART5 + 1)
-#define SISMISCR                  (SiS_Pr.RelIO + 0x1c)
-#define SISMISCW                  SiS_Pr.SiS_P3c2
-#define SISINPSTAT		  (SiS_Pr.RelIO + 0x2a)
-#define SISPEL			  SiS_Pr.SiS_P3c6
-
-#define IND_SIS_PASSWORD          0x05  /* SRs */
-#define IND_SIS_COLOR_MODE        0x06
-#define IND_SIS_RAMDAC_CONTROL    0x07
-#define IND_SIS_DRAM_SIZE         0x14
-#define IND_SIS_SCRATCH_REG_16    0x16
-#define IND_SIS_SCRATCH_REG_17    0x17
-#define IND_SIS_SCRATCH_REG_1A    0x1A
-#define IND_SIS_MODULE_ENABLE     0x1E
-#define IND_SIS_PCI_ADDRESS_SET   0x20
-#define IND_SIS_TURBOQUEUE_ADR    0x26
-#define IND_SIS_TURBOQUEUE_SET    0x27
-#define IND_SIS_POWER_ON_TRAP     0x38
-#define IND_SIS_POWER_ON_TRAP2    0x39
-#define IND_SIS_CMDQUEUE_SET      0x26
-#define IND_SIS_CMDQUEUE_THRESHOLD  0x27
-
-#define IND_SIS_SCRATCH_REG_CR30  0x30  /* CRs */
-#define IND_SIS_SCRATCH_REG_CR31  0x31
-#define IND_SIS_SCRATCH_REG_CR32  0x32
-#define IND_SIS_SCRATCH_REG_CR33  0x33
-#define IND_SIS_LCD_PANEL         0x36
-#define IND_SIS_SCRATCH_REG_CR37  0x37
-#define IND_SIS_AGP_IO_PAD        0x48
-
-#define IND_BRI_DRAM_STATUS       0x63 /* PCI config memory size offset */
-
-#define MMIO_QUEUE_PHYBASE        0x85C0
-#define MMIO_QUEUE_WRITEPORT      0x85C4
-#define MMIO_QUEUE_READPORT       0x85C8
-
-#define IND_SIS_CRT2_WRITE_ENABLE_300 0x24
-#define IND_SIS_CRT2_WRITE_ENABLE_315 0x2F
-
-#define SIS_PASSWORD              0x86  /* SR05 */
-#define SIS_INTERLACED_MODE       0x20  /* SR06 */
-#define SIS_8BPP_COLOR_MODE       0x0 
-#define SIS_15BPP_COLOR_MODE      0x1 
-#define SIS_16BPP_COLOR_MODE      0x2 
-#define SIS_32BPP_COLOR_MODE      0x4 
-#define SIS_DRAM_SIZE_MASK        0x3F  /* 300/630/730 SR14 */
-#define SIS_DRAM_SIZE_1MB         0x00
-#define SIS_DRAM_SIZE_2MB         0x01
-#define SIS_DRAM_SIZE_4MB         0x03
-#define SIS_DRAM_SIZE_8MB         0x07
-#define SIS_DRAM_SIZE_16MB        0x0F
-#define SIS_DRAM_SIZE_32MB        0x1F
-#define SIS_DRAM_SIZE_64MB        0x3F
-#define SIS_DATA_BUS_MASK         0xC0
-#define SIS_DATA_BUS_32           0x00
-#define SIS_DATA_BUS_64           0x01
-#define SIS_DATA_BUS_128          0x02
-
-#define SIS315_DATA_BUS_MASK      0x02
-#define SIS315_DATA_BUS_64        0x00
-#define SIS315_DATA_BUS_128       0x01
-#define SIS315_DUAL_CHANNEL_MASK  0x0C
-#define SIS315_SINGLE_CHANNEL_1_RANK  	0x0
-#define SIS315_SINGLE_CHANNEL_2_RANK  	0x1
-#define SIS315_ASYM_DDR		  	0x02
-#define SIS315_DUAL_CHANNEL_1_RANK    	0x3
-
-#define SIS_SCRATCH_REG_1A_MASK   0x10
-
-#define SIS_ENABLE_2D             0x40  /* SR1E */
-
-#define SIS_MEM_MAP_IO_ENABLE     0x01  /* SR20 */
-#define SIS_PCI_ADDR_ENABLE       0x80
-
-#define SIS_AGP_CMDQUEUE_ENABLE   0x80  /* 315/650/740 SR26 */
-#define SIS_VRAM_CMDQUEUE_ENABLE  0x40
-#define SIS_MMIO_CMD_ENABLE       0x20
-#define SIS_CMD_QUEUE_SIZE_512k   0x00
-#define SIS_CMD_QUEUE_SIZE_1M     0x04
-#define SIS_CMD_QUEUE_SIZE_2M     0x08
-#define SIS_CMD_QUEUE_SIZE_4M     0x0C
-#define SIS_CMD_QUEUE_RESET       0x01
-#define SIS_CMD_AUTO_CORR	  0x02
-
-#define SIS_SIMULTANEOUS_VIEW_ENABLE  0x01  /* CR30 */
-#define SIS_MODE_SELECT_CRT2      0x02
-#define SIS_VB_OUTPUT_COMPOSITE   0x04
-#define SIS_VB_OUTPUT_SVIDEO      0x08
-#define SIS_VB_OUTPUT_SCART       0x10
-#define SIS_VB_OUTPUT_LCD         0x20
-#define SIS_VB_OUTPUT_CRT2        0x40
-#define SIS_VB_OUTPUT_HIVISION    0x80
-
-#define SIS_VB_OUTPUT_DISABLE     0x20  /* CR31 */
-#define SIS_DRIVER_MODE           0x40
-
-#define SIS_VB_COMPOSITE          0x01  /* CR32 */
-#define SIS_VB_SVIDEO             0x02
-#define SIS_VB_SCART              0x04
-#define SIS_VB_LCD                0x08
-#define SIS_VB_CRT2               0x10
-#define SIS_CRT1                  0x20
-#define SIS_VB_HIVISION           0x40
-#define SIS_VB_DVI                0x80
-#define SIS_VB_TV                 (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
-                                   SIS_VB_SCART | SIS_VB_HIVISION)
-
-#define SIS_EXTERNAL_CHIP_MASK    	   0x0E  /* CR37 (< SiS 660) */
-#define SIS_EXTERNAL_CHIP_SIS301           0x01  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS             0x02  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_TRUMPION         0x03  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL    0x04  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_CHRONTEL         0x05  /* in CR37 << 1 ! */
-#define SIS310_EXTERNAL_CHIP_LVDS          0x02  /* in CR37 << 1 ! */
-#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03  /* in CR37 << 1 ! */
-
-#define SIS_AGP_2X                0x20  /* CR48 */
-
-#define BRI_DRAM_SIZE_MASK        0x70  /* PCI bridge config data */
-#define BRI_DRAM_SIZE_2MB         0x00
-#define BRI_DRAM_SIZE_4MB         0x01
-#define BRI_DRAM_SIZE_8MB         0x02
-#define BRI_DRAM_SIZE_16MB        0x03
-#define BRI_DRAM_SIZE_32MB        0x04
-#define BRI_DRAM_SIZE_64MB        0x05
-
-#define HW_DEVICE_EXTENSION	  SIS_HW_INFO
-#define PHW_DEVICE_EXTENSION      PSIS_HW_INFO
-
-#define SR_BUFFER_SIZE            5
-#define CR_BUFFER_SIZE            5
-
-/* entries for disp_state - deprecated as of 1.6.02 */
-#define DISPTYPE_CRT1       0x00000008L
-#define DISPTYPE_CRT2       0x00000004L
-#define DISPTYPE_LCD        0x00000002L
-#define DISPTYPE_TV         0x00000001L
-#define DISPTYPE_DISP1      DISPTYPE_CRT1
-#define DISPTYPE_DISP2      (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV)
-#define DISPMODE_SINGLE	    0x00000020L
-#define DISPMODE_MIRROR	    0x00000010L
-#define DISPMODE_DUALVIEW   0x00000040L
-
-/* Deprecated as of 1.6.02 - use vbflags instead */
-#define HASVB_NONE      	0x00
-#define HASVB_301       	0x01
-#define HASVB_LVDS      	0x02
-#define HASVB_TRUMPION  	0x04
-#define HASVB_LVDS_CHRONTEL	0x10
-#define HASVB_302       	0x20
-#define HASVB_303       	0x40
-#define HASVB_CHRONTEL  	0x80
-
-/* Useful macros */
-#define inSISREG(base)          inb(base)
-#define outSISREG(base,val)     outb(val,base)
-#define orSISREG(base,val)      do { \
-                                  unsigned char __Temp = inb(base); \
-                                  outSISREG(base, __Temp | (val)); \
-                                } while (0)
-#define andSISREG(base,val)     do { \
-                                  unsigned char __Temp = inb(base); \
-                                  outSISREG(base, __Temp & (val)); \
-                                } while (0)
-#define inSISIDXREG(base,idx,var)   do { \
-                                      outb(idx,base); var=inb((base)+1); \
-                                    } while (0)
-#define outSISIDXREG(base,idx,val)  do { \
-                                      outb(idx,base); outb((val),(base)+1); \
-                                    } while (0)
-#define orSISIDXREG(base,idx,val)   do { \
-                                      unsigned char __Temp; \
-                                      outb(idx,base);   \
-                                      __Temp = inb((base)+1)|(val); \
-                                      outSISIDXREG(base,idx,__Temp); \
-                                    } while (0)
-#define andSISIDXREG(base,idx,and)  do { \
-                                      unsigned char __Temp; \
-                                      outb(idx,base);   \
-                                      __Temp = inb((base)+1)&(and); \
-                                      outSISIDXREG(base,idx,__Temp); \
-                                    } while (0)
-#define setSISIDXREG(base,idx,and,or)   do { \
-                                          unsigned char __Temp; \
-                                          outb(idx,base);   \
-                                          __Temp = (inb((base)+1)&(and))|(or); \
-                                          outSISIDXREG(base,idx,__Temp); \
-                                        } while (0)
-
-/* ------------------- Global Variables ----------------------------- */
-
-/* Fbcon variables */
-static struct fb_info *sis_fb_info;
+#define MODE_INDEX_NONE           0  /* index for mode=none */
 
-static struct fb_var_screeninfo default_var = {
+/* Fbcon stuff */
+static struct fb_var_screeninfo my_default_var = {
 	.xres            = 0,
 	.yres            = 0,
 	.xres_virtual    = 0,
@@ -346,125 +58,110 @@
 	.vsync_len       = 0,
 	.sync            = 0,
 	.vmode           = FB_VMODE_NONINTERLACED,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	.reserved        = {0, 0, 0, 0, 0, 0}
-#endif
 };
 
+/* Boot-time parameters */
+static int sisfb_off = 0;
+static int sisfb_parm_mem = 0;
+static int sisfb_accel = -1;
+static int sisfb_ypan = -1;
+static int sisfb_max = -1;
+static int sisfb_userom = 1;
+static int sisfb_useoem = -1;
+#ifdef MODULE
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static struct fb_fix_screeninfo sisfb_fix = {
-	.id		= "SiS",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.xpanstep	= 0,
-	.ypanstep	= 1,
-};
-static char myid[40];
-static u32 pseudo_palette[17];
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static struct display sis_disp;
-
-static struct display_switch sisfb_sw;	
-
-static struct {
-	u16 blue, green, red, pad;
-} sis_palette[256];
-
-static union {
-#ifdef FBCON_HAS_CFB16
-	u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-	u32 cfb32[16];
+static int sisfb_mode_idx = -1;
+#else
+static int sisfb_mode_idx = MODE_INDEX_NONE;  /* Don't use a mode by default if we are a module */
 #endif
-} sis_fbcon_cmap;
-
-static int sisfb_inverse = 0;
-static int currcon = 0;
+#else
+static int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
 #endif
-
-/* global flags */
-static int sisfb_off = 0;
+static int sisfb_parm_rate = -1;
 static int sisfb_crt1off = 0;
 static int sisfb_forcecrt1 = -1;
-static int sisvga_enabled = 0;
-static int sisfb_userom = 1;
-static int sisfb_useoem = -1;
-static int sisfb_parm_rate = -1;
-static int sisfb_registered = 0;
-static int sisfb_mem = 0;
-static int sisfb_pdc = 0;
-static int sisfb_ypan = -1;
-static int sisfb_max = -1;
-static int sisfb_nocrt2rate = 0;
+static int sisfb_crt2type  = -1;	/* CRT2 type (for overriding autodetection) */
+static int sisfb_crt2flags = 0;
+static int sisfb_pdc = 0xff;
+static int sisfb_pdca = 0xff;
+static int sisfb_scalelcd = -1;
+static int sisfb_specialtiming = CUT_NONE;
+static int sisfb_lvdshl = -1;
 static int sisfb_dstn = 0;
 static int sisfb_fstn = 0;
-
-VGA_ENGINE sisvga_engine = UNKNOWN_VGA;
-int 	   sisfb_accel = -1;
-
-/* These are to adapted according to VGA_ENGINE type */
-static int sisfb_hwcursor_size = 0;
-static int sisfb_CRT2_write_enable = 0;
-
-int sisfb_crt2type  = -1;	/* CRT2 type (for overriding autodetection) */
-int sisfb_tvplug    = -1;	/* Tv plug type (for overriding autodetection) */
-
-int sisfb_queuemode = -1; 	/* Use MMIO queue mode by default (315 series only) */
-
-unsigned char sisfb_detectedpdc = 0;
-
-unsigned char sisfb_detectedlcda = 0xff;
-
-/* data for sis hardware ("par") */
-struct video_info ivideo;
-
-/* For ioctl SISFB_GET_INFO */
-sisfb_info sisfbinfo;
-
-/* Hardware info; contains data on hardware */
-SIS_HW_INFO sishw_ext;
-
-/* SiS private structure */
-SiS_Private  SiS_Pr;
-
-/* Card parameters */
-static unsigned long sisfb_mmio_size = 0;
-static u8            sisfb_caps = 0;
-
-typedef enum _SIS_CMDTYPE {
-	MMIO_CMD = 0,
-	AGP_CMD_QUEUE,
-	VM_CMD_QUEUE,
-} SIS_CMDTYPE;
+static int sisfb_tvplug = -1;		/* Tv plug type (for overriding autodetection) */
+static int sisfb_tvstd  = -1;
+static int sisfb_tvxposoffset = 0;
+static int sisfb_tvyposoffset = 0;
+static int sisfb_filter = -1;
+static int sisfb_nocrt2rate = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static int  sisfb_inverse = 0;
+static char sisfb_fontname[40];
+#endif
+#if !defined(__i386__) && !defined(__x86_64__)
+static int sisfb_resetcard = 0;
+static int sisfb_videoram = 0;
+#endif
 
 /* List of supported chips */
-static struct board {
-	u16 vendor, device;
-	const char *name;
-} sisdev_list[] = {
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     "SIS 300"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630/730 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H,    "SIS 315H"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315,     "SIS 315"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO,  "SIS 315PRO"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, "SIS 550 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, "SIS 65x/M65x/740 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330,     "SIS 330"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, "SIS 661FX/M661FX/741/760 VGA"},
-	{0, 0, NULL}
+static struct sisfb_chip_info {
+        int 		chip;
+	int 		vgaengine;
+	int		mni;
+	int 		hwcursor_size;
+	int		CRT2_write_enable;
+	const char 	*chip_name;
+} sisfb_chip_info[] __devinitdata = {
+	{ SIS_300,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
+	{ SIS_540,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
+	{ SIS_630,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" },
+	{ SIS_315H,   SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315H" },
+	{ SIS_315,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315" },
+	{ SIS_315PRO, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315PRO" },
+	{ SIS_550,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 55x" },
+	{ SIS_650,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 650" },
+	{ SIS_330,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
+	{ SIS_660,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
 };
 
+static struct pci_device_id __devinitdata sisfb_pci_table[] = {
+#ifdef CONFIG_FB_SIS_300
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+#endif
+#ifdef CONFIG_FB_SIS_315
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H,    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+#endif
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
+
+static struct sis_video_info *card_list = NULL;
+
+/* TODO: This is not handled card-wise because the DRM
+   does not refer to a unique fb when calling sis_alloc
+   or sis_free. Therefore, this is handled globally for
+   now (hoping that nobody is crazy enough to run two
+   SiS cards at the same time).
+ */
+SIS_HEAP       	sisfb_heap;
+
 #define MD_SIS300 1
 #define MD_SIS315 2
 
 /* Mode table */
-/* NOT const - will be patched for 1280x768 mode number chaos reasons */
-struct _sisbios_mode {
+static const struct _sisbios_mode {
 	char name[15];
-	u8 mode_no;
+	u8  mode_no[2];
 	u16 vesa_mode_no_1;  /* "SiS defined" VESA mode number */
 	u16 vesa_mode_no_2;  /* Real VESA mode numbers */
 	u16 xres;
@@ -475,190 +172,231 @@
 	u16 rows;
 	u8  chipset;
 } sisbios_mode[] = {
-#define MODE_INDEX_NONE           0  /* index for mode=none */
-	{"none",         0xff, 0x0000, 0x0000,    0,    0,  0, 0,   0,  0, MD_SIS300|MD_SIS315},
-	{"320x200x8",    0x59, 0x0138, 0x0000,  320,  200,  8, 1,  40, 12, MD_SIS300|MD_SIS315},
-	{"320x200x16",   0x41, 0x010e, 0x0000,  320,  200, 16, 1,  40, 12, MD_SIS300|MD_SIS315},
-	{"320x200x24",   0x4f, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},  /* TW: That's for people who mix up color- and fb depth */
-	{"320x200x32",   0x4f, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},
-	{"320x240x8",    0x50, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x16",   0x56, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x24",   0x53, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x32",   0x53, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x8",    0x5a, 0x0132, 0x0000,  320,  480,  8, 1,  40, 30,           MD_SIS315},  /* TW: FSTN */
-	{"320x240x16",   0x5b, 0x0135, 0x0000,  320,  480, 16, 1,  40, 30,           MD_SIS315},  /* TW: FSTN */
-	{"400x300x8",    0x51, 0x0133, 0x0000,  400,  300,  8, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"400x300x16",   0x57, 0x0136, 0x0000,  400,  300, 16, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"400x300x24",   0x54, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"400x300x32",   0x54, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"512x384x8",    0x52, 0x0000, 0x0000,  512,  384,  8, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"512x384x16",   0x58, 0x0000, 0x0000,  512,  384, 16, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"512x384x24",   0x5c, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"512x384x32",   0x5c, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"640x400x8",    0x2f, 0x0000, 0x0000,  640,  400,  8, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x400x16",   0x5d, 0x0000, 0x0000,  640,  400, 16, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x400x24",   0x5e, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x400x32",   0x5e, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x480x8",    0x2e, 0x0101, 0x0101,  640,  480,  8, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"640x480x16",   0x44, 0x0111, 0x0111,  640,  480, 16, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"640x480x24",   0x62, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"640x480x32",   0x62, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"720x480x8",    0x31, 0x0000, 0x0000,  720,  480,  8, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x480x16",   0x33, 0x0000, 0x0000,  720,  480, 16, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x480x24",   0x35, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x480x32",   0x35, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x576x8",    0x32, 0x0000, 0x0000,  720,  576,  8, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"720x576x16",   0x34, 0x0000, 0x0000,  720,  576, 16, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"720x576x24",   0x36, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"720x576x32",   0x36, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"768x576x8",    0x5f, 0x0000, 0x0000,  768,  576,  8, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"768x576x16",   0x60, 0x0000, 0x0000,  768,  576, 16, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"768x576x24",   0x61, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"768x576x32",   0x61, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"800x480x8",    0x70, 0x0000, 0x0000,  800,  480,  8, 1, 100, 30, MD_SIS300|MD_SIS315},
-	{"800x480x16",   0x7a, 0x0000, 0x0000,  800,  480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
-	{"800x480x24",   0x76, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
-	{"800x480x32",   0x76, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
+/*0*/	{"none",         {0xff,0xff}, 0x0000, 0x0000,    0,    0,  0, 0,   0,  0, MD_SIS300|MD_SIS315},
+	{"320x200x8",    {0x59,0x59}, 0x0138, 0x0000,  320,  200,  8, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x200x16",   {0x41,0x41}, 0x010e, 0x0000,  320,  200, 16, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x200x24",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},  /* That's for people who mix up color- and fb depth */
+	{"320x200x32",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x240x8",    {0x50,0x50}, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x16",   {0x56,0x56}, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x24",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x32",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x8",    {0x5a,0x5a}, 0x0132, 0x0000,  320,  480,  8, 1,  40, 30,           MD_SIS315},  /* FSTN */
+/*10*/	{"320x240x16",   {0x5b,0x5b}, 0x0135, 0x0000,  320,  480, 16, 1,  40, 30,           MD_SIS315},  /* FSTN */
+	{"400x300x8",    {0x51,0x51}, 0x0133, 0x0000,  400,  300,  8, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x16",   {0x57,0x57}, 0x0136, 0x0000,  400,  300, 16, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x24",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x32",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"512x384x8",    {0x52,0x52}, 0x0000, 0x0000,  512,  384,  8, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x16",   {0x58,0x58}, 0x0000, 0x0000,  512,  384, 16, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x24",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x32",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"640x400x8",    {0x2f,0x2f}, 0x0000, 0x0000,  640,  400,  8, 1,  80, 25, MD_SIS300|MD_SIS315},
+/*20*/	{"640x400x16",   {0x5d,0x5d}, 0x0000, 0x0000,  640,  400, 16, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x400x24",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x400x32",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x480x8",    {0x2e,0x2e}, 0x0101, 0x0101,  640,  480,  8, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x16",   {0x44,0x44}, 0x0111, 0x0111,  640,  480, 16, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x24",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x32",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"720x480x8",    {0x31,0x31}, 0x0000, 0x0000,  720,  480,  8, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x480x16",   {0x33,0x33}, 0x0000, 0x0000,  720,  480, 16, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x480x24",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
+/*30*/	{"720x480x32",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x576x8",    {0x32,0x32}, 0x0000, 0x0000,  720,  576,  8, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x16",   {0x34,0x34}, 0x0000, 0x0000,  720,  576, 16, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x24",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x32",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"768x576x8",    {0x5f,0x5f}, 0x0000, 0x0000,  768,  576,  8, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x16",   {0x60,0x60}, 0x0000, 0x0000,  768,  576, 16, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x24",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x32",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"800x480x8",    {0x70,0x70}, 0x0000, 0x0000,  800,  480,  8, 1, 100, 30, MD_SIS300|MD_SIS315},
+/*40*/	{"800x480x16",   {0x7a,0x7a}, 0x0000, 0x0000,  800,  480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
+	{"800x480x24",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
+	{"800x480x32",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
 #define DEFAULT_MODE              43 /* index for 800x600x8 */
 #define DEFAULT_LCDMODE           43 /* index for 800x600x8 */
 #define DEFAULT_TVMODE            43 /* index for 800x600x8 */
-	{"800x600x8",    0x30, 0x0103, 0x0103,  800,  600,  8, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"800x600x16",   0x47, 0x0114, 0x0114,  800,  600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"800x600x24",   0x63, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"800x600x32",   0x63, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"848x480x8",    0x39, 0x0000, 0x0000,  848,  480,  8, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"848x480x16",   0x3b, 0x0000, 0x0000,  848,  480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"848x480x24",   0x3e, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"848x480x32",   0x3e, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"856x480x8",    0x3f, 0x0000, 0x0000,  856,  480,  8, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"856x480x16",   0x42, 0x0000, 0x0000,  856,  480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"856x480x24",   0x45, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"856x480x32",   0x45, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"1024x576x8",   0x71, 0x0000, 0x0000, 1024,  576,  8, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x576x16",  0x74, 0x0000, 0x0000, 1024,  576, 16, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x576x24",  0x77, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x576x32",  0x77, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x600x8",   0x20, 0x0000, 0x0000, 1024,  600,  8, 1, 128, 37, MD_SIS300          },
-	{"1024x600x16",  0x21, 0x0000, 0x0000, 1024,  600, 16, 1, 128, 37, MD_SIS300          },
-	{"1024x600x24",  0x22, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
-	{"1024x600x32",  0x22, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
-	{"1024x768x8",   0x38, 0x0105, 0x0105, 1024,  768,  8, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1024x768x16",  0x4a, 0x0117, 0x0117, 1024,  768, 16, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1024x768x24",  0x64, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1024x768x32",  0x64, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1152x768x8",   0x23, 0x0000, 0x0000, 1152,  768,  8, 1, 144, 48, MD_SIS300          },
-	{"1152x768x16",  0x24, 0x0000, 0x0000, 1152,  768, 16, 1, 144, 48, MD_SIS300          },
-	{"1152x768x24",  0x25, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
-	{"1152x768x32",  0x25, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
-	{"1152x864x8",   0x29, 0x0000, 0x0000, 1152,  864,  8, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1152x864x16",  0x2a, 0x0000, 0x0000, 1152,  864, 16, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1152x864x24",  0x2b, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1152x864x32",  0x2b, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1280x720x8",   0x79, 0x0000, 0x0000, 1280,  720,  8, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x720x16",  0x75, 0x0000, 0x0000, 1280,  720, 16, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x720x24",  0x78, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x720x32",  0x78, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
-#define MODEINDEX_1280x768 79
-	{"1280x768x8",   0x23, 0x0000, 0x0000, 1280,  768,  8, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x768x16",  0x24, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x768x24",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x768x32",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x960x8",   0x7c, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x960x16",  0x7d, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x960x24",  0x7e, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x960x32",  0x7e, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x1024x8",  0x3a, 0x0107, 0x0107, 1280, 1024,  8, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1280x1024x16", 0x4d, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1280x1024x24", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1280x1024x32", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1360x768x8",   0x48, 0x0000, 0x0000, 1360,  768,  8, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x768x16",  0x4b, 0x0000, 0x0000, 1360,  768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x768x24",  0x4e, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x768x32",  0x4e, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x1024x8",  0x67, 0x0000, 0x0000, 1360, 1024,  8, 1, 170, 64, MD_SIS300          },
-	{"1360x1024x16", 0x6f, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300          },
-	{"1360x1024x24", 0x72, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
-	{"1360x1024x32", 0x72, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
-	{"1400x1050x8",  0x26, 0x0000, 0x0000, 1400, 1050,  8, 1, 175, 65,           MD_SIS315},
-	{"1400x1050x16", 0x27, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,           MD_SIS315},
-	{"1400x1050x24", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
-	{"1400x1050x32", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
-	{"1600x1200x8",  0x3c, 0x0130, 0x011c, 1600, 1200,  8, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1600x1200x16", 0x3d, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1600x1200x24", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1600x1200x32", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x8",  0x68, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x16", 0x69, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x24", 0x6b, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x32", 0x6b, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"2048x1536x8",  0x6c, 0x0000, 0x0000, 2048, 1536,  8, 1, 256, 96,           MD_SIS315},
-	{"2048x1536x16", 0x6d, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,           MD_SIS315},
-	{"2048x1536x24", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
-	{"2048x1536x32", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
-	{"\0", 0x00, 0, 0, 0, 0, 0, 0, 0}
+	{"800x600x8",    {0x30,0x30}, 0x0103, 0x0103,  800,  600,  8, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x16",   {0x47,0x47}, 0x0114, 0x0114,  800,  600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x24",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x32",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"848x480x8",    {0x39,0x39}, 0x0000, 0x0000,  848,  480,  8, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"848x480x16",   {0x3b,0x3b}, 0x0000, 0x0000,  848,  480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"848x480x24",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
+/*50*/	{"848x480x32",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"856x480x8",    {0x3f,0x3f}, 0x0000, 0x0000,  856,  480,  8, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x16",   {0x42,0x42}, 0x0000, 0x0000,  856,  480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x24",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x32",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"960x540x8",    {0x1d,0x1d}, 0x0000, 0x0000,  960,  540,  8, 1, 120, 33,           MD_SIS315},
+	{"960x540x16",   {0x1e,0x1e}, 0x0000, 0x0000,  960,  540, 16, 1, 120, 33,           MD_SIS315},
+	{"960x540x24",   {0x1f,0x1f}, 0x0000, 0x0000,  960,  540, 32, 1, 120, 33,           MD_SIS315},
+	{"960x540x32",   {0x1f,0x1f}, 0x0000, 0x0000,  960,  540, 32, 1, 120, 33,           MD_SIS315},
+	{"1024x576x8",   {0x71,0x71}, 0x0000, 0x0000, 1024,  576,  8, 1, 128, 36, MD_SIS300|MD_SIS315},
+/*60*/	{"1024x576x16",  {0x74,0x74}, 0x0000, 0x0000, 1024,  576, 16, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x24",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x32",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x600x8",   {0x20,0x20}, 0x0000, 0x0000, 1024,  600,  8, 1, 128, 37, MD_SIS300          },
+	{"1024x600x16",  {0x21,0x21}, 0x0000, 0x0000, 1024,  600, 16, 1, 128, 37, MD_SIS300          },
+	{"1024x600x24",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
+	{"1024x600x32",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
+	{"1024x768x8",   {0x38,0x38}, 0x0105, 0x0105, 1024,  768,  8, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x16",  {0x4a,0x4a}, 0x0117, 0x0117, 1024,  768, 16, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x24",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+/*70*/	{"1024x768x32",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1152x768x8",   {0x23,0x23}, 0x0000, 0x0000, 1152,  768,  8, 1, 144, 48, MD_SIS300          },
+	{"1152x768x16",  {0x24,0x24}, 0x0000, 0x0000, 1152,  768, 16, 1, 144, 48, MD_SIS300          },
+	{"1152x768x24",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
+	{"1152x768x32",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
+	{"1152x864x8",   {0x29,0x29}, 0x0000, 0x0000, 1152,  864,  8, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x16",  {0x2a,0x2a}, 0x0000, 0x0000, 1152,  864, 16, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x24",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x32",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1280x720x8",   {0x79,0x79}, 0x0000, 0x0000, 1280,  720,  8, 1, 160, 45, MD_SIS300|MD_SIS315},
+/*80*/	{"1280x720x16",  {0x75,0x75}, 0x0000, 0x0000, 1280,  720, 16, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x24",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x32",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x768x8",   {0x55,0x23}, 0x0000, 0x0000, 1280,  768,  8, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x768x16",  {0x5a,0x24}, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x768x24",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x768x32",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x800x8",   {0x14,0x14}, 0x0000, 0x0000, 1280,  800,  8, 1, 160, 50,           MD_SIS315},
+	{"1280x800x16",  {0x15,0x15}, 0x0000, 0x0000, 1280,  800, 16, 1, 160, 50,           MD_SIS315},
+	{"1280x800x24",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+/*90*/	{"1280x800x32",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+	{"1280x960x8",   {0x7c,0x7c}, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x960x16",  {0x7d,0x7d}, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x960x24",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x960x32",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x1024x8",  {0x3a,0x3a}, 0x0107, 0x0107, 1280, 1024,  8, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x24", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x32", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1360x768x8",   {0x48,0x48}, 0x0000, 0x0000, 1360,  768,  8, 1, 170, 48, MD_SIS300|MD_SIS315},
+/*100*/	{"1360x768x16",  {0x4b,0x4b}, 0x0000, 0x0000, 1360,  768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x24",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x32",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x1024x8",  {0x67,0x67}, 0x0000, 0x0000, 1360, 1024,  8, 1, 170, 64, MD_SIS300          },
+	{"1360x1024x16", {0x6f,0x6f}, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300          },
+	{"1360x1024x24", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
+	{"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
+	{"1400x1050x8",  {0x26,0x26}, 0x0000, 0x0000, 1400, 1050,  8, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x16", {0x27,0x27}, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x24", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
+/*110*/	{"1400x1050x32", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
+	{"1600x1200x8",  {0x3c,0x3c}, 0x0130, 0x011c, 1600, 1200,  8, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1600x1200x24", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1600x1200x32", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1680x1050x8",  {0x17,0x17}, 0x0000, 0x0000, 1680, 1050,  8, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x24", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x32", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
+	{"1920x1080x8",  {0x2c,0x2c}, 0x0000, 0x0000, 1920, 1080,  8, 1, 240, 67,           MD_SIS315},
+/*120*/	{"1920x1080x16", {0x2d,0x2d}, 0x0000, 0x0000, 1920, 1080, 16, 1, 240, 67,           MD_SIS315},
+	{"1920x1080x24", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67,           MD_SIS315},
+	{"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67,           MD_SIS315},
+	{"1920x1440x8",  {0x68,0x68}, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x16", {0x69,0x69}, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x24", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"2048x1536x8",  {0x6c,0x6c}, 0x0000, 0x0000, 2048, 1536,  8, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x16", {0x6d,0x6d}, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x24", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
+/*130*/	{"2048x1536x32", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
+	{"\0", {0x00,0x00}, 0, 0, 0, 0, 0, 0, 0}
+};
+
+#define SIS_LCD_NUMBER 17
+static const struct _sis_lcd_data {
+	u32 lcdtype;
+	u16 xres;
+	u16 yres;
+	u8  default_mode_idx;
+} sis_lcd_data[] = {
+	{ LCD_640x480,    640,  480,  23 },
+	{ LCD_800x600,    800,  600,  43 },
+	{ LCD_1024x600,  1024,  600,  63 },
+	{ LCD_1024x768,  1024,  768,  67 },
+	{ LCD_1152x768,  1152,  768,  71 },
+	{ LCD_1152x864,  1152,  864,  75 },
+	{ LCD_1280x720,  1280,  720,  79 },
+	{ LCD_1280x768,  1280,  768,  83 },
+	{ LCD_1280x800,  1280,  800,  87 },
+	{ LCD_1280x960,  1280,  960,  91 },
+	{ LCD_1280x1024, 1280, 1024,  95 },
+	{ LCD_1400x1050, 1400, 1050, 107 },
+	{ LCD_1680x1050, 1680, 1050, 115 },
+	{ LCD_1600x1200, 1600, 1200, 111 },
+	{ LCD_640x480_2,  640,  480,  23 },
+	{ LCD_640x480_3,  640,  480,  23 },
+	{ LCD_320x480,    320,  480,   9 },
 };
 
-/* mode-related variables */
-#ifdef MODULE
-int sisfb_mode_idx = MODE_INDEX_NONE;  /* Don't use a mode by default if we are a module */
-#else
-int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
-#endif
-u8  sisfb_mode_no  = 0;
-u8  sisfb_rate_idx = 0;
-
 /* CR36 evaluation */
 const USHORT sis300paneltype[] =
     { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
       LCD_1280x960,  LCD_640x480,   LCD_1024x600,  LCD_1152x768,
-      LCD_1024x768,  LCD_1024x768,  LCD_1024x768,  LCD_1024x768,
-      LCD_1024x768,  LCD_1024x768,  LCD_320x480,   LCD_1024x768 };
+      LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,
+      LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN };
 
 const USHORT sis310paneltype[] =
     { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
       LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
       LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
-      LCD_640x480_2, LCD_640x480_3, LCD_320x480,   LCD_1024x768 };
+      LCD_640x480_2, LCD_640x480_3, LCD_UNKNOWN,   LCD_UNKNOWN };
+
+const USHORT sis661paneltype[] =
+    { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
+      LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
+      LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
+      LCD_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_UNKNOWN };
 
 #define FL_550_DSTN 0x01
 #define FL_550_FSTN 0x02
+#define FL_300      0x04
+#define FL_315      0x08
 
-static const struct _sis_crt2type {
-	char name[10];
-	int type_no;
-	int tvplug_no;
-	unsigned short flags;
-} sis_crt2type[] = {
-	{"NONE", 	0, 		-1,        0},
-	{"LCD",  	CRT2_LCD, 	-1,        0},
-	{"TV",   	CRT2_TV, 	-1,        0},
-	{"VGA",  	CRT2_VGA, 	-1,        0},
-	{"SVIDEO", 	CRT2_TV, 	TV_SVIDEO, 0},
-	{"COMPOSITE", 	CRT2_TV, 	TV_AVIDEO, 0},
-	{"SCART", 	CRT2_TV, 	TV_SCART,  0},
-	{"DSTN",        CRT2_LCD,       -1,        FL_550_DSTN},
-	{"FSTN",        CRT2_LCD,       -1,        FL_550_FSTN},
-	{"\0",  	-1, 		-1,        0}
-};
-
-/* Queue mode selection for 310 series */
-static const struct _sis_queuemode {
-	char name[6];
-	int type_no;
-} sis_queuemode[] = {
-	{"AGP",  	AGP_CMD_QUEUE},
-	{"VRAM", 	VM_CMD_QUEUE},
-	{"MMIO", 	MMIO_CMD},
-	{"\0",   	-1}
+static struct _sis_crt2type {
+	char name[32];
+	u32 type_no;
+	u32 tvplug_no;
+	u16 flags;
+} sis_crt2type[] __initdata = {
+	{"NONE", 	     0, 	-1,                     FL_300|FL_315},
+	{"LCD",  	     CRT2_LCD, 	-1,                     FL_300|FL_315},
+	{"TV",   	     CRT2_TV, 	-1,                     FL_300|FL_315},
+	{"VGA",  	     CRT2_VGA, 	-1,                     FL_300|FL_315},
+	{"SVIDEO", 	     CRT2_TV, 	TV_SVIDEO,              FL_300|FL_315},
+	{"COMPOSITE", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
+	{"CVBS", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
+	{"SVIDEO+COMPOSITE", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"COMPOSITE+SVIDEO", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"SVIDEO+CVBS",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"CVBS+SVIDEO",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"SCART", 	     CRT2_TV, 	TV_SCART,               FL_300|FL_315},
+	{"HIVISION",	     CRT2_TV,   TV_HIVISION,            FL_315},
+	{"YPBPR480I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525I,  FL_315},
+	{"YPBPR480P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525P,  FL_315},
+	{"YPBPR720P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR750P,  FL_315},
+	{"YPBPR1080I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR1080I, FL_315},
+	{"DSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_DSTN},
+	{"FSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_FSTN},
+	{"\0",  	     -1, 	-1,                     0}
 };
 
 /* TV standard */
-static const struct _sis_tvtype {
+static struct _sis_tvtype {
 	char name[6];
-	int type_no;
-} sis_tvtype[] = {
+	u32 type_no;
+} sis_tvtype[] __initdata = {
 	{"PAL",  	TV_PAL},
 	{"NTSC", 	TV_NTSC},
+	{"PALM",  	TV_PAL|TV_PALM},
+	{"PALN",  	TV_PAL|TV_PALN},
+	{"NTSCJ",  	TV_NTSC|TV_NTSCJ},
 	{"\0",   	-1}
 };
 
@@ -687,6 +425,7 @@
 	{7,  800,  600, 120,  TRUE}, {8,  800,  600, 160,  TRUE},
 	{1,  848,  480,  39,  TRUE}, {2,  848,  480,  60,  TRUE},
 	{1,  856,  480,  39,  TRUE}, {2,  856,  480,  60,  TRUE},
+	{1,  960,  540,  60,  TRUE},
 	{1, 1024,  576,  60,  TRUE}, {2, 1024,  576,  75,  TRUE}, {3, 1024,  576,  85,  TRUE},
 	{1, 1024,  600,  60,  TRUE},
 	{1, 1024,  768,  43,  TRUE}, {2, 1024,  768,  60,  TRUE}, {3, 1024,  768,  70, FALSE},
@@ -696,6 +435,7 @@
 	{1, 1152,  864,  75,  TRUE}, {2, 1152,  864,  84,  TRUE},
 	{1, 1280,  720,  60,  TRUE}, {2, 1280,  720,  75,  TRUE}, {3, 1280,  720,  85,  TRUE},
 	{1, 1280,  768,  60,  TRUE},
+	{1, 1280,  800,  60,  TRUE},
 	{1, 1280,  960,  60,  TRUE}, {2, 1280,  960,  85,  TRUE},
 	{1, 1280, 1024,  43,  TRUE}, {2, 1280, 1024,  60,  TRUE}, {3, 1280, 1024,  75,  TRUE},
 	{4, 1280, 1024,  85,  TRUE},
@@ -705,6 +445,8 @@
 	{1, 1600, 1200,  60,  TRUE}, {2, 1600, 1200,  65,  TRUE}, {3, 1600, 1200,  70,  TRUE},
 	{4, 1600, 1200,  75,  TRUE}, {5, 1600, 1200,  85,  TRUE}, {6, 1600, 1200, 100,  TRUE},
 	{7, 1600, 1200, 120,  TRUE},
+	{1, 1680, 1050,  60,  TRUE},
+	{1, 1920, 1080,  30,  TRUE},
 	{1, 1920, 1440,  60,  TRUE}, {2, 1920, 1440,  65,  TRUE}, {3, 1920, 1440,  70,  TRUE},
 	{4, 1920, 1440,  75,  TRUE}, {5, 1920, 1440,  85,  TRUE}, {6, 1920, 1440, 100,  TRUE},
 	{1, 2048, 1536,  60,  TRUE}, {2, 2048, 1536,  65,  TRUE}, {3, 2048, 1536,  70,  TRUE},
@@ -712,16 +454,6 @@
 	{0,    0,    0,   0, FALSE}
 };
 
-static struct sisfb_monitor {
-	u16 hmin;
-	u16 hmax;
-	u16 vmin;
-	u16 vmax;
-	u32 dclockmax;
-	u8  feature;
-	BOOLEAN datavalid;
-} sisfb_thismonitor;
-
 static const struct _sisfbddcsmodes {
 	u32 mask;
 	u16 h;
@@ -760,35 +492,33 @@
        { 1920, 1440, 75, 113,297000}
 };
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static u8 sisfb_lastrates[128];
-#endif
-
-static const struct _chswtable {
-    int subsysVendor;
-    int subsysCard;
+#ifdef CONFIG_FB_SIS_300
+static struct _chswtable {
+    u16  subsysVendor;
+    u16  subsysCard;
     char *vendorName;
     char *cardName;
-} mychswtable[] = {
+} mychswtable[] __devinitdata = {
         { 0x1631, 0x1002, "Mitachi", "0x1002" },
 	{ 0x1071, 0x7521, "Mitac"  , "7521P"  },
 	{ 0,      0,      ""       , ""       }
 };
+#endif
 
-static const struct _customttable {
-    unsigned short chipID;
-    char *biosversion;
-    char *biosdate;
-    unsigned long bioschksum;
-    unsigned short biosFootprintAddr[5];
-    unsigned char biosFootprintData[5];
-    unsigned short pcisubsysvendor;
-    unsigned short pcisubsyscard;
-    char *vendorName;
-    char *cardName;
-    unsigned long SpecialID;
-    char *optionName;
-} mycustomttable[] = {
+static struct _customttable {
+    u16   chipID;
+    char  *biosversion;
+    char  *biosdate;
+    u32   bioschksum;
+    u16   biosFootprintAddr[5];
+    u8    biosFootprintData[5];
+    u16   pcisubsysvendor;
+    u16   pcisubsyscard;
+    char  *vendorName;
+    char  *cardName;
+    u32   SpecialID;
+    char  *optionName;
+} mycustomttable[] __devinitdata = {
 	{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
 	  0x3240A8,
 	  { 0x220, 0x227, 0x228, 0x229, 0x0ee },
@@ -917,46 +647,6 @@
 	}
 };
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* Offscreen layout */
-typedef struct _SIS_GLYINFO {
-	unsigned char ch;
-	int fontwidth;
-	int fontheight;
-	u8 gmask[72];
-	int ngmask;
-} SIS_GLYINFO;
-
-static char sisfb_fontname[40];
-#endif
-
-typedef struct _SIS_OH {
-	struct _SIS_OH *poh_next;
-	struct _SIS_OH *poh_prev;
-	unsigned long offset;
-	unsigned long size;
-} SIS_OH;
-
-typedef struct _SIS_OHALLOC {
-	struct _SIS_OHALLOC *poha_next;
-	SIS_OH aoh[1];
-} SIS_OHALLOC;
-
-typedef struct _SIS_HEAP {
-	SIS_OH oh_free;
-	SIS_OH oh_used;
-	SIS_OH *poh_freelist;
-	SIS_OHALLOC *poha_chain;
-	unsigned long max_freesize;
-} SIS_HEAP;
-
-static unsigned long sisfb_hwcursor_vbase;
-
-static unsigned long sisfb_heap_start;
-static unsigned long sisfb_heap_end;
-static unsigned long sisfb_heap_size;
-static SIS_HEAP      sisfb_heap;
-
 static const struct _sis_TV_filter {
 	u8 filter[9][4];
 } sis_TV_filter[] = {
@@ -1106,9 +796,6 @@
 	   {0xFF,0xFF,0xFF,0xFF} }}
 };
 
-static int           filter = -1;
-static unsigned char filter_tb;
-
 /* ---------------------- Prototypes ------------------------- */
 
 /* Interface used by the world */
@@ -1119,7 +806,11 @@
 /* Interface to the low level console driver */
 int             sisfb_init(void);
 
+
 /* fbdev routines */
+static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			      struct fb_info *info);
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, 
 			      int con,
@@ -1130,7 +821,8 @@
 static int      sisfb_set_var(struct fb_var_screeninfo *var, 
 			      int con,
 			      struct fb_info *info);
-static void     sisfb_crtc_to_var(struct fb_var_screeninfo *var);			      
+static void     sisfb_crtc_to_var(struct sis_video_info *ivideo,
+			          struct fb_var_screeninfo *var);
 static int      sisfb_get_cmap(struct fb_cmap *cmap, 
 			       int kspc, 
 			       int con,
@@ -1153,108 +845,67 @@
 			      struct fb_info *fb_info);
 static void     sisfb_do_install_cmap(int con, 
                                       struct fb_info *info);
-static void     sis_get_glyph(struct fb_info *info, 
-                              SIS_GLYINFO *gly);
-static int 	sisfb_mmap(struct fb_info *info, struct file *file,
-		           struct vm_area_struct *vma);	
 static int      sisfb_ioctl(struct inode *inode, struct file *file,
 		       	    unsigned int cmd, unsigned long arg, int con,
 		       	    struct fb_info *info);		      
 #endif			
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static int      sisfb_ioctl(struct inode *inode, struct file *file,
+		       	    unsigned int cmd, unsigned long arg,
+		       	    struct fb_info *info);
 static int      sisfb_set_par(struct fb_info *info);
 static int      sisfb_blank(int blank, 
                             struct fb_info *info);			
-static int 	sisfb_mmap(struct fb_info *info, struct file *file,
-		           struct vm_area_struct *vma);			    
 extern void     fbcon_sis_fillrect(struct fb_info *info, 
                                    const struct fb_fillrect *rect);
 extern void     fbcon_sis_copyarea(struct fb_info *info, 
                                    const struct fb_copyarea *area);
 extern int      fbcon_sis_sync(struct fb_info *info);
-static int      sisfb_ioctl(struct inode *inode, 
-	 		    struct file *file,
-		       	    unsigned int cmd, 
-			    unsigned long arg, 
-		       	    struct fb_info *info);
-extern int	sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, 
-			      PSIS_HW_INFO HwDeviceExtension,
-			      unsigned char modeno, unsigned char rateindex);	
-extern int      sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
-			 unsigned char modeno, unsigned char rateindex,
-			 unsigned int *left_margin, unsigned int *right_margin, 
-			 unsigned int *upper_margin, unsigned int *lower_margin,
-			 unsigned int *hsync_len, unsigned int *vsync_len,
-			 unsigned int *sync, unsigned int *vmode);
 #endif
 			
-static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			      struct fb_info *info);
-
 /* Internal 2D accelerator functions */
-extern int      sisfb_initaccel(void);
-extern void     sisfb_syncaccel(void);
+extern int      sisfb_initaccel(struct sis_video_info *ivideo);
+extern void     sisfb_syncaccel(struct sis_video_info *ivideo);
 
 /* Internal general routines */
 static void     sisfb_search_mode(char *name, BOOLEAN quiet);
-static int      sisfb_validate_mode(int modeindex, unsigned long vbflags);
-static u8       sisfb_search_refresh_rate(unsigned int rate, int index);
+static int      sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
+static u8       sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
+			int index);
 static int      sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 			unsigned blue, unsigned transp,
 			struct fb_info *fb_info);
 static int      sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		      	struct fb_info *info);
-static void     sisfb_pre_setmode(void);
-static void     sisfb_post_setmode(void);
+static void     sisfb_pre_setmode(struct sis_video_info *ivideo);
+static void     sisfb_post_setmode(struct sis_video_info *ivideo);
+static char *   sis_find_rom(struct pci_dev *pdev);
+static BOOLEAN  sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static BOOLEAN  sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static BOOLEAN  sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static BOOLEAN  sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static void     sisfb_detect_VB_connect(struct sis_video_info *ivideo);
+static void     sisfb_get_VB_type(struct sis_video_info *ivideo);
+static void     sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
+static void     sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
 
-static char *   sis_find_rom(void);
-static BOOLEAN  sisfb_CheckVBRetrace(void);
-static BOOLEAN  sisfbcheckvretracecrt2(void);
-static BOOLEAN  sisfbcheckvretracecrt1(void);
-static BOOLEAN  sisfb_bridgeisslave(void);
-static void     sisfb_detect_VB_connect(void);
-static void     sisfb_get_VB_type(void);
-
-static void     sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno);
-static BOOLEAN  sisfb_interpret_edid(struct sisfb_monitor *monitor, unsigned char *buffer);
-
-/* SiS-specific Export functions */
-void            sis_dispinfo(struct ap_data *rec);
+/* SiS-specific exported functions */
 void            sis_malloc(struct sis_memreq *req);
-void            sis_free(unsigned long base);
-
-/* Internal hardware access routines */
-void            sisfb_set_reg4(u16 port, unsigned long data);
-u32             sisfb_get_reg3(u16 port);
-
-/* Chipset-dependent internal routines */
-#ifdef CONFIG_FB_SIS_300
-static int      sisfb_get_dram_size_300(void);
-#endif
-#ifdef CONFIG_FB_SIS_315
-static int      sisfb_get_dram_size_315(void);
-#endif
+void            sis_free(u32 base);
 
 /* Internal heap routines */
-static int      sisfb_heap_init(void);
+static int      sisfb_heap_init(struct sis_video_info *ivideo);
 static SIS_OH   *sisfb_poh_new_node(void);
-static SIS_OH   *sisfb_poh_allocate(unsigned long size);
+static SIS_OH   *sisfb_poh_allocate(u32 size);
 static void     sisfb_delete_node(SIS_OH *poh);
 static void     sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh);
-static SIS_OH   *sisfb_poh_free(unsigned long base);
+static SIS_OH   *sisfb_poh_free(u32 base);
 static void     sisfb_free_node(SIS_OH *poh);
 
-/* Internal routines to access PCI configuration space */
-BOOLEAN         sisfb_query_VGA_config_space(PSIS_HW_INFO psishw_ext,
-	          	unsigned long offset, unsigned long set, unsigned long *value);
-BOOLEAN         sisfb_query_north_bridge_space(PSIS_HW_INFO psishw_ext,
-	         	unsigned long offset, unsigned long set, unsigned long *value);
-
 /* Sensing routines */
-static void     SiS_Sense30x(void);
-static int      SISDoSense(int tempbl, int tempbh, int tempcl, int tempch);
-static void     SiS_SenseCh(void);
+static void     SiS_Sense30x(struct sis_video_info *ivideo);
+static void     SiS_SenseCh(struct sis_video_info *ivideo);
 
 /* Routines from init.c/init301.c */
 extern USHORT   SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN);
@@ -1268,10 +919,20 @@
 extern void     SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
 extern void     SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
 
+extern BOOLEAN  SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
+
 extern BOOLEAN  sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
 		       unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+extern int	sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr,
+		    	PSIS_HW_INFO HwDeviceExtension,
+			unsigned char modeno, unsigned char rateindex);
+extern int      sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
+			unsigned char modeno, unsigned char rateindex,
+			struct fb_var_screeninfo *var);
+#endif
 
-/* Chrontel TV functions */
+/* Chrontel TV, DDC and DPMS functions */
 extern USHORT 	SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
 extern void 	SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
 extern USHORT 	SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
@@ -1279,13 +940,13 @@
 extern void     SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
 extern void     SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
 extern void     SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
-extern USHORT   SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
+extern USHORT   SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
 		              USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
 extern USHORT   SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
 extern void 	SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
 extern void 	SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
 extern void 	SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
 extern void 	SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
-
-			
 #endif
+
+
diff -Nru a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
--- a/drivers/video/sis/vgatypes.h	2004-06-23 19:04:25 -07:00
+++ b/drivers/video/sis/vgatypes.h	2004-06-23 19:04:25 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * General type definitions for universal mode switching modules
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -121,21 +119,17 @@
 #endif
 #endif
 
-#ifndef LINUX_KERNEL   /* For the linux kernel, this is defined in sisfb.h */
-#ifndef SIS_CHIP_TYPE
-typedef enum _SIS_CHIP_TYPE {
+enum _SIS_CHIP_TYPE {
     SIS_VGALegacy = 0,
-#ifdef LINUX_XF86
     SIS_530,
     SIS_OLD,
-#endif
     SIS_300,
     SIS_630,
     SIS_730,
     SIS_540,
     SIS_315H,   /* SiS 310 */
     SIS_315,
-    SIS_315PRO, /* SiS 325 */
+    SIS_315PRO,
     SIS_550,
     SIS_650,
     SIS_740,
@@ -144,29 +138,13 @@
     SIS_741,
     SIS_660,
     SIS_760,
+    SIS_761,
+    SIS_340,
     MAX_SIS_CHIP
-} SIS_CHIP_TYPE;
-#endif
-#endif
-
-#ifndef SIS_VB_CHIP_TYPE
-typedef enum _SIS_VB_CHIP_TYPE {
-    VB_CHIP_Legacy = 0,
-    VB_CHIP_301,
-    VB_CHIP_301B,
-    VB_CHIP_301LV,
-    VB_CHIP_302,
-    VB_CHIP_302B,
-    VB_CHIP_302LV,
-    VB_CHIP_301C,
-    VB_CHIP_302ELV,
-    VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */
-    MAX_VB_CHIP
-} SIS_VB_CHIP_TYPE;
-#endif
+};
 
-#ifndef SIS_LCD_TYPE
-typedef enum _SIS_LCD_TYPE {
+#ifdef LINUX_KERNEL
+enum _SIS_LCD_TYPE {
     LCD_INVALID = 0,
     LCD_800x600,
     LCD_1024x768,
@@ -176,28 +154,22 @@
     LCD_1600x1200,
     LCD_1920x1440,
     LCD_2048x1536,
-    LCD_320x480,       /* FSTN, DSTN */
+    LCD_320x480,       /* FSTN */
     LCD_1400x1050,
     LCD_1152x864,
     LCD_1152x768,
     LCD_1280x768,
     LCD_1024x600,
-    LCD_640x480_2,     /* FSTN, DSTN */
-    LCD_640x480_3,     /* FSTN, DSTN */
+    LCD_640x480_2,     /* DSTN */
+    LCD_640x480_3,     /* DSTN */
     LCD_848x480,
     LCD_1280x800,
     LCD_1680x1050,
+    LCD_1280x720,
     LCD_CUSTOM,
     LCD_UNKNOWN
-} SIS_LCD_TYPE;
-#endif
-
-#ifndef PSIS_DSReg
-typedef struct _SIS_DSReg
-{
-  UCHAR  jIdx;
-  UCHAR  jVal;
-} SIS_DSReg, *PSIS_DSReg;
+};
+typedef unsigned int SIS_LCD_TYPE;
 #endif
 
 #ifndef SIS_HW_INFO
@@ -220,97 +192,84 @@
                                  /* of Linear VGA memory */
 
     ULONG  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
-    SISIOADDRESS ulIOAddress;    /* base I/O address of VGA ports (0x3B0) */
+
+    SISIOADDRESS ulIOAddress;    /* base I/O address of VGA ports (0x3B0; relocated) */
+
     UCHAR  jChipType;            /* Used to Identify SiS Graphics Chip */
-                                 /* defined in the data structure type  */
-                                 /* "SIS_CHIP_TYPE" */
+                                 /* defined in the enum "SIS_CHIP_TYPE" (above or sisfb.h) */
 
     UCHAR  jChipRevision;        /* Used to Identify SiS Graphics Chip Revision */
-    UCHAR  ujVBChipID;           /* the ID of video bridge */
-                                 /* defined in the data structure type */
-                                 /* "SIS_VB_CHIP_TYPE" */
-#ifdef LINUX_KERNEL
-    BOOLEAN Is301BDH;
-#endif
 
-    USHORT usExternalChip;       /* NO VB or other video bridge (other than  */
-                                 /* SiS video bridge) */
-
-    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
-                                 /* "SIS_LCD_TYPE" */
-                                     
     BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
-                                      
-    BOOLEAN bSkipDramSizing;     /* True: Skip video memory sizing. */
 
 #ifdef LINUX_KERNEL
-    PSIS_DSReg  pSR;             /* restore SR registers in initial function. */
-                                 /* end data :(idx, val) =  (FF, FF). */
-                                 /* Note : restore SR registers if  */
-                                 /* bSkipDramSizing = TRUE */
-
-    PSIS_DSReg  pCR;             /* restore CR registers in initial function. */
-                                 /* end data :(idx, val) =  (FF, FF) */
-                                 /* Note : restore cR registers if  */
-                                 /* bSkipDramSizing = TRUE */
-#endif
-
-    PSIS_QUERYSPACE  pQueryVGAConfigSpace; /* Get/Set VGA Configuration  */
-                                           /* space */
- 
-    PSIS_QUERYSPACE  pQueryNorthBridgeSpace;/* Get/Set North Bridge  */
-                                            /* space  */
+    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
+                                 /* "SIS_LCD_TYPE" */
+#endif
 };
 #endif
 
-/* Addtional IOCTL for communication sisfb <> X driver        */
+/* Addtional IOCTLs for communication sisfb <> X driver        */
 /* If changing this, sisfb.h must also be changed (for sisfb) */
 
 #ifdef LINUX_XF86  /* We don't want the X driver to depend on the kernel source */
 
 /* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO    0x80046ef8  /* Wow, what a terrible hack... */
+#define SISFB_GET_INFO_SIZE	0x8004f300
+#define SISFB_GET_INFO		0x8000f301  /* Must be patched with result from ..._SIZE at D[29:16] */
+/* deprecated ioctl number (for older versions of sisfb) */
+#define SISFB_GET_INFO_OLD    	0x80046ef8
+
+/* ioctls for tv parameters (position) */
+#define SISFB_SET_TVPOSOFFSET   0x4004f304
+
+/* lock sisfb from register access */
+#define SISFB_SET_LOCK		0x4004f306
 
 /* Structure argument for SISFB_GET_INFO ioctl  */
 typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
 
 struct _SISFB_INFO {
-	unsigned long sisfb_id;         /* for identifying sisfb */
+	CARD32 	sisfb_id;         	/* for identifying sisfb */
 #ifndef SISFB_ID
 #define SISFB_ID	  0x53495346    /* Identify myself with 'SISF' */
 #endif
- 	int    chip_id;			/* PCI ID of detected chip */
-	int    memory;			/* video memory in KB which sisfb manages */
-	int    heapstart;               /* heap start (= sisfb "mem" argument) in KB */
-	unsigned char fbvidmode;	/* current sisfb mode */
+ 	CARD32 	chip_id;		/* PCI ID of detected chip */
+	CARD32	memory;			/* video memory in KB which sisfb manages */
+	CARD32	heapstart;             	/* heap start (= sisfb "mem" argument) in KB */
+	CARD8 	fbvidmode;		/* current sisfb mode */
+
+	CARD8 	sisfb_version;
+	CARD8	sisfb_revision;
+	CARD8 	sisfb_patchlevel;
+
+	CARD8 	sisfb_caps;		/* sisfb's capabilities */
+
+	CARD32 	sisfb_tqlen;		/* turbo queue length (in KB) */
 
-	unsigned char sisfb_version;
-	unsigned char sisfb_revision;
-	unsigned char sisfb_patchlevel;
+	CARD32 	sisfb_pcibus;      	/* The card's PCI ID */
+	CARD32 	sisfb_pcislot;
+	CARD32 	sisfb_pcifunc;
 
-	unsigned char sisfb_caps;	/* sisfb's capabilities */
+	CARD8 	sisfb_lcdpdc;
 
-	int    sisfb_tqlen;		/* turbo queue length (in KB) */
+	CARD8	sisfb_lcda;
 
-	unsigned int sisfb_pcibus;      /* The card's PCI ID */
-	unsigned int sisfb_pcislot;
-	unsigned int sisfb_pcifunc;
+	CARD32	sisfb_vbflags;
+	CARD32	sisfb_currentvbflags;
 
-	unsigned char sisfb_lcdpdc;
-	
-	unsigned char sisfb_lcda;
+	CARD32 	sisfb_scalelcd;
+	CARD32 	sisfb_specialtiming;
 
-	unsigned long sisfb_vbflags;
-	unsigned long sisfb_currentvbflags;
+	CARD8 	sisfb_haveemi;
+	CARD8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+	CARD8 	sisfb_haveemilcd;
 
-	int sisfb_scalelcd;
-	unsigned long sisfb_specialtiming;
+	CARD8 	sisfb_lcdpdca;
 
-	unsigned char sisfb_haveemi;
-	unsigned char sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-	unsigned char sisfb_haveemilcd;
+	CARD16  sisfb_tvxpos, sisfb_tvypos;  	/* Warning: Values + 32 ! */
 
-	char reserved[213]; 		/* for future use */
+	CARD8 reserved[208]; 			/* for future use */
 };
 #endif
 
diff -Nru a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h
--- a/drivers/video/sis/vstruct.h	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/sis/vstruct.h	2004-06-23 19:04:27 -07:00
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * General structure definitions for universal mode switching modules
  *
@@ -31,13 +32,10 @@
  * * 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) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * 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,
@@ -164,7 +162,6 @@
 {
 	UCHAR  Ext_ModeID;
 	USHORT Ext_ModeFlag;
-	UCHAR  Ext_ModeOffset;
 	USHORT Ext_VESAID;
 	UCHAR  Ext_RESINFO;
 	UCHAR  VB_ExtTVFlickerIndex;
@@ -172,6 +169,7 @@
 	UCHAR  VB_ExtTVYFilterIndex;
 	UCHAR  VB_ExtTVYFilterIndexROM661;
 	UCHAR  REFindex;
+	CHAR   ROMMODEIDX661;
 } SiS_ExtStruct;
 
 typedef struct _SiS_Ext2Struct
@@ -180,6 +178,7 @@
 	UCHAR  Ext_CRT1CRTC;
 	UCHAR  Ext_CRTVCLK;
 	UCHAR  Ext_CRT2CRTC;
+	UCHAR  Ext_CRT2CRTC_NS;
 	UCHAR  ModeID;
 	USHORT XRes;
 	USHORT YRes;
@@ -228,6 +227,8 @@
 	UCHAR  YChar;
 } SiS_ModeResInfoStruct;
 
+
+
 typedef UCHAR DRAM4Type[4];
 
 /* Defines for SiS_CustomT */
@@ -289,18 +290,21 @@
         USHORT SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
 #endif
 	BOOLEAN SiS_UseROM;
-	int    SiS_CHOverScan;
+	BOOLEAN SiS_ROMNew;
+	BOOLEAN SiS_NeedRomModeData;
+	BOOLEAN PanelSelfDetected;
+	int     SiS_CHOverScan;
 	BOOLEAN SiS_CHSOverScan;
 	BOOLEAN SiS_ChSW;
 	BOOLEAN SiS_UseLCDA;
-	int    SiS_UseOEM;
-	ULONG  SiS_CustomT;
-	USHORT SiS_Backup70xx;
+	int     SiS_UseOEM;
+	ULONG   SiS_CustomT;
+	USHORT  SiS_Backup70xx;
 	BOOLEAN HaveEMI;
 	BOOLEAN HaveEMILCD;
 	BOOLEAN OverruleEMI;
 	UCHAR  EMI_30,EMI_31,EMI_32,EMI_33;
-	UCHAR  PDC;
+	SHORT  PDC, PDCA;
 	UCHAR  SiS_MyCR63;
 	USHORT SiS_CRT1Mode;
 	USHORT SiS_flag_clearbuffer;
@@ -346,28 +350,13 @@
 	USHORT SiS_DDC_DeviceAddr;
 	USHORT SiS_DDC_ReadAddr;
 	USHORT SiS_DDC_SecAddr;
+	USHORT SiS_ChrontelInit;
 	BOOLEAN SiS_SensibleSR11;
-	USHORT SiS_Panel800x600;
-	USHORT SiS_Panel1024x768;
-	USHORT SiS_Panel1280x1024;
-	USHORT SiS_Panel1600x1200;
-	USHORT SiS_Panel1280x960;
-	USHORT SiS_Panel1400x1050;
-	USHORT SiS_Panel320x480;
-	USHORT SiS_Panel1152x768;
-	USHORT SiS_Panel1280x768;
-	USHORT SiS_Panel1024x600;
-	USHORT SiS_Panel640x480;
-	USHORT SiS_Panel640x480_2;
-	USHORT SiS_Panel640x480_3;
-	USHORT SiS_Panel1152x864;
-	USHORT SiS_PanelCustom;
-	USHORT SiS_PanelBarco1366;
-	USHORT SiS_PanelMax;
+	USHORT SiS661LCD2TableSize;
+
 	USHORT SiS_PanelMinLVDS;
 	USHORT SiS_PanelMin301;
-	USHORT SiS_ChrontelInit;
-	
+
 	const SiS_StStruct          *SiS_SModeIDTable;
 	SiS_StandTableStruct        *SiS_StandTable;
 	const SiS_ExtStruct         *SiS_EModeIDTable;
@@ -376,11 +365,10 @@
 	const SiS_CRT1TableStruct   *SiS_CRT1Table;
 	const SiS_MCLKDataStruct    *SiS_MCLKData_0;
 	const SiS_MCLKDataStruct    *SiS_MCLKData_1;
-	const SiS_VCLKDataStruct    *SiS_VCLKData;
-	const SiS_VBVCLKDataStruct  *SiS_VBVCLKData;
+	SiS_VCLKDataStruct    	    *SiS_VCLKData;
+	SiS_VBVCLKDataStruct        *SiS_VBVCLKData;
 	const SiS_StResInfoStruct   *SiS_StResInfo;
 	const SiS_ModeResInfoStruct *SiS_ModeResInfo;
-	const UCHAR                 *SiS_ScreenOffset;
 
 	const UCHAR                 *pSiS_OutputSelect;
 	const UCHAR                 *pSiS_SoftSetting;
@@ -410,6 +398,12 @@
 	const USHORT *pSiS_VideoSenseData2;
 	const USHORT *pSiS_YCSenseData2;
 #endif
+
+	const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
+	const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS;
+
+	/* SiS bridge */
+
 	const UCHAR *SiS_NTSCPhase;
 	const UCHAR *SiS_PALPhase;
 	const UCHAR *SiS_NTSCPhase2;
@@ -421,24 +415,21 @@
 	const UCHAR *SiS_SpecialPhase;
 	const UCHAR *SiS_SpecialPhaseM;
 	const UCHAR *SiS_SpecialPhaseJ;
-	const SiS_LCDDataStruct  *SiS_StLCD1024x768Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1024x768Data;
 	const SiS_LCDDataStruct  *SiS_St2LCD1024x768Data;
-	const SiS_LCDDataStruct  *SiS_StLCD1280x1024Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x720Data;
+	const SiS_LCDDataStruct  *SiS_StLCD1280x768_2Data;
+	const SiS_LCDDataStruct  *SiS_ExtLCD1280x768_2Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x768_3Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x800Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x960Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1280x1024Data;
 	const SiS_LCDDataStruct  *SiS_St2LCD1280x1024Data;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1024x768;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1280x1024;
-	const SiS_LCDDataStruct  *SiS_LCD1280x960Data;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1400x1050;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1600x1200;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1280x768;
 	const SiS_LCDDataStruct  *SiS_StLCD1400x1050Data;
-	const SiS_LCDDataStruct  *SiS_StLCD1600x1200Data;
-	const SiS_LCDDataStruct  *SiS_StLCD1280x768Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1400x1050Data;
+	const SiS_LCDDataStruct  *SiS_StLCD1600x1200Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1600x1200Data;
-	const SiS_LCDDataStruct  *SiS_ExtLCD1280x768Data;
+	const SiS_LCDDataStruct  *SiS_LCD1680x1050Data;
 	const SiS_LCDDataStruct  *SiS_NoScaleData;
 	const SiS_TVDataStruct   *SiS_StPALData;
 	const SiS_TVDataStruct   *SiS_ExtPALData;
@@ -464,8 +455,16 @@
 	const UCHAR *SiS_HiTVTextTiming;
 	const UCHAR *SiS_HiTVGroup3Text;
 #endif
-	const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
-	const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS;
+
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3;
+
+	/* LVDS, Chrontel */
+
 	const SiS_LVDSDataStruct  *SiS_LVDS800x600Data_1;
 	const SiS_LVDSDataStruct  *SiS_LVDS800x600Data_2;
 	const SiS_LVDSDataStruct  *SiS_LVDS1024x768Data_1;
@@ -487,14 +486,6 @@
 	const SiS_LVDSDataStruct  *SiS_LVDS640x480Data_1;
 	const SiS_LVDSDataStruct  *SiS_LVDS640x480Data_2;
 	const SiS_LVDSDataStruct  *SiS_LVDS320x480Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1024x768Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1024x768Data_2;
-	const SiS_LVDSDataStruct  *SiS_LCDA1280x1024Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1280x1024Data_2;
-	const SiS_LVDSDataStruct  *SiS_LCDA1400x1050Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1400x1050Data_2;
-	const SiS_LVDSDataStruct  *SiS_LCDA1600x1200Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1600x1200Data_2;
 	const SiS_LVDSDataStruct  *SiS_LVDSXXXxXXXData_1;
 	const SiS_LVDSDataStruct  *SiS_LVDSBARCO1366Data_1;
 	const SiS_LVDSDataStruct  *SiS_LVDSBARCO1366Data_2;
@@ -511,6 +502,7 @@
 	const SiS_LVDSDataStruct  *SiS_CHTVUPALNData;
 	const SiS_LVDSDataStruct  *SiS_CHTVOPALNData;
 	const SiS_LVDSDataStruct  *SiS_CHTVSOPALData;
+
 	const SiS_LVDSDesStruct  *SiS_PanelType00_1;
 	const SiS_LVDSDesStruct  *SiS_PanelType01_1;
 	const SiS_LVDSDesStruct  *SiS_PanelType02_1;
@@ -545,20 +537,11 @@
 	const SiS_LVDSDesStruct  *SiS_PanelType0e_2;
 	const SiS_LVDSDesStruct  *SiS_PanelType0f_2;
 	const SiS_LVDSDesStruct  *SiS_PanelTypeNS_2;
-
-	const SiS_LVDSDesStruct  *LVDS1024x768Des_1;
-	const SiS_LVDSDesStruct  *LVDS1280x1024Des_1;
-	const SiS_LVDSDesStruct  *LVDS1400x1050Des_1;
-	const SiS_LVDSDesStruct  *LVDS1600x1200Des_1;
-	const SiS_LVDSDesStruct  *LVDS1024x768Des_2;
-	const SiS_LVDSDesStruct  *LVDS1280x1024Des_2;
-	const SiS_LVDSDesStruct  *LVDS1400x1050Des_2;
-	const SiS_LVDSDesStruct  *LVDS1600x1200Des_2;
-
 	const SiS_LVDSDesStruct  *SiS_CHTVUNTSCDesData;
 	const SiS_LVDSDesStruct  *SiS_CHTVONTSCDesData;
 	const SiS_LVDSDesStruct  *SiS_CHTVUPALDesData;
 	const SiS_LVDSDesStruct  *SiS_CHTVOPALDesData;
+
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1800x600_1;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x768_1;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x1024_1;
@@ -599,44 +582,13 @@
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_2_H;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_3;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_3_H;
+	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1320x480_1;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1UNTSC;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1ONTSC;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1UPAL;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1OPAL;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1SOPAL;
 
-	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1320x480_1;
-
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_2_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_2_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_2_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_2_H;
-
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_3;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_3;
-
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_UNTSC;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_ONTSC;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPAL;
@@ -646,6 +598,7 @@
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALN;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALN;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_SOPAL;
+
 	const UCHAR *SiS_CHTVVCLKUNTSC;
 	const UCHAR *SiS_CHTVVCLKONTSC;
 	const UCHAR *SiS_CHTVVCLKUPAL;
@@ -656,9 +609,13 @@
 	const UCHAR *SiS_CHTVVCLKOPALN;
 	const UCHAR *SiS_CHTVVCLKSOPAL;
 
-	USHORT  PanelXRes;
-	USHORT  PanelYRes;
-	
+	USHORT  PanelXRes, PanelHT;
+	USHORT  PanelYRes, PanelVT;
+	USHORT  PanelHRS,  PanelHRE;
+  	USHORT 	PanelVRS,  PanelVRE;
+	USHORT  PanelVCLKIdx300;
+	USHORT  PanelVCLKIdx315;
+
 	BOOLEAN UseCustomMode;
 	BOOLEAN CRT1UsesCustomMode;
 	USHORT  CHDisplay;
@@ -700,10 +657,11 @@
 	UCHAR Backup_1d;
 	
 	int     UsePanelScaler;
+	int	CenterScreen;
 
 	USHORT  CP_Vendor, CP_Product;
 	BOOLEAN CP_HaveCustomData;
-	int     CP_PreferredX, CP_PreferredY;
+	int     CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
 	int	CP_MaxX, CP_MaxY, CP_MaxClock;
 	BOOLEAN CP_Supports64048075;
 	int     CP_HDisplay[7], CP_VDisplay[7];	/* For Custom LCD panel dimensions */
diff -Nru a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
--- a/drivers/video/skeletonfb.c	2004-06-23 19:04:25 -07:00
+++ b/drivers/video/skeletonfb.c	2004-06-23 19:04:25 -07:00
@@ -539,7 +539,13 @@
     info.fbops = &xxxfb_ops;
     info.fix = xxxfb_fix;
     info.pseudo_palette = pseudo_palette;
-    info.flags = FBINFO_FLAG_DEFAULT;
+
+    /*
+     * Set up flags to indicate what sort of acceleration your
+     * driver can provide (pan/wrap/copyarea/etc.) and whether it
+     * is a module -- see FBINFO_* in include/linux/fb.h
+     */
+    info.flags = FBINFO_DEFAULT;
     info.par = current_par;
 
     /*
diff -Nru a/drivers/video/sstfb.c b/drivers/video/sstfb.c
--- a/drivers/video/sstfb.c	2004-06-23 19:04:27 -07:00
+++ b/drivers/video/sstfb.c	2004-06-23 19:04:27 -07:00
@@ -790,7 +790,7 @@
 		
 	/* fills lfb with #arg pixels */
 	case _IOW('F', 0xdc, u32):	/* 0x46dc */
-		if (copy_from_user(&val, (void *)arg, sizeof(val)))
+		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
 			return -EFAULT;
 		if (val > info->fix.smem_len)
 			val = info->fix.smem_len;
@@ -801,7 +801,7 @@
 		
 	/* change VGA pass_through mode */
 	case _IOW('F', 0xdd, u32):	/* 0x46dd */
-		if (copy_from_user(&val, (void *)arg, sizeof(val)))
+		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
 			return -EFAULT;
 		pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
 		pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
diff -Nru a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
--- a/drivers/video/tdfxfb.c	2004-06-23 19:04:26 -07:00
+++ b/drivers/video/tdfxfb.c	2004-06-23 19:04:26 -07:00
@@ -1101,7 +1101,7 @@
 		 */
 		u8 *cursorbase = (u8 *) info->cursor.image.data;
 		char *bitmap = (char *)cursor->image.data;
-		char *mask = cursor->mask;
+		const char *mask = cursor->mask;
 		int i, j, k, h = 0;
 
 		for (i = 0; i < 64; i++) {
diff -Nru a/fs/Kconfig b/fs/Kconfig
--- a/fs/Kconfig	2004-06-23 19:04:27 -07:00
+++ b/fs/Kconfig	2004-06-23 19:04:27 -07:00
@@ -672,6 +672,25 @@
 	  To compile this as a module, choose M here: the module will be called
 	  vfat.
 
+config FAT_DEFAULT_CODEPAGE
+	int "Default codepage for FAT"
+	depends on MSDOS_FS || VFAT_FS
+	default 437
+	help
+	  This option should be set to the codepage of your FAT filesystems.
+	  It can be overridden with the 'codepage' mount option.
+
+config FAT_DEFAULT_IOCHARSET
+	string "Default iocharset for FAT"
+	depends on VFAT_FS
+	default "iso8859-1"
+	help
+	  Set this to the default I/O character set you'd like FAT to use.
+	  It should probably match the character set that most of your
+	  FAT filesystems use, and can be overridded with the 'iocharset'
+	  mount option for FAT filesystems.  Note that UTF8 is *not* a
+	  supported charset for FAT filesystems.
+
 config UMSDOS_FS
 #dep_tristate '    UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
 # UMSDOS is temprory broken
@@ -1562,7 +1581,7 @@
 	  smbmount from samba 2.2.0 or later supports this.
 
 config CIFS
-	tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)(EXPERIMENTAL)"
+	tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)"
 	depends on INET
 	select NLS
 	help
@@ -1592,7 +1611,16 @@
         depends on CIFS
         help
           Enabling this option will cause statistics for each server share
-	  mounted by the cifs client to be displayed in /proc/fs/cifs/DebugData
+	  mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
+
+config CIFS_POSIX
+        bool "CIFS POSIX Extensions (EXPERIMENTAL)"
+        depends on CIFS
+        help
+          Enabling this option will cause the cifs client to attempt to
+	  negotiate a newer dialect with servers, such as Samba 3.0.5
+	  or later, that optionally can handle more POSIX like (rather
+	  than Windows like) file behavior.  If unsure, say N.
 
 config NCP_FS
 	tristate "NCP file system support (to mount NetWare volumes)"
diff -Nru a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
--- a/fs/affs/amigaffs.c	2004-06-23 19:04:26 -07:00
+++ b/fs/affs/amigaffs.c	2004-06-23 19:04:26 -07:00
@@ -458,7 +458,6 @@
 	if (!(sb->s_flags & MS_RDONLY))
 		printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n");
 	sb->s_flags |= MS_RDONLY;
-	AFFS_SB(sb)->s_flags |= SF_READONLY;	/* Don't allow to remount rw */
 }
 
 void
diff -Nru a/fs/affs/bitmap.c b/fs/affs/bitmap.c
--- a/fs/affs/bitmap.c	2004-06-23 19:04:28 -07:00
+++ b/fs/affs/bitmap.c	2004-06-23 19:04:28 -07:00
@@ -272,8 +272,7 @@
 	return 0;
 }
 
-int
-affs_init_bitmap(struct super_block *sb)
+int affs_init_bitmap(struct super_block *sb, int *flags)
 {
 	struct affs_bm_info *bm;
 	struct buffer_head *bmap_bh = NULL, *bh = NULL;
@@ -282,13 +281,13 @@
 	int i, res = 0;
 	struct affs_sb_info *sbi = AFFS_SB(sb);
 
-	if (sb->s_flags & MS_RDONLY)
+	if (*flags & MS_RDONLY)
 		return 0;
 
 	if (!AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag) {
 		printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n",
 			sb->s_id);
-		sb->s_flags |= MS_RDONLY;
+		*flags |= MS_RDONLY;
 		return 0;
 	}
 
@@ -301,7 +300,7 @@
 	bm = sbi->s_bitmap = kmalloc(size, GFP_KERNEL);
 	if (!sbi->s_bitmap) {
 		printk(KERN_ERR "AFFS: Bitmap allocation failed\n");
-		return 1;
+		return -ENOMEM;
 	}
 	memset(sbi->s_bitmap, 0, size);
 
@@ -316,13 +315,13 @@
 		bh = affs_bread(sb, bm->bm_key);
 		if (!bh) {
 			printk(KERN_ERR "AFFS: Cannot read bitmap\n");
-			res = 1;
+			res = -EIO;
 			goto out;
 		}
 		if (affs_checksum_block(sb, bh)) {
 			printk(KERN_WARNING "AFFS: Bitmap %u invalid - mounting %s read only.\n",
 			       bm->bm_key, sb->s_id);
-			sb->s_flags |= MS_RDONLY;
+			*flags |= MS_RDONLY;
 			goto out;
 		}
 		pr_debug("AFFS: read bitmap block %d: %d\n", blk, bm->bm_key);
@@ -338,7 +337,7 @@
 		bmap_bh = affs_bread(sb, be32_to_cpu(bmap_blk[blk]));
 		if (!bmap_bh) {
 			printk(KERN_ERR "AFFS: Cannot read bitmap extension\n");
-			res = 1;
+			res = -EIO;
 			goto out;
 		}
 		bmap_blk = (u32 *)bmap_bh->b_data;
@@ -382,4 +381,18 @@
 	affs_brelse(bh);
 	affs_brelse(bmap_bh);
 	return res;
+}
+
+void affs_free_bitmap(struct super_block *sb)
+{
+	struct affs_sb_info *sbi = AFFS_SB(sb);
+
+	if (!sbi->s_bitmap)
+		return;
+
+	affs_brelse(sbi->s_bmap_bh);
+	sbi->s_bmap_bh = NULL;
+	sbi->s_last_bmap = ~0;
+	kfree(sbi->s_bitmap);
+	sbi->s_bitmap = NULL;
 }
diff -Nru a/fs/affs/super.c b/fs/affs/super.c
--- a/fs/affs/super.c	2004-06-23 19:04:27 -07:00
+++ b/fs/affs/super.c	2004-06-23 19:04:27 -07:00
@@ -51,10 +51,9 @@
 		mark_buffer_dirty(sbi->s_root_bh);
 	}
 
-	affs_brelse(sbi->s_bmap_bh);
 	if (sbi->s_prefix)
 		kfree(sbi->s_prefix);
-	kfree(sbi->s_bitmap);
+	affs_free_bitmap(sb);
 	affs_brelse(sbi->s_root_bh);
 	kfree(sbi);
 	sb->s_fs_info = NULL;
@@ -288,6 +287,7 @@
 	gid_t			 gid;
 	int			 reserved;
 	unsigned long		 mount_flags;
+	int			 tmp_flags;	/* fix remount prototype... */
 
 	pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
 
@@ -399,7 +399,6 @@
 		printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
 			sb->s_id);
 		sb->s_flags |= MS_RDONLY;
-		sbi->s_flags |= SF_READONLY;
 	}
 	switch (chksum) {
 		case MUFS_FS:
@@ -455,8 +454,10 @@
 	sbi->s_root_bh = root_bh;
 	/* N.B. after this point s_root_bh must be released */
 
-	if (affs_init_bitmap(sb))
+	tmp_flags = sb->s_flags;
+	if (affs_init_bitmap(sb, &tmp_flags))
 		goto out_error;
+	sb->s_flags = tmp_flags;
 
 	/* set up enough so that it can read an inode */
 
@@ -498,7 +499,7 @@
 	int			 reserved;
 	int			 root_block;
 	unsigned long		 mount_flags;
-	unsigned long		 read_only = sbi->s_flags & SF_READONLY;
+	int			 res = 0;
 
 	pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
 
@@ -507,7 +508,7 @@
 	if (!parse_options(data,&uid,&gid,&mode,&reserved,&root_block,
 	    &blocksize,&sbi->s_prefix,sbi->s_volume,&mount_flags))
 		return -EINVAL;
-	sbi->s_flags = mount_flags | read_only;
+	sbi->s_flags = mount_flags;
 	sbi->s_mode  = mode;
 	sbi->s_uid   = uid;
 	sbi->s_gid   = gid;
@@ -518,14 +519,11 @@
 		sb->s_dirt = 1;
 		while (sb->s_dirt)
 			affs_write_super(sb);
-		sb->s_flags |= MS_RDONLY;
-	} else if (!(sbi->s_flags & SF_READONLY)) {
-		sb->s_flags &= ~MS_RDONLY;
-	} else {
-		affs_warning(sb,"remount","Cannot remount fs read/write because of errors");
-		return -EINVAL;
-	}
-	return 0;
+		affs_free_bitmap(sb);
+	} else
+		res = affs_init_bitmap(sb, flags);
+
+	return res;
 }
 
 static int
diff -Nru a/fs/aio.c b/fs/aio.c
--- a/fs/aio.c	2004-06-23 19:04:26 -07:00
+++ b/fs/aio.c	2004-06-23 19:04:26 -07:00
@@ -27,6 +27,7 @@
 #include <linux/aio.h>
 #include <linux/highmem.h>
 #include <linux/workqueue.h>
+#include <linux/security.h>
 
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
@@ -1036,6 +1037,9 @@
 		ret = -EFAULT;
 		if (unlikely(!access_ok(VERIFY_WRITE, buf, iocb->aio_nbytes)))
 			goto out_put_req;
+		ret = security_file_permission (file, MAY_READ);
+		if (ret)
+			goto out_put_req;
 		ret = -EINVAL;
 		if (file->f_op->aio_read)
 			ret = file->f_op->aio_read(req, buf,
@@ -1047,6 +1051,9 @@
 			goto out_put_req;
 		ret = -EFAULT;
 		if (unlikely(!access_ok(VERIFY_READ, buf, iocb->aio_nbytes)))
+			goto out_put_req;
+		ret = security_file_permission (file, MAY_WRITE);
+		if (ret)
 			goto out_put_req;
 		ret = -EINVAL;
 		if (file->f_op->aio_write)
diff -Nru a/fs/autofs/root.c b/fs/autofs/root.c
--- a/fs/autofs/root.c	2004-06-23 19:04:27 -07:00
+++ b/fs/autofs/root.c	2004-06-23 19:04:27 -07:00
@@ -468,7 +468,7 @@
 
 /* Get/set timeout ioctl() operation */
 static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,
-					 unsigned long *p)
+					 unsigned long __user *p)
 {
 	unsigned long ntimeout;
 
@@ -485,7 +485,7 @@
 }
 
 /* Return protocol version */
-static inline int autofs_get_protover(int *p)
+static inline int autofs_get_protover(int __user *p)
 {
 	return put_user(AUTOFS_PROTO_VERSION, p);
 }
@@ -494,7 +494,7 @@
 static inline int autofs_expire_run(struct super_block *sb,
 				    struct autofs_sb_info *sbi,
 				    struct vfsmount *mnt,
-				    struct autofs_packet_expire *pkt_p)
+				    struct autofs_packet_expire __user *pkt_p)
 {
 	struct autofs_dir_ent *ent;
 	struct autofs_packet_expire pkt;
@@ -526,6 +526,7 @@
 			     unsigned int cmd, unsigned long arg)
 {
 	struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb);
+	void __user *argp = (void __user *)arg;
 
 	DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,process_group(current)));
 
@@ -545,12 +546,12 @@
 		autofs_catatonic_mode(sbi);
 		return 0;
 	case AUTOFS_IOC_PROTOVER: /* Get protocol version */
-		return autofs_get_protover((int *)arg);
+		return autofs_get_protover(argp);
 	case AUTOFS_IOC_SETTIMEOUT:
-		return autofs_get_set_timeout(sbi,(unsigned long *)arg);
+		return autofs_get_set_timeout(sbi, argp);
 	case AUTOFS_IOC_EXPIRE:
 		return autofs_expire_run(inode->i_sb, sbi, filp->f_vfsmnt,
-					 (struct autofs_packet_expire *)arg);
+					 argp);
 	default:
 		return -ENOSYS;
 	}
diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
--- a/fs/binfmt_aout.c	2004-06-23 19:04:25 -07:00
+++ b/fs/binfmt_aout.c	2004-06-23 19:04:25 -07:00
@@ -27,7 +27,6 @@
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
@@ -141,14 +140,14 @@
 /* make sure we actually have a data and stack area to dump */
 	set_fs(USER_DS);
 #ifdef __sparc__
-	if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize))
+	if (verify_area(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize))
 		dump.u_dsize = 0;
-	if (verify_area(VERIFY_READ, (void *) START_STACK(dump), dump.u_ssize))
+	if (verify_area(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize))
 		dump.u_ssize = 0;
 #else
-	if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
+	if (verify_area(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
 		dump.u_dsize = 0;
-	if (verify_area(VERIFY_READ, (void *) START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
+	if (verify_area(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
 		dump.u_ssize = 0;
 #endif
 
@@ -194,17 +193,18 @@
  * memory and creates the pointer tables from them, and puts their
  * addresses on the "stack", returning the new stack pointer value.
  */
-static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
+static unsigned long __user *create_aout_tables(char __user *p, struct linux_binprm * bprm)
 {
-	char **argv, **envp;
-	unsigned long * sp;
+	char __user * __user *argv;
+	char __user * __user *envp;
+	unsigned long __user *sp;
 	int argc = bprm->argc;
 	int envc = bprm->envc;
 
-	sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
+	sp = (void __user *)((-(unsigned long)sizeof(char *)) & (unsigned long) p);
 #ifdef __sparc__
 	/* This imposes the proper stack alignment for a new process. */
-	sp = (unsigned long *) (((unsigned long) sp) & ~7);
+	sp = (void __user *) (((unsigned long) sp) & ~7);
 	if ((envc+argc+3)&1) --sp;
 #endif
 #ifdef __alpha__
@@ -221,9 +221,9 @@
 	put_user(0x3e9, --sp);
 #endif
 	sp -= envc+1;
-	envp = (char **) sp;
+	envp = (char __user * __user *) sp;
 	sp -= argc+1;
-	argv = (char **) sp;
+	argv = (char __user * __user *) sp;
 #if defined(__i386__) || defined(__mc68000__) || defined(__arm__) || defined(__arch_um__)
 	put_user((unsigned long) envp,--sp);
 	put_user((unsigned long) argv,--sp);
@@ -421,7 +421,7 @@
 	}
 
 	current->mm->start_stack =
-		(unsigned long) create_aout_tables((char *) bprm->p, bprm);
+		(unsigned long) create_aout_tables((char __user *) bprm->p, bprm);
 #ifdef __alpha__
 	regs->gp = ex.a_gpvalue;
 #endif
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	2004-06-23 19:04:26 -07:00
+++ b/fs/binfmt_elf.c	2004-06-23 19:04:26 -07:00
@@ -40,7 +40,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
-#include <asm/pgalloc.h>
 
 #include <linux/elf.h>
 
diff -Nru a/fs/binfmt_flat.c b/fs/binfmt_flat.c
--- a/fs/binfmt_flat.c	2004-06-23 19:04:24 -07:00
+++ b/fs/binfmt_flat.c	2004-06-23 19:04:24 -07:00
@@ -40,7 +40,6 @@
 #include <asm/byteorder.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/unaligned.h>
 #include <asm/cacheflush.h>
 
diff -Nru a/fs/binfmt_misc.c b/fs/binfmt_misc.c
--- a/fs/binfmt_misc.c	2004-06-23 19:04:26 -07:00
+++ b/fs/binfmt_misc.c	2004-06-23 19:04:26 -07:00
@@ -39,6 +39,8 @@
 
 enum {Enabled, Magic};
 #define MISC_FMT_PRESERVE_ARGV0 (1<<31)
+#define MISC_FMT_OPEN_BINARY (1<<30)
+#define MISC_FMT_CREDENTIALS (1<<29)
 
 typedef struct {
 	struct list_head list;
@@ -102,10 +104,13 @@
 static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 {
 	Node *fmt;
-	struct file * file;
+	struct file * interp_file = NULL;
 	char iname[BINPRM_BUF_SIZE];
 	char *iname_addr = iname;
 	int retval;
+	int fd_binary = -1;
+	char fd_str[12];
+	struct files_struct *files = NULL;
 
 	retval = -ENOEXEC;
 	if (!enabled)
@@ -120,33 +125,102 @@
 	if (!fmt)
 		goto _ret;
 
-	allow_write_access(bprm->file);
-	fput(bprm->file);
-	bprm->file = NULL;
-
-	/* Build args for interpreter */
 	if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
 		remove_arg_zero(bprm);
 	}
-	retval = copy_strings_kernel(1, &bprm->interp, bprm);
-	if (retval < 0) goto _ret; 
-	bprm->argc++;
-	retval = copy_strings_kernel(1, &iname_addr, bprm);
-	if (retval < 0) goto _ret; 
-	bprm->argc++;
-	bprm->interp = iname;	/* for binfmt_script */
 
-	file = open_exec(iname);
-	retval = PTR_ERR(file);
-	if (IS_ERR(file))
-		goto _ret;
-	bprm->file = file;
+	if (fmt->flags & MISC_FMT_OPEN_BINARY) {
+		char *fdsp = fd_str;
+
+		files = current->files;
+		retval = unshare_files();
+		if (retval < 0)
+			goto _ret;
+		if (files == current->files) {
+			put_files_struct(files);
+			files = NULL;
+		}
+		/* if the binary should be opened on behalf of the
+		 * interpreter than keep it open and assign descriptor
+		 * to it */
+ 		fd_binary = get_unused_fd();
+ 		if (fd_binary < 0) {
+ 			retval = fd_binary;
+ 			goto _unshare;
+ 		}
+ 		fd_install(fd_binary, bprm->file);
+
+		/* if the binary is not readable than enforce mm->dumpable=0
+		   regardless of the interpreter's permissions */
+		if (permission(bprm->file->f_dentry->d_inode, MAY_READ, NULL))
+			bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+
+		allow_write_access(bprm->file);
+		bprm->file = NULL;
+
+		/* make argv[1] be the file descriptor of the binary */
+ 		snprintf(fd_str, sizeof(fd_str), "%d", fd_binary);
+ 		retval = copy_strings_kernel(1, &fdsp, bprm);
+		if (retval < 0)
+			goto _error;
+		bprm->argc++;
+
+ 	} else {
+ 		allow_write_access(bprm->file);
+ 		fput(bprm->file);
+ 		bprm->file = NULL;
+		/* make argv[1] be the path to the binary */
+ 		retval = copy_strings_kernel (1, &bprm->interp, bprm);
+		if (retval < 0)
+			goto _error;
+		bprm->argc++;
+ 	}
+	retval = copy_strings_kernel (1, &iname_addr, bprm);
+	if (retval < 0)
+		goto _error;
+	bprm->argc ++;
+	bprm->interp = iname;	/* for binfmt_script */
 
-	retval = prepare_binprm(bprm);
-	if (retval >= 0)
-		retval = search_binary_handler(bprm, regs);
+	interp_file = open_exec (iname);
+	retval = PTR_ERR (interp_file);
+	if (IS_ERR (interp_file))
+		goto _error;
+
+	bprm->file = interp_file;
+	if (fmt->flags & MISC_FMT_CREDENTIALS) {
+		/*
+		 * No need to call prepare_binprm(), it's already been
+		 * done.  bprm->buf is stale, update from interp_file.
+		 */
+		memset(bprm->buf, 0, BINPRM_BUF_SIZE);
+		retval = kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
+	} else
+		retval = prepare_binprm (bprm);
+
+	if (retval < 0)
+		goto _error;
+
+	retval = search_binary_handler (bprm, regs);
+	if (retval < 0)
+		goto _error;
+
+	if (files) {
+		steal_locks(files);
+		put_files_struct(files);
+		files = NULL;
+	}
 _ret:
 	return retval;
+_error:
+	if (fd_binary > 0)
+		sys_close(fd_binary);
+	bprm->interp_flags = 0;
+_unshare:
+	if (files) {
+		put_files_struct(current->files);
+		current->files = files;
+	}
+	goto _ret;
 }
 
 /* Command parsers */
@@ -191,9 +265,39 @@
 	return p - from;
 }
 
+static inline char * check_special_flags (char * sfs, Node * e)
+{
+	char * p = sfs;
+	int cont = 1;
+
+	/* special flags */
+	while (cont) {
+		switch (*p) {
+			case 'P':
+				p++;
+				e->flags |= MISC_FMT_PRESERVE_ARGV0;
+				break;
+			case 'O':
+				p++;
+				e->flags |= MISC_FMT_OPEN_BINARY;
+				break;
+			case 'C':
+				p++;
+				/* this flags also implies the
+				   open-binary flag */
+				e->flags |= (MISC_FMT_CREDENTIALS |
+						MISC_FMT_OPEN_BINARY);
+				break;
+			default:
+				cont = 0;
+		}
+	}
+
+	return p;
+}
 /*
  * This registers a new binary format, it recognises the syntax
- * ':name:type:offset:magic:mask:interpreter:'
+ * ':name:type:offset:magic:mask:interpreter:flags'
  * where the ':' is the IFS, that can be chosen with the first char
  */
 static Node *create_entry(const char __user *buffer, size_t count)
@@ -293,10 +397,8 @@
 	if (!e->interpreter[0])
 		goto Einval;
 
-	if (*p == 'P') {
-		p++;
-		e->flags |= MISC_FMT_PRESERVE_ARGV0;
-	}
+
+	p = check_special_flags (p, e);
 
 	if (*p == '\n')
 		p++;
@@ -346,6 +448,7 @@
 {
 	char *dp;
 	char *status = "disabled";
+	const char * flags = "flags: ";
 
 	if (test_bit(Enabled, &e->flags))
 		status = "enabled";
@@ -357,6 +460,22 @@
 
 	sprintf(page, "%s\ninterpreter %s\n", status, e->interpreter);
 	dp = page + strlen(page);
+
+	/* print the special flags */
+	sprintf (dp, "%s", flags);
+	dp += strlen (flags);
+	if (e->flags & MISC_FMT_PRESERVE_ARGV0) {
+		*dp ++ = 'P';
+	}
+	if (e->flags & MISC_FMT_OPEN_BINARY) {
+		*dp ++ = 'O';
+	}
+	if (e->flags & MISC_FMT_CREDENTIALS) {
+		*dp ++ = 'C';
+	}
+	*dp ++ = '\n';
+
+
 	if (!test_bit(Magic, &e->flags)) {
 		sprintf(dp, "extension .%s\n", e->magic);
 	} else {
diff -Nru a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c	2004-06-23 19:04:27 -07:00
+++ b/fs/bio.c	2004-06-23 19:04:27 -07:00
@@ -116,6 +116,8 @@
 	bio->bi_idx = 0;
 	bio->bi_phys_segments = 0;
 	bio->bi_hw_segments = 0;
+	bio->bi_hw_front_size = 0;
+	bio->bi_hw_back_size = 0;
 	bio->bi_size = 0;
 	bio->bi_max_vecs = 0;
 	bio->bi_end_io = NULL;
@@ -304,14 +306,15 @@
 	 * make this too complex.
 	 */
 
-	while (bio_phys_segments(q, bio) >= q->max_phys_segments
-	    || bio_hw_segments(q, bio) >= q->max_hw_segments) {
+	while (bio->bi_phys_segments >= q->max_phys_segments
+	       || bio->bi_hw_segments >= q->max_hw_segments
+	       || BIOVEC_VIRT_OVERSIZE(bio->bi_size)) {
 
 		if (retried_segments)
 			return 0;
 
-		bio->bi_flags &= ~(1 << BIO_SEG_VALID);
 		retried_segments = 1;
+		blk_recount_segments(q, bio);
 	}
 
 	/*
@@ -340,6 +343,11 @@
 			return 0;
 		}
 	}
+
+	/* If we may be able to merge these biovecs, force a recount */
+	if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec) ||
+	    BIOVEC_VIRT_MERGEABLE(bvec-1, bvec)))
+		bio->bi_flags &= ~(1 << BIO_SEG_VALID);
 
 	bio->bi_vcnt++;
 	bio->bi_phys_segments++;
diff -Nru a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
--- a/fs/cifs/AUTHORS	2004-06-23 19:04:25 -07:00
+++ b/fs/cifs/AUTHORS	2004-06-23 19:04:25 -07:00
@@ -31,7 +31,7 @@
 and debug of problems they have found:  Jochen Dolze, David Blaine,
 Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
 Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
-Olaf Kirch, Kieron Briggs and others. 
+Olaf Kirch, Kieron Briggs, Nick Millington and others. 
 
 And thanks to the IBM LTC and Power test teams and SuSE testers for
 finding multiple bugs during excellent stress test runs.
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	2004-06-23 19:04:28 -07:00
+++ b/fs/cifs/CHANGES	2004-06-23 19:04:28 -07:00
@@ -1,9 +1,21 @@
+Version 1.19
+------------
+Fix /proc/fs/cifs/Stats and DebugData display to handle larger
+amounts of return data. Properly limit requests to MAX_REQ (50
+is the usual maximum active multiplex SMB/CIFS requests per server).
+Do not kill cifsd (and thus hurt the other SMB session) when more than one
+session to the same server (but with different userids) exists and one
+of the two user's smb sessions is being removed while leaving the other.
+
+
 Version 1.18
 ------------
 Do not rename hardlinked files (since that should be a noop). Flush
 cached write behind data when reopening a file after session abend,
 except when already in write. Grab per socket sem during reconnect 
-to avoid oops in sendmsg if overlapping with reconnect.
+to avoid oops in sendmsg if overlapping with reconnect. Do not
+reset cached inode file size on readdir for files open for write on 
+client.
 
 
 Version 1.17
diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
--- a/fs/cifs/cifs_debug.c	2004-06-23 19:04:26 -07:00
+++ b/fs/cifs/cifs_debug.c	2004-06-23 19:04:26 -07:00
@@ -62,12 +62,17 @@
 		     int count, int *eof, void *data)
 {
 	struct list_head *tmp;
+	struct list_head *tmp1;
+	struct mid_q_entry * mid_entry;
 	struct cifsSesInfo *ses;
 	struct cifsTconInfo *tcon;
 	int i;
 	int length = 0;
-	char *buf_start = buf;
+	char * original_buf = buf;
 
+	*beginBuffer = buf + offset;
+
+	
 	length =
 	    sprintf(buf,
 		    "Display Internal CIFS Data Structures for Debugging\n"
@@ -94,7 +99,7 @@
 				ses->server->secMode,
 				atomic_read(&ses->server->inFlight));
 			
-			/* length = sprintf(buf, "\nMIDs: \n");
+			length = sprintf(buf, "\nMIDs: \n");
 			buf += length;
 
 			spin_lock(&GlobalMid_Lock);
@@ -103,11 +108,11 @@
 					mid_q_entry,
 					qhead);
 				if(mid_entry) {
-					length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk);
+					length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid);
 					buf += length;
 				}
 			}
-			spin_unlock(&GlobalMid_Lock); */
+			spin_unlock(&GlobalMid_Lock); 
 		}
 
 	}
@@ -152,19 +157,22 @@
 	length = sprintf(buf, "\n");
 	buf += length;
 
-	*eof = 1;
 	/* BB add code to dump additional info such as TCP session info now */
-	/*
-	   if (offset >= (buf - buf_start)) 
-	   {
-	   *beginBuffer = buf;
-	   return 0;
-	   }
-	   *beginBuffer = buf + offset;
-	   if ((buf - buf_start - offset) > count)
-	   return count;
-   else */
-	return (buf - buf_start - offset);
+	/* Now calculate total size of returned data */
+	length = buf - original_buf;
+
+	if(offset + count >= length)
+		*eof = 1;
+	if(length < offset) {
+		*eof = 1;
+		return 0;
+	} else {
+		length = length - offset;
+	}
+	if (length > count)
+		length = count;
+
+	return length;
 }
 
 int
@@ -183,12 +191,14 @@
 #ifdef CONFIG_CIFS_STATS
 int
 cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
-		  int length, int *eof, void *data)
+		  int count, int *eof, void *data)
 {
-	int item_length,i;
+	int item_length,i,length;
 	struct list_head *tmp;
 	struct cifsTconInfo *tcon;
 
+	*beginBuffer = buf + offset;
+
 	length = sprintf(buf,
 			"Resources in use\nCIFS Session: %d\n",
 			sesInfoAllocCount.counter);
@@ -235,10 +245,12 @@
 			atomic_read(&tcon->num_reads),
 			(long long)(tcon->bytes_read));
 		buf += item_length;
+		length += item_length;
 		item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
 			atomic_read(&tcon->num_writes),
 			(long long)(tcon->bytes_written));
 		buf += item_length;
+		length += item_length;
 		item_length = sprintf(buf,
 			"\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
 			atomic_read(&tcon->num_opens),
@@ -247,10 +259,29 @@
 			atomic_read(&tcon->num_rmdirs));
 		buf += item_length;
 		length += item_length;
+		item_length = sprintf(buf,
+			"\nRenames: %d T2 Renames %d",
+			atomic_read(&tcon->num_renames),
+			atomic_read(&tcon->num_t2renames));
+		buf += item_length;
+		length += item_length;
 	}
 	read_unlock(&GlobalSMBSeslock);
 
+	buf += sprintf(buf,"\n");
+	length++;
 
+	if(offset + count >= length)
+		*eof = 1;
+	if(length < offset) {
+		*eof = 1;
+		return 0;
+	} else {
+		length = length - offset;
+	}
+	if (length > count)
+		length = count;
+		
 	return length;
 }
 #endif
diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
--- a/fs/cifs/cifsfs.h	2004-06-23 19:04:25 -07:00
+++ b/fs/cifs/cifsfs.h	2004-06-23 19:04:25 -07:00
@@ -93,5 +93,5 @@
 			 size_t, int);
 extern ssize_t	cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
-#define CIFS_VERSION   "1.18"
+#define CIFS_VERSION   "1.19"
 #endif				/* _CIFSFS_H */
diff -Nru a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
--- a/fs/cifs/cifsglob.h	2004-06-23 19:04:25 -07:00
+++ b/fs/cifs/cifsglob.h	2004-06-23 19:04:25 -07:00
@@ -211,6 +211,8 @@
 	atomic_t num_deletes;
 	atomic_t num_mkdirs;
 	atomic_t num_rmdirs;
+	atomic_t num_renames;
+	atomic_t num_t2renames;
 	__u64    bytes_read;
 	__u64    bytes_written;
 	spinlock_t stat_lock;
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c	2004-06-23 19:04:26 -07:00
+++ b/fs/cifs/cifssmb.c	2004-06-23 19:04:26 -07:00
@@ -387,6 +387,7 @@
 			spin_lock(&GlobalMid_Lock);
 			ses->server->tcpStatus = CifsExiting;
 			spin_unlock(&GlobalMid_Lock);
+			rc = -ESHUTDOWN;
 		}
 	}
 	if (pSMB)
@@ -819,14 +820,20 @@
 	pSMB->AndXCommand = 0xFF;	/* none */
 	pSMB->Fid = smb_file_id; /* netfid stays le */
 
-	pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
-	temp = cpu_to_le64(len);
-	pSMB->Locks[0].LengthLow = (__u32)(len & 0xFFFFFFFF);
-	pSMB->Locks[0].LengthHigh =  (__u32)(len>>32);
-	temp = cpu_to_le64(offset);
-	pSMB->Locks[0].OffsetLow = (__u32)(offset & 0xFFFFFFFF);
-	pSMB->Locks[0].OffsetHigh = (__u32)(offset>>32);
-	pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
+	if(numLock != 0) {
+		pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
+		/* BB where to store pid high? */
+		temp = cpu_to_le64(len);
+		pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
+		pSMB->Locks[0].LengthHigh =  (__u32)(temp>>32);
+		temp = cpu_to_le64(offset);
+		pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
+		pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
+		pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
+	} else {
+		/* oplock break */
+		pSMB->ByteCount = 0;
+	}
 	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
 	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
 
@@ -941,7 +948,14 @@
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in rename = %d", rc));
+	} 
+
+#ifdef CONFIG_CIFS_STATS
+	  else {
+		atomic_inc(&tcon->num_renames);
 	}
+#endif
+
 	if (pSMB)
 		cifs_buf_release(pSMB);
 
@@ -1017,7 +1031,11 @@
 	if (rc) {
 		cFYI(1,("Send error in Rename (by file handle) = %d", rc));
 	}
-
+#ifdef CONFIG_CIFS_STATS
+	  else {
+		atomic_inc(&pTcon->num_t2renames);
+	}
+#endif
 	if (pSMB)
 		cifs_buf_release(pSMB);
 
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	2004-06-23 19:04:28 -07:00
+++ b/fs/cifs/connect.c	2004-06-23 19:04:28 -07:00
@@ -175,7 +175,7 @@
 			if(server->tcpStatus != CifsExiting)
 				server->tcpStatus = CifsGood;
 			spin_unlock(&GlobalMid_Lock);
-			atomic_set(&server->inFlight,0);
+	/*		atomic_set(&server->inFlight,0);*/
 			wake_up(&server->response_q);
 		}
 	}
@@ -453,7 +453,7 @@
 		spin_unlock(&GlobalMid_Lock);
 		read_unlock(&GlobalSMBSeslock);
 		set_current_state(TASK_INTERRUPTIBLE);
-		/* 1/8th of sec should be more than enough time for them to exit */
+		/* 1/8th of sec is more than enough time for them to exit */
 		schedule_timeout(HZ/8); 
 	}
 
@@ -468,7 +468,8 @@
 	}
 	kfree(server);
 
-	cFYI(1, ("About to exit from demultiplex thread"));
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ/4);
 	return 0;
 }
 
@@ -2769,6 +2770,7 @@
 	int rc = 0;
 	int xid;
 	struct cifsSesInfo *ses = NULL;
+	struct task_struct *cifsd_task;
 
 	xid = GetXid();
 
@@ -2781,19 +2783,25 @@
 		}
 		tconInfoFree(cifs_sb->tcon);
 		if ((ses) && (ses->server)) {
+			/* save off task so we do not refer to ses later */
+			cifsd_task = ses->server->tsk;
 			cFYI(1, ("About to do SMBLogoff "));
 			rc = CIFSSMBLogoff(xid, ses);
 			if (rc == -EBUSY) {
 				FreeXid(xid);
 				return 0;
-			}
- 
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ / 4);	/* give captive thread time to exit */
-			if((ses->server) && (ses->server->ssocket)) {            
-				cFYI(1,("Waking up socket by sending it signal "));
-				send_sig(SIGKILL,ses->server->tsk,1);
-			}
+			} else if (rc == -ESHUTDOWN) {
+			/* should we add wake_up_all(&server->request_q); 
+			   and add a check in  the check inFlight loop
+			   for the session ending */
+				set_current_state(TASK_INTERRUPTIBLE);
+			/* give captive thread time to exit */
+				schedule_timeout(HZ / 4);
+				cFYI(1,("Waking up socket by sending it signal"));
+				send_sig(SIGKILL,cifsd_task,1);
+				rc = 0;
+			} /* else - we have an smb session
+				left on this socket do not kill cifsd */
 		} else
 			cFYI(1, ("No session or bad tcon"));
 	}
diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c
--- a/fs/cifs/file.c	2004-06-23 19:04:25 -07:00
+++ b/fs/cifs/file.c	2004-06-23 19:04:25 -07:00
@@ -588,9 +588,10 @@
 	if(file->f_dentry == NULL)
 		return -EBADF;
 
-	xid = GetXid();
-
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	if(cifs_sb == NULL) {
+		return -EBADF;
+	}
 	pTcon = cifs_sb->tcon;
 
 	/*cFYI(1,
@@ -598,11 +599,12 @@
 	   *poffset, file->f_dentry->d_name.name)); */
 
 	if (file->private_data == NULL) {
-		FreeXid(xid);
 		return -EBADF;
+	} else {
+		open_file = (struct cifsFileInfo *) file->private_data;
 	}
-	open_file = (struct cifsFileInfo *) file->private_data;
-
+	
+	xid = GetXid();
 	if(file->f_dentry->d_inode == NULL) {
 		FreeXid(xid);
 		return -EBADF;
@@ -620,10 +622,22 @@
 			if(file->private_data == NULL) {
 				/* file has been closed on us */
 				FreeXid(xid);
+			/* if we have gotten here we have written some data
+			and blocked, and the file has been freed on us
+			while we blocked so return what we managed to write */
 				return total_written;
+			} 
+                        open_file = (struct cifsFileInfo *) file->private_data;
+			if(open_file->closePend) {
+				FreeXid(xid);
+				if(total_written)
+					return total_written;
+				else
+					return -EBADF;
 			}
-			if ((open_file->invalidHandle) && (!open_file->closePend)) {
-				if((file->f_dentry == NULL) || (file->f_dentry->d_inode == NULL)) {
+			if (open_file->invalidHandle) {
+				if((file->f_dentry == NULL) ||
+				   (file->f_dentry->d_inode == NULL)) {
 					FreeXid(xid);
 					return total_written;
 				}
diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c
--- a/fs/cifs/transport.c	2004-06-23 19:04:26 -07:00
+++ b/fs/cifs/transport.c	2004-06-23 19:04:26 -07:00
@@ -200,23 +200,35 @@
 	}
 
 	/* Ensure that we do not send more than 50 overlapping requests 
-		to the same server. We may make this configurable later or
-		use ses->maxReq */
-
-	/* can not count locking commands against the total since
-		they are allowed to block on server */
-	if(long_op < 3) {
-		/* update # of requests on the wire to this server */
-		atomic_inc(&ses->server->inFlight); 
+	   to the same server. We may make this configurable later or
+	   use ses->maxReq */
+	if(long_op == -1) {
+		/* oplock breaks must not be held up */
+		atomic_inc(&ses->server->inFlight);
+	} else {
+		spin_lock(&GlobalMid_Lock); 
+		while(1) {        
+			if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){
+				spin_unlock(&GlobalMid_Lock);
+				wait_event(ses->server->request_q,
+					atomic_read(&ses->server->inFlight)
+					 < CIFS_MAX_REQ);
+				spin_lock(&GlobalMid_Lock);
+			} else {
+			/* can not count locking commands against total since
+			   they are allowed to block on server */
+				if(long_op < 3) {
+				/* update # of requests on the wire to server */
+					atomic_inc(&ses->server->inFlight);
+				}
+				spin_unlock(&GlobalMid_Lock);
+				break;
+			}
+		}
 	}
- 
-	if(atomic_read(&ses->server->inFlight) > CIFS_MAX_REQ) {
-		wait_event(ses->server->request_q,atomic_read(&ses->server->inFlight) <= CIFS_MAX_REQ);
-	}
-
 	/* make sure that we sign in the same order that we send on this socket 
-		and avoid races inside tcp sendmsg code that could cause corruption
-		of smb data */
+	   and avoid races inside tcp sendmsg code that could cause corruption
+	   of smb data */
 
 	down(&ses->server->tcpSem); 
 
diff -Nru a/fs/compat.c b/fs/compat.c
--- a/fs/compat.c	2004-06-23 19:04:26 -07:00
+++ b/fs/compat.c	2004-06-23 19:04:26 -07:00
@@ -34,6 +34,7 @@
 #include <linux/syscalls.h>
 #include <linux/ctype.h>
 #include <linux/module.h>
+#include <linux/dirent.h>
 #include <linux/dnotify.h>
 #include <linux/highuid.h>
 #include <linux/sunrpc/svc.h>
@@ -796,6 +797,260 @@
  out:
 	return retval;
 }
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
+#define COMPAT_ROUND_UP(x) (((x)+sizeof(compat_long_t)-1) & \
+				~(sizeof(compat_long_t)-1))
+
+struct compat_old_linux_dirent {
+	compat_ulong_t	d_ino;
+	compat_ulong_t	d_offset;
+	unsigned short	d_namlen;
+	char		d_name[1];
+};
+
+struct compat_readdir_callback {
+	struct compat_old_linux_dirent __user *dirent;
+	int result;
+};
+
+static int compat_fillonedir(void *__buf, const char *name, int namlen,
+			loff_t offset, ino_t ino, unsigned int d_type)
+{
+	struct compat_readdir_callback *buf = __buf;
+	struct compat_old_linux_dirent __user *dirent;
+
+	if (buf->result)
+		return -EINVAL;
+	buf->result++;
+	dirent = buf->dirent;
+	if (!access_ok(VERIFY_WRITE, (unsigned long)dirent,
+			(unsigned long)(dirent->d_name + namlen + 1) -
+				(unsigned long)dirent))
+		goto efault;
+	if (	__put_user(ino, &dirent->d_ino) ||
+		__put_user(offset, &dirent->d_offset) ||
+		__put_user(namlen, &dirent->d_namlen) ||
+		__copy_to_user(dirent->d_name, name, namlen) ||
+		__put_user(0, dirent->d_name + namlen))
+		goto efault;
+	return 0;
+efault:
+	buf->result = -EFAULT;
+	return -EFAULT;
+}
+
+asmlinkage long compat_old_readdir(unsigned int fd,
+	struct compat_old_linux_dirent __user *dirent, unsigned int count)
+{
+	int error;
+	struct file *file;
+	struct compat_readdir_callback buf;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.result = 0;
+	buf.dirent = dirent;
+
+	error = vfs_readdir(file, compat_fillonedir, &buf);
+	if (error >= 0)
+		error = buf.result;
+
+	fput(file);
+out:
+	return error;
+}
+
+struct compat_linux_dirent {
+	compat_ulong_t	d_ino;
+	compat_ulong_t	d_off;
+	unsigned short	d_reclen;
+	char		d_name[1];
+};
+
+struct compat_getdents_callback {
+	struct compat_linux_dirent __user *current_dir;
+	struct compat_linux_dirent __user *previous;
+	int count;
+	int error;
+};
+
+static int compat_filldir(void *__buf, const char *name, int namlen,
+		loff_t offset, ino_t ino, unsigned int d_type)
+{
+	struct compat_linux_dirent __user * dirent;
+	struct compat_getdents_callback *buf = __buf;
+	int reclen = COMPAT_ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent) {
+		if (__put_user(offset, &dirent->d_off))
+			goto efault;
+	}
+	dirent = buf->current_dir;
+	if (__put_user(ino, &dirent->d_ino))
+		goto efault;
+	if (__put_user(reclen, &dirent->d_reclen))
+		goto efault;
+	if (copy_to_user(dirent->d_name, name, namlen))
+		goto efault;
+	if (__put_user(0, dirent->d_name + namlen))
+		goto efault;
+	if (__put_user(d_type, (char  __user *) dirent + reclen - 1))
+		goto efault;
+	buf->previous = dirent;
+	dirent = (void __user *)dirent + reclen;
+	buf->current_dir = dirent;
+	buf->count -= reclen;
+	return 0;
+efault:
+	buf->error = -EFAULT;
+	return -EFAULT;
+}
+
+asmlinkage long compat_sys_getdents(unsigned int fd,
+		struct compat_linux_dirent __user *dirent, unsigned int count)
+{
+	struct file * file;
+	struct compat_linux_dirent __user * lastdirent;
+	struct compat_getdents_callback buf;
+	int error;
+
+	error = -EFAULT;
+	if (!access_ok(VERIFY_WRITE, dirent, count))
+		goto out;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.current_dir = dirent;
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+
+	error = vfs_readdir(file, compat_filldir, &buf);
+	if (error < 0)
+		goto out_putf;
+	error = buf.error;
+	lastdirent = buf.previous;
+	if (lastdirent) {
+		if (put_user(file->f_pos, &lastdirent->d_off))
+			error = -EFAULT;
+		else
+			error = count - buf.count;
+	}
+
+out_putf:
+	fput(file);
+out:
+	return error;
+}
+
+#ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64
+#define COMPAT_ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
+
+struct compat_getdents_callback64 {
+	struct linux_dirent64 __user *current_dir;
+	struct linux_dirent64 __user *previous;
+	int count;
+	int error;
+};
+
+static int compat_filldir64(void * __buf, const char * name, int namlen, loff_t offset,
+		     ino_t ino, unsigned int d_type)
+{
+	struct linux_dirent64 __user *dirent;
+	struct compat_getdents_callback64 *buf = __buf;
+	int jj = NAME_OFFSET(dirent);
+	int reclen = COMPAT_ROUND_UP64(jj + namlen + 1);
+	u64 off;
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+
+	if (dirent) {
+		if (__put_user(offset, (u32 __user *)&dirent->d_off))
+			goto efault;
+		if (__put_user(offset >> 32,
+				((u32 __user *)&dirent->d_off) + 1))
+			goto efault;
+	}
+	dirent = buf->current_dir;
+	if ((__put_user(ino, (u32 __user *)&dirent->d_ino))
+	 || (__put_user(ino >> 32, ((u32 __user *)&dirent->d_ino) + 1)))
+		goto efault;
+	off = 0;
+	if ((__put_user(off, (u32 __user *)&dirent->d_off))
+	 || (__put_user(off >> 32, ((u32 __user *)&dirent->d_off) + 1)))
+		goto efault;
+	if (__put_user(reclen, &dirent->d_reclen))
+		goto efault;
+	if (__put_user(d_type, &dirent->d_type))
+		goto efault;
+	if (copy_to_user(dirent->d_name, name, namlen))
+		goto efault;
+	if (__put_user(0, dirent->d_name + namlen))
+		goto efault;
+	buf->previous = dirent;
+	dirent = (void __user *)dirent + reclen;
+	buf->current_dir = dirent;
+	buf->count -= reclen;
+	return 0;
+efault:
+	buf->error = -EFAULT;
+	return -EFAULT;
+}
+
+asmlinkage long compat_sys_getdents64(unsigned int fd,
+		struct linux_dirent64 __user * dirent, unsigned int count)
+{
+	struct file * file;
+	struct linux_dirent64 __user * lastdirent;
+	struct compat_getdents_callback64 buf;
+	int error;
+
+	error = -EFAULT;
+	if (!access_ok(VERIFY_WRITE, dirent, count))
+		goto out;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.current_dir = dirent;
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+
+	error = vfs_readdir(file, compat_filldir64, &buf);
+	if (error < 0)
+		goto out_putf;
+	error = buf.error;
+	lastdirent = buf.previous;
+	if (lastdirent) {
+		typeof(lastdirent->d_off) d_off = file->f_pos;
+		__put_user(d_off, (u32 __user *)&lastdirent->d_off);
+		__put_user(d_off >> 32, ((u32 __user *)&lastdirent->d_off) + 1);
+		error = count - buf.count;
+	}
+
+out_putf:
+	fput(file);
+out:
+	return error;
+}
+#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
 
 static ssize_t compat_do_readv_writev(int type, struct file *file,
 			       const struct compat_iovec __user *uvector,
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	2004-06-23 19:04:25 -07:00
+++ b/fs/dcache.c	2004-06-23 19:04:25 -07:00
@@ -30,6 +30,7 @@
 #include <linux/security.h>
 #include <linux/seqlock.h>
 #include <linux/swap.h>
+#include <linux/bootmem.h>
 
 #define DCACHE_PARANOIA 1
 /* #define DCACHE_DEBUG 1 */
@@ -1561,13 +1562,25 @@
 }
 __setup("dhash_entries=", set_dhash_entries);
 
-static void __init dcache_init(unsigned long mempages)
+static void __init dcache_init_early(void)
 {
-	struct hlist_head *d;
-	unsigned long order;
-	unsigned int nr_hash;
-	int i;
+	int loop;
+
+	dentry_hashtable =
+		alloc_large_system_hash("Dentry cache",
+					sizeof(struct hlist_head),
+					dhash_entries,
+					13,
+					0,
+					&d_hash_shift,
+					&d_hash_mask);
 
+	for (loop = 0; loop < (1 << d_hash_shift); loop++)
+		INIT_HLIST_HEAD(&dentry_hashtable[loop]);
+}
+
+static void __init dcache_init(unsigned long mempages)
+{
 	/* 
 	 * A constructor could be added for stable state like the lists,
 	 * but it is probably not worth it because of the cache nature
@@ -1580,45 +1593,6 @@
 					 NULL, NULL);
 	
 	set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
-
-	if (!dhash_entries)
-		dhash_entries = PAGE_SHIFT < 13 ?
-				mempages >> (13 - PAGE_SHIFT) :
-				mempages << (PAGE_SHIFT - 13);
-
-	dhash_entries *= sizeof(struct hlist_head);
-	for (order = 0; ((1UL << order) << PAGE_SHIFT) < dhash_entries; order++)
-		;
-
-	do {
-		unsigned long tmp;
-
-		nr_hash = (1UL << order) * PAGE_SIZE /
-			sizeof(struct hlist_head);
-		d_hash_mask = (nr_hash - 1);
-
-		tmp = nr_hash;
-		d_hash_shift = 0;
-		while ((tmp >>= 1UL) != 0UL)
-			d_hash_shift++;
-
-		dentry_hashtable = (struct hlist_head *)
-			__get_free_pages(GFP_ATOMIC, order);
-	} while (dentry_hashtable == NULL && --order >= 0);
-
-	printk(KERN_INFO "Dentry cache hash table entries: %d (order: %ld, %ld bytes)\n",
-			nr_hash, order, (PAGE_SIZE << order));
-
-	if (!dentry_hashtable)
-		panic("Failed to allocate dcache hash table\n");
-
-	d = dentry_hashtable;
-	i = nr_hash;
-	do {
-		INIT_HLIST_HEAD(d);
-		d++;
-		i--;
-	} while (i);
 }
 
 /* SLAB cache for __getname() consumers */
@@ -1631,6 +1605,12 @@
 
 extern void bdev_cache_init(void);
 extern void chrdev_init(void);
+
+void __init vfs_caches_init_early(void)
+{
+	dcache_init_early();
+	inode_init_early();
+}
 
 void __init vfs_caches_init(unsigned long mempages)
 {
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	2004-06-23 19:04:25 -07:00
+++ b/fs/devfs/base.c	2004-06-23 19:04:25 -07:00
@@ -2490,7 +2490,8 @@
 	return 0;
 }				/*  End Function devfs_mknod  */
 
-static int devfs_readlink(struct dentry *dentry, char *buffer, int buflen)
+static int devfs_readlink(struct dentry *dentry, char __user *buffer,
+			  int buflen)
 {
 	int err;
 	struct devfs_entry *de;
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c	2004-06-23 19:04:27 -07:00
+++ b/fs/direct-io.c	2004-06-23 19:04:27 -07:00
@@ -990,6 +990,13 @@
 		}
 	} /* end iovec loop */
 
+	if (ret == -ENOTBLK && rw == WRITE) {
+		/*
+		 * The remaining part of the request will be
+		 * be handled by buffered I/O when we return
+		 */
+		ret = 0;
+	}
 	/*
 	 * There may be some unwritten disk at the end of a part-written
 	 * fs-block-sized block.  Go zero that now.
@@ -1088,13 +1095,6 @@
 			 */
 			aio_complete(iocb, ret, 0);
 		kfree(dio);
-	}
-	if (ret == -ENOTBLK && rw == WRITE) {
-		/*
-		 * The entire request will be be handled by buffered I/O
-		 * when we return
-		 */
-		ret = 0;
 	}
 	return ret;
 }
diff -Nru a/fs/eventpoll.c b/fs/eventpoll.c
--- a/fs/eventpoll.c	2004-06-23 19:04:26 -07:00
+++ b/fs/eventpoll.c	2004-06-23 19:04:26 -07:00
@@ -29,6 +29,7 @@
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
 #include <linux/rwsem.h>
+#include <linux/rbtree.h>
 #include <linux/wait.h>
 #include <linux/eventpoll.h>
 #include <linux/mount.h>
@@ -100,22 +101,6 @@
 /* Maximum number of poll wake up nests we are allowing */
 #define EP_MAX_POLLWAKE_NESTS 4
 
-/* Maximum size of the hash in bits ( 2^N ) */
-#define EP_MAX_HASH_BITS 17
-
-/* Minimum size of the hash in bits ( 2^N ) */
-#define EP_MIN_HASH_BITS 9
-
-/* Number of hash entries ( "struct list_head" ) inside a page */
-#define EP_HENTRY_X_PAGE (PAGE_SIZE / sizeof(struct list_head))
-
-/* Maximum size of the hash in pages */
-#define EP_MAX_HPAGES ((1 << EP_MAX_HASH_BITS) / EP_HENTRY_X_PAGE + 1)
-
-/* Number of pages allocated for an "hbits" sized hash table */
-#define EP_HASH_PAGES(hbits) ((int) ((1 << (hbits)) / EP_HENTRY_X_PAGE + \
-				     ((1 << (hbits)) % EP_HENTRY_X_PAGE ? 1: 0)))
-
 /* Macro to allocate a "struct epitem" from the slab cache */
 #define EPI_MEM_ALLOC()	(struct epitem *) kmem_cache_alloc(epi_cache, SLAB_KERNEL)
 
@@ -131,6 +116,22 @@
 /* Fast test to see if the file is an evenpoll file */
 #define IS_FILE_EPOLL(f) ((f)->f_op == &eventpoll_fops)
 
+/* Setup the structure that is used as key for the rb-tree */
+#define EP_SET_FFD(p, f, d) do { (p)->file = (f); (p)->fd = (d); } while (0)
+
+/* Compare rb-tree keys */
+#define EP_CMP_FFD(p1, p2) ((p1)->file > (p2)->file ? +1: \
+			    ((p1)->file < (p2)->file ? -1: (p1)->fd - (p2)->fd))
+
+/* Special initialization for the rb-tree node to detect linkage */
+#define EP_RB_INITNODE(n) (n)->rb_parent = (n)
+
+/* Removes a node from the rb-tree and marks it for a fast is-linked check */
+#define EP_RB_ERASE(n, r) do { rb_erase(n, r); (n)->rb_parent = (n); } while (0)
+
+/* Fast check to verify that the item is linked to the main rb-tree */
+#define EP_RB_LINKED(n) ((n)->rb_parent != (n))
+
 /*
  * Remove the item from the list and perform its initialization.
  * This is useful for us because we can test if the item is linked
@@ -147,6 +148,12 @@
 /* Get the "struct epitem" from an epoll queue wrapper */
 #define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->epi)
 
+
+struct epoll_filefd {
+	struct file *file;
+	int fd;
+};
+
 /*
  * Node that is linked into the "wake_task_list" member of the "struct poll_safewake".
  * It is used to keep track on all tasks that are currently inside the wake_up() code
@@ -195,11 +202,8 @@
 	/* List of ready file descriptors */
 	struct list_head rdllist;
 
-	/* Size of the hash */
-	unsigned int hashbits;
-
-	/* Pages for the "struct epitem" hash */
-	char *hpages[EP_MAX_HPAGES];
+	/* RB-Tree root used to store monitored fd structs */
+	struct rb_root rbr;
 };
 
 /* Wait structure used by the poll hooks */
@@ -225,14 +229,14 @@
  * have an entry of this type linked to the hash.
  */
 struct epitem {
-	/* List header used to link this structure to the eventpoll hash */
-	struct list_head llink;
+	/* RB-Tree node used to link this structure to the eventpoll rb-tree */
+	struct rb_node rbn;
 
 	/* List header used to link this structure to the eventpoll ready list */
 	struct list_head rdllink;
 
-	/* The file descriptor this item refers to */
-	int fd;
+	/* The file descriptor information this item refers to */
+	struct epoll_filefd ffd;
 
 	/* Number of active wait queue attached to poll operations */
 	int nwait;
@@ -243,9 +247,6 @@
 	/* The "container" of this item */
 	struct eventpoll *ep;
 
-	/* The file this item refers to */
-	struct file *file;
-
 	/* The structure that describe the interested events and the source fd */
 	struct epoll_event event;
 
@@ -278,22 +279,15 @@
 
 static void ep_poll_safewake_init(struct poll_safewake *psw);
 static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
-static unsigned int ep_get_hash_bits(unsigned int hintsize);
 static int ep_getfd(int *efd, struct inode **einode, struct file **efile);
-static int ep_alloc_pages(char **pages, int numpages);
-static int ep_free_pages(char **pages, int numpages);
-static int ep_file_init(struct file *file, unsigned int hashbits);
-static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file,
-				  int fd);
-static struct list_head *ep_hash_entry(struct eventpoll *ep,
-				       unsigned int index);
-static int ep_init(struct eventpoll *ep, unsigned int hashbits);
+static int ep_file_init(struct file *file);
 static void ep_free(struct eventpoll *ep);
 static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
 static void ep_use_epitem(struct epitem *epi);
 static void ep_release_epitem(struct epitem *epi);
 static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
 				 poll_table *pt);
+static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi);
 static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 		     struct file *tfile, int fd);
 static int ep_modify(struct eventpoll *ep, struct epitem *epi,
@@ -424,19 +418,6 @@
 }
 
 
-/*
- * Calculate the size of the hash in bits. The returned size will be
- * bounded between EP_MIN_HASH_BITS and EP_MAX_HASH_BITS.
- */
-static unsigned int ep_get_hash_bits(unsigned int hintsize)
-{
-	unsigned int i, val;
-
-	for (i = 0, val = 1; val < hintsize && i < EP_MAX_HASH_BITS; i++, val <<= 1);
-	return i <  EP_MIN_HASH_BITS ?	EP_MIN_HASH_BITS: i;
-}
-
-
 /* Used to initialize the epoll bits inside the "struct file" */
 void eventpoll_init_file(struct file *file)
 {
@@ -492,7 +473,6 @@
 asmlinkage long sys_epoll_create(int size)
 {
 	int error, fd;
-	unsigned int hashbits;
 	struct inode *inode;
 	struct file *file;
 
@@ -504,9 +484,6 @@
 	if (size <= 0)
 		goto eexit_1;
 
-	/* Correctly size the hash */
-	hashbits = ep_get_hash_bits((unsigned int) size);
-
 	/*
 	 * Creates all the items needed to setup an eventpoll file. That is,
 	 * a file structure, and inode and a free file descriptor.
@@ -516,7 +493,7 @@
 		goto eexit_1;
 
 	/* Setup the file internal data structure ( "struct eventpoll" ) */
-	error = ep_file_init(file, hashbits);
+	error = ep_file_init(file);
 	if (error)
 		goto eexit_2;
 
@@ -768,114 +745,32 @@
 }
 
 
-static int ep_alloc_pages(char **pages, int numpages)
+static int ep_file_init(struct file *file)
 {
-	int i;
-
-	for (i = 0; i < numpages; i++) {
-		pages[i] = (char *) __get_free_pages(GFP_KERNEL, 0);
-		if (!pages[i]) {
-			for (--i; i >= 0; i--) {
-				ClearPageReserved(virt_to_page(pages[i]));
-				free_pages((unsigned long) pages[i], 0);
-			}
-			return -ENOMEM;
-		}
-		SetPageReserved(virt_to_page(pages[i]));
-	}
-	return 0;
-}
-
-
-static int ep_free_pages(char **pages, int numpages)
-{
-	int i;
-
-	for (i = 0; i < numpages; i++) {
-		ClearPageReserved(virt_to_page(pages[i]));
-		free_pages((unsigned long) pages[i], 0);
-	}
-	return 0;
-}
-
-
-static int ep_file_init(struct file *file, unsigned int hashbits)
-{
-	int error;
 	struct eventpoll *ep;
 
 	if (!(ep = kmalloc(sizeof(struct eventpoll), GFP_KERNEL)))
 		return -ENOMEM;
 
 	memset(ep, 0, sizeof(*ep));
-
-	error = ep_init(ep, hashbits);
-	if (error) {
-		kfree(ep);
-		return error;
-	}
-
-	file->private_data = ep;
-
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_file_init() ep=%p\n",
-		     current, ep));
-	return 0;
-}
-
-
-/*
- * Calculate the index of the hash relative to "file".
- */
-static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file, int fd)
-{
-	unsigned long ptr = (unsigned long) file ^ (fd << ep->hashbits);
-
-	return (unsigned int) hash_ptr((void *) ptr, ep->hashbits);
-}
-
-
-/*
- * Returns the hash entry ( struct list_head * ) of the passed index.
- */
-static struct list_head *ep_hash_entry(struct eventpoll *ep, unsigned int index)
-{
-
-	return (struct list_head *) (ep->hpages[index / EP_HENTRY_X_PAGE] +
-				     (index % EP_HENTRY_X_PAGE) * sizeof(struct list_head));
-}
-
-
-static int ep_init(struct eventpoll *ep, unsigned int hashbits)
-{
-	int error;
-	unsigned int i, hsize;
-
 	rwlock_init(&ep->lock);
 	init_rwsem(&ep->sem);
 	init_waitqueue_head(&ep->wq);
 	init_waitqueue_head(&ep->poll_wait);
 	INIT_LIST_HEAD(&ep->rdllist);
+	ep->rbr = RB_ROOT;
 
-	/* Hash allocation and setup */
-	ep->hashbits = hashbits;
-	error = ep_alloc_pages(ep->hpages, EP_HASH_PAGES(ep->hashbits));
-	if (error)
-		goto eexit_1;
-
-	/* Initialize hash buckets */
-	for (i = 0, hsize = 1 << hashbits; i < hsize; i++)
-		INIT_LIST_HEAD(ep_hash_entry(ep, i));
+	file->private_data = ep;
 
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_file_init() ep=%p\n",
+		     current, ep));
 	return 0;
-eexit_1:
-	return error;
 }
 
 
 static void ep_free(struct eventpoll *ep)
 {
-	unsigned int i, hsize;
-	struct list_head *lsthead, *lnk;
+	struct rb_node *rbp;
 	struct epitem *epi;
 
 	/* We need to release all tasks waiting for these file */
@@ -893,16 +788,12 @@
 	down(&epsem);
 
 	/*
-	 * Walks through the whole hash by unregistering poll callbacks.
+	 * Walks through the whole tree by unregistering poll callbacks.
 	 */
-	for (i = 0, hsize = 1 << ep->hashbits; i < hsize; i++) {
-		lsthead = ep_hash_entry(ep, i);
+	for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
+		epi = rb_entry(rbp, struct epitem, rbn);
 
-		list_for_each(lnk, lsthead) {
-			epi = list_entry(lnk, struct epitem, llink);
-
-			ep_unregister_pollwait(ep, epi);
-		}
+		ep_unregister_pollwait(ep, epi);
 	}
 
 	/*
@@ -911,20 +802,12 @@
 	 * write-holding "sem" we can be sure that no file cleanup code will hit
 	 * us during this operation. So we can avoid the lock on "ep->lock".
 	 */
-	for (i = 0, hsize = 1 << ep->hashbits; i < hsize; i++) {
-		lsthead = ep_hash_entry(ep, i);
-
-		while (!list_empty(lsthead)) {
-			epi = list_entry(lsthead->next, struct epitem, llink);
-
-			ep_remove(ep, epi);
-		}
+	while ((rbp = rb_first(&ep->rbr))) {
+		epi = rb_entry(rbp, struct epitem, rbn);
+		ep_remove(ep, epi);
 	}
 
 	up(&epsem);
-
-	/* Free hash pages */
-	ep_free_pages(ep->hpages, EP_HASH_PAGES(ep->hashbits));
 }
 
 
@@ -935,29 +818,33 @@
  */
 static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd)
 {
+	int kcmp;
 	unsigned long flags;
-	struct list_head *lsthead, *lnk;
-	struct epitem *epi = NULL;
+	struct rb_node *rbp;
+	struct epitem *epi, *epir = NULL;
+	struct epoll_filefd ffd;
 
+	EP_SET_FFD(&ffd, file, fd);
 	read_lock_irqsave(&ep->lock, flags);
-
-	lsthead = ep_hash_entry(ep, ep_hash_index(ep, file, fd));
-	list_for_each(lnk, lsthead) {
-		epi = list_entry(lnk, struct epitem, llink);
-
-		if (epi->file == file && epi->fd == fd) {
+	for (rbp = ep->rbr.rb_node; rbp; ) {
+		epi = rb_entry(rbp, struct epitem, rbn);
+		kcmp = EP_CMP_FFD(&ffd, &epi->ffd);
+		if (kcmp > 0)
+			rbp = rbp->rb_right;
+		else if (kcmp < 0)
+			rbp = rbp->rb_left;
+		else {
 			ep_use_epitem(epi);
+			epir = epi;
 			break;
 		}
-		epi = NULL;
 	}
-
 	read_unlock_irqrestore(&ep->lock, flags);
 
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_find(%p) -> %p\n",
-		     current, file, epi));
+		     current, file, epir));
 
-	return epi;
+	return epir;
 }
 
 
@@ -1009,6 +896,26 @@
 }
 
 
+static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
+{
+	int kcmp;
+	struct rb_node **p = &ep->rbr.rb_node, *parent = NULL;
+	struct epitem *epic;
+
+	while (*p) {
+		parent = *p;
+		epic = rb_entry(parent, struct epitem, rbn);
+		kcmp = EP_CMP_FFD(&epi->ffd, &epic->ffd);
+		if (kcmp > 0)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
+	}
+	rb_link_node(&epi->rbn, parent, p);
+	rb_insert_color(&epi->rbn, &ep->rbr);
+}
+
+
 static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 		     struct file *tfile, int fd)
 {
@@ -1022,14 +929,13 @@
 		goto eexit_1;
 
 	/* Item initialization follow here ... */
-	INIT_LIST_HEAD(&epi->llink);
+	EP_RB_INITNODE(&epi->rbn);
 	INIT_LIST_HEAD(&epi->rdllink);
 	INIT_LIST_HEAD(&epi->fllink);
 	INIT_LIST_HEAD(&epi->txlink);
 	INIT_LIST_HEAD(&epi->pwqlist);
 	epi->ep = ep;
-	epi->file = tfile;
-	epi->fd = fd;
+	EP_SET_FFD(&epi->ffd, tfile, fd);
 	epi->event = *event;
 	atomic_set(&epi->usecnt, 1);
 	epi->nwait = 0;
@@ -1061,8 +967,8 @@
 	/* We have to drop the new item inside our item list to keep track of it */
 	write_lock_irqsave(&ep->lock, flags);
 
-	/* Add the current item to the hash table */
-	list_add(&epi->llink, ep_hash_entry(ep, ep_hash_index(ep, tfile, fd)));
+	/* Add the current item to the rb-tree */
+	ep_rbtree_insert(ep, epi);
 
 	/* If the file is already "ready" we drop it inside the ready list */
 	if ((revents & event->events) && !EP_IS_LINKED(&epi->rdllink)) {
@@ -1126,7 +1032,7 @@
 	 * Get current event bits. We can safely use the file* here because
 	 * its usage count has been increased by the caller of this function.
 	 */
-	revents = epi->file->f_op->poll(epi->file, NULL);
+	revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL);
 
 	write_lock_irqsave(&ep->lock, flags);
 
@@ -1137,7 +1043,7 @@
 	 * If the item is not linked to the hash it means that it's on its
 	 * way toward the removal. Do nothing in this case.
 	 */
-	if (EP_IS_LINKED(&epi->llink)) {
+	if (EP_RB_LINKED(&epi->rbn)) {
 		/*
 		 * If the item is "hot" and it is not registered inside the ready
 		 * list, push it inside. If the item is not "hot" and it is currently
@@ -1205,7 +1111,7 @@
 	 * The check protect us from doing a double unlink ( crash ).
 	 */
 	error = -ENOENT;
-	if (!EP_IS_LINKED(&epi->llink))
+	if (!EP_RB_LINKED(&epi->rbn))
 		goto eexit_1;
 
 	/*
@@ -1216,11 +1122,11 @@
 	epi->event.events = 0;
 
 	/*
-	 * At this point is safe to do the job, unlink the item from our list.
+	 * At this point is safe to do the job, unlink the item from our rb-tree.
 	 * This operation togheter with the above check closes the door to
 	 * double unlinks.
 	 */
-	EP_LIST_DEL(&epi->llink);
+	EP_RB_ERASE(&epi->rbn, &ep->rbr);
 
 	/*
 	 * If the item we are going to remove is inside the ready file descriptors
@@ -1247,7 +1153,7 @@
 {
 	int error;
 	unsigned long flags;
-	struct file *file = epi->file;
+	struct file *file = epi->ffd.file;
 
 	/*
 	 * Removes poll wait queue hooks. We _have_ to do this without holding
@@ -1446,7 +1352,7 @@
 		 * because we are holding the "sem" in read and this will
 		 * guarantee that both the file and the item will not vanish.
 		 */
-		revents = epi->file->f_op->poll(epi->file, NULL);
+		revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL);
 
 		/*
 		 * Set the return event set for the current file descriptor.
@@ -1497,7 +1403,7 @@
 		 * item is set to have an Edge Triggered behaviour, we don't have
 		 * to push it back either.
 		 */
-		if (EP_IS_LINKED(&epi->llink) && !(epi->event.events & EPOLLET) &&
+		if (EP_RB_LINKED(&epi->rbn) && !(epi->event.events & EPOLLET) &&
 		    (epi->revents & epi->event.events) && !EP_IS_LINKED(&epi->rdllink)) {
 			list_add_tail(&epi->rdllink, &ep->rdllist);
 			ricnt++;
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	2004-06-23 19:04:26 -07:00
+++ b/fs/exec.c	2004-06-23 19:04:26 -07:00
@@ -48,7 +48,6 @@
 #include <linux/rmap.h>
 
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 
 #ifdef CONFIG_KMOD
@@ -839,7 +838,8 @@
 	flush_thread();
 
 	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
-	    permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL))
+	    permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) ||
+	    (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP))
 		current->mm->dumpable = 0;
 
 	/* An exec changes our domain. We are no longer part of the thread
@@ -1088,6 +1088,7 @@
 	bprm.file = file;
 	bprm.filename = filename;
 	bprm.interp = filename;
+	bprm.interp_flags = 0;
 	bprm.sh_bang = 0;
 	bprm.loader = 0;
 	bprm.exec = 0;
diff -Nru a/fs/ext3/acl.c b/fs/ext3/acl.c
--- a/fs/ext3/acl.c	2004-06-23 19:04:26 -07:00
+++ b/fs/ext3/acl.c	2004-06-23 19:04:26 -07:00
@@ -428,7 +428,9 @@
 	error = posix_acl_chmod_masq(clone, inode->i_mode);
 	if (!error) {
 		handle_t *handle;
+		int retries = 0;
 
+	retry:
 		handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
 		if (IS_ERR(handle)) {
 			error = PTR_ERR(handle);
@@ -437,6 +439,9 @@
 		}
 		error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
 		ext3_journal_stop(handle);
+		if (error == -ENOSPC &&
+		    ext3_should_retry_alloc(inode->i_sb, &retries))
+			goto retry;
 	}
 out:
 	posix_acl_release(clone);
@@ -516,7 +521,7 @@
 {
 	handle_t *handle;
 	struct posix_acl *acl;
-	int error;
+	int error, retries = 0;
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
@@ -535,11 +540,14 @@
 	} else
 		acl = NULL;
 
+retry:
 	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 	error = ext3_set_acl(handle, inode, type, acl);
 	ext3_journal_stop(handle);
+	if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
+		goto retry;
 
 release_and_out:
 	posix_acl_release(acl);
diff -Nru a/fs/ext3/balloc.c b/fs/ext3/balloc.c
--- a/fs/ext3/balloc.c	2004-06-23 19:04:25 -07:00
+++ b/fs/ext3/balloc.c	2004-06-23 19:04:25 -07:00
@@ -465,6 +465,36 @@
 	return -1;
 }
 
+static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
+{
+	int free_blocks, root_blocks;
+
+	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
+	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
+	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
+		sbi->s_resuid != current->fsuid &&
+		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+		return 0;
+	}
+	return 1;
+}
+
+/*
+ * ext3_should_retry_alloc() is called when ENOSPC is returned, and if
+ * it is profitable to retry the operation, this function will wait
+ * for the current or commiting transaction to complete, and then
+ * return TRUE.
+ */
+int ext3_should_retry_alloc(struct super_block *sb, int *retries)
+{
+	if (!ext3_has_free_blocks(EXT3_SB(sb)) || (*retries)++ > 3)
+		return 0;
+
+	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
+
+	return journal_force_commit_nested(EXT3_SB(sb)->s_journal);
+}
+
 /*
  * ext3_new_block uses a goal block to assist allocation.  If the goal is
  * free, or there is a free block within 32 blocks of the goal, that block
@@ -485,7 +515,7 @@
 	int target_block;			/* tmp */
 	int fatal = 0, err;
 	int performed_allocation = 0;
-	int free_blocks, root_blocks;
+	int free_blocks;
 	struct super_block *sb;
 	struct ext3_group_desc *gdp;
 	struct ext3_super_block *es;
@@ -512,11 +542,7 @@
 	es = EXT3_SB(sb)->s_es;
 	ext3_debug("goal=%lu.\n", goal);
 
-	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
-	root_blocks = le32_to_cpu(es->s_r_blocks_count);
-	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-		sbi->s_resuid != current->fsuid &&
-		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+	if (!ext3_has_free_blocks(sbi)) {
 		*errp = -ENOSPC;
 		goto out;
 	}
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	2004-06-23 19:04:27 -07:00
+++ b/fs/ext3/inode.c	2004-06-23 19:04:27 -07:00
@@ -1080,7 +1080,7 @@
 	struct inode *inode = page->mapping->host;
 	int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
 	handle_t *handle;
-	int tried_commit = 0;
+	int retries = 0;
 
 retry:
 	handle = ext3_journal_start(inode, needed_blocks);
@@ -1089,19 +1089,8 @@
 		goto out;
 	}
 	ret = block_prepare_write(page, from, to, ext3_get_block);
-	if (ret) {
-		if (ret != -ENOSPC || tried_commit)
-			goto prepare_write_failed;
-		/*
-		 * It could be that there _is_ free space, but it's all tied up
-		 * in uncommitted bitmaps.  So force a commit here, which makes
-		 * those blocks allocatable and try again.
-		 */
-		tried_commit = 1;
-		handle->h_sync = 1;
-		ext3_journal_stop(handle);
-		goto retry;
-	}
+	if (ret)
+		goto prepare_write_failed;
 
 	if (ext3_should_journal_data(inode)) {
 		ret = walk_page_buffers(handle, page_buffers(page),
@@ -1110,6 +1099,8 @@
 prepare_write_failed:
 	if (ret)
 		ext3_journal_stop(handle);
+	if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
+		goto retry;
 out:
 	return ret;
 }
diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c
--- a/fs/ext3/namei.c	2004-06-23 19:04:27 -07:00
+++ b/fs/ext3/namei.c	2004-06-23 19:04:27 -07:00
@@ -557,6 +557,8 @@
 		    ((hinfo->hash == start_hash) &&
 		     (hinfo->minor_hash < start_minor_hash)))
 			continue;
+		if (de->inode == 0)
+			continue;
 		if ((err = ext3_htree_store_dirent(dir_file,
 				   hinfo->hash, hinfo->minor_hash, de)) != 0) {
 			brelse(bh);
@@ -1630,8 +1632,9 @@
 {
 	handle_t *handle; 
 	struct inode * inode;
-	int err;
+	int err, retries = 0;
 
+retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
 					2*EXT3_QUOTA_INIT_BLOCKS);
@@ -1650,6 +1653,8 @@
 		err = ext3_add_nondir(handle, dentry, inode);
 	}
 	ext3_journal_stop(handle);
+	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
 	return err;
 }
 
@@ -1658,11 +1663,12 @@
 {
 	handle_t *handle;
 	struct inode *inode;
-	int err;
+	int err, retries = 0;
 
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
 
+retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
 			 		EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
 					2*EXT3_QUOTA_INIT_BLOCKS);
@@ -1682,6 +1688,8 @@
 		err = ext3_add_nondir(handle, dentry, inode);
 	}
 	ext3_journal_stop(handle);
+	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
 	return err;
 }
 
@@ -1691,11 +1699,12 @@
 	struct inode * inode;
 	struct buffer_head * dir_block;
 	struct ext3_dir_entry_2 * de;
-	int err;
+	int err, retries = 0;
 
 	if (dir->i_nlink >= EXT3_LINK_MAX)
 		return -EMLINK;
 
+retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
 					2*EXT3_QUOTA_INIT_BLOCKS);
@@ -1753,6 +1762,8 @@
 	d_instantiate(dentry, inode);
 out_stop:
 	ext3_journal_stop(handle);
+	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
 	return err;
 }
 
@@ -2092,12 +2103,13 @@
 {
 	handle_t *handle;
 	struct inode * inode;
-	int l, err;
+	int l, err, retries = 0;
 
 	l = strlen(symname)+1;
 	if (l > dir->i_sb->s_blocksize)
 		return -ENAMETOOLONG;
 
+retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
 			 		EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
 					2*EXT3_QUOTA_INIT_BLOCKS);
@@ -2136,6 +2148,8 @@
 	err = ext3_add_nondir(handle, dentry, inode);
 out_stop:
 	ext3_journal_stop(handle);
+	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
 	return err;
 }
 
@@ -2144,11 +2158,12 @@
 {
 	handle_t *handle;
 	struct inode *inode = old_dentry->d_inode;
-	int err;
+	int err, retries = 0;
 
 	if (inode->i_nlink >= EXT3_LINK_MAX)
 		return -EMLINK;
 
+retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS);
 	if (IS_ERR(handle))
@@ -2163,6 +2178,8 @@
 
 	err = ext3_add_nondir(handle, dentry, inode);
 	ext3_journal_stop(handle);
+	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+		goto retry;
 	return err;
 }
 
diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
--- a/fs/ext3/xattr.c	2004-06-23 19:04:27 -07:00
+++ b/fs/ext3/xattr.c	2004-06-23 19:04:27 -07:00
@@ -875,8 +875,9 @@
 	       const void *value, size_t value_len, int flags)
 {
 	handle_t *handle;
-	int error;
+	int error, retries = 0;
 
+retry:
 	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
 	if (IS_ERR(handle)) {
 		error = PTR_ERR(handle);
@@ -886,6 +887,9 @@
 		error = ext3_xattr_set_handle(handle, inode, name_index, name,
 					      value, value_len, flags);
 		error2 = ext3_journal_stop(handle);
+		if (error == -ENOSPC &&
+		    ext3_should_retry_alloc(inode->i_sb, &retries))
+			goto retry;
 		if (error == 0)
 			error = error2;
 	}
diff -Nru a/fs/fat/inode.c b/fs/fat/inode.c
--- a/fs/fat/inode.c	2004-06-23 19:04:26 -07:00
+++ b/fs/fat/inode.c	2004-06-23 19:04:26 -07:00
@@ -23,6 +23,14 @@
 #include <linux/parser.h>
 #include <asm/unaligned.h>
 
+#ifndef CONFIG_FAT_DEFAULT_IOCHARSET
+/* if user don't select VFAT, this is undefined. */
+#define CONFIG_FAT_DEFAULT_IOCHARSET	""
+#endif
+
+static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
+static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
+
 /*
  * New FAT inode stuff. We do the following:
  *	a) i_ino is constant and has nothing with on-disk location.
@@ -166,20 +174,17 @@
 	if (sbi->nls_disk) {
 		unload_nls(sbi->nls_disk);
 		sbi->nls_disk = NULL;
-		sbi->options.codepage = 0;
+		sbi->options.codepage = fat_default_codepage;
 	}
 	if (sbi->nls_io) {
 		unload_nls(sbi->nls_io);
 		sbi->nls_io = NULL;
 	}
-	/*
-	 * Note: the iocharset option might have been specified
-	 * without enabling nls_io, so check for it here.
-	 */
-	if (sbi->options.iocharset) {
+	if (sbi->options.iocharset != fat_default_iocharset) {
 		kfree(sbi->options.iocharset);
-		sbi->options.iocharset = NULL;
+		sbi->options.iocharset = fat_default_iocharset;
 	}
+
 	sb->s_fs_info = NULL;
 	kfree(sbi);
 }
@@ -196,11 +201,11 @@
 		seq_printf(m, ",gid=%u", opts->fs_gid);
 	seq_printf(m, ",fmask=%04o", opts->fs_fmask);
 	seq_printf(m, ",dmask=%04o", opts->fs_dmask);
-	if (sbi->nls_disk)
+	if (sbi->nls_disk && opts->codepage != fat_default_codepage)
 		seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);
 	if (isvfat) {
-		if (sbi->nls_io
-		    && strcmp(sbi->nls_io->charset, CONFIG_NLS_DEFAULT))
+		if (sbi->nls_io &&
+		    strcmp(opts->iocharset, fat_default_iocharset))
 			seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);
 
 		switch (opts->shortname) {
@@ -331,14 +336,15 @@
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
 	int option;
+	char *iocharset;
 
 	opts->isvfat = is_vfat;
 
 	opts->fs_uid = current->uid;
 	opts->fs_gid = current->gid;
 	opts->fs_fmask = opts->fs_dmask = current->fs->umask;
-	opts->codepage = 0;
-	opts->iocharset = NULL;
+	opts->codepage = fat_default_codepage;
+	opts->iocharset = fat_default_iocharset;
 	if (is_vfat)
 		opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95;
 	else
@@ -351,7 +357,7 @@
 	*debug = 0;
 
 	if (!options)
-		return 1;
+		return 0;
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
@@ -437,10 +443,12 @@
 
 		/* vfat specific */
 		case Opt_charset:
-			kfree(opts->iocharset);
-			opts->iocharset = match_strdup(&args[0]);
-			if (!opts->iocharset)
-				return 0;
+			if (opts->iocharset != fat_default_iocharset)
+				kfree(opts->iocharset);
+			iocharset = match_strdup(&args[0]);
+			if (!iocharset)
+				return -ENOMEM;
+			opts->iocharset = iocharset;
 			break;
 		case Opt_shortname_lower:
 			opts->shortname = VFAT_SFN_DISPLAY_LOWER
@@ -486,14 +494,20 @@
 		default:
 			printk(KERN_ERR "FAT: Unrecognized mount option \"%s\" "
 			       "or missing value\n", p);
-			return 0;
+			return -EINVAL;
 		}
 	}
+	/* UTF8 doesn't provide FAT semantics */
+	if (!strcmp(opts->iocharset, "utf8")) {
+		printk(KERN_ERR "FAT: utf8 is not a valid IO charset"
+		       " for FAT filesystems\n");
+		return -EINVAL;
+	}
 
 	if (opts->unicode_xlate)
 		opts->utf8 = 0;
 	
-	return 1;
+	return 0;
 }
 
 static int fat_calc_dir_size(struct inode *inode)
@@ -784,7 +798,7 @@
 	struct msdos_sb_info *sbi;
 	u16 logical_sector_size;
 	u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors;
-	int debug, cp, first;
+	int debug, first;
 	unsigned int media;
 	long error;
 	char buf[50];
@@ -801,8 +815,8 @@
 	sb->s_export_op = &fat_export_ops;
 	sbi->dir_ops = fs_dir_inode_ops;
 
-	error = -EINVAL;
-	if (!parse_options(data, isvfat, &debug, &sbi->options))
+	error = parse_options(data, isvfat, &debug, &sbi->options);
+	if (error)
 		goto out_fail;
 
 	fat_cache_init(sb);
@@ -1009,31 +1023,21 @@
 	}
 
 	error = -EINVAL;
-	cp = sbi->options.codepage ? sbi->options.codepage : 437;
-	sprintf(buf, "cp%d", cp);
+	sprintf(buf, "cp%d", sbi->options.codepage);
 	sbi->nls_disk = load_nls(buf);
 	if (!sbi->nls_disk) {
-		/* Fail only if explicit charset specified */
-		if (sbi->options.codepage != 0) {
-			printk(KERN_ERR "FAT: codepage %s not found\n", buf);
-			goto out_fail;
-		}
-		sbi->options.codepage = 0; /* already 0?? */
-		sbi->nls_disk = load_nls_default();
+		printk(KERN_ERR "FAT: codepage %s not found\n", buf);
+		goto out_fail;
 	}
 
 	/* FIXME: utf8 is using iocharset for upper/lower conversion */
 	if (sbi->options.isvfat) {
-		if (sbi->options.iocharset != NULL) {
-			sbi->nls_io = load_nls(sbi->options.iocharset);
-			if (!sbi->nls_io) {
-				printk(KERN_ERR
-				       "FAT: IO charset %s not found\n",
-				       sbi->options.iocharset);
-				goto out_fail;
-			}
-		} else
-			sbi->nls_io = load_nls_default();
+		sbi->nls_io = load_nls(sbi->options.iocharset);
+		if (!sbi->nls_io) {
+			printk(KERN_ERR "FAT: IO charset %s not found\n",
+			       sbi->options.iocharset);
+			goto out_fail;
+		}
 	}
 
 	error = -ENOMEM;
@@ -1068,7 +1072,7 @@
 		unload_nls(sbi->nls_io);
 	if (sbi->nls_disk)
 		unload_nls(sbi->nls_disk);
-	if (sbi->options.iocharset)
+	if (sbi->options.iocharset != fat_default_iocharset)
 		kfree(sbi->options.iocharset);
 	sb->s_fs_info = NULL;
 	kfree(sbi);
diff -Nru a/fs/fcntl.c b/fs/fcntl.c
--- a/fs/fcntl.c	2004-06-23 19:04:27 -07:00
+++ b/fs/fcntl.c	2004-06-23 19:04:27 -07:00
@@ -212,7 +212,7 @@
 	return ret;
 }
 
-#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT)
+#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME)
 
 static int setfl(int fd, struct file * filp, unsigned long arg)
 {
@@ -222,6 +222,11 @@
 	/* O_APPEND cannot be cleared if the file is marked as append-only */
 	if (!(arg & O_APPEND) && IS_APPEND(inode))
 		return -EPERM;
+
+	/* O_NOATIME can only be set by the owner or superuser */
+	if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME))
+		if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+			return -EPERM;
 
 	/* required for strict SunOS emulation */
 	if (O_NONBLOCK != O_NDELAY)
diff -Nru a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c
--- a/fs/hpfs/alloc.c	2004-06-23 19:04:25 -07:00
+++ b/fs/hpfs/alloc.c	2004-06-23 19:04:25 -07:00
@@ -79,11 +79,11 @@
 	} else {
 		if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) goto uls;
 	}
-	/*if (!tstbits(bmp, nr + n, n + forward)) {
+	if (!tstbits(bmp, nr, n + forward)) {
 		ret = bs + nr;
 		goto rt;
 	}
-	if (!tstbits(bmp, nr + 2*n, n + forward)) {
+	/*if (!tstbits(bmp, nr + n, n + forward)) {
 		ret = bs + nr + n;
 		goto rt;
 	}*/
@@ -103,9 +103,11 @@
 		goto rt;
 	}
 	nr >>= 5;
-	for (i = nr + 1; i != nr; i++, i &= 0x1ff) {
-		if (!bmp[i]) continue;
-		if (n + forward >= 0x3f && bmp[i] != -1) continue;
+	/*for (i = nr + 1; i != nr; i++, i &= 0x1ff) {*/
+	i = nr;
+	do {
+		if (!bmp[i]) goto cont;
+		if (n + forward >= 0x3f && bmp[i] != -1) goto cont;
 		q = i<<5;
 		if (i > 0) {
 			unsigned k = bmp[i-1];
@@ -123,7 +125,9 @@
 			ret = bs + q;
 			goto rt;
 		}
-	}
+		cont:
+		i++, i &= 0x1ff;
+	} while (i != nr);
 	rt:
 	if (ret) {
 		if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (bmp[(ret & 0x3fff) >> 5] | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) {
@@ -152,46 +156,57 @@
 secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward, int lock)
 {
 	secno sec;
-	unsigned i;
+	int i;
 	unsigned n_bmps;
 	struct hpfs_sb_info *sbi = hpfs_sb(s);
-	int b = sbi->sb_c_bitmap;
 	int f_p = 0;
+	int near_bmp;
 	if (forward < 0) {
 		forward = -forward;
 		f_p = 1;
 	}
 	if (lock) hpfs_lock_creation(s);
-	if (near && near < sbi->sb_fs_size)
+	n_bmps = (sbi->sb_fs_size + 0x4000 - 1) >> 14;
+	if (near && near < sbi->sb_fs_size) {
 		if ((sec = alloc_in_bmp(s, near, n, f_p ? forward : forward/4))) goto ret;
+		near_bmp = near >> 14;
+	} else near_bmp = n_bmps / 2;
+	/*
 	if (b != -1) {
 		if ((sec = alloc_in_bmp(s, b<<14, n, f_p ? forward : forward/2))) {
 			b &= 0x0fffffff;
 			goto ret;
 		}
 		if (b > 0x10000000) if ((sec = alloc_in_bmp(s, (b&0xfffffff)<<14, n, f_p ? forward : 0))) goto ret;
-	}	
-	n_bmps = (sbi->sb_fs_size + 0x4000 - 1) >> 14;
-	for (i = 0; i < n_bmps / 2; i++) {
-		if ((sec = alloc_in_bmp(s, (n_bmps/2+i) << 14, n, forward))) {
-			sbi->sb_c_bitmap = n_bmps/2+i;
+	*/
+	if (!f_p) if (forward > sbi->sb_max_fwd_alloc) forward = sbi->sb_max_fwd_alloc;
+	less_fwd:
+	for (i = 0; i < n_bmps; i++) {
+		if (near_bmp+i < n_bmps && ((sec = alloc_in_bmp(s, (near_bmp+i) << 14, n, forward)))) {
+			sbi->sb_c_bitmap = near_bmp+i;
 			goto ret;
 		}	
-		if ((sec = alloc_in_bmp(s, (n_bmps/2-i-1) << 14, n, forward))) {
-			sbi->sb_c_bitmap = n_bmps/2-i-1;
+		if (!forward) {
+			if (near_bmp-i-1 >= 0 && ((sec = alloc_in_bmp(s, (near_bmp-i-1) << 14, n, forward)))) {
+				sbi->sb_c_bitmap = near_bmp-i-1;
+				goto ret;
+			}
+		} else {
+			if (near_bmp+i >= n_bmps && ((sec = alloc_in_bmp(s, (near_bmp+i-n_bmps) << 14, n, forward)))) {
+				sbi->sb_c_bitmap = near_bmp+i-n_bmps;
+				goto ret;
+			}
+		}
+		if (i == 1 && sbi->sb_c_bitmap != -1 && ((sec = alloc_in_bmp(s, (sbi->sb_c_bitmap) << 14, n, forward)))) {
 			goto ret;
 		}
 	}
-	if ((sec = alloc_in_bmp(s, (n_bmps-1) << 14, n, forward))) {
-		sbi->sb_c_bitmap = n_bmps-1;
-		goto ret;
-	}
 	if (!f_p) {
-		for (i = 0; i < n_bmps; i++)
-			if ((sec = alloc_in_bmp(s, i << 14, n, 0))) {
-				sbi->sb_c_bitmap = 0x10000000 + i;
-				goto ret;
-			}
+		if (forward) {
+			sbi->sb_max_fwd_alloc = forward * 3 / 4;
+			forward /= 2;
+			goto less_fwd;
+		}
 	}
 	sec = 0;
 	ret:
@@ -262,6 +277,7 @@
 {
 	struct quad_buffer_head qbh;
 	unsigned *bmp;
+	struct hpfs_sb_info *sbi = hpfs_sb(s);
 	/*printk("2 - ");*/
 	if (!n) return;
 	if (sec < 0x12) {
@@ -269,6 +285,8 @@
 		return;
 	}
 	lock_super(s);
+	sbi->sb_max_fwd_alloc += n > 0xffff ? 0xffff : n;
+	if (sbi->sb_max_fwd_alloc > 0xffffff) sbi->sb_max_fwd_alloc = 0xffffff;
 	new_map:
 	if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "free"))) {
 		unlock_super(s);
@@ -321,7 +339,7 @@
 	}
 	hpfs_brelse4(&qbh);
 	i = 0;
-	if (hpfs_sb(s)->sb_c_bitmap != -1 ) {
+	if (hpfs_sb(s)->sb_c_bitmap != -1) {
 		bmp = hpfs_map_bitmap(s, b, &qbh, "chkdn1");
 		goto chk_bmp;
 	}
diff -Nru a/fs/hpfs/anode.c b/fs/hpfs/anode.c
--- a/fs/hpfs/anode.c	2004-06-23 19:04:25 -07:00
+++ b/fs/hpfs/anode.c	2004-06-23 19:04:25 -07:00
@@ -113,7 +113,7 @@
 			brelse(bh);
 			return -1;
 		}
-		se = node;
+		se = !fnod ? node : (node + 16384) & ~16383;
 	}	
 	if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M, 1))) {
 		brelse(bh);
@@ -192,7 +192,6 @@
 		}
 		up = up != node ? anode->up : -1;
 		btree->u.internal[btree->n_used_nodes - 1].file_secno = /*fs*/-1;
-		if (up == -1) anode->up = ra;
 		mark_buffer_dirty(bh);
 		brelse(bh);
 		a = na;
diff -Nru a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c
--- a/fs/hpfs/buffer.c	2004-06-23 19:04:26 -07:00
+++ b/fs/hpfs/buffer.c	2004-06-23 19:04:26 -07:00
@@ -31,6 +31,8 @@
 {
 	struct buffer_head *bh;
 
+	cond_resched();
+
 	*bhp = bh = sb_bread(s, secno);
 	if (bh != NULL)
 		return bh->b_data;
@@ -47,6 +49,8 @@
 	struct buffer_head *bh;
 	/*return hpfs_map_sector(s, secno, bhp, 0);*/
 
+	cond_resched();
+
 	if ((*bhp = bh = sb_getblk(s, secno)) != NULL) {
 		if (!buffer_uptodate(bh)) wait_on_buffer(bh);
 		set_buffer_uptodate(bh);
@@ -65,6 +69,8 @@
 	struct buffer_head *bh;
 	char *data;
 
+	cond_resched();
+
 	if (secno & 3) {
 		printk("HPFS: hpfs_map_4sectors: unaligned read\n");
 		return 0;
@@ -116,6 +122,8 @@
 void *hpfs_get_4sectors(struct super_block *s, unsigned secno,
                           struct quad_buffer_head *qbh)
 {
+	cond_resched();
+
 	if (secno & 3) {
 		printk("HPFS: hpfs_get_4sectors: unaligned read\n");
 		return 0;
diff -Nru a/fs/hpfs/ea.c b/fs/hpfs/ea.c
--- a/fs/hpfs/ea.c	2004-06-23 19:04:25 -07:00
+++ b/fs/hpfs/ea.c	2004-06-23 19:04:25 -07:00
@@ -234,7 +234,7 @@
 		}
 		pos += ea->namelen + ea->valuelen + 5;
 	}
-	if (!fnode->ea_size_s) {
+	if (!fnode->ea_offs) {
 		/*if (fnode->ea_size_s) {
 			hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0",
 				inode->i_ino, fnode->ea_size_s);
@@ -242,15 +242,13 @@
 		}*/
 		fnode->ea_offs = 0xc4;
 	}
-	if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->ea_size_s > 0x200) {
+	if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200) {
 		hpfs_error(s, "fnode %08x: ea_offs == %03x, ea_size_s == %03x",
 			inode->i_ino, fnode->ea_offs, fnode->ea_size_s);
 		return;
 	}
 	if ((fnode->ea_size_s || !fnode->ea_size_l) &&
-	     fnode->ea_offs + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) {
-		/* I'm not sure ... maybe we overwrite ACL here. I have no info
-		   on it right now :-( */
+	     fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) {
 		ea = fnode_end_ea(fnode);
 		*(char *)ea = 0;
 		ea->namelen = strlen(key);
diff -Nru a/fs/hpfs/hpfs.h b/fs/hpfs/hpfs.h
--- a/fs/hpfs/hpfs.h	2004-06-23 19:04:28 -07:00
+++ b/fs/hpfs/hpfs.h	2004-06-23 19:04:28 -07:00
@@ -408,7 +408,7 @@
   unsigned file_size;			/* file length, bytes */
   unsigned n_needea;			/* number of EA's with NEEDEA set */
   char user_id[16];			/* unused */
-  unsigned ea_offs;			/* offset from start of fnode
+  unsigned short ea_offs;		/* offset from start of fnode
 					   to first fnode-resident ea */
   char dasd_limit_treshhold;
   char dasd_limit_delta;
diff -Nru a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
--- a/fs/hpfs/hpfs_fn.h	2004-06-23 19:04:27 -07:00
+++ b/fs/hpfs/hpfs_fn.h	2004-06-23 19:04:27 -07:00
@@ -87,6 +87,7 @@
 					/*	128 bytes lowercasing table */
 	unsigned *sb_bmp_dir;		/* main bitmap directory */
 	unsigned sb_c_bitmap;		/* current bitmap */
+	unsigned sb_max_fwd_alloc;	/* max forwad allocation */
 	struct semaphore hpfs_creation_de; /* when creating dirents, nobody else
 					   can alloc blocks */
 	/*unsigned sb_mounting : 1;*/
@@ -141,12 +142,12 @@
 
 static inline struct extended_attribute *fnode_ea(struct fnode *fnode)
 {
-	return (struct extended_attribute *)((char *)fnode + fnode->ea_offs);
+	return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s);
 }
 
 static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode)
 {
-	return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->ea_size_s);
+	return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s);
 }
 
 static inline struct extended_attribute *next_ea(struct extended_attribute *ea)
diff -Nru a/fs/hpfs/inode.c b/fs/hpfs/inode.c
--- a/fs/hpfs/inode.c	2004-06-23 19:04:26 -07:00
+++ b/fs/hpfs/inode.c	2004-06-23 19:04:26 -07:00
@@ -144,11 +144,11 @@
 void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode)
 {
 	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
-	if (fnode->acl_size_l || fnode->acl_size_s) {
-		/* Some unknown structures like ACL may be in fnode,
-		   we'd better not overwrite them */
+	/*if (fnode->acl_size_l || fnode->acl_size_s) {
+		   Some unknown structures like ACL may be in fnode,
+		   we'd better not overwrite them
 		hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino);
-	} else if (hpfs_sb(i->i_sb)->sb_eas >= 2) {
+	} else*/ if (hpfs_sb(i->i_sb)->sb_eas >= 2) {
 		u32 ea;
 		if ((i->i_uid != hpfs_sb(i->i_sb)->sb_uid) || hpfs_inode->i_ea_uid) {
 			ea = cpu_to_le32(i->i_uid);
@@ -218,16 +218,18 @@
 	struct hpfs_dirent *de;
 	if (i->i_ino == hpfs_sb(i->i_sb)->sb_root) return;
 	if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) return;
-	if (i->i_ino != hpfs_sb(i->i_sb)->sb_root) {
+	if (i->i_ino != hpfs_sb(i->i_sb)->sb_root && i->i_nlink) {
 		if (!(de = map_fnode_dirent(i->i_sb, i->i_ino, fnode, &qbh))) {
 			brelse(bh);
 			return;
 		}
 	} else de = NULL;
 	if (S_ISREG(i->i_mode)) {
-		fnode->file_size = de->file_size = i->i_size;
+		fnode->file_size = i->i_size;
+		if (de) de->file_size = i->i_size;
 	} else if (S_ISDIR(i->i_mode)) {
-		fnode->file_size = de->file_size = 0;
+		fnode->file_size = 0;
+		if (de) de->file_size = 0;
 	}
 	hpfs_write_inode_ea(i, fnode);
 	if (de) {
diff -Nru a/fs/hpfs/map.c b/fs/hpfs/map.c
--- a/fs/hpfs/map.c	2004-06-23 19:04:26 -07:00
+++ b/fs/hpfs/map.c	2004-06-23 19:04:26 -07:00
@@ -142,7 +142,7 @@
 				}
 			}
 			if (fnode->ea_size_s && ((signed int)fnode->ea_offs < 0xc4 ||
-			   (signed int)fnode->ea_offs + fnode->ea_size_s > 0x200)) {
+			   (signed int)fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200)) {
 				hpfs_error(s, "bad EA info in fnode %08x: ea_offs == %04x ea_size_s == %04x",
 					ino, fnode->ea_offs, fnode->ea_size_s);
 				goto bail;
@@ -225,14 +225,16 @@
 			}
 			for (p = 20; p < dnode->first_free; p += d[p] + (d[p+1] << 8)) {
 				struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p);
-				if (de->length > 292 || (de->length < 32) || (de->length & 3)) {
+				if (de->length > 292 || (de->length < 32) || (de->length & 3) || p + de->length > 2048) {
 					hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
 					goto bail;
 				}
 				if (((31 + de->namelen + de->down*4 + 3) & ~3) != de->length) {
+					if (((31 + de->namelen + de->down*4 + 3) & ~3) < de->length && s->s_flags & MS_RDONLY) goto ok;
 					hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
 					goto bail;
 				}
+				ok:
 				if (hpfs_sb(s)->sb_chk >= 2) b |= 1 << de->down;
 				if (de->down) if (de_down_pointer(de) < 0x10) {
 					hpfs_error(s, "bad down pointer in dnode %08x, dirent %03x, last %03x", secno, p, pp);
diff -Nru a/fs/hpfs/super.c b/fs/hpfs/super.c
--- a/fs/hpfs/super.c	2004-06-23 19:04:27 -07:00
+++ b/fs/hpfs/super.c	2004-06-23 19:04:27 -07:00
@@ -542,6 +542,7 @@
 	sbi->sb_was_error = 0;
 	sbi->sb_cp_table = NULL;
 	sbi->sb_c_bitmap = -1;
+	sbi->sb_max_fwd_alloc = 0xffffff;
 	
 	/* Load bitmap directory */
 	if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, superblock->bitmaps)))
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	2004-06-23 19:04:29 -07:00
+++ b/fs/inode.c	2004-06-23 19:04:29 -07:00
@@ -20,6 +20,7 @@
 #include <linux/security.h>
 #include <linux/pagemap.h>
 #include <linux/cdev.h>
+#include <linux/bootmem.h>
 
 /*
  * This is needed for the following functions:
@@ -1345,54 +1346,29 @@
 /*
  * Initialize the waitqueues and inode hash table.
  */
+void __init inode_init_early(void)
+{
+	int loop;
+
+	inode_hashtable =
+		alloc_large_system_hash("Inode-cache",
+					sizeof(struct hlist_head),
+					ihash_entries,
+					14,
+					0,
+					&i_hash_shift,
+					&i_hash_mask);
+
+	for (loop = 0; loop < (1 << i_hash_shift); loop++)
+		INIT_HLIST_HEAD(&inode_hashtable[loop]);
+}
+
 void __init inode_init(unsigned long mempages)
 {
-	struct hlist_head *head;
-	unsigned long order;
-	unsigned int nr_hash;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(i_wait_queue_heads); i++)
 		init_waitqueue_head(&i_wait_queue_heads[i].wqh);
-
-	if (!ihash_entries)
-		ihash_entries = PAGE_SHIFT < 14 ?
-				mempages >> (14 - PAGE_SHIFT) :
-				mempages << (PAGE_SHIFT - 14);
-
-	ihash_entries *= sizeof(struct hlist_head);
-	for (order = 0; ((1UL << order) << PAGE_SHIFT) < ihash_entries; order++)
-		;
-
-	do {
-		unsigned long tmp;
-
-		nr_hash = (1UL << order) * PAGE_SIZE /
-			sizeof(struct hlist_head);
-		i_hash_mask = (nr_hash - 1);
-
-		tmp = nr_hash;
-		i_hash_shift = 0;
-		while ((tmp >>= 1UL) != 0UL)
-			i_hash_shift++;
-
-		inode_hashtable = (struct hlist_head *)
-			__get_free_pages(GFP_ATOMIC, order);
-	} while (inode_hashtable == NULL && --order >= 0);
-
-	printk("Inode-cache hash table entries: %d (order: %ld, %ld bytes)\n",
-			nr_hash, order, (PAGE_SIZE << order));
-
-	if (!inode_hashtable)
-		panic("Failed to allocate inode hash table\n");
-
-	head = inode_hashtable;
-	i = nr_hash;
-	do {
-		INIT_HLIST_HEAD(head);
-		head++;
-		i--;
-	} while (i);
 
 	/* inode slab cache */
 	inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode),
diff -Nru a/fs/ioctl.c b/fs/ioctl.c
--- a/fs/ioctl.c	2004-06-23 19:04:25 -07:00
+++ b/fs/ioctl.c	2004-06-23 19:04:25 -07:00
@@ -4,11 +4,13 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/security.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -133,3 +135,11 @@
 out:
 	return error;
 }
+
+/*
+ * Platforms implementing 32 bit compatibility ioctl handlers in
+ * modules need this exported
+ */
+#ifdef CONFIG_COMPAT
+EXPORT_SYMBOL(sys_ioctl);
+#endif
diff -Nru a/fs/isofs/Makefile b/fs/isofs/Makefile
--- a/fs/isofs/Makefile	2004-06-23 19:04:29 -07:00
+++ b/fs/isofs/Makefile	2004-06-23 19:04:29 -07:00
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_ISO9660_FS) += isofs.o
 
-isofs-objs-y 			:= namei.o inode.o dir.o util.o rock.o
+isofs-objs-y 			:= namei.o inode.o dir.o util.o rock.o export.o
 isofs-objs-$(CONFIG_JOLIET)	+= joliet.o
 isofs-objs-$(CONFIG_ZISOFS)	+= compress.o
 isofs-objs			:= $(isofs-objs-y)
diff -Nru a/fs/isofs/dir.c b/fs/isofs/dir.c
--- a/fs/isofs/dir.c	2004-06-23 19:04:28 -07:00
+++ b/fs/isofs/dir.c	2004-06-23 19:04:28 -07:00
@@ -64,7 +64,8 @@
 			break;
 
 		/* Convert remaining ';' to '.' */
-		if (c == ';')
+		/* Also '/' to '.' (broken Acorn-generated ISO9660 images) */
+		if (c == ';' || c == '/')
 			c = '.';
 
 		new[i] = c;
@@ -106,8 +107,8 @@
 {
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
-	unsigned int block, offset;
-	int inode_number = 0;	/* Quiet GCC */
+	unsigned long block, offset, block_saved, offset_saved;
+	unsigned long inode_number = 0;	/* Quiet GCC */
 	struct buffer_head *bh = NULL;
 	int len;
 	int map;
@@ -129,8 +130,6 @@
 		}
 
 		de = (struct iso_directory_record *) (bh->b_data + offset);
-		if (first_de)
-			inode_number = (bh->b_blocknr << bufbits) + offset;
 
 		de_len = *(unsigned char *) de;
 
@@ -147,6 +146,8 @@
 			continue;
 		}
 
+		block_saved = block;
+		offset_saved = offset;
 		offset += de_len;
 
 		/* Make sure we have a full directory entry */
@@ -164,6 +165,15 @@
 				memcpy((void *) tmpde + slop, bh->b_data, offset);
 			}
 			de = tmpde;
+		}
+
+		if (first_de) {
+			isofs_normalize_block_and_offset(de,
+							 &block_saved,
+							 &offset_saved);
+			inode_number = isofs_get_ino(block_saved,
+						     offset_saved,
+						     bufbits);
 		}
 
 		if (de->flags[-sbi->s_high_sierra] & 0x80) {
diff -Nru a/fs/isofs/export.c b/fs/isofs/export.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/isofs/export.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,228 @@
+/*
+ * fs/isofs/export.c
+ *
+ *  (C) 2004  Paul Serice - The new inode scheme requires switching
+ *                          from iget() to iget5_locked() which means
+ *                          the NFS export operations have to be hand
+ *                          coded because the default routines rely on
+ *                          iget().
+ *
+ * The following files are helpful:
+ *
+ *     Documentation/filesystems/Exporting
+ *     fs/exportfs/expfs.c.
+ */
+
+#include <linux/buffer_head.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/iso_fs.h>
+#include <linux/kernel.h>
+
+static struct dentry *
+isofs_export_iget(struct super_block *sb,
+		  unsigned long block,
+		  unsigned long offset,
+		  __u32 generation)
+{
+	struct inode *inode;
+	struct dentry *result;
+	if (block == 0)
+		return ERR_PTR(-ESTALE);
+	inode = isofs_iget(sb, block, offset);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+	if (is_bad_inode(inode)
+	    || (generation && inode->i_generation != generation))
+	{
+		iput(inode);
+		return ERR_PTR(-ESTALE);
+	}
+	result = d_alloc_anon(inode);
+	if (!result) {
+		iput(inode);
+		return ERR_PTR(-ENOMEM);
+	}
+	return result;
+}
+
+static struct dentry *
+isofs_export_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long block = objp[0];
+	unsigned long offset = objp[1];
+	__u32 generation = objp[2];
+	return isofs_export_iget(sb, block, offset, generation);
+}
+
+/* This function is surprisingly simple.  The trick is understanding
+ * that "child" is always a directory. So, to find its parent, you
+ * simply need to find its ".." entry, normalize its block and offset,
+ * and return the underlying inode.  See the comments for
+ * isofs_normalize_block_and_offset(). */
+static struct dentry *isofs_export_get_parent(struct dentry *child)
+{
+	unsigned long parent_block = 0;
+	unsigned long parent_offset = 0;
+	struct inode *child_inode = child->d_inode;
+	struct iso_inode_info *e_child_inode = ISOFS_I(child_inode);
+	struct inode *parent_inode = NULL;
+	struct iso_directory_record *de = NULL;
+	struct buffer_head * bh = NULL;
+	struct dentry *rv = NULL;
+
+	/* "child" must always be a directory. */
+	if (!S_ISDIR(child_inode->i_mode)) {
+		printk(KERN_ERR "isofs: isofs_export_get_parent(): "
+		       "child is not a directory!\n");
+		rv = ERR_PTR(-EACCES);
+		goto out;
+	}
+
+	/* It is an invariant that the directory offset is zero.  If
+	 * it is not zero, it means the directory failed to be
+	 * normalized for some reason. */
+	if (e_child_inode->i_iget5_offset != 0) {
+		printk(KERN_ERR "isofs: isofs_export_get_parent(): "
+		       "child directory not normalized!\n");
+		rv = ERR_PTR(-EACCES);
+		goto out;
+	}
+
+	/* The child inode has been normalized such that its
+	 * i_iget5_block value points to the "." entry.  Fortunately,
+	 * the ".." entry is located in the same block. */
+	parent_block = e_child_inode->i_iget5_block;
+
+	/* Get the block in question. */
+	bh = sb_bread(child_inode->i_sb, parent_block);
+	if (bh == NULL) {
+		rv = ERR_PTR(-EACCES);
+		goto out;
+	}
+
+	/* This is the "." entry. */
+	de = (struct iso_directory_record*)bh->b_data;
+
+	/* The ".." entry is always the second entry. */
+	parent_offset = (unsigned long)isonum_711(de->length);
+	de = (struct iso_directory_record*)(bh->b_data + parent_offset);
+
+	/* Verify it is in fact the ".." entry. */
+	if ((isonum_711(de->name_len) != 1) || (de->name[0] != 1)) {
+		printk(KERN_ERR "isofs: Unable to find the \"..\" "
+		       "directory for NFS.\n");
+		rv = ERR_PTR(-EACCES);
+		goto out;
+	}
+
+	/* Normalize */
+	isofs_normalize_block_and_offset(de, &parent_block, &parent_offset);
+
+	/* Get the inode. */
+	parent_inode = isofs_iget(child_inode->i_sb,
+				  parent_block,
+				  parent_offset);
+	if (parent_inode == NULL) {
+		rv = ERR_PTR(-EACCES);
+		goto out;
+	}
+
+	/* Allocate the dentry. */
+	rv = d_alloc_anon(parent_inode);
+	if (rv == NULL) {
+		rv = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+ out:
+	if (bh) {
+		brelse(bh);
+	}
+	return rv;
+}
+
+static int
+isofs_export_encode_fh(struct dentry *dentry,
+		       __u32 *fh32,
+		       int *max_len,
+		       int connectable)
+{
+	struct inode * inode = dentry->d_inode;
+	struct iso_inode_info * ei = ISOFS_I(inode);
+	int len = *max_len;
+	int type = 1;
+	__u16 *fh16 = (__u16*)fh32;
+
+	/*
+	 * WARNING: max_len is 5 for NFSv2.  Because of this
+	 * limitation, we use the lower 16 bits of fh32[1] to hold the
+	 * offset of the inode and the upper 16 bits of fh32[1] to
+	 * hold the offset of the parent.
+	 */
+
+	if (len < 3 || (connectable && len < 5))
+		return 255;
+
+	len = 3;
+	fh32[0] = ei->i_iget5_block;
+ 	fh16[2] = (__u16)ei->i_iget5_offset;  /* fh16 [sic] */
+	fh32[2] = inode->i_generation;
+	if (connectable && !S_ISDIR(inode->i_mode)) {
+		struct inode *parent;
+		struct iso_inode_info *eparent;
+		spin_lock(&dentry->d_lock);
+		parent = dentry->d_parent->d_inode;
+		eparent = ISOFS_I(parent);
+		fh32[3] = eparent->i_iget5_block;
+		fh16[3] = (__u16)eparent->i_iget5_offset;  /* fh16 [sic] */
+		fh32[4] = parent->i_generation;
+		spin_unlock(&dentry->d_lock);
+		len = 5;
+		type = 2;
+	}
+	*max_len = len;
+	return type;
+}
+
+
+static struct dentry *
+isofs_export_decode_fh(struct super_block *sb,
+		       __u32 *fh32,
+		       int fh_len,
+		       int fileid_type,
+		       int (*acceptable)(void *context, struct dentry *de),
+		       void *context)
+{
+	__u16 *fh16 = (__u16*)fh32;
+	__u32 child[3];   /* The child is what triggered all this. */
+	__u32 parent[3];  /* The parent is just along for the ride. */
+
+	if (fh_len < 3 || fileid_type > 2)
+		return NULL;
+
+	child[0] = fh32[0];
+	child[1] = fh16[2];  /* fh16 [sic] */
+	child[2] = fh32[2];
+
+	parent[0] = 0;
+	parent[1] = 0;
+	parent[2] = 0;
+	if (fileid_type == 2) {
+		if (fh_len > 2) parent[0] = fh32[3];
+		parent[1] = fh16[3];  /* fh16 [sic] */
+		if (fh_len > 4) parent[2] = fh32[4];
+	}
+
+	return sb->s_export_op->find_exported_dentry(sb, child, parent,
+						     acceptable, context);
+}
+
+
+struct export_operations isofs_export_ops = {
+	.decode_fh	= isofs_export_decode_fh,
+	.encode_fh	= isofs_export_encode_fh,
+	.get_dentry	= isofs_export_get_dentry,
+	.get_parent     = isofs_export_get_parent,
+};
diff -Nru a/fs/isofs/inode.c b/fs/isofs/inode.c
--- a/fs/isofs/inode.c	2004-06-23 19:04:28 -07:00
+++ b/fs/isofs/inode.c	2004-06-23 19:04:28 -07:00
@@ -7,6 +7,8 @@
  *      1995  Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs.
  *	1997  Gordon Chaffee - Joliet CDs
  *	1998  Eric Lammerts - ISO 9660 Level 3
+ *	2004  Paul Serice - Inode Support pushed out from 4GB to 128GB
+ *	2004  Paul Serice - NFS Export Operations
  */
 
 #include <linux/config.h>
@@ -135,20 +137,6 @@
 	.remount_fs	= isofs_remount,
 };
 
-/* the export_operations structure for describing
- * how to export (e.g. via kNFSd) is deliberately
- * empty.
- * This means that the filesystem want to use iget
- * to map an inode number into an inode.
- * The lack of a get_parent operation means that 
- * if something isn't in the cache, then you cannot
- * access it.
- * It should be possible to write a get_parent,
- * but it would be a bit hairy...
- */
-static struct export_operations isofs_export_ops = {
-};
-
 
 static struct dentry_operations isofs_dentry_ops[] = {
 	{
@@ -738,19 +726,14 @@
 	/* Set this for reference. Its not currently used except on write
 	   which we don't have .. */
 	   
-	/* RDE: data zone now byte offset! */
-
-	first_data_zone = ((isonum_733 (rootp->extent) +
-			  isonum_711 (rootp->ext_attr_length))
-			 << sbi->s_log_zone_size);
+	first_data_zone = isonum_733 (rootp->extent) +
+			  isonum_711 (rootp->ext_attr_length);
 	sbi->s_firstdatazone = first_data_zone;
 #ifndef BEQUIET
 	printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
 	       sbi->s_max_size,
 	       1UL << sbi->s_log_zone_size);
-	printk(KERN_DEBUG "First datazone:%ld   Root inode number:%ld\n",
-	       sbi->s_firstdatazone >> sbi->s_log_zone_size,
-	       sbi->s_firstdatazone);
+	printk(KERN_DEBUG "First datazone:%ld\n", sbi->s_firstdatazone);
 	if(sbi->s_high_sierra)
 		printk(KERN_DEBUG "Disc in High Sierra format.\n");
 #endif
@@ -767,9 +750,8 @@
 		pri = (struct iso_primary_descriptor *) sec;
 		rootp = (struct iso_directory_record *)
 			pri->root_directory_record;
-		first_data_zone = ((isonum_733 (rootp->extent) +
-			  	isonum_711 (rootp->ext_attr_length))
-				 << sbi->s_log_zone_size);
+		first_data_zone = isonum_733 (rootp->extent) +
+			  	isonum_711 (rootp->ext_attr_length);
 	}
 
 	/*
@@ -835,7 +817,7 @@
 	 * the s_rock flag. Once we have the final s_rock value,
 	 * we then decide whether to use the Joliet descriptor.
 	 */
-	inode = iget(s, sbi->s_firstdatazone);
+	inode = isofs_iget(s, sbi->s_firstdatazone, 0);
 
 	/*
 	 * If this disk has both Rock Ridge and Joliet on it, then we
@@ -854,7 +836,7 @@
 			printk(KERN_DEBUG 
 				"ISOFS: changing to secondary root\n");
 			iput(inode);
-			inode = iget(s, sbi->s_firstdatazone);
+			inode = isofs_iget(s, sbi->s_firstdatazone, 0);
 		}
 	}
 
@@ -952,7 +934,7 @@
 	unsigned long b_off;
 	unsigned offset, sect_size;
 	unsigned int firstext;
-	unsigned long nextino;
+	unsigned long nextblk, nextoff;
 	long iblock = (long)iblock_s;
 	int section, rv;
 	struct iso_inode_info *ei = ISOFS_I(inode);
@@ -970,7 +952,8 @@
 	offset    = 0;
 	firstext  = ei->i_first_extent;
 	sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode);
-	nextino   = ei->i_next_section_ino;
+	nextblk   = ei->i_next_section_block;
+	nextoff   = ei->i_next_section_offset;
 	section   = 0;
 
 	while ( nblocks ) {
@@ -987,25 +970,28 @@
 			goto abort;
 		}
 		
-		if (nextino) {
+		if (nextblk) {
 			while (b_off >= (offset + sect_size)) {
 				struct inode *ninode;
 				
 				offset += sect_size;
-				if (nextino == 0)
+				if (nextblk == 0)
 					goto abort;
-				ninode = iget(inode->i_sb, nextino);
+				ninode = isofs_iget(inode->i_sb, nextblk, nextoff);
 				if (!ninode)
 					goto abort;
 				firstext  = ISOFS_I(ninode)->i_first_extent;
-				sect_size = ISOFS_I(ninode)->i_section_size;
-				nextino   = ISOFS_I(ninode)->i_next_section_ino;
+				sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode);
+				nextblk   = ISOFS_I(ninode)->i_next_section_block;
+				nextoff   = ISOFS_I(ninode)->i_next_section_offset;
 				iput(ninode);
 				
 				if (++section > 100) {
 					printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
-					printk("isofs_get_blocks: ino=%lu block=%ld firstext=%u sect_size=%u nextino=%lu\n",
-					       inode->i_ino, iblock, firstext, (unsigned) sect_size, nextino);
+					printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u "
+					       "nextblk=%lu nextoff=%lu\n",
+					       iblock, firstext, (unsigned) sect_size,
+					       nextblk, nextoff);
 					goto abort;
 				}
 			}
@@ -1044,7 +1030,7 @@
 	return isofs_get_blocks(inode, iblock, &bh_result, 1) ? 0 : -EIO;
 }
 
-static int isofs_bmap(struct inode *inode, int block)
+static int isofs_bmap(struct inode *inode, sector_t block)
 {
 	struct buffer_head dummy;
 	int error;
@@ -1097,21 +1083,25 @@
 
 static int isofs_read_level3_size(struct inode * inode)
 {
-	unsigned long f_pos = inode->i_ino;
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
 	struct buffer_head * bh = NULL;
-	unsigned long block, offset;
+	unsigned long block, offset, block_saved, offset_saved;
 	int i = 0;
 	int more_entries = 0;
 	struct iso_directory_record * tmpde = NULL;
 	struct iso_inode_info *ei = ISOFS_I(inode);
 
 	inode->i_size = 0;
-	ei->i_next_section_ino = 0;
 
-	block = f_pos >> ISOFS_BUFFER_BITS(inode);
-	offset = f_pos & (bufsize-1);
+	/* The first 16 blocks are reserved as the System Area.  Thus,
+	 * no inodes can appear in block 0.  We use this to flag that
+	 * this is the last section. */
+	ei->i_next_section_block = 0;
+	ei->i_next_section_offset = 0;
+
+	block = ei->i_iget5_block;
+	offset = ei->i_iget5_offset;
 
 	do {
 		struct iso_directory_record * de;
@@ -1128,12 +1118,13 @@
 		if (de_len == 0) {
 			brelse(bh);
 			bh = NULL;
-			f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
-			block = f_pos >> ISOFS_BUFFER_BITS(inode);
+			++block;
 			offset = 0;
 			continue;
 		}
 
+		block_saved = block;
+		offset_saved = offset;
 		offset += de_len;
 
 		/* Make sure we have a full directory entry */
@@ -1159,12 +1150,13 @@
 		}
 
 		inode->i_size += isonum_733(de->size);
-		if (i == 1)
-			ei->i_next_section_ino = f_pos;
+		if (i == 1) {
+			ei->i_next_section_block = block_saved;
+			ei->i_next_section_offset = offset_saved;
+		}
 
 		more_entries = de->flags[-high_sierra] & 0x80;
 
-		f_pos += de_len;
 		i++;
 		if(i > 100)
 			goto out_toomany;
@@ -1190,8 +1182,8 @@
 out_toomany:
 	printk(KERN_INFO "isofs_read_level3_size: "
 		"More than 100 file sections ?!?, aborting...\n"
-	  	"isofs_read_level3_size: inode=%lu ino=%lu\n",
-		inode->i_ino, f_pos);
+	  	"isofs_read_level3_size: inode=%lu\n",
+		inode->i_ino);
 	goto out;
 }
 
@@ -1200,21 +1192,22 @@
 	struct super_block *sb = inode->i_sb;
 	struct isofs_sb_info *sbi = ISOFS_SB(sb);
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
-	int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
+	unsigned long block;
 	int high_sierra = sbi->s_high_sierra;
 	struct buffer_head * bh = NULL;
 	struct iso_directory_record * de;
 	struct iso_directory_record * tmpde = NULL;
 	unsigned int de_len;
 	unsigned long offset;
-	int i;
 	struct iso_inode_info *ei = ISOFS_I(inode);
 
+	block = ei->i_iget5_block;
 	bh = sb_bread(inode->i_sb, block);
 	if (!bh)
 		goto out_badread;
 
-	offset = (inode->i_ino & (bufsize - 1));
+	offset = ei->i_iget5_offset;
+
 	de = (struct iso_directory_record *) (bh->b_data + offset);
 	de_len = *(unsigned char *) de;
 
@@ -1235,6 +1228,10 @@
 		de = tmpde;
 	}
 
+	inode->i_ino = isofs_get_ino(ei->i_iget5_block,
+				     ei->i_iget5_offset,
+				     ISOFS_BUFFER_BITS(inode));
+
 	/* Assume it is a normal-format file unless told otherwise */
 	ei->i_file_format = isofs_file_normal;
 
@@ -1250,14 +1247,6 @@
 		inode->i_mode = sbi->s_mode;
 		inode->i_nlink = 1;
 	        inode->i_mode |= S_IFREG;
-		/* If there are no periods in the name,
-		 * then set the execute permission bit
-		 */
-		for(i=0; i< de->name_len[0]; i++)
-			if(de->name[i]=='.' || de->name[i]==';')
-				break;
-		if(i == de->name_len[0] || de->name[i] == ';')
-			inode->i_mode |= S_IXUGO; /* execute permission */
 	}
 	inode->i_uid = sbi->s_uid;
 	inode->i_gid = sbi->s_gid;
@@ -1271,7 +1260,8 @@
 	if(de->flags[-high_sierra] & 0x80) {
 		if(isofs_read_level3_size(inode)) goto fail;
 	} else {
-		ei->i_next_section_ino = 0;
+		ei->i_next_section_block = 0;
+		ei->i_next_section_offset = 0;
 		inode->i_size = isonum_733 (de->size);
 	}
 
@@ -1383,6 +1373,61 @@
  fail:
 	make_bad_inode(inode);
 	goto out;
+}
+
+struct isofs_iget5_callback_data {
+	unsigned long block;
+	unsigned long offset;
+};
+
+static int isofs_iget5_test(struct inode *ino, void *data)
+{
+	struct iso_inode_info *i = ISOFS_I(ino);
+	struct isofs_iget5_callback_data *d =
+		(struct isofs_iget5_callback_data*)data;
+	return (i->i_iget5_block == d->block)
+	       && (i->i_iget5_offset == d->offset);
+}
+
+static int isofs_iget5_set(struct inode *ino, void *data)
+{
+	struct iso_inode_info *i = ISOFS_I(ino);
+	struct isofs_iget5_callback_data *d =
+		(struct isofs_iget5_callback_data*)data;
+	i->i_iget5_block = d->block;
+	i->i_iget5_offset = d->offset;
+	return 0;
+}
+
+/* Store, in the inode's containing structure, the block and block
+ * offset that point to the underlying meta-data for the inode.  The
+ * code below is otherwise similar to the iget() code in
+ * include/linux/fs.h */
+struct inode *isofs_iget(struct super_block *sb,
+			 unsigned long block,
+			 unsigned long offset)
+{
+	unsigned long hashval;
+	struct inode *inode;
+	struct isofs_iget5_callback_data data;
+
+	data.block = block;
+	data.offset = offset;
+
+	hashval = (block << sb->s_blocksize_bits) | offset;
+
+	inode = iget5_locked(sb,
+			     hashval,
+			     &isofs_iget5_test,
+			     &isofs_iget5_set,
+			     &data);
+
+	if (inode && (inode->i_state & I_NEW)) {
+		sb->s_op->read_inode(inode);
+		unlock_new_inode(inode);
+	}
+
+	return inode;
 }
 
 #ifdef LEAK_CHECK
diff -Nru a/fs/isofs/namei.c b/fs/isofs/namei.c
--- a/fs/isofs/namei.c	2004-06-23 19:04:28 -07:00
+++ b/fs/isofs/namei.c	2004-06-23 19:04:28 -07:00
@@ -17,6 +17,7 @@
 #include <linux/config.h>	/* Joliet? */
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/dcache.h>
 
 #include <asm/uaccess.h>
 
@@ -59,12 +60,12 @@
  */
 static unsigned long
 isofs_find_entry(struct inode *dir, struct dentry *dentry,
+	unsigned long *block_rv, unsigned long* offset_rv,
 	char * tmpname, struct iso_directory_record * tmpde)
 {
-	unsigned long inode_number;
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
 	unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
-	unsigned int block, f_pos, offset;
+	unsigned long block, f_pos, offset, block_saved, offset_saved;
 	struct buffer_head * bh = NULL;
 	struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
 
@@ -87,7 +88,6 @@
 		}
 
 		de = (struct iso_directory_record *) (bh->b_data + offset);
-		inode_number = (bh->b_blocknr << bufbits) + offset;
 
 		de_len = *(unsigned char *) de;
 		if (!de_len) {
@@ -99,6 +99,8 @@
 			continue;
 		}
 
+		block_saved = bh->b_blocknr;
+		offset_saved = offset;
 		offset += de_len;
 		f_pos += de_len;
 
@@ -150,8 +152,13 @@
 			match = (isofs_cmp(dentry,dpnt,dlen) == 0);
 		}
 		if (match) {
+			isofs_normalize_block_and_offset(de,
+							 &block_saved,
+							 &offset_saved);
+                        *block_rv = block_saved;
+                        *offset_rv = offset_saved;
 			if (bh) brelse(bh);
-			return inode_number;
+			return 1;
 		}
 	}
 	if (bh) brelse(bh);
@@ -160,7 +167,8 @@
 
 struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
 {
-	unsigned long ino;
+	int found;
+	unsigned long block, offset;
 	struct inode *inode;
 	struct page *page;
 
@@ -171,19 +179,23 @@
 		return ERR_PTR(-ENOMEM);
 
 	lock_kernel();
-	ino = isofs_find_entry(dir, dentry, page_address(page),
-			       1024 + page_address(page));
+	found = isofs_find_entry(dir, dentry,
+				 &block, &offset,
+				 page_address(page),
+				 1024 + page_address(page));
 	__free_page(page);
 
 	inode = NULL;
-	if (ino) {
-		inode = iget(dir->i_sb, ino);
+	if (found) {
+		inode = isofs_iget(dir->i_sb, block, offset);
 		if (!inode) {
 			unlock_kernel();
 			return ERR_PTR(-EACCES);
 		}
 	}
 	unlock_kernel();
+	if (inode)
+		return d_splice_alias(inode, dentry);
 	d_add(dentry, inode);
 	return NULL;
 }
diff -Nru a/fs/isofs/rock.c b/fs/isofs/rock.c
--- a/fs/isofs/rock.c	2004-06-23 19:04:27 -07:00
+++ b/fs/isofs/rock.c	2004-06-23 19:04:27 -07:00
@@ -306,9 +306,7 @@
 	goto out;
       case SIG('C','L'):
 	ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
-	reloc = iget(inode->i_sb,
-		     (ISOFS_I(inode)->i_first_extent <<
-		      ISOFS_SB(inode->i_sb)->s_log_zone_size));
+	reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0);
 	if (!reloc)
 		goto out;
 	inode->i_mode = reloc->i_mode;
@@ -447,15 +445,15 @@
 static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
 {
 	struct inode *inode = page->mapping->host;
+        struct iso_inode_info *ei = ISOFS_I(inode);
 	char *link = kmap(page);
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
-	unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
 	struct buffer_head *bh;
 	char *rpnt = link;
 	unsigned char *pnt;
 	struct iso_directory_record *raw_inode;
 	CONTINUE_DECLS;
-	int block;
+	unsigned long block, offset;
 	int sig;
 	int len;
 	unsigned char *chr;
@@ -464,20 +462,21 @@
 	if (!ISOFS_SB(inode->i_sb)->s_rock)
 		panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
 
-	block = inode->i_ino >> bufbits;
+	block = ei->i_iget5_block;
 	lock_kernel();
 	bh = sb_bread(inode->i_sb, block);
 	if (!bh)
 		goto out_noread;
 
-	pnt = (unsigned char *) bh->b_data + (inode->i_ino & (bufsize - 1));
+        offset = ei->i_iget5_offset;
+	pnt = (unsigned char *) bh->b_data + offset;
 
 	raw_inode = (struct iso_directory_record *) pnt;
 
 	/*
 	 * If we go past the end of the buffer, there is some sort of error.
 	 */
-	if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
+	if (offset + *pnt > bufsize)
 		goto out_bad_span;
 
 	/* Now test for possible Rock Ridge extensions which will override
diff -Nru a/fs/jbd/journal.c b/fs/jbd/journal.c
--- a/fs/jbd/journal.c	2004-06-23 19:04:25 -07:00
+++ b/fs/jbd/journal.c	2004-06-23 19:04:25 -07:00
@@ -73,6 +73,7 @@
 EXPORT_SYMBOL(journal_clear_err);
 EXPORT_SYMBOL(log_wait_commit);
 EXPORT_SYMBOL(journal_start_commit);
+EXPORT_SYMBOL(journal_force_commit_nested);
 EXPORT_SYMBOL(journal_wipe);
 EXPORT_SYMBOL(journal_blocks_per_page);
 EXPORT_SYMBOL(journal_invalidatepage);
@@ -462,6 +463,39 @@
 	ret = __log_start_commit(journal, tid);
 	spin_unlock(&journal->j_state_lock);
 	return ret;
+}
+
+/*
+ * Force and wait upon a commit if the calling process is not within
+ * transaction.  This is used for forcing out undo-protected data which contains
+ * bitmaps, when the fs is running out of space.
+ *
+ * We can only force the running transaction if we don't have an active handle;
+ * otherwise, we will deadlock.
+ *
+ * Returns true if a transaction was started.
+ */
+int journal_force_commit_nested(journal_t *journal)
+{
+	transaction_t *transaction = NULL;
+	tid_t tid;
+
+	spin_lock(&journal->j_state_lock);
+	if (journal->j_running_transaction && !current->journal_info) {
+		transaction = journal->j_running_transaction;
+		__log_start_commit(journal, transaction->t_tid);
+	} else if (journal->j_committing_transaction)
+		transaction = journal->j_committing_transaction;
+
+	if (!transaction) {
+		spin_unlock(&journal->j_state_lock);
+		return 0;	/* Nothing to retry */
+	}
+
+	tid = transaction->t_tid;
+	spin_unlock(&journal->j_state_lock);
+	log_wait_commit(journal, tid);
+	return 1;
 }
 
 /*
diff -Nru a/fs/jfs/jfs_btree.h b/fs/jfs/jfs_btree.h
--- a/fs/jfs/jfs_btree.h	2004-06-23 19:04:25 -07:00
+++ b/fs/jfs/jfs_btree.h	2004-06-23 19:04:25 -07:00
@@ -147,7 +147,7 @@
 	printk("btstack dump:\n");
 	for (i = 0; i < MAXTREEHEIGHT; i++)
 		printk(KERN_ERR "bn = %Lx, index = %d\n",
-		       btstack->stack[i].bn,
+		       (long long)btstack->stack[i].bn,
 		       btstack->stack[i].index);
 }
 
diff -Nru a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
--- a/fs/jfs/jfs_dtree.c	2004-06-23 19:04:27 -07:00
+++ b/fs/jfs/jfs_dtree.c	2004-06-23 19:04:27 -07:00
@@ -374,6 +374,8 @@
 		return index;
 	}
 	if (index == (MAX_INLINE_DIRTABLE_ENTRY + 1)) {
+		struct dir_table_slot temp_table[12];
+
 		/*
 		 * It's time to move the inline table to an external
 		 * page and begin to build the xtree
@@ -385,7 +387,6 @@
 		 * Save the table, we're going to overwrite it with the
 		 * xtree root
 		 */
-		struct dir_table_slot temp_table[12];
 		memcpy(temp_table, &jfs_ip->i_dirtable, sizeof(temp_table));
 
 		/*
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	2004-06-23 19:04:26 -07:00
+++ b/fs/namei.c	2004-06-23 19:04:26 -07:00
@@ -1206,6 +1206,11 @@
 			return -EPERM;
 	}
 
+	/* O_NOATIME can only be set by the owner or superuser */
+	if (flag & O_NOATIME)
+		if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+			return -EPERM;
+
 	/*
 	 * Ensure there are no outstanding leases on the file.
 	 */
diff -Nru a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
--- a/fs/ncpfs/dir.c	2004-06-23 19:04:27 -07:00
+++ b/fs/ncpfs/dir.c	2004-06-23 19:04:27 -07:00
@@ -762,12 +762,12 @@
 int ncp_conn_logged_in(struct super_block *sb)
 {
 	struct ncp_server* server = NCP_SBP(sb);
-	struct nw_info_struct i;
 	int result;
 
 	if (ncp_single_volume(server)) {
 		int len;
 		struct dentry* dent;
+		__u32 volNumber, dirEntNum, DosDirNum;
 		__u8 __name[NCP_MAXPATHLEN + 1];
 
 		len = sizeof(__name);
@@ -776,7 +776,7 @@
 		if (result)
 			goto out;
 		result = -ENOENT;
-		if (ncp_lookup_volume(server, __name, &i)) {
+		if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
 			PPRINTK("ncp_conn_logged_in: %s not found\n",
 				server->m.mounted_vol);
 			goto out;
@@ -785,9 +785,9 @@
 		if (dent) {
 			struct inode* ino = dent->d_inode;
 			if (ino) {
-				NCP_FINFO(ino)->volNumber = i.volNumber;
-				NCP_FINFO(ino)->dirEntNum = i.dirEntNum;
-				NCP_FINFO(ino)->DosDirNum = i.DosDirNum;
+				NCP_FINFO(ino)->volNumber = volNumber;
+				NCP_FINFO(ino)->dirEntNum = dirEntNum;
+				NCP_FINFO(ino)->DosDirNum = DosDirNum;
 			} else {
 				DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
 			}
diff -Nru a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
--- a/fs/ncpfs/ioctl.c	2004-06-23 19:04:27 -07:00
+++ b/fs/ncpfs/ioctl.c	2004-06-23 19:04:27 -07:00
@@ -29,6 +29,155 @@
 /* maximum negotiable packet size */
 #define NCP_PACKET_SIZE_INTERNAL 65536
 
+static int
+ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_info __user *arg)
+{
+	struct ncp_fs_info info;
+
+	if ((permission(inode, MAY_WRITE, NULL) != 0)
+	    && (current->uid != server->m.mounted_uid)) {
+		return -EACCES;
+	}
+	if (copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+
+	if (info.version != NCP_GET_FS_INFO_VERSION) {
+		DPRINTK("info.version invalid: %d\n", info.version);
+		return -EINVAL;
+	}
+	/* TODO: info.addr = server->m.serv_addr; */
+	SET_UID(info.mounted_uid, server->m.mounted_uid);
+	info.connection		= server->connection;
+	info.buffer_size	= server->buffer_size;
+	info.volume_number	= NCP_FINFO(inode)->volNumber;
+	info.directory_id	= NCP_FINFO(inode)->DosDirNum;
+
+	if (copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+static int
+ncp_get_fs_info_v2(struct ncp_server* server, struct inode* inode, struct ncp_fs_info_v2 __user * arg)
+{
+	struct ncp_fs_info_v2 info2;
+
+	if ((permission(inode, MAY_WRITE, NULL) != 0)
+	    && (current->uid != server->m.mounted_uid)) {
+		return -EACCES;
+	}
+	if (copy_from_user(&info2, arg, sizeof(info2)))
+		return -EFAULT;
+
+	if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
+		DPRINTK("info.version invalid: %d\n", info2.version);
+		return -EINVAL;
+	}
+	info2.mounted_uid   = server->m.mounted_uid;
+	info2.connection    = server->connection;
+	info2.buffer_size   = server->buffer_size;
+	info2.volume_number = NCP_FINFO(inode)->volNumber;
+	info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
+	info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
+
+	if (copy_to_user(arg, &info2, sizeof(info2)))
+		return -EFAULT;
+	return 0;
+}
+
+#ifdef CONFIG_NCPFS_NLS
+/* Here we are select the iocharset and the codepage for NLS.
+ * Thanks Petr Vandrovec for idea and many hints.
+ */
+static int
+ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
+{
+	struct ncp_nls_ioctl user;
+	struct nls_table *codepage;
+	struct nls_table *iocharset;
+	struct nls_table *oldset_io;
+	struct nls_table *oldset_cp;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	if (server->root_setuped)
+		return -EBUSY;
+
+	if (copy_from_user(&user, arg, sizeof(user)))
+		return -EFAULT;
+
+	codepage = NULL;
+	user.codepage[NCP_IOCSNAME_LEN] = 0;
+	if (!user.codepage[0] || !strcmp(user.codepage, "default"))
+		codepage = load_nls_default();
+	else {
+		codepage = load_nls(user.codepage);
+		if (!codepage) {
+			return -EBADRQC;
+		}
+	}
+
+	iocharset = NULL;
+	user.iocharset[NCP_IOCSNAME_LEN] = 0;
+	if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
+		iocharset = load_nls_default();
+		NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+	} else if (!strcmp(user.iocharset, "utf8")) {
+		iocharset = load_nls_default();
+		NCP_SET_FLAG(server, NCP_FLAG_UTF8);
+	} else {
+		iocharset = load_nls(user.iocharset);
+		if (!iocharset) {
+			unload_nls(codepage);
+			return -EBADRQC;
+		}
+		NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+	}
+
+	oldset_cp = server->nls_vol;
+	server->nls_vol = codepage;
+	oldset_io = server->nls_io;
+	server->nls_io = iocharset;
+
+	if (oldset_cp)
+		unload_nls(oldset_cp);
+	if (oldset_io)
+		unload_nls(oldset_io);
+
+	return 0;
+}
+
+static int
+ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
+{
+	struct ncp_nls_ioctl user;
+	int len;
+
+	memset(&user, 0, sizeof(user));
+	if (server->nls_vol && server->nls_vol->charset) {
+		len = strlen(server->nls_vol->charset);
+		if (len > NCP_IOCSNAME_LEN)
+			len = NCP_IOCSNAME_LEN;
+		strncpy(user.codepage, server->nls_vol->charset, len);
+		user.codepage[len] = 0;
+	}
+
+	if (NCP_IS_FLAG(server, NCP_FLAG_UTF8))
+		strcpy(user.iocharset, "utf8");
+	else if (server->nls_io && server->nls_io->charset) {
+		len = strlen(server->nls_io->charset);
+		if (len > NCP_IOCSNAME_LEN)
+			len = NCP_IOCSNAME_LEN;
+		strncpy(user.iocharset,	server->nls_io->charset, len);
+		user.iocharset[len] = 0;
+	}
+
+	if (copy_to_user(arg, &user, sizeof(user)))
+		return -EFAULT;
+	return 0;
+}
+#endif /* CONFIG_NCPFS_NLS */
+
 int ncp_ioctl(struct inode *inode, struct file *filp,
 	      unsigned int cmd, unsigned long arg)
 {
@@ -36,6 +185,7 @@
 	int result;
 	struct ncp_ioctl_request request;
 	char* bouncebuffer;
+	void __user *argp = (void __user *)arg;
 
 	switch (cmd) {
 	case NCP_IOC_NCPREQUEST:
@@ -44,8 +194,7 @@
 		    && (current->uid != server->m.mounted_uid)) {
 			return -EACCES;
 		}
-		if (copy_from_user(&request, (struct ncp_ioctl_request *) arg,
-			       sizeof(request)))
+		if (copy_from_user(&request, argp, sizeof(request)))
 			return -EFAULT;
 
 		if ((request.function > 255)
@@ -96,60 +245,10 @@
 		return ncp_conn_logged_in(inode->i_sb);
 
 	case NCP_IOC_GET_FS_INFO:
-		{
-			struct ncp_fs_info info;
-
-			if ((permission(inode, MAY_WRITE, NULL) != 0)
-			    && (current->uid != server->m.mounted_uid)) {
-				return -EACCES;
-			}
-			if (copy_from_user(&info, (struct ncp_fs_info *) arg, 
-				sizeof(info)))
-				return -EFAULT;
-
-			if (info.version != NCP_GET_FS_INFO_VERSION) {
-				DPRINTK("info.version invalid: %d\n", info.version);
-				return -EINVAL;
-			}
-			/* TODO: info.addr = server->m.serv_addr; */
-			SET_UID(info.mounted_uid, server->m.mounted_uid);
-			info.connection		= server->connection;
-			info.buffer_size	= server->buffer_size;
-			info.volume_number	= NCP_FINFO(inode)->volNumber;
-			info.directory_id	= NCP_FINFO(inode)->DosDirNum;
-
-			if (copy_to_user((struct ncp_fs_info *) arg, &info, 
-				sizeof(info))) return -EFAULT;
-			return 0;
-		}
+		return ncp_get_fs_info(server, inode, argp);
 
 	case NCP_IOC_GET_FS_INFO_V2:
-		{
-			struct ncp_fs_info_v2 info2;
-
-			if ((permission(inode, MAY_WRITE, NULL) != 0)
-			    && (current->uid != server->m.mounted_uid)) {
-				return -EACCES;
-			}
-			if (copy_from_user(&info2, (struct ncp_fs_info_v2 *) arg, 
-				sizeof(info2)))
-				return -EFAULT;
-
-			if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
-				DPRINTK("info.version invalid: %d\n", info2.version);
-				return -EINVAL;
-			}
-			info2.mounted_uid   = server->m.mounted_uid;
-			info2.connection    = server->connection;
-			info2.buffer_size   = server->buffer_size;
-			info2.volume_number = NCP_FINFO(inode)->volNumber;
-			info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
-			info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
-
-			if (copy_to_user((struct ncp_fs_info_v2 *) arg, &info2, 
-				sizeof(info2))) return -EFAULT;
-			return 0;
-		}
+		return ncp_get_fs_info_v2(server, inode, argp);
 
 	case NCP_IOC_GETMOUNTUID2:
 		{
@@ -160,7 +259,7 @@
 			{
 				return -EACCES;
 			}
-			if (put_user(tmp, (unsigned long*) arg)) 
+			if (put_user(tmp, (unsigned long __user *)argp)) 
 				return -EFAULT;
 			return 0;
 		}
@@ -193,15 +292,14 @@
 				sr.namespace = 0;
 				sr.dirEntNum = 0;
 			}
-			if (copy_to_user((struct ncp_setroot_ioctl*)arg, 
-				    	  &sr, 
-					  sizeof(sr))) return -EFAULT;
+			if (copy_to_user(argp, &sr, sizeof(sr)))
+				return -EFAULT;
 			return 0;
 		}
 	case NCP_IOC_SETROOT:
 		{
 			struct ncp_setroot_ioctl sr;
-			unsigned int vnum, de, dosde;
+			__u32 vnum, de, dosde;
 			struct dentry* dentry;
 
 			if (!capable(CAP_SYS_ADMIN))
@@ -209,9 +307,8 @@
 				return -EACCES;
 			}
 			if (server->root_setuped) return -EBUSY;
-			if (copy_from_user(&sr,
-					   (struct ncp_setroot_ioctl*)arg, 
-					   sizeof(sr))) return -EFAULT;
+			if (copy_from_user(&sr, argp, sizeof(sr)))
+				return -EFAULT;
 			if (sr.volNumber < 0) {
 				server->m.mounted_vol[0] = 0;
 				vnum = NCP_NUMBER_OF_VOLUMES;
@@ -219,15 +316,10 @@
 				dosde = 0;
 			} else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
 				return -EINVAL;
-			} else {
-				struct nw_info_struct ni;
-				
-				if (ncp_mount_subdir(server, &ni, sr.volNumber,
-						sr.namespace, sr.dirEntNum))
-					return -ENOENT;
-				vnum = ni.volNumber;
-				de = ni.dirEntNum;
-				dosde = ni.DosDirNum;
+			} else if (ncp_mount_subdir(server, sr.volNumber,
+						sr.namespace, sr.dirEntNum,
+						&vnum, &de, &dosde)) {
+				return -ENOENT;
 			}
 			
 			dentry = inode->i_sb->s_root;
@@ -254,13 +346,13 @@
 		{
 			return -EACCES;
 		}
-		if (arg) {
+		if (argp) {
 			if (server->sign_wanted)
 			{
 				struct ncp_sign_init sign;
 
-				if (copy_from_user(&sign, (struct ncp_sign_init *) arg,
-				      sizeof(sign))) return -EFAULT;
+				if (copy_from_user(&sign, argp, sizeof(sign)))
+					return -EFAULT;
 				memcpy(server->sign_root,sign.sign_root,8);
 				memcpy(server->sign_last,sign.sign_last,16);
 				server->sign_active = 1;
@@ -278,7 +370,7 @@
 			return -EACCES;
 		}
 		
-                if (put_user(server->sign_wanted, (int*) arg))
+                if (put_user(server->sign_wanted, (int __user *)argp))
 			return -EFAULT;
                 return 0;
 	case NCP_IOC_SET_SIGN_WANTED:
@@ -291,7 +383,7 @@
 				return -EACCES;
 			}
 			/* get only low 8 bits... */
-			if (get_user(newstate, (unsigned char *) arg))
+			if (get_user(newstate, (unsigned char __user *)argp))
 				return -EFAULT;
 			if (server->sign_active) {
 				/* cannot turn signatures OFF when active */
@@ -315,8 +407,8 @@
 			struct ncp_lock_ioctl	 rqdata;
 			int result;
 
-			if (copy_from_user(&rqdata, (struct ncp_lock_ioctl*)arg,
-				sizeof(rqdata))) return -EFAULT;
+			if (copy_from_user(&rqdata, argp, sizeof(rqdata)))
+				return -EFAULT;
 			if (rqdata.origin != 0)
 				return -EINVAL;
 			/* check for cmd */
@@ -386,9 +478,8 @@
 			struct ncp_objectname_ioctl user;
 			size_t outl;
 
-			if (copy_from_user(&user, 
-					   (struct ncp_objectname_ioctl*)arg,
-					   sizeof(user))) return -EFAULT;
+			if (copy_from_user(&user, argp, sizeof(user)))
+				return -EFAULT;
 			user.auth_type = server->auth.auth_type;
 			outl = user.object_name_len;
 			user.object_name_len = server->auth.object_name_len;
@@ -399,9 +490,8 @@
 						 server->auth.object_name,
 						 outl)) return -EFAULT;
 			}
-			if (copy_to_user((struct ncp_objectname_ioctl*)arg,
-					 &user,
-					 sizeof(user))) return -EFAULT;
+			if (copy_to_user(argp, &user, sizeof(user)))
+				return -EFAULT;
 			return 0;
 		}
 	case NCP_IOC_SETOBJECTNAME:
@@ -416,9 +506,8 @@
 			void* oldprivate;
 			size_t oldprivatelen;
 
-			if (copy_from_user(&user, 
-					   (struct ncp_objectname_ioctl*)arg,
-					   sizeof(user))) return -EFAULT;
+			if (copy_from_user(&user, argp, sizeof(user)))
+				return -EFAULT;
 			if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
 				return -ENOMEM;
 			if (user.object_name_len) {
@@ -456,9 +545,8 @@
 			struct ncp_privatedata_ioctl user;
 			size_t outl;
 
-			if (copy_from_user(&user, 
-					   (struct ncp_privatedata_ioctl*)arg,
-					   sizeof(user))) return -EFAULT;
+			if (copy_from_user(&user, argp, sizeof(user)))
+				return -EFAULT;
 			outl = user.len;
 			user.len = server->priv.len;
 			if (outl > user.len) outl = user.len;
@@ -467,9 +555,8 @@
 						 server->priv.data,
 						 outl)) return -EFAULT;
 			}
-			if (copy_to_user((struct ncp_privatedata_ioctl*)arg,
-					 &user,
-					 sizeof(user))) return -EFAULT;
+			if (copy_to_user(argp, &user, sizeof(user)))
+				return -EFAULT;
 			return 0;
 		}
 	case NCP_IOC_SETPRIVATEDATA:
@@ -482,9 +569,8 @@
 			void* old;
 			size_t oldlen;
 
-			if (copy_from_user(&user, 
-					   (struct ncp_privatedata_ioctl*)arg,
-					   sizeof(user))) return -EFAULT;
+			if (copy_from_user(&user, argp, sizeof(user)))
+				return -EFAULT;
 			if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
 				return -ENOMEM;
 			if (user.len) {
@@ -508,105 +594,14 @@
 		}
 
 #ifdef CONFIG_NCPFS_NLS
-/* Here we are select the iocharset and the codepage for NLS.
- * Thanks Petr Vandrovec for idea and many hints.
- */
 	case NCP_IOC_SETCHARSETS:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EACCES;
-		if (server->root_setuped)
-			return -EBUSY;
-
-		{
-			struct ncp_nls_ioctl user;
-			struct nls_table *codepage;
-			struct nls_table *iocharset;
-			struct nls_table *oldset_io;
-			struct nls_table *oldset_cp;
-			
-			if (copy_from_user(&user, (struct ncp_nls_ioctl*)arg,
-					sizeof(user)))
-				return -EFAULT;
-
-			codepage = NULL;
-			user.codepage[NCP_IOCSNAME_LEN] = 0;
-			if (!user.codepage[0] ||
-					!strcmp(user.codepage, "default"))
-				codepage = load_nls_default();
-			else {
-				codepage = load_nls(user.codepage);
-				if (!codepage) {
-					return -EBADRQC;
-				}
-			}
-
-			iocharset = NULL;
-			user.iocharset[NCP_IOCSNAME_LEN] = 0;
-			if (!user.iocharset[0] ||
-					!strcmp(user.iocharset, "default")) {
-				iocharset = load_nls_default();
-				NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
-			} else {
-				if (!strcmp(user.iocharset, "utf8")) {
-					iocharset = load_nls_default();
-					NCP_SET_FLAG(server, NCP_FLAG_UTF8);
-				} else {
-					iocharset = load_nls(user.iocharset);
-					if (!iocharset) {
-						unload_nls(codepage);
-						return -EBADRQC;
-					}
-					NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
-				}
-			}
-
-			oldset_cp = server->nls_vol;
-			server->nls_vol = codepage;
-			oldset_io = server->nls_io;
-			server->nls_io = iocharset;
-
-			if (oldset_cp)
-				unload_nls(oldset_cp);
-			if (oldset_io)
-				unload_nls(oldset_io);
-
-			return 0;
-		}
+		return ncp_set_charsets(server, argp);
 		
-	case NCP_IOC_GETCHARSETS: /* not tested */
-		{
-			struct ncp_nls_ioctl user;
-			int len;
-
-			memset(&user, 0, sizeof(user));
-			if (server->nls_vol && server->nls_vol->charset) {
-				len = strlen(server->nls_vol->charset);
-				if (len > NCP_IOCSNAME_LEN)
-					len = NCP_IOCSNAME_LEN;
-				strncpy(user.codepage,
-						server->nls_vol->charset, len);
-				user.codepage[len] = 0;
-			}
-
-			if (NCP_IS_FLAG(server, NCP_FLAG_UTF8))
-				strcpy(user.iocharset, "utf8");
-			else
-				if (server->nls_io && server->nls_io->charset) {
-					len = strlen(server->nls_io->charset);
-					if (len > NCP_IOCSNAME_LEN)
-						len = NCP_IOCSNAME_LEN;
-					strncpy(user.iocharset,
-						server->nls_io->charset, len);
-					user.iocharset[len] = 0;
-				}
-
-			if (copy_to_user((struct ncp_nls_ioctl*)arg, &user,
-					sizeof(user)))
-				return -EFAULT;
+	case NCP_IOC_GETCHARSETS:
+		return ncp_get_charsets(server, argp);
 
-			return 0;
-		}
 #endif /* CONFIG_NCPFS_NLS */
+
 	case NCP_IOC_SETDENTRYTTL:
 		if ((permission(inode, MAY_WRITE, NULL) != 0) &&
 				 (current->uid != server->m.mounted_uid))
@@ -614,7 +609,7 @@
 		{
 			u_int32_t user;
 
-			if (copy_from_user(&user, (u_int32_t*)arg, sizeof(user)))
+			if (copy_from_user(&user, argp, sizeof(user)))
 				return -EFAULT;
 			/* 20 secs at most... */
 			if (user > 20000)
@@ -627,7 +622,7 @@
 	case NCP_IOC_GETDENTRYTTL:
 		{
 			u_int32_t user = (server->dentry_ttl * 1000) / HZ;
-			if (copy_to_user((u_int32_t*)arg, &user, sizeof(user)))
+			if (copy_to_user(argp, &user, sizeof(user)))
 				return -EFAULT;
 			return 0;
 		}
@@ -643,7 +638,7 @@
 			return -EACCES;
 		}
 		SET_UID(uid, server->m.mounted_uid);
-		if (put_user(uid, (__kernel_uid_t *) arg))
+		if (put_user(uid, (__kernel_uid_t __user *)argp))
 			return -EFAULT;
 		return 0;
 	}
diff -Nru a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
--- a/fs/ncpfs/ncplib_kernel.c	2004-06-23 19:04:26 -07:00
+++ b/fs/ncpfs/ncplib_kernel.c	2004-06-23 19:04:26 -07:00
@@ -536,37 +536,34 @@
 }
 
 int
-ncp_mount_subdir(struct ncp_server *server, struct nw_info_struct *i,
-			__u8 volNumber, __u8 srcNS, __u32 dirEntNum)
+ncp_mount_subdir(struct ncp_server *server,
+		 __u8 volNumber, __u8 srcNS, __u32 dirEntNum,
+		 __u32* volume, __u32* newDirEnt, __u32* newDosEnt)
 {
 	int dstNS;
 	int result;
-	__u32 newDirEnt;
-	__u32 newDosEnt;
 	
 	dstNS = ncp_get_known_namespace(server, volNumber);
 	if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, 
-				      dirEntNum, NULL, &newDirEnt, &newDosEnt)) != 0)
+				      dirEntNum, NULL, newDirEnt, newDosEnt)) != 0)
 	{
 		return result;
 	}
 	server->name_space[volNumber] = dstNS;
-	i->volNumber = volNumber;
-	i->dirEntNum = newDirEnt;
-	i->DosDirNum = newDosEnt;
+	*volume = volNumber;
 	server->m.mounted_vol[1] = 0;
 	server->m.mounted_vol[0] = 'X';
 	return 0;
 }
 
 int 
-ncp_lookup_volume(struct ncp_server *server, char *volname,
-		      struct nw_info_struct *target)
+ncp_get_volume_root(struct ncp_server *server, const char *volname,
+		    __u32* volume, __u32* dirent, __u32* dosdirent)
 {
 	int result;
-	int volnum;
+	__u8 volnum;
 
-	DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
+	DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname);
 
 	ncp_init_request(server);
 	ncp_add_byte(server, 22);	/* Subfunction: Generate dir handle */
@@ -585,16 +582,31 @@
 		ncp_unlock_server(server);
 		return result;
 	}
-	memset(target, 0, sizeof(*target));
-	target->DosDirNum = target->dirEntNum = ncp_reply_dword(server, 4);
-	target->volNumber = volnum = ncp_reply_byte(server, 8);
+	*dirent = *dosdirent = ncp_reply_dword(server, 4);
+	volnum = ncp_reply_byte(server, 8);
 	ncp_unlock_server(server);
+	*volume = volnum;
 
 	server->name_space[volnum] = ncp_get_known_namespace(server, volnum);
 
 	DPRINTK("lookup_vol: namespace[%d] = %d\n",
 		volnum, server->name_space[volnum]);
 
+	return 0;
+}
+
+int
+ncp_lookup_volume(struct ncp_server *server, const char *volname,
+		  struct nw_info_struct *target)
+{
+	int result;
+
+	memset(target, 0, sizeof(*target));
+	result = ncp_get_volume_root(server, volname,
+			&target->volNumber, &target->dirEntNum, &target->DosDirNum);
+	if (result) {
+		return result;
+	}
 	target->nameLen = strlen(volname);
 	memcpy(target->entryName, volname, target->nameLen+1);
 	target->attributes = aDIR;
diff -Nru a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
--- a/fs/ncpfs/ncplib_kernel.h	2004-06-23 19:04:26 -07:00
+++ b/fs/ncpfs/ncplib_kernel.h	2004-06-23 19:04:26 -07:00
@@ -70,7 +70,9 @@
 int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
 		struct nw_info_struct *target);
 int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
-int ncp_lookup_volume(struct ncp_server *, char *, struct nw_info_struct *);
+int ncp_get_volume_root(struct ncp_server *server, const char *volname,
+			__u32 *volume, __u32 *dirent, __u32 *dosdirent);
+int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *);
 int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *,
 	 __u32, const struct nw_modify_dos_info *info);
 int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *,
@@ -111,8 +113,8 @@
 #endif	/* CONFIG_NCPFS_IOCTL_LOCKING */
 
 int
-ncp_mount_subdir(struct ncp_server *, struct nw_info_struct *,
-			__u8, __u8, __u32);
+ncp_mount_subdir(struct ncp_server *, __u8, __u8, __u32,
+		 __u32* volume, __u32* dirent, __u32* dosdirent);
 int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __u32 dirent, __u8 *dirhandle);
 int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle);
 
diff -Nru a/fs/nfs/direct.c b/fs/nfs/direct.c
--- a/fs/nfs/direct.c	2004-06-23 19:04:28 -07:00
+++ b/fs/nfs/direct.c	2004-06-23 19:04:28 -07:00
@@ -475,7 +475,7 @@
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
 	struct iovec iov = {
-		.iov_base = (char *)buf,
+		.iov_base = buf,
 		.iov_len = count,
 	};
 
diff -Nru a/fs/nfs/idmap.c b/fs/nfs/idmap.c
--- a/fs/nfs/idmap.c	2004-06-23 19:04:26 -07:00
+++ b/fs/nfs/idmap.c	2004-06-23 19:04:26 -07:00
@@ -75,9 +75,10 @@
 	struct idmap_hashtable idmap_group_hash;
 };
 
-static ssize_t   idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *, char *,
-                     size_t);
-static ssize_t   idmap_pipe_downcall(struct file *, const char *, size_t);
+static ssize_t   idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *,
+		     char __user *, size_t);
+static ssize_t   idmap_pipe_downcall(struct file *, const char __user *,
+		     size_t);
 void             idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
 
 static unsigned int fnvhash32(const void *, size_t);
@@ -332,7 +333,7 @@
 /* RPC pipefs upcall/downcall routines */
 static ssize_t
 idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
-    char *dst, size_t buflen)
+    char __user *dst, size_t buflen)
 {
         char *data = (char *)msg->data + msg->copied;
         ssize_t mlen = msg->len - msg->copied;
@@ -353,7 +354,7 @@
 }
 
 static ssize_t
-idmap_pipe_downcall(struct file *filp, const char *src, size_t mlen)
+idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
 {
         struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
 	struct idmap *idmap = (struct idmap *)rpci->private;
diff -Nru a/fs/nls/Kconfig b/fs/nls/Kconfig
--- a/fs/nls/Kconfig	2004-06-23 19:04:25 -07:00
+++ b/fs/nls/Kconfig	2004-06-23 19:04:25 -07:00
@@ -332,6 +332,14 @@
 	  say Y here if you want to include the DOS codepage for Russian and
 	  Bulgarian and Belarusian.
 
+config NLS_ASCII
+	tristate "ASCII (United States)"
+	depends on NLS
+	help
+	  An ASCII NLS module is needed if you want to override the
+	  DEFAULT NLS with this very basic charset and don't want any
+	  non-ASCII characters to be translated.
+
 config NLS_ISO8859_1
 	tristate "NLS ISO 8859-1  (Latin 1; Western European Languages)"
 	depends on NLS
diff -Nru a/fs/nls/Makefile b/fs/nls/Makefile
--- a/fs/nls/Makefile	2004-06-23 19:04:25 -07:00
+++ b/fs/nls/Makefile	2004-06-23 19:04:25 -07:00
@@ -26,6 +26,7 @@
 obj-$(CONFIG_NLS_CODEPAGE_950)	+= nls_cp950.o
 obj-$(CONFIG_NLS_CODEPAGE_1250) += nls_cp1250.o
 obj-$(CONFIG_NLS_CODEPAGE_1251)	+= nls_cp1251.o
+obj-$(CONFIG_NLS_ASCII)		+= nls_ascii.o
 obj-$(CONFIG_NLS_ISO8859_1)	+= nls_iso8859-1.o
 obj-$(CONFIG_NLS_ISO8859_2)	+= nls_iso8859-2.o
 obj-$(CONFIG_NLS_ISO8859_3)	+= nls_iso8859-3.o
diff -Nru a/fs/nls/nls_ascii.c b/fs/nls/nls_ascii.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/nls/nls_ascii.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,167 @@
+/*
+ * linux/fs/nls_ascii.c
+ *
+ * Charset ascii translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/nls.h>
+#include <linux/errno.h>
+
+static wchar_t charset2uni[128] = {
+	/* 0x00*/
+	0x0000, 0x0001, 0x0002, 0x0003,
+	0x0004, 0x0005, 0x0006, 0x0007,
+	0x0008, 0x0009, 0x000a, 0x000b,
+	0x000c, 0x000d, 0x000e, 0x000f,
+	/* 0x10*/
+	0x0010, 0x0011, 0x0012, 0x0013,
+	0x0014, 0x0015, 0x0016, 0x0017,
+	0x0018, 0x0019, 0x001a, 0x001b,
+	0x001c, 0x001d, 0x001e, 0x001f,
+	/* 0x20*/
+	0x0020, 0x0021, 0x0022, 0x0023,
+	0x0024, 0x0025, 0x0026, 0x0027,
+	0x0028, 0x0029, 0x002a, 0x002b,
+	0x002c, 0x002d, 0x002e, 0x002f,
+	/* 0x30*/
+	0x0030, 0x0031, 0x0032, 0x0033,
+	0x0034, 0x0035, 0x0036, 0x0037,
+	0x0038, 0x0039, 0x003a, 0x003b,
+	0x003c, 0x003d, 0x003e, 0x003f,
+	/* 0x40*/
+	0x0040, 0x0041, 0x0042, 0x0043,
+	0x0044, 0x0045, 0x0046, 0x0047,
+	0x0048, 0x0049, 0x004a, 0x004b,
+	0x004c, 0x004d, 0x004e, 0x004f,
+	/* 0x50*/
+	0x0050, 0x0051, 0x0052, 0x0053,
+	0x0054, 0x0055, 0x0056, 0x0057,
+	0x0058, 0x0059, 0x005a, 0x005b,
+	0x005c, 0x005d, 0x005e, 0x005f,
+	/* 0x60*/
+	0x0060, 0x0061, 0x0062, 0x0063,
+	0x0064, 0x0065, 0x0066, 0x0067,
+	0x0068, 0x0069, 0x006a, 0x006b,
+	0x006c, 0x006d, 0x006e, 0x006f,
+	/* 0x70*/
+	0x0070, 0x0071, 0x0072, 0x0073,
+	0x0074, 0x0075, 0x0076, 0x0077,
+	0x0078, 0x0079, 0x007a, 0x007b,
+	0x007c, 0x007d, 0x007e, 0x007f,
+};
+
+static unsigned char page00[128] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+};
+
+static unsigned char *page_uni2charset[128] = {
+	page00, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+static unsigned char charset2lower[128] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+	0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+};
+
+static unsigned char charset2upper[128] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+	0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+};
+
+static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
+{
+	unsigned char *uni2charset;
+	unsigned char cl = uni & 0x00ff;
+	unsigned char ch = (uni & 0xff00) >> 8;
+
+	if (boundlen <= 0)
+		return -ENAMETOOLONG;
+
+	uni2charset = page_uni2charset[ch];
+	if (uni2charset && uni2charset[cl])
+		out[0] = uni2charset[cl];
+	else
+		return -EINVAL;
+	return 1;
+}
+
+static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
+{
+	*uni = charset2uni[*rawstring];
+	if (*uni == 0x0000)
+		return -EINVAL;
+	return 1;
+}
+
+static struct nls_table table = {
+	.charset	= "ascii",
+	.uni2char	= uni2char,
+	.char2uni	= char2uni,
+	.charset2lower	= charset2lower,
+	.charset2upper	= charset2upper,
+	.owner		= THIS_MODULE,
+};
+
+static int __init init_nls_ascii(void)
+{
+	return register_nls(&table);
+}
+
+static void __exit exit_nls_ascii(void)
+{
+	unregister_nls(&table);
+}
+
+module_init(init_nls_ascii)
+module_exit(exit_nls_ascii)
+
+MODULE_LICENSE("Dual BSD/GPL");
diff -Nru a/fs/partitions/Kconfig b/fs/partitions/Kconfig
--- a/fs/partitions/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/fs/partitions/Kconfig	2004-06-23 19:04:28 -07:00
@@ -187,13 +187,6 @@
 
 	  If unsure, say N.
 
-config NEC98_PARTITION
-	bool "NEC PC-9800 partition table support" if PARTITION_ADVANCED
-	default y if !PARTITION_ADVANCED && X86_PC9800
-	help
-	  Say Y here if you would like to be able to read the hard disk
-	  partition table format used by NEC PC-9800 machines.
-
 config SGI_PARTITION
 	bool "SGI partition support" if PARTITION_ADVANCED
 	default y if !PARTITION_ADVANCED && (SGI_IP22 || SGI_IP27)
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	2004-06-23 19:04:28 -07:00
+++ b/fs/partitions/check.c	2004-06-23 19:04:28 -07:00
@@ -29,7 +29,6 @@
 #include "ldm.h"
 #include "mac.h"
 #include "msdos.h"
-#include "nec98.h"
 #include "osf.h"
 #include "sgi.h"
 #include "sun.h"
diff -Nru a/fs/partitions/nec98.c b/fs/partitions/nec98.c
--- a/fs/partitions/nec98.c	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,188 +0,0 @@
-/*
- *  NEC PC-9800 series partition supports
- *
- *  Copyright (C) 1999	Kyoto University Microcomputer Club
- */
-
-#include <linux/config.h>
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/kernel.h>
-#include <linux/hdreg.h>
-
-#include "check.h"
-#include "nec98.h"
-
-struct nec98_partition {
-	__u8	mid;		/* 0x80 - active */
-	__u8	sid;		/* 0x80 - bootable */
-	__u16	pad1;		/* dummy for padding */
-	__u8	ipl_sector;	/* IPL sector	*/
-	__u8	ipl_head;	/* IPL head	*/
-	__u16	ipl_cyl;	/* IPL cylinder	*/
-	__u8	sector;		/* starting sector	*/
-	__u8	head;		/* starting head	*/
-	__u16	cyl;		/* starting cylinder	*/
-	__u8	end_sector;	/* end sector	*/
-	__u8	end_head;	/* end head	*/
-	__u16	end_cyl;	/* end cylinder	*/
-	unsigned char name[16];
-} __attribute__((__packed__));
-
-#define NEC98_BSD_PARTITION_MID 0x14
-#define NEC98_BSD_PARTITION_SID 0x44
-#define MID_SID_16(mid, sid)	(((mid) & 0xFF) | (((sid) & 0xFF) << 8))
-#define NEC98_BSD_PARTITION_MID_SID	\
-	MID_SID_16(NEC98_BSD_PARTITION_MID, NEC98_BSD_PARTITION_SID)
-#define NEC98_VALID_PTABLE_ENTRY(P) \
-	(!(P)->pad1 && (P)->cyl <= (P)->end_cyl)
-
-extern int pc98_bios_param(struct block_device *bdev, int *ip);
-
-static inline int
-is_valid_nec98_partition_table(const struct nec98_partition *ptable,
-				__u8 nsectors, __u8 nheads)
-{
-	int i;
-	int valid = 0;
-
-	for (i = 0; i < 16; i++) {
-		if (!*(__u16 *)&ptable[i])
-			continue;	/* empty slot */
-		if (ptable[i].pad1	/* `pad1' contains junk */
-		    || ptable[i].ipl_sector	>= nsectors
-		    || ptable[i].sector		>= nsectors
-		    || ptable[i].end_sector	>= nsectors
-		    || ptable[i].ipl_head	>= nheads
-		    || ptable[i].head		>= nheads
-		    || ptable[i].end_head	>= nheads
-		    || ptable[i].cyl > ptable[i].end_cyl)
-			return 0;
-		valid = 1;	/* We have a valid partition.  */
-	}
-	/* If no valid PC-9800-style partitions found,
-	   the disk may have other type of partition table.  */
-	return valid;
-}
-
-int nec98_partition(struct parsed_partitions *state, struct block_device *bdev)
-{
-	unsigned int nr;
-	struct hd_geometry geo;
-	Sector sect;
-	const struct nec98_partition *part;
-	unsigned char *data;
-	int sector_size = bdev_hardsect_size(bdev);
-
-	if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)&geo) != 0) {
-		printk(" unsupported disk (%s)\n", bdev->bd_disk->disk_name);
-		return 0;
-	}
-
-#ifdef NEC98_PARTITION_DEBUG
-	printk("ioctl_by_bdev head=%d sect=%d\n", geo.heads, geo.sectors);
-#endif
-	data = read_dev_sector(bdev, 0, &sect);
-	if (!data) {
-		if (warn_no_part)
-			printk(" unable to read partition table\n");
-		return -1;
-	}
-
-	/* magic(?) check */
-	if (*(__u16 *)(data + sector_size - 2) != NEC98_PTABLE_MAGIC) {
-		put_dev_sector(sect);
-		return 0;
-	}
-
-	put_dev_sector(sect);
-	data = read_dev_sector(bdev, 1, &sect);
-	if (!data) {
-		if (warn_no_part)
-			printk(" unable to read partition table\n");
-		return -1;
-	}
-
-	if (!is_valid_nec98_partition_table((struct nec98_partition *)data,
-					     geo.sectors, geo.heads)) {
-#ifdef NEC98_PARTITION_DEBUG
-		if (warn_no_part)
-			printk(" partition table consistency check failed"
-				" (not PC-9800 disk?)\n");
-#endif
-		put_dev_sector(sect);
-		return 0;
-	}
-
-	part = (const struct nec98_partition *)data;
-	for (nr = 0; nr < 16; nr++, part++) {
-		unsigned int start_sect, end_sect;
-
-		if (part->mid == 0 || part->sid == 0)
-			continue;
-
-		if (nr)
-			printk("     ");
-
-		{	/* Print partition name. Fdisk98 might put NUL
-			   characters in partition name... */
-
-			int j;
-			unsigned char *p;
-			unsigned char buf[sizeof (part->name) * 2 + 1];
-
-			for (p = buf, j = 0; j < sizeof (part->name); j++, p++)
-				if ((*p = part->name[j]) < ' ') {
-					*p++ = '^';
-					*p = part->name[j] + '@';
-				}
-
-			*p = 0;
-			printk(" <%s>", buf);
-		}
-		start_sect = (part->cyl * geo.heads + part->head) * geo.sectors
-			+ part->sector;
-		end_sect = (part->end_cyl + 1) * geo.heads * geo.sectors;
-		if (end_sect <= start_sect) {
-			printk(" (invalid partition info)\n");
-			continue;
-		}
-
-		put_partition(state, nr + 1, start_sect, end_sect - start_sect);
-#ifdef CONFIG_BSD_DISKLABEL
-		if ((*(__u16 *)&part->mid & 0x7F7F)
-		    == NEC98_BSD_PARTITION_MID_SID) {
-			printk("!");
-			/* NEC98_BSD_PARTITION_MID_SID is not valid SYSIND for
-			   IBM PC's MS-DOS partition table, so we simply pass
-			   it to bsd_disklabel_partition;
-			   it will just print `<bsd: ... >'. */
-			parse_bsd(state, bdev, start_sect,
-					end_sect - start_sect, nr + 1,
-					"bsd98", BSD_MAXPARTITIONS);
-		}
-#endif
-		{	/* Pretty size printing. */
-			/* XXX sector size? */
-			unsigned int psize = (end_sect - start_sect) / 2;
-			int unit_char = 'K';
-
-			if (psize > 99999) {
-				psize >>= 10;
-				unit_char = 'M';
-			}
-			printk(" %5d%cB (%5d-%5d)\n", 
-			       psize, unit_char, part->cyl, part->end_cyl);
-		}
-	}
-
-	put_dev_sector(sect);
-
-	return nr ? 1 : 0;
-}
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff -Nru a/fs/partitions/nec98.h b/fs/partitions/nec98.h
--- a/fs/partitions/nec98.h	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,10 +0,0 @@
-/*
- *  NEC PC-9800 series partition supports
- *
- *  Copyright (C) 1998-2000	Kyoto University Microcomputer Club
- */
-
-#define NEC98_PTABLE_MAGIC	0xAA55
-
-extern int nec98_partition(struct parsed_partitions *state,
-				struct block_device *bdev);
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	2004-06-23 19:04:27 -07:00
+++ b/fs/proc/base.c	2004-06-23 19:04:27 -07:00
@@ -1463,7 +1463,8 @@
 /*
  * /proc/self:
  */
-static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
+static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
+			      int buflen)
 {
 	char tmp[30];
 	sprintf(tmp, "%d", current->tgid);
@@ -1747,7 +1748,9 @@
 		ino_t ino = fake_ino(tgid,PROC_TGID_INO);
 		unsigned long j = PROC_NUMBUF;
 
-		do buf[--j] = '0' + (tgid % 10); while (tgid/=10);
+		do
+			buf[--j] = '0' + (tgid % 10);
+		while ((tgid /= 10) != 0);
 
 		if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) {
 			filp->f_version = tgid;
@@ -1799,7 +1802,7 @@
 
 		do
 			buf[--j] = '0' + (tid % 10);
-		while (tid /= 10);
+		while ((tid /= 10) != 0);
 
 		if (filldir(dirent, buf+j, PROC_NUMBUF-j, pos, ino, DT_DIR) < 0)
 			break;
diff -Nru a/fs/proc/generic.c b/fs/proc/generic.c
--- a/fs/proc/generic.c	2004-06-23 19:04:29 -07:00
+++ b/fs/proc/generic.c	2004-06-23 19:04:29 -07:00
@@ -288,18 +288,20 @@
  */
 static unsigned int get_inode_number(void)
 {
-	unsigned int i, inum = 0;
+	int i, inum = 0;
+	int error;
 
 retry:
 	if (idr_pre_get(&proc_inum_idr, GFP_KERNEL) == 0)
 		return 0;
 
 	spin_lock(&proc_inum_lock);
-	i = idr_get_new(&proc_inum_idr, NULL);
+	error = idr_get_new(&proc_inum_idr, NULL, &i);
 	spin_unlock(&proc_inum_lock);
-
-	if (i == -1)
+	if (error == -EAGAIN)
 		goto retry;
+	else if (error)
+		return 0;
 
 	inum = (i & MAX_ID_MASK) + PROC_DYNAMIC_FIRST;
 
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	2004-06-23 19:04:25 -07:00
+++ b/fs/proc/proc_misc.c	2004-06-23 19:04:25 -07:00
@@ -47,7 +47,6 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
-#include <asm/pgalloc.h>
 #include <asm/tlb.h>
 #include <asm/div64.h>
 
@@ -67,9 +66,6 @@
 extern int get_exec_domain_list(char *);
 extern int get_dma_list(char *);
 extern int get_locks_status (char *, char **, off_t, int);
-#ifdef CONFIG_SGI_DS1286
-extern int get_ds1286_status(char *);
-#endif
 
 static int proc_calc_metrics(char *page, char **start, off_t off,
 				 int count, int *eof, int len)
@@ -529,15 +525,6 @@
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
-#ifdef CONFIG_SGI_DS1286
-static int ds1286_read_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
-{
-	int len = get_ds1286_status(page);
-	return proc_calc_metrics(page, start, off, count, eof, len);
-}
-#endif
-
 static int locks_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
@@ -671,9 +658,6 @@
 		{"devices",	devices_read_proc},
 		{"filesystems",	filesystems_read_proc},
 		{"cmdline",	cmdline_read_proc},
-#ifdef CONFIG_SGI_DS1286
-		{"rtc",		ds1286_read_proc},
-#endif
 		{"locks",	locks_read_proc},
 		{"execdomains",	execdomains_read_proc},
 		{NULL,}
diff -Nru a/fs/quota.c b/fs/quota.c
--- a/fs/quota.c	2004-06-23 19:04:28 -07:00
+++ b/fs/quota.c	2004-06-23 19:04:28 -07:00
@@ -150,7 +150,7 @@
 }
 
 /* Copy parameters and call proper function */
-static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr)
+static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void __user *addr)
 {
 	int ret;
 
@@ -264,7 +264,7 @@
  * calls. Maybe we need to add the process quotas etc. in the future,
  * but we probably should use rlimits for that.
  */
-asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr)
+asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, void __user *addr)
 {
 	uint cmds, type;
 	struct super_block *sb = NULL;
diff -Nru a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
--- a/fs/reiserfs/bitmap.c	2004-06-23 19:04:27 -07:00
+++ b/fs/reiserfs/bitmap.c	2004-06-23 19:04:27 -07:00
@@ -30,6 +30,9 @@
 #define  _ALLOC_hashed_formatted_nodes 7
 #define  _ALLOC_old_way 8
 #define  _ALLOC_hundredth_slices 9
+#define  _ALLOC_dirid_groups 10
+#define  _ALLOC_oid_groups 11
+#define  _ALLOC_packing_groups 12
 
 #define  concentrating_formatted_nodes(s)	test_bit(_ALLOC_concentrating_formatted_nodes, &SB_ALLOC_OPTS(s))
 #define  displacing_large_files(s)		test_bit(_ALLOC_displacing_large_files, &SB_ALLOC_OPTS(s))
@@ -150,11 +153,6 @@
        __wait_on_buffer (bi->bh);
     }
 
-    /* If we know that first zero bit is only one or first zero bit is
-       closer to the end of bitmap than our start pointer */
-    if (bi->first_zero_hint > *beg || bi->free_count == 1)
-	*beg = bi->first_zero_hint;
-
     while (1) {
 	cont:
 	if (bi->free_count < min)
@@ -204,21 +202,12 @@
 		    while (--i >= *beg)
 			reiserfs_test_and_clear_le_bit (i, bi->bh->b_data);
 		    reiserfs_restore_prepared_buffer (s, bi->bh);
-		    *beg = max(org, (int)bi->first_zero_hint);
+		    *beg = org;
 		    /* ... and search again in current block from beginning */
 		    goto cont;	
 		}
 	    }
 	    bi->free_count -= (end - *beg);
-
-	    /* if search started from zero_hint bit, and zero hint have not
-                changed since, then we need to update first_zero_hint */
-	    if ( bi->first_zero_hint >= *beg)
-		/* no point in looking for free bit if there is not any */
-		bi->first_zero_hint = (bi->free_count > 0 ) ?
-			reiserfs_find_next_zero_le_bit
-			((unsigned long*)(bi->bh->b_data), s->s_blocksize << 3, end) : (s->s_blocksize << 3);
-
 	    journal_mark_dirty (th, s, bi->bh);
 
 	    /* free block count calculation */
@@ -231,7 +220,57 @@
 	    *beg = next;
 	}
     }
-  }
+}
+
+static int bmap_hash_id(struct super_block *s, u32 id) {
+    char * hash_in = NULL;
+    unsigned long hash;
+    unsigned bm;
+
+    if (id <= 2) {
+	bm = 1;
+    } else {
+        hash_in = (char *)(&id);
+        hash = keyed_hash(hash_in, 4);
+	bm = hash % SB_BMAP_NR(s);
+	if (!bm)
+	    bm = 1;
+    }
+    return bm;
+}
+
+/*
+ * hashes the id and then returns > 0 if the block group for the
+ * corresponding hash is full
+ */
+static inline int block_group_used(struct super_block *s, u32 id) {
+    int bm;
+    bm = bmap_hash_id(s, id);
+    if (SB_AP_BITMAP(s)[bm].free_count > ((s->s_blocksize << 3) * 60 / 100) ) {
+        return 0;
+    }
+    return 1;
+}
+
+/*
+ * the packing is returned in disk byte order
+ */
+u32 reiserfs_choose_packing(struct inode *dir) {
+    u32 packing;
+    if (TEST_OPTION(packing_groups, dir->i_sb)) {
+	u32 parent_dir = le32_to_cpu(INODE_PKEY(dir)->k_dir_id);
+	/*
+	 * some versions of reiserfsck expect packing locality 1 to be
+	 * special
+	 */
+	if (parent_dir == 1 || block_group_used(dir->i_sb,parent_dir))
+            packing = INODE_PKEY(dir)->k_objectid;
+        else
+            packing = INODE_PKEY(dir)->k_dir_id;
+    } else
+        packing = INODE_PKEY(dir)->k_objectid;
+    return packing;
+}
   
 /* Tries to find contiguous zero bit window (given size) in given region of
  * bitmap and place new blocks there. Returns number of allocated blocks. */
@@ -255,8 +294,18 @@
     get_bit_address (s, *start, &bm, &off);
     get_bit_address (s, finish, &end_bm, &end_off);
 
-    // With this option set first we try to find a bitmap that is at least 10%
-    // free, and if that fails, then we fall back to old whole bitmap scanning
+    /* When the bitmap is more than 10% free, anyone can allocate.
+     * When it's less than 10% free, only files that already use the
+     * bitmap are allowed. Once we pass 80% full, this restriction
+     * is lifted.
+     *
+     * We do this so that files that grow later still have space close to
+     * their original allocation. This improves locality, and presumably
+     * performance as a result.
+     *
+     * This is only an allocation policy and does not make up for getting a
+     * bad hint. Decent hinting must be implemented for this to work well.
+     */
     if ( TEST_OPTION(skip_busy, s) && SB_FREE_BLOCKS(s) > SB_BLOCK_COUNT(s)/20 ) {
 	for (;bm < end_bm; bm++, off = 0) {
 	    if ( ( off && (!unfm || (file_block != 0))) || SB_AP_BITMAP(s)[bm].free_count > (s->s_blocksize << 3) / 10 )
@@ -314,9 +363,6 @@
 			  "free_block (%s:%lu)[dev:blocknr]: bit already cleared",
 			  reiserfs_bdevname (s), block);
     }
-    if (offset < apbi[nr].first_zero_hint) {
-      apbi[nr].first_zero_hint = offset;
-    }
     apbi[nr].free_count ++;
     journal_mark_dirty (th, s, apbi[nr].bh);
 
@@ -396,6 +442,14 @@
 	__discard_prealloc(th, ei);
     }
 }
+
+void reiserfs_init_alloc_options (struct super_block *s)
+{
+    set_bit (_ALLOC_skip_busy, &SB_ALLOC_OPTS(s));
+    set_bit (_ALLOC_dirid_groups, &SB_ALLOC_OPTS(s));
+    set_bit (_ALLOC_packing_groups, &SB_ALLOC_OPTS(s));
+}
+
 /* block allocator related options are parsed here */
 int reiserfs_parse_alloc_options(struct super_block * s, char * options)
 {
@@ -439,6 +493,18 @@
 	    continue;
 	}
 
+        if (!strcmp(this_char, "dirid_groups")) {
+	    SET_OPTION(dirid_groups);
+	    continue;
+        }
+        if (!strcmp(this_char, "oid_groups")) {
+	    SET_OPTION(oid_groups);
+	    continue;
+        }
+        if (!strcmp(this_char, "packing_groups")) {
+	    SET_OPTION(packing_groups);
+	    continue;
+        }
 	if (!strcmp(this_char, "hashed_formatted_nodes")) {
 	    SET_OPTION(hashed_formatted_nodes);
 	    continue;
@@ -481,6 +547,7 @@
 	return 1;
       }
   
+    reiserfs_warning (s, "allocator options = [%08x]\n", SB_ALLOC_OPTS(s));
     return 0;
 }
   
@@ -503,17 +570,76 @@
     hint->search_start = hint->beg + keyed_hash(hash_in, 4) % (hint->end - hint->beg);
 }
 
-static inline void get_left_neighbor(reiserfs_blocknr_hint_t *hint)
+/*
+ * Relocation based on dirid, hashing them into a given bitmap block
+ * files. Formatted nodes are unaffected, a seperate policy covers them
+ */
+static void
+dirid_groups (reiserfs_blocknr_hint_t *hint)
+{
+    unsigned long hash;
+    __u32 dirid = 0;
+    int bm = 0;
+    struct super_block *sb = hint->th->t_super;
+    if (hint->inode)
+	dirid = le32_to_cpu(INODE_PKEY(hint->inode)->k_dir_id);
+    else if (hint->formatted_node)
+        dirid = hint->key.k_dir_id;
+
+    if (dirid) {
+	bm = bmap_hash_id(sb, dirid);
+	hash = bm * (sb->s_blocksize << 3);
+	/* give a portion of the block group to metadata */
+	if (hint->inode)
+	    hash += sb->s_blocksize/2;
+	hint->search_start = hash;
+    }
+}
+
+/*
+ * Relocation based on oid, hashing them into a given bitmap block
+ * files. Formatted nodes are unaffected, a seperate policy covers them
+ */
+static void
+oid_groups (reiserfs_blocknr_hint_t *hint)
+{
+    if (hint->inode) {
+	unsigned long hash;
+	__u32 oid;
+	__u32 dirid;
+	int bm;
+
+	dirid = le32_to_cpu(INODE_PKEY(hint->inode)->k_dir_id);
+
+	/* keep the root dir and it's first set of subdirs close to
+	 * the start of the disk
+	 */
+	if (dirid <= 2)
+	    hash = (hint->inode->i_sb->s_blocksize << 3);
+	else {
+	    oid = le32_to_cpu(INODE_PKEY(hint->inode)->k_objectid);
+	    bm = bmap_hash_id(hint->inode->i_sb, oid);
+	    hash = bm * (hint->inode->i_sb->s_blocksize << 3);
+	}
+	hint->search_start = hash;
+    }
+}
+
+/* returns 1 if it finds an indirect item and gets valid hint info
+ * from it, otherwise 0
+ */
+static int get_left_neighbor(reiserfs_blocknr_hint_t *hint)
 {
     struct path * path;
     struct buffer_head * bh;
     struct item_head * ih;
     int pos_in_item;
     __u32 * item;
+    int ret = 0;
 
     if (!hint->path)		/* reiserfs code can call this function w/o pointer to path
 				 * structure supplied; then we rely on supplied search_start */
-	return;
+	return 0;
 
     path = hint->path;
     bh = get_last_bh(path);
@@ -534,15 +660,15 @@
 	    int t=get_block_num(item,pos_in_item);
 	    if (t) {
 		hint->search_start = t;
+		ret = 1;
 		break;
 	    }
 	    pos_in_item --;
 	}
-    } else {
-      }
+    }
 
     /* does result value fit into specified region? */
-    return;
+    return ret;
 }
 
 /* should be, if formatted node, then try to put on first part of the device
@@ -639,10 +765,12 @@
     }
 }
   
-static inline void determine_search_start(reiserfs_blocknr_hint_t *hint,
+static void determine_search_start(reiserfs_blocknr_hint_t *hint,
 					  int amount_needed)
 {
     struct super_block *s = hint->th->t_super;
+    int unfm_hint;
+
     hint->beg = 0;
     hint->end = SB_BLOCK_COUNT(s) - 1;
 
@@ -673,19 +801,14 @@
 	return;
     }
 
-    /* attempt to copy a feature from old block allocator code */
-    if (TEST_OPTION(old_hashed_relocation, s) && !hint->formatted_node) {
-	old_hashed_relocation(hint);
-    }
-
     /* if none of our special cases is relevant, use the left neighbor in the
        tree order of the new node we are allocating for */
     if (hint->formatted_node && TEST_OPTION(hashed_formatted_nodes,s)) {
-	hash_formatted_node(hint);
+        hash_formatted_node(hint);
 	return;
-    } 
+    }
 
-    get_left_neighbor(hint);
+    unfm_hint = get_left_neighbor(hint);
 
     /* Mimic old block allocator behaviour, that is if VFS allowed for preallocation,
        new blocks are displaced based on directory ID. Also, if suggested search_start
@@ -710,10 +833,36 @@
 	return;
     }
 
-    if (TEST_OPTION(old_hashed_relocation, s))
+    /* old_hashed_relocation only works on unformatted */
+    if (!unfm_hint && !hint->formatted_node &&
+        TEST_OPTION(old_hashed_relocation, s))
+    {
 	old_hashed_relocation(hint);
-    if (TEST_OPTION(new_hashed_relocation, s))
+    }
+    /* new_hashed_relocation works with both formatted/unformatted nodes */
+    if ((!unfm_hint || hint->formatted_node) &&
+        TEST_OPTION(new_hashed_relocation, s))
+    {
 	new_hashed_relocation(hint);
+    }
+    /* dirid grouping works only on unformatted nodes */
+    if (!unfm_hint && !hint->formatted_node && TEST_OPTION(dirid_groups,s))
+    {
+        dirid_groups(hint);
+    }
+
+#ifdef DISPLACE_NEW_PACKING_LOCALITIES
+    if (hint->formatted_node && TEST_OPTION(dirid_groups,s))
+    {
+        dirid_groups(hint);
+    }
+#endif
+
+    /* oid grouping works only on unformatted nodes */
+    if (!unfm_hint && !hint->formatted_node && TEST_OPTION(oid_groups,s))
+    {
+        oid_groups(hint);
+    }
     return;
 }
 
@@ -738,13 +887,14 @@
 static inline int allocate_without_wrapping_disk (reiserfs_blocknr_hint_t * hint,
 					 b_blocknr_t * new_blocknrs,
 					 b_blocknr_t start, b_blocknr_t finish,
+					 int min,
 					 int amount_needed, int prealloc_size)
 {
     int rest = amount_needed;
     int nr_allocated;
   
     while (rest > 0 && start <= finish) {
-	nr_allocated = scan_bitmap (hint->th, &start, finish, 1,
+	nr_allocated = scan_bitmap (hint->th, &start, finish, min,
 				    rest + prealloc_size, !hint->formatted_node,
 				    hint->block);
 
@@ -777,8 +927,9 @@
     struct super_block *s = hint->th->t_super;
     b_blocknr_t start = hint->search_start;
     b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1;
-    int second_pass = 0;
+    int passno = 0;
     int nr_allocated = 0;
+    int bigalloc = 0;
 
     determine_prealloc_size(hint);
     if (!hint->formatted_node) {
@@ -797,32 +948,61 @@
 	    if (quota_ret)
 		hint->preallocate=hint->prealloc_size=0;
 	}
+	/* for unformatted nodes, force large allocations */
+	bigalloc = amount_needed;
     }
 
-    while((nr_allocated
-	  += allocate_without_wrapping_disk(hint, new_blocknrs + nr_allocated, start, finish,
-					  amount_needed - nr_allocated, hint->prealloc_size))
-	  < amount_needed) {
-
-	/* not all blocks were successfully allocated yet*/
-	if (second_pass) {	/* it was a second pass; we must free all blocks */
+    do {
+	/* in bigalloc mode, nr_allocated should stay zero until
+	 * the entire allocation is filled
+	 */
+	if (unlikely(bigalloc && nr_allocated)) {
+	    reiserfs_warning(s, "bigalloc is %d, nr_allocated %d\n",
+	    bigalloc, nr_allocated);
+	    /* reset things to a sane value */
+	    bigalloc = amount_needed - nr_allocated;
+	}
+	/*
+	 * try pass 0 and pass 1 looking for a nice big
+	 * contiguous allocation.  Then reset and look
+	 * for anything you can find.
+	 */
+	if (passno == 2 && bigalloc) {
+	    passno = 0;
+	    bigalloc = 0;
+	}
+	switch (passno++) {
+        case 0: /* Search from hint->search_start to end of disk */
+	    start = hint->search_start;
+	    finish = SB_BLOCK_COUNT(s) - 1;
+	    break;
+        case 1: /* Search from hint->beg to hint->search_start */
+	    start = hint->beg;
+	    finish = hint->search_start;
+	    break;
+	case 2: /* Last chance: Search from 0 to hint->beg */
+	    start = 0;
+	    finish = hint->beg;
+	    break;
+	default: /* We've tried searching everywhere, not enough space */
+	    /* Free the blocks */
 	    if (!hint->formatted_node) {
 #ifdef REISERQUOTA_DEBUG
 		reiserfs_debug (s, "reiserquota: freeing (nospace) %d blocks id=%u", amount_needed + hint->prealloc_size - nr_allocated, hint->inode->i_uid);
 #endif
 		DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed + hint->prealloc_size - nr_allocated);     /* Free not allocated blocks */
 	    }
-	    while (nr_allocated --)
+  	    while (nr_allocated --)
 		reiserfs_free_block(hint->th, hint->inode, new_blocknrs[nr_allocated], !hint->formatted_node);
 
 	    return NO_DISK_SPACE;
-	} else {		/* refine search parameters for next pass */
-	    second_pass = 1;
-	    finish = start;
-	    start = 0;
-	    continue;
 	}
-    }
+    } while ((nr_allocated += allocate_without_wrapping_disk (hint,
+			    new_blocknrs + nr_allocated, start, finish,
+			    bigalloc ? bigalloc : 1,
+			    amount_needed - nr_allocated,
+			    hint->prealloc_size))
+			< amount_needed);
     if ( !hint->formatted_node &&
          amount_needed + hint->prealloc_size >
 	 nr_allocated + REISERFS_I(hint->inode)->i_prealloc_count) {
diff -Nru a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
--- a/fs/reiserfs/dir.c	2004-06-23 19:04:27 -07:00
+++ b/fs/reiserfs/dir.c	2004-06-23 19:04:27 -07:00
@@ -64,6 +64,7 @@
 
     /*  reiserfs_warning (inode->i_sb, "reiserfs_readdir 1: f_pos = %Ld", filp->f_pos);*/
 
+    path_to_entry.reada = PATH_READA;
     while (1) {
     research:
 	/* search the directory item, containing entry with specified key */
diff -Nru a/fs/reiserfs/file.c b/fs/reiserfs/file.c
--- a/fs/reiserfs/file.c	2004-06-23 19:04:25 -07:00
+++ b/fs/reiserfs/file.c	2004-06-23 19:04:25 -07:00
@@ -131,7 +131,7 @@
     struct buffer_head *bh; // Buffer head that contains items that we are going to deal with
     __u32 * item; // pointer to item we are going to deal with
     INITIALIZE_PATH(path); // path to item, that we are going to deal with.
-    b_blocknr_t allocated_blocks[blocks_to_allocate]; // Pointer to a place where allocated blocknumbers would be stored. Right now statically allocated, later that will change.
+    b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored.
     reiserfs_blocknr_hint_t hint; // hint structure for block allocator.
     size_t res; // return value of various functions that we call.
     int curr_block; // current block used to keep track of unmapped blocks.
@@ -144,10 +144,20 @@
     int modifying_this_item = 0; // Flag for items traversal code to keep track
 				 // of the fact that we already prepared
 				 // current block for journal
-
+    int will_prealloc = 0;
 
     RFALSE(!blocks_to_allocate, "green-9004: tried to allocate zero blocks?");
 
+    /* only preallocate if this is a small write */
+    if (REISERFS_I(inode)->i_prealloc_count ||
+       (!(write_bytes & (inode->i_sb->s_blocksize -1)) &&
+        blocks_to_allocate <
+        REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize))
+        will_prealloc = REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize;
+
+    allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) *
+    					sizeof(b_blocknr_t), GFP_NOFS);
+
     /* First we compose a key to point at the writing position, we want to do
        that outside of any locking region. */
     make_cpu_key (&key, inode, pos+1, TYPE_ANY, 3/*key length*/);
@@ -174,13 +184,7 @@
     hint.key = key.on_disk_key; // on disk key of file.
     hint.block = inode->i_blocks>>(inode->i_sb->s_blocksize_bits-9); // Number of disk blocks this file occupies already.
     hint.formatted_node = 0; // We are allocating blocks for unformatted node.
-
-    /* only preallocate if this is a small write */
-    if (blocks_to_allocate <
-        REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize)
-        hint.preallocate = 1;
-    else
-        hint.preallocate = 0;
+    hint.preallocate = will_prealloc;
 
     /* Call block allocator to allocate blocks */
     res = reiserfs_allocate_blocknrs(&hint, allocated_blocks, blocks_to_allocate, blocks_to_allocate);
@@ -467,6 +471,12 @@
     // the inode.
     //
     pathrelse(&path);
+    /*
+     * cleanup prellocation from previous writes
+     * if this is a partial block write
+     */
+    if (write_bytes & (inode->i_sb->s_blocksize -1))
+        reiserfs_discard_prealloc(th, inode);
     reiserfs_write_unlock(inode->i_sb);
 
     // go through all the pages/buffers and map the buffers to newly allocated
@@ -504,6 +514,7 @@
 
     RFALSE( curr_block > blocks_to_allocate, "green-9007: Used too many blocks? weird");
 
+    kfree(allocated_blocks);
     return 0;
 
 // Need to deal with transaction here.
@@ -517,6 +528,7 @@
     reiserfs_update_sd(th, inode); // update any changes we made to blk count
     journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1);
     reiserfs_write_unlock(inode->i_sb);
+    kfree(allocated_blocks);
 
     return res;
 }
@@ -585,9 +597,19 @@
     struct buffer_head *bh, *head;
     unsigned long i_size_index = inode->i_size >> PAGE_CACHE_SHIFT;
     int new;
+    int logit = reiserfs_file_data_log(inode);
+    struct super_block *s = inode->i_sb;
+    int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize;
+    struct reiserfs_transaction_handle th;
+    th.t_trans_id = 0;
 
     blocksize = 1 << inode->i_blkbits;
 
+    if (logit) {
+	reiserfs_write_lock(s);
+	journal_begin(&th, s, bh_per_page + 1);
+	reiserfs_update_inode_transaction(inode);
+    }
     for(bh = head = page_buffers(page), block_start = 0;
         bh != head || !block_start;
 	block_start=block_end, bh = bh->b_this_page)
@@ -601,7 +623,10 @@
 		    partial = 1;
 	} else {
 	    set_buffer_uptodate(bh);
-	    if (!buffer_dirty(bh)) {
+	    if (logit) {
+		reiserfs_prepare_for_journal(s, bh, 1);
+		journal_mark_dirty(&th, s, bh);
+	    } else if (!buffer_dirty(bh)) {
 		mark_buffer_dirty(bh);
 		/* do data=ordered on any page past the end
 		 * of file and any buffer marked BH_New.
@@ -613,7 +638,10 @@
 	    }
 	}
     }
-
+    if (logit) {
+	journal_end(&th, s, bh_per_page + 1);
+	reiserfs_write_unlock(s);
+    }
     /*
      * If this is a partial write which happened to make all buffers
      * uptodate then we can optimize away a bogus readpage() for
@@ -1254,6 +1282,7 @@
 	journal_end(&th, th.t_super, th.t_blocks_allocated);
         reiserfs_write_unlock(inode->i_sb);
     }
+
     if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
 	res = generic_osync_inode(inode, file->f_mapping, OSYNC_METADATA|OSYNC_DATA);
 
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	2004-06-23 19:04:26 -07:00
+++ b/fs/reiserfs/inode.c	2004-06-23 19:04:26 -07:00
@@ -1660,7 +1660,7 @@
     sb = dir->i_sb;
 
     /* item head of new item */
-    ih.ih_key.k_dir_id = INODE_PKEY (dir)->k_objectid;
+    ih.ih_key.k_dir_id = reiserfs_choose_packing(dir);
     ih.ih_key.k_objectid = cpu_to_le32 (reiserfs_get_unused_objectid (th));
     if (!ih.ih_key.k_objectid) {
 	err = -ENOMEM;
@@ -1729,7 +1729,6 @@
 	err = -EEXIST;
 	goto out_bad_inode;
     }
-
     if (old_format_only (sb)) {
 	if (inode->i_uid & ~0xffff || inode->i_gid & ~0xffff) {
 	    pathrelse (&path_to_key);
@@ -2148,6 +2147,11 @@
     struct buffer_head *head, *bh;
     int partial = 0 ;
     int nr = 0;
+    int checked = PageChecked(page);
+    struct reiserfs_transaction_handle th;
+    struct super_block *s = inode->i_sb;
+    int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize;
+    th.t_trans_id = 0;
 
     /* The page dirty bit is cleared before writepage is called, which
      * means we have to tell create_empty_buffers to make dirty buffers
@@ -2155,7 +2159,7 @@
      * in the BH_Uptodate is just a sanity check.
      */
     if (!page_has_buffers(page)) {
-	create_empty_buffers(page, inode->i_sb->s_blocksize, 
+	create_empty_buffers(page, s->s_blocksize,
 	                    (1 << BH_Dirty) | (1 << BH_Uptodate));
     }
     head = page_buffers(page) ;
@@ -2179,10 +2183,10 @@
 	kunmap_atomic(kaddr, KM_USER0) ;
     }
     bh = head ;
-    block = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits) ;
+    block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits) ;
     /* first map all the buffers, logging any direct items we find */
     do {
-	if (buffer_dirty(bh) && (!buffer_mapped(bh) ||
+	if ((checked || buffer_dirty(bh)) && (!buffer_mapped(bh) ||
 	   (buffer_mapped(bh) && bh->b_blocknr == 0))) {
 	    /* not mapped yet, or it points to a direct item, search
 	     * the btree for the mapping info, and log any direct
@@ -2196,6 +2200,18 @@
 	block++;
     } while(bh != head) ;
 
+    /*
+     * we start the transaction after map_block_for_writepage,
+     * because it can create holes in the file (an unbounded operation).
+     * starting it here, we can make a reliable estimate for how many
+     * blocks we're going to log
+     */
+    if (checked) {
+	ClearPageChecked(page);
+	reiserfs_write_lock(s);
+	journal_begin(&th, s, bh_per_page + 1);
+	reiserfs_update_inode_transaction(inode);
+    }
     /* now go through and lock any dirty buffers on the page */
     do {
 	get_bh(bh);
@@ -2204,6 +2220,11 @@
 	if (buffer_mapped(bh) && bh->b_blocknr == 0)
 	    continue;
 
+	if (checked) {
+	    reiserfs_prepare_for_journal(s, bh, 1);
+	    journal_mark_dirty(&th, s, bh);
+	    continue;
+	}
 	/* from this point on, we know the buffer is mapped to a
 	 * real block and not a direct item
 	 */
@@ -2222,6 +2243,10 @@
 	}
     } while((bh = bh->b_this_page) != head);
 
+    if (checked) {
+	journal_end(&th, s, bh_per_page + 1);
+	reiserfs_write_unlock(s);
+    }
     BUG_ON(PageWriteback(page));
     set_page_writeback(page);
     unlock_page(page);
@@ -2481,17 +2506,15 @@
     /* the page is locked, and the only places that log a data buffer
      * also lock the page.
      */
-#if 0
     if (reiserfs_file_data_log(inode)) {
-	/* very conservative, leave the buffer pinned if anyone might need it.
-	** this should be changed to drop the buffer if it is only in the
-	** current transaction
-	*/
+	/*
+	 * very conservative, leave the buffer pinned if
+	 * anyone might need it.
+	 */
         if (buffer_journaled(bh) || buffer_journal_dirty(bh)) {
 	    ret = 0 ;
 	}
     } else
-#endif
     if (buffer_dirty(bh) || buffer_locked(bh)) {
 	struct reiserfs_journal_list *jl;
 	struct reiserfs_jh *jh = bh->b_private;
@@ -2529,6 +2552,10 @@
     int ret = 1;
 
     BUG_ON(!PageLocked(page));
+
+    if (offset == 0)
+	ClearPageChecked(page);
+
     if (!page_has_buffers(page))
 	goto out;
 
@@ -2562,6 +2589,15 @@
     return ret;
 }
 
+static int reiserfs_set_page_dirty(struct page *page) {
+    struct inode *inode = page->mapping->host;
+    if (reiserfs_file_data_log(inode)) {
+	SetPageChecked(page);
+	return __set_page_dirty_nobuffers(page);
+    }
+    return __set_page_dirty_buffers(page);
+}
+
 /*
  * Returns 1 if the page's buffers were dropped.  The page is locked.
  *
@@ -2579,6 +2615,7 @@
     struct buffer_head *bh ;
     int ret = 1 ;
 
+    WARN_ON(PageChecked(page));
     spin_lock(&j->j_dirty_buffers_lock) ;
     head = page_buffers(page) ;
     bh = head ;
@@ -2684,5 +2721,6 @@
     .prepare_write = reiserfs_prepare_write,
     .commit_write = reiserfs_commit_write,
     .bmap = reiserfs_aop_bmap,
-    .direct_IO = reiserfs_direct_IO
+    .direct_IO = reiserfs_direct_IO,
+    .set_page_dirty = reiserfs_set_page_dirty,
 } ;
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c	2004-06-23 19:04:27 -07:00
+++ b/fs/reiserfs/journal.c	2004-06-23 19:04:27 -07:00
@@ -1024,7 +1024,6 @@
   up(&jl->j_commit_lock);
 put_jl:
   put_journal_list(s, jl);
-
   return 0 ;
 }
 
@@ -1544,14 +1543,18 @@
     unsigned long cur_len;
     int ret;
     int i;
+    int limit = 256;
     struct reiserfs_journal_list *tjl;
     struct reiserfs_journal_list *flush_jl;
     unsigned long trans_id;
 
     flush_jl = tjl = jl;
 
-    /* flush for 256 transactions or 256 blocks, whichever comes first */
-    for(i = 0 ; i < 256 && len < 256 ; i++) {
+    /* in data logging mode, try harder to flush a lot of blocks */
+    if (reiserfs_data_log(s))
+	limit = 1024;
+    /* flush for 256 transactions or limit blocks, whichever comes first */
+    for(i = 0 ; i < 256 && len < limit ; i++) {
 	if (atomic_read(&tjl->j_commit_left) ||
 	    tjl->j_trans_id < jl->j_trans_id) {
 	    break;
@@ -3482,10 +3485,16 @@
     /* copy all the real blocks into log area.  dirty log blocks */
     if (test_bit(BH_JDirty, &cn->bh->b_state)) {
       struct buffer_head *tmp_bh ;
+      char *addr;
+      struct page *page;
       tmp_bh =  journal_getblk(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + 
 		       ((cur_write_start + jindex) % SB_ONDISK_JOURNAL_SIZE(p_s_sb))) ;
       set_buffer_uptodate(tmp_bh);
-      memcpy(tmp_bh->b_data, cn->bh->b_data, cn->bh->b_size) ;  
+      page = cn->bh->b_page;
+      addr = kmap(page);
+      memcpy(tmp_bh->b_data, addr + offset_in_page(cn->bh->b_data),
+             cn->bh->b_size);
+      kunmap(page);
       mark_buffer_dirty(tmp_bh);
       jindex++ ;
       set_bit(BH_JDirty_wait, &(cn->bh->b_state)) ; 
diff -Nru a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
--- a/fs/reiserfs/stree.c	2004-06-23 19:04:27 -07:00
+++ b/fs/reiserfs/stree.c	2004-06-23 19:04:27 -07:00
@@ -596,26 +596,29 @@
 
 
 
-#ifdef SEARCH_BY_KEY_READA
+#define SEARCH_BY_KEY_READA 16
 
 /* The function is NOT SCHEDULE-SAFE! */
-static void search_by_key_reada (struct super_block * s, int blocknr)
+static void search_by_key_reada (struct super_block * s,
+                                 struct buffer_head **bh,
+				 unsigned long *b, int num)
 {
-    struct buffer_head * bh;
+    int i,j;
   
-    if (blocknr == 0)
-	return;
-
-    bh = sb_getblk (s, blocknr);
-  
-    if (!buffer_uptodate (bh)) {
-	ll_rw_block (READA, 1, &bh);
+    for (i = 0 ; i < num ; i++) {
+	bh[i] = sb_getblk (s, b[i]);
+    }
+    for (j = 0 ; j < i ; j++) {
+	/*
+	 * note, this needs attention if we are getting rid of the BKL
+	 * you have to make sure the prepared bit isn't set on this buffer
+	 */
+	if (!buffer_uptodate(bh[j]))
+	    ll_rw_block(READA, 1, bh + j);
+    	brelse(bh[j]);
     }
-    bh->b_count --;
 }
 
-#endif
-
 /**************************************************************************
  * Algorithm   SearchByKey                                                *
  *             look for item in the Disk S+Tree by its key                *
@@ -657,6 +660,9 @@
     int				n_node_level, n_retval;
     int 			right_neighbor_of_leaf_node;
     int				fs_gen;
+    struct buffer_head *reada_bh[SEARCH_BY_KEY_READA];
+    unsigned long      reada_blocks[SEARCH_BY_KEY_READA];
+    int reada_count = 0;
 
 #ifdef CONFIG_REISERFS_CHECK
     int n_repeat_counter = 0;
@@ -691,19 +697,25 @@
 	p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path, ++p_s_search_path->path_length);
 	fs_gen = get_generation (p_s_sb);
 
-#ifdef SEARCH_BY_KEY_READA
-	/* schedule read of right neighbor */
-	search_by_key_reada (p_s_sb, right_neighbor_of_leaf_node);
-#endif
-
 	/* Read the next tree node, and set the last element in the path to
            have a pointer to it. */
-	if ( ! (p_s_bh = p_s_last_element->pe_buffer =
-		sb_bread(p_s_sb, n_block_number)) ) {
+	if ((p_s_bh = p_s_last_element->pe_buffer =
+	     sb_getblk(p_s_sb, n_block_number)) ) {
+	    if (!buffer_uptodate(p_s_bh) && reada_count > 1) {
+		search_by_key_reada (p_s_sb, reada_bh,
+		                     reada_blocks, reada_count);
+	    }
+	    ll_rw_block(READ, 1, &p_s_bh);
+	    wait_on_buffer(p_s_bh);
+	    if (!buffer_uptodate(p_s_bh))
+	        goto io_error;
+	} else {
+io_error:
 	    p_s_search_path->path_length --;
 	    pathrelse(p_s_search_path);
 	    return IO_ERROR;
 	}
+	reada_count = 0;
 	if (expected_level == -1)
 		expected_level = SB_TREE_HEIGHT (p_s_sb);
 	expected_level --;
@@ -784,11 +796,36 @@
 	   position in the node. */
 	n_block_number = B_N_CHILD_NUM(p_s_bh, p_s_last_element->pe_position);
 
-#ifdef SEARCH_BY_KEY_READA
-	/* if we are going to read leaf node, then calculate its right neighbor if possible */
-	if (n_node_level == DISK_LEAF_NODE_LEVEL + 1 && p_s_last_element->pe_position < B_NR_ITEMS (p_s_bh))
-	    right_neighbor_of_leaf_node = B_N_CHILD_NUM(p_s_bh, p_s_last_element->pe_position + 1);
-#endif
+	/* if we are going to read leaf nodes, try for read ahead as well */
+	if ((p_s_search_path->reada & PATH_READA) &&
+	    n_node_level == DISK_LEAF_NODE_LEVEL + 1)
+	{
+	    int pos = p_s_last_element->pe_position;
+	    int limit = B_NR_ITEMS(p_s_bh);
+	    struct key *le_key;
+
+	    if (p_s_search_path->reada & PATH_READA_BACK)
+		limit = 0;
+	    while(reada_count < SEARCH_BY_KEY_READA) {
+		if (pos == limit)
+		    break;
+	        reada_blocks[reada_count++] = B_N_CHILD_NUM(p_s_bh, pos);
+		if (p_s_search_path->reada & PATH_READA_BACK)
+		    pos--;
+		else
+		    pos++;
+
+		/*
+		 * check to make sure we're in the same object
+		 */
+		le_key = B_N_PDELIM_KEY(p_s_bh, pos);
+		if (le32_to_cpu(le_key->k_objectid) !=
+		    p_s_key->on_disk_key.k_objectid)
+		{
+		    break;
+		}
+	    }
+        }
     }
 }
 
@@ -1458,6 +1495,41 @@
     reiserfs_delete_solid_item (th, inode, INODE_PKEY (inode));
 }
 
+static void
+unmap_buffers(struct page *page, loff_t pos) {
+    struct buffer_head *bh ;
+    struct buffer_head *head ;
+    struct buffer_head *next ;
+    unsigned long tail_index ;
+    unsigned long cur_index ;
+
+    if (page) {
+	if (page_has_buffers(page)) {
+	    tail_index = pos & (PAGE_CACHE_SIZE - 1) ;
+	    cur_index = 0 ;
+	    head = page_buffers(page) ;
+	    bh = head ;
+	    do {
+		next = bh->b_this_page ;
+
+		/* we want to unmap the buffers that contain the tail, and
+		** all the buffers after it (since the tail must be at the
+		** end of the file).  We don't want to unmap file data
+		** before the tail, since it might be dirty and waiting to
+		** reach disk
+		*/
+		cur_index += bh->b_size ;
+		if (cur_index > tail_index) {
+		    reiserfs_unmap_buffer(bh) ;
+		}
+		bh = next ;
+	    } while (bh != head) ;
+	    if ( PAGE_SIZE == bh->b_size ) {
+		clear_page_dirty(page);
+	    }
+	}
+    }
+}
 
 static int maybe_indirect_to_direct (struct reiserfs_transaction_handle *th, 
 			      struct inode * p_s_inode,
@@ -1550,7 +1622,7 @@
     char                c_mode;            /* Mode of the balance. */
     int retval2 = -1;
     int quota_cut_bytes;
-    
+    loff_t tail_pos = 0;
     
     init_tb_struct(th, &s_cut_balance, p_s_inode->i_sb, p_s_path, n_cut_size);
 
@@ -1590,6 +1662,7 @@
       	    set_cpu_key_k_type (p_s_item_key, TYPE_INDIRECT);
 	    p_s_item_key->key_length = 4;
 	    n_new_file_size -= (n_new_file_size & (p_s_sb->s_blocksize - 1));
+	    tail_pos = n_new_file_size;
 	    set_cpu_key_k_offset (p_s_item_key, n_new_file_size + 1);
 	    if ( search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path) == POSITION_NOT_FOUND ){
 		print_block (PATH_PLAST_BUFFER (p_s_path), 3, PATH_LAST_POSITION (p_s_path) - 1, PATH_LAST_POSITION (p_s_path) + 1);
@@ -1687,9 +1760,10 @@
     if ( n_is_inode_locked ) {
 	/* we've done an indirect->direct conversion.  when the data block
 	** was freed, it was removed from the list of blocks that must
-	** be flushed before the transaction commits, so we don't need to
-	** deal with it here.
+	** be flushed before the transaction commits, make sure to
+	** unmap and invalidate it
 	*/
+	unmap_buffers(page, tail_pos);
 	REISERFS_I(p_s_inode)->i_flags &= ~i_pack_on_close_mask ;
     }
 #ifdef REISERQUOTA_DEBUG
@@ -1778,6 +1852,12 @@
            space, this file would have this file size */
 	n_file_size = offset + bytes - 1;
     }
+    /*
+     * are we doing a full truncate or delete, if so
+     * kick in the reada code
+     */
+    if (n_new_file_size == 0)
+        s_search_path.reada = PATH_READA | PATH_READA_BACK;
 
     if ( n_file_size == 0 || n_file_size < n_new_file_size ) {
 	goto update_and_out ;
diff -Nru a/fs/reiserfs/super.c b/fs/reiserfs/super.c
--- a/fs/reiserfs/super.c	2004-06-23 19:04:26 -07:00
+++ b/fs/reiserfs/super.c	2004-06-23 19:04:26 -07:00
@@ -492,7 +492,6 @@
     REISERFS_I(inode)->i_acl_default = NULL;
 }
 
-
 struct super_operations reiserfs_sops = 
 {
   .alloc_inode = reiserfs_alloc_inode,
@@ -651,7 +650,7 @@
 	reiserfs_warning (s, "head of option \"%s\" is only correct", opt->option_name);
 	return -1;
     }
-	
+
     /* move to the argument, or to next option if argument is not required */
     p ++;
     
@@ -1345,14 +1344,16 @@
     memset (sbi, 0, sizeof (struct reiserfs_sb_info));
     /* Set default values for options: non-aggressive tails */
     REISERFS_SB(s)->s_mount_opt = ( 1 << REISERFS_SMALLTAIL );
-    /* default block allocator option: skip_busy */
-    REISERFS_SB(s)->s_alloc_options.bits = ( 1 << 5);
-    /* If file grew past 4 blocks, start preallocation blocks for it. */
-    REISERFS_SB(s)->s_alloc_options.preallocmin = 4;
+    /* no preallocation minimum, be smart in
+       reiserfs_file_write instead */
+    REISERFS_SB(s)->s_alloc_options.preallocmin = 0;
     /* Preallocate by 16 blocks (17-1) at once */
     REISERFS_SB(s)->s_alloc_options.preallocsize = 17;
     /* Initialize the rwsem for xattr dir */
     init_rwsem(&REISERFS_SB(s)->xattr_dir_sem);
+
+    /* setup default block allocator options */
+    reiserfs_init_alloc_options(s);
 
     jdev_name = NULL;
     if (reiserfs_parse_options (s, (char *) data, &(sbi->s_mount_opt), &blocks, &jdev_name, &commit_max_age) == 0) {
diff -Nru a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
--- a/fs/reiserfs/tail_conversion.c	2004-06-23 19:04:29 -07:00
+++ b/fs/reiserfs/tail_conversion.c	2004-06-23 19:04:29 -07:00
@@ -162,42 +162,6 @@
     unlock_buffer(bh) ;
 }
 
-static void
-unmap_buffers(struct page *page, loff_t pos) {
-  struct buffer_head *bh ;
-  struct buffer_head *head ;
-  struct buffer_head *next ;
-  unsigned long tail_index ;
-  unsigned long cur_index ;
-
-  if (page) {
-    if (page_has_buffers(page)) {
-      tail_index = pos & (PAGE_CACHE_SIZE - 1) ;
-      cur_index = 0 ;
-      head = page_buffers(page) ;
-      bh = head ;
-      do {
-	next = bh->b_this_page ;
-
-        /* we want to unmap the buffers that contain the tail, and
-        ** all the buffers after it (since the tail must be at the
-        ** end of the file).  We don't want to unmap file data 
-        ** before the tail, since it might be dirty and waiting to 
-        ** reach disk
-        */
-        cur_index += bh->b_size ;
-        if (cur_index > tail_index) {
-          reiserfs_unmap_buffer(bh) ;
-        }
-	bh = next ;
-      } while (bh != head) ;
-      if ( PAGE_SIZE == bh->b_size ) {
-	clear_page_dirty(page);
-      }
-    }
-  } 
-}
-
 /* this first locks inode (neither reads nor sync are permitted),
    reads tail through page cache, insert direct item. When direct item
    inserted successfully inode is left locked. Return value is always
@@ -286,11 +250,6 @@
 	return n_block_size - round_tail_len;
     }
     kunmap(page) ;
-
-    /* this will invalidate all the buffers in the page after
-    ** pos1
-    */
-    unmap_buffers(page, pos1) ;
 
     /* make sure to get the i_blocks changes from reiserfs_insert_item */
     reiserfs_update_sd(th, p_s_inode);
diff -Nru a/fs/super.c b/fs/super.c
--- a/fs/super.c	2004-06-23 19:04:26 -07:00
+++ b/fs/super.c	2004-06-23 19:04:26 -07:00
@@ -569,14 +569,19 @@
 int set_anon_super(struct super_block *s, void *data)
 {
 	int dev;
+	int error;
 
-	spin_lock(&unnamed_dev_lock);
-	if (idr_pre_get(&unnamed_dev_idr, GFP_ATOMIC) == 0) {
-		spin_unlock(&unnamed_dev_lock);
+ retry:
+	if (idr_pre_get(&unnamed_dev_idr, GFP_ATOMIC) == 0)
 		return -ENOMEM;
-	}
-	dev = idr_get_new(&unnamed_dev_idr, NULL);
+	spin_lock(&unnamed_dev_lock);
+	error = idr_get_new(&unnamed_dev_idr, NULL, &dev);
 	spin_unlock(&unnamed_dev_lock);
+	if (error == -EAGAIN)
+		/* We raced and lost with another CPU. */
+		goto retry;
+	else if (error)
+		return -EAGAIN;
 
 	if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) {
 		spin_lock(&unnamed_dev_lock);
diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
--- a/fs/sysfs/inode.c	2004-06-23 19:04:28 -07:00
+++ b/fs/sysfs/inode.c	2004-06-23 19:04:28 -07:00
@@ -46,8 +46,13 @@
 	struct inode * inode = NULL;
 	if (dentry) {
 		if (!dentry->d_inode) {
-			if ((inode = sysfs_new_inode(mode)))
+			if ((inode = sysfs_new_inode(mode))) {
+				if (dentry->d_parent && dentry->d_parent->d_inode) {
+					struct inode *p_inode = dentry->d_parent->d_inode;
+					p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
+				}
 				goto Proceed;
+			}
 			else 
 				error = -ENOMEM;
 		} else
diff -Nru a/fs/udf/crc.c b/fs/udf/crc.c
--- a/fs/udf/crc.c	2004-06-23 19:04:28 -07:00
+++ b/fs/udf/crc.c	2004-06-23 19:04:28 -07:00
@@ -84,7 +84,7 @@
  *	July 21, 1997 - Andrew E. Mileski
  *	Adapted from OSTA-UDF(tm) 1.50 standard.
  */
-extern uint16_t
+uint16_t
 udf_crc(uint8_t *data, uint32_t size, uint16_t crc)
 {
 	while (size--)
diff -Nru a/fs/udf/misc.c b/fs/udf/misc.c
--- a/fs/udf/misc.c	2004-06-23 19:04:27 -07:00
+++ b/fs/udf/misc.c	2004-06-23 19:04:27 -07:00
@@ -34,7 +34,7 @@
 #include "udf_i.h"
 #include "udf_sb.h"
 
-extern struct buffer_head *
+struct buffer_head *
 udf_tgetblk(struct super_block *sb, int block)
 {
 	if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
@@ -43,7 +43,7 @@
 		return sb_getblk(sb, block);
 }
 
-extern struct buffer_head *
+struct buffer_head *
 udf_tread(struct super_block *sb, int block)
 {
 	if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
@@ -52,7 +52,7 @@
 		return sb_bread(sb, block);
 }
 
-extern struct genericFormat *
+struct genericFormat *
 udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
 	uint8_t loc)
 {
@@ -157,7 +157,7 @@
 	return NULL;
 }
 
-extern struct genericFormat *
+struct genericFormat *
 udf_get_extendedattr(struct inode *inode, uint32_t type, uint8_t subtype)
 {
 	struct genericFormat *gaf;
@@ -207,7 +207,7 @@
  *	July 1, 1997 - Andrew E. Mileski
  *	Written, tested, and released.
  */
-extern struct buffer_head *
+struct buffer_head *
 udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint16_t *ident)
 {
 	tag *tag_p;
@@ -272,7 +272,7 @@
 	return NULL;
 }
 
-extern struct buffer_head *
+struct buffer_head *
 udf_read_ptagged(struct super_block *sb, lb_addr loc, uint32_t offset, uint16_t *ident)
 {
 	return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
diff -Nru a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
--- a/include/acpi/acpi_drivers.h	2004-06-23 19:04:28 -07:00
+++ b/include/acpi/acpi_drivers.h	2004-06-23 19:04:28 -07:00
@@ -55,7 +55,7 @@
 
 /* ACPI PCI Interrupt Link (pci_link.c) */
 
-int acpi_pci_link_check (void);
+int acpi_irq_penalty_init (void);
 int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low);
 
 /* ACPI PCI Interrupt Routing (pci_irq.c) */
diff -Nru a/include/asm-alpha/fcntl.h b/include/asm-alpha/fcntl.h
--- a/include/asm-alpha/fcntl.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-alpha/fcntl.h	2004-06-23 19:04:27 -07:00
@@ -21,6 +21,7 @@
 #define O_NOFOLLOW	0200000 /* don't follow links */
 #define O_LARGEFILE	0400000 /* will be set by the kernel on every open */
 #define O_DIRECT	02000000 /* direct disk access - should check with OSF/1 */
+#define O_NOATIME	04000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-alpha/resource.h b/include/asm-alpha/resource.h
--- a/include/asm-alpha/resource.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-alpha/resource.h	2004-06-23 19:04:25 -07:00
@@ -15,9 +15,11 @@
 #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_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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.  Fine, it's unsigned, but
@@ -40,7 +42,9 @@
     {LONG_MAX, LONG_MAX},			/* RLIMIT_AS */		\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_NPROC */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_MEMLOCK */	\
-    {LONG_MAX, LONG_MAX},                       /* RLIMIT_LOCKS */      \
+    {LONG_MAX, LONG_MAX},			/* RLIMIT_LOCKS */	\
+    {MAX_SIGPENDING, MAX_SIGPENDING},		/* RLIMIT_SIGPENDING */ \
+    {MQ_BYTES_MAX, MQ_BYTES_MAX},		/* RLIMIT_MSGQUEUE */	\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-arm/arch-adifcc/adi_evb.h b/include/asm-arm/arch-adifcc/adi_evb.h
--- a/include/asm-arm/arch-adifcc/adi_evb.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,19 +0,0 @@
-/*
- * linux/include/asm/arch-80200fcc/adi_evb.h
- *
- * ADI 80200FCC evaluation board definitions
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#define ADI_EVB__RAMBASE	0xa0000000
-#define ADI_EVB__UART		0x00400000    /* UART */
-#define ADI_EVB_7SEG_1		0x00500000    /* 7-Segment */
-
diff -Nru a/include/asm-arm/arch-adifcc/dma.h b/include/asm-arm/arch-adifcc/dma.h
--- a/include/asm-arm/arch-adifcc/dma.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,18 +0,0 @@
-/*
- * linux/include/asm-arm/arch-80200fcc/dma.h
- *
- * Copyright (C) 2001 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS		0xffffffff
-
-/* No DMA */
-#define MAX_DMA_CHANNELS	0
-
-#endif /* _ASM_ARCH_DMA_H */
diff -Nru a/include/asm-arm/arch-adifcc/hardware.h b/include/asm-arm/arch-adifcc/hardware.h
--- a/include/asm-arm/arch-adifcc/hardware.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,27 +0,0 @@
-/*
- * linux/include/asm-arm/arch-adifcc/hardware.h
- *
- * Hardware definitions for ADI based systems
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright (C) 2000-2001 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <linux/config.h>
-
-#define PCIO_BASE	0
-
-#if defined(CONFIG_ARCH_ADI_EVB)
-#include "adi_evb.h"
-#endif
-
-#endif  /* _ASM_ARCH_HARDWARE_H */
diff -Nru a/include/asm-arm/arch-adifcc/io.h b/include/asm-arm/arch-adifcc/io.h
--- a/include/asm-arm/arch-adifcc/io.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,22 +0,0 @@
-/*
- * linux/include/asm-arm/arch-adifcc/io.h
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright (C) 2001  MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)			(PCIO_BASE + (a))
-#define __mem_pci(a)		((unsigned long)(a))
-#define __mem_isa(a)		((unsigned long)(a))
-
-#endif
diff -Nru a/include/asm-arm/arch-adifcc/irqs.h b/include/asm-arm/arch-adifcc/irqs.h
--- a/include/asm-arm/arch-adifcc/irqs.h	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,20 +0,0 @@
-/*
- * linux/include/asm-arm/arch-80200fcc/irqs.h
- *
- * Author:	Deepak Saxena <dsaxena@mvista.com>
- * Copyright:	(C) 2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#define IRQ_XS80200_BCU		0	/* Bus Control Unit */
-#define IRQ_XS80200_PMU		1	/* Performance Monitoring Unit */
-#define IRQ_XS80200_EXTIRQ	2	/* external IRQ signal */
-#define IRQ_XS80200_EXTFIQ	3	/* external IRQ signal */
-
-#define NR_XS80200_IRQS		4
-#define NR_IRQS			NR_XS80200_IRQS
-
-#define	IRQ_XSCALE_PMU		IRQ_XS80200_PMU
diff -Nru a/include/asm-arm/arch-adifcc/memory.h b/include/asm-arm/arch-adifcc/memory.h
--- a/include/asm-arm/arch-adifcc/memory.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,27 +0,0 @@
-/*
- * linux/include/asm-arm/arch-adifcc/memory.h
- *
- * Copyright (c) 2001 MontaVista Software, Inc.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PHYS_OFFSET	(0xC0000000UL)
-
-/*
- * Virtual view <-> DMA view memory address translations
- * virt_to_bus: Used to translate the virtual address to an
- *		address suitable to be passed to set_dma_addr
- * bus_to_virt: Used to convert an address for DMA operations
- *		to an address that the kernel can use.
- *
- * These are dummies for now.
- */
-#define __virt_to_bus(x)	 __virt_to_phys(x)
-#define __bus_to_virt(x)	 __phys_to_virt(x)
-
-#endif
diff -Nru a/include/asm-arm/arch-adifcc/param.h b/include/asm-arm/arch-adifcc/param.h
--- a/include/asm-arm/arch-adifcc/param.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,3 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-adifcc/param.h
- */
diff -Nru a/include/asm-arm/arch-adifcc/serial.h b/include/asm-arm/arch-adifcc/serial.h
--- a/include/asm-arm/arch-adifcc/serial.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,34 +0,0 @@
-/*
- * include/asm-arm/arch-adifcc/serial.h
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright (c) 2001 MontaVista Software, Inc.
- */
-#include <linux/config.h>
-
-/*
- * This assumes you have a 1.8432 MHz clock for your UART.
- *
- * It'd be nice if someone built a serial card with a 24.576 MHz
- * clock, since the 16550A is capable of handling a top speed of 1.5
- * megabits/second; but this requires the faster clock.
- */
-#define BASE_BAUD ( 1852000 / 16 )
-
-/* Standard COM flags */
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
-#ifdef CONFIG_ARCH_ADI_EVB
-
-/*
- * One serial port, int goes to FIQ, so we run in polled mode
- */
-#define STD_SERIAL_PORT_DEFNS			\
-       /* UART CLK      PORT        IRQ        FLAGS        */			\
-	{ 0, BASE_BAUD, 0xff400000, 0,  STD_COM_FLAGS }  /* ttyS0 */
-
-#define EXTRA_SERIAL_PORT_DEFNS
-
-#endif
-
diff -Nru a/include/asm-arm/arch-adifcc/system.h b/include/asm-arm/arch-adifcc/system.h
--- a/include/asm-arm/arch-adifcc/system.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,28 +0,0 @@
-/*
- * linux/include/asm-arm/arch-adifcc/system.h
- *
- * Copyright (C) 2001 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-static inline void arch_idle(void)
-{
-#if 0
-	cpu_do_idle();
-#endif
-}
-
-
-static inline void arch_reset(char mode)
-{
-	if ( 1 && mode == 's') {
-		/* Jump into ROM at address 0 */
-		cpu_reset(0);
-	} else {
-		/* Use on-chip reset capability */
-	}
-}
-
diff -Nru a/include/asm-arm/arch-adifcc/time.h b/include/asm-arm/arch-adifcc/time.h
--- a/include/asm-arm/arch-adifcc/time.h	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,9 +0,0 @@
-/*
- * linux/include/asm-arm/arch-adifcc/time.h
- *
- */
-
-/*
- * No on board timer, implementation @ arch/arm/kernel/xscale-time.c
- */
-
diff -Nru a/include/asm-arm/arch-adifcc/timex.h b/include/asm-arm/arch-adifcc/timex.h
--- a/include/asm-arm/arch-adifcc/timex.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,10 +0,0 @@
-/*
- * linux/include/asm-arm/arch-adifcc/timex.h
- *
- * XScale architecture timex specifications
- */
-
-/* This is for a timer based on the XS80200's PMU counter */
-
-#define CLOCK_TICK_RATE 600000000 /* Underlying HZ */
-
diff -Nru a/include/asm-arm/arch-adifcc/uncompress.h b/include/asm-arm/arch-adifcc/uncompress.h
--- a/include/asm-arm/arch-adifcc/uncompress.h	2004-06-23 19:04:24 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,35 +0,0 @@
-/*
- * linux/include/asm-arm/arch-adifcc/uncompress.h
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright (c) 2001 MontaVista Software, Inc.
- *
- */
-
-#define UART_BASE    ((volatile unsigned char *)0x00400000)
-
-static __inline__ void putc(char c)
-{
-	while ((UART_BASE[5] & 0x60) != 0x60);
-	UART_BASE[0] = c;
-}
-
-/*
- * This does not append a newline
- */
-static void puts(const char *s)
-{
-	while (*s) {
-		putc(*s);
-		if (*s == '\n')
-			putc('\r');
-		s++;
-	}
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff -Nru a/include/asm-arm/arch-adifcc/vmalloc.h b/include/asm-arm/arch-adifcc/vmalloc.h
--- a/include/asm-arm/arch-adifcc/vmalloc.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,15 +0,0 @@
-/*
- * linux/include/asm-arm/arch-adifcc/vmalloc.h
- */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_END       (0xe8000000)
diff -Nru a/include/asm-arm/arch-cl7500/time.h b/include/asm-arm/arch-cl7500/time.h
--- a/include/asm-arm/arch-cl7500/time.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,43 +0,0 @@
-/*
- * linux/include/asm-arm/arch-cl7500/time.h
- *
- * Copyright (c) 1996-2000 Russell King.
- *
- * Changelog:
- *  24-Sep-1996	RMK	Created
- *  10-Oct-1996	RMK	Brought up to date with arch-sa110eval
- *  04-Dec-1997	RMK	Updated for new arch/arm/time.c
- */
-
-extern void ioctime_init(void);
-
-static irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	do_timer(regs);
-	do_set_rtc();
-	do_profile(regs);
-
-	{
-		/* Twinkle the lights. */
-		static int count, state = 0xff00;
-		if (count-- == 0) {
-			state ^= 0x100;
-			count = 25;
-			*((volatile unsigned int *)LED_ADDRESS) = state;
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-/*
- * Set up timer interrupt.
- */
-void __init time_init(void)
-{
-	ioctime_init();
-
-	timer_irq.handler = timer_interrupt;
-
-	setup_irq(IRQ_TIMER, &timer_irq);
-}
diff -Nru a/include/asm-arm/arch-ebsa110/time.h b/include/asm-arm/arch-ebsa110/time.h
--- a/include/asm-arm/arch-ebsa110/time.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,118 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-ebsa110/time.h
- *
- *  Copyright (C) 1996,1997,1998 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
- * published by the Free Software Foundation.
- *
- * No real time clock on the evalulation board!
- *
- * Changelog:
- *  10-Oct-1996	RMK	Created
- *  04-Dec-1997	RMK	Updated for new arch/arm/kernel/time.c
- *  07-Aug-1998	RMK	Updated for arch/arm/kernel/leds.c
- *  28-Dec-1998	APH	Made leds code optional
- */
-
-#include <asm/leds.h>
-#include <asm/io.h>
-
-extern unsigned long (*gettimeoffset)(void);
-
-#define PIT_CTRL		(PIT_BASE + 0x0d)
-#define PIT_T2			(PIT_BASE + 0x09)
-#define PIT_T1			(PIT_BASE + 0x05)
-#define PIT_T0			(PIT_BASE + 0x01)
-
-/*
- * This is the rate at which your MCLK signal toggles (in Hz)
- * This was measured on a 10 digit frequency counter sampling
- * over 1 second.
- */
-#define MCLK	47894000
-
-/*
- * This is the rate at which the PIT timers get clocked
- */
-#define CLKBY7	(MCLK / 7)
-
-/*
- * This is the counter value.  We tick at 200Hz on this platform.
- */
-#define COUNT	((CLKBY7 + (HZ / 2)) / HZ)
-
-/*
- * Get the time offset from the system PIT.  Note that if we have missed an
- * interrupt, then the PIT counter will roll over (ie, be negative).
- * This actually works out to be convenient.
- */
-static unsigned long ebsa110_gettimeoffset(void)
-{
-	unsigned long offset, count;
-
-	__raw_writeb(0x40, PIT_CTRL);
-	count = __raw_readb(PIT_T1);
-	count |= __raw_readb(PIT_T1) << 8;
-
-	/*
-	 * If count > COUNT, make the number negative.
-	 */
-	if (count > COUNT)
-		count |= 0xffff0000;
-
-	offset = COUNT;
-	offset -= count;
-
-	/*
-	 * `offset' is in units of timer counts.  Convert
-	 * offset to units of microseconds.
-	 */
-	offset = offset * (1000000 / HZ) / COUNT;
-
-	return offset;
-}
-
-static irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	u32 count;
-
-	/* latch and read timer 1 */
-	__raw_writeb(0x40, PIT_CTRL);
-	count = __raw_readb(PIT_T1);
-	count |= __raw_readb(PIT_T1) << 8;
-
-	count += COUNT;
-
-	__raw_writeb(count & 0xff, PIT_T1);
-	__raw_writeb(count >> 8, PIT_T1);
-
-	do_leds();
-	do_timer(regs);
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Set up timer interrupt.
- */
-void __init time_init(void)
-{
-	/*
-	 * Timer 1, mode 2, LSB/MSB
-	 */
-	__raw_writeb(0x70, PIT_CTRL);
-	__raw_writeb(COUNT & 0xff, PIT_T1);
-	__raw_writeb(COUNT >> 8, PIT_T1);
-
-	gettimeoffset = ebsa110_gettimeoffset;
-
-	timer_irq.handler = timer_interrupt;
-
-	setup_irq(IRQ_EBSA110_TIMER0, &timer_irq);
-}
-
-
diff -Nru a/include/asm-arm/arch-ebsa285/time.h b/include/asm-arm/arch-ebsa285/time.h
--- a/include/asm-arm/arch-ebsa285/time.h	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,287 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-ebsa285/time.h
- *
- *  Copyright (C) 1998 Russell King.
- *  Copyright (C) 1998 Phil Blundell
- *
- * CATS has a real-time clock, though the evaluation board doesn't.
- *
- * Changelog:
- *  21-Mar-1998	RMK	Created
- *  27-Aug-1998	PJB	CATS support
- *  28-Dec-1998	APH	Made leds optional
- *  20-Jan-1999	RMK	Started merge of EBSA285, CATS and NetWinder
- *  16-Mar-1999	RMK	More support for EBSA285-like machines with RTCs in
- */
-
-#define RTC_PORT(x)		(rtc_base+(x))
-#define RTC_ALWAYS_BCD		0
-
-#include <linux/mc146818rtc.h>
-#include <linux/bcd.h>
-
-#include <asm/hardware/dec21285.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-static int rtc_base;
-
-#define mSEC_10_from_14 ((14318180 + 100) / 200)
-
-static unsigned long isa_gettimeoffset(void)
-{
-	int count;
-
-	static int count_p = (mSEC_10_from_14/6);    /* for the first call after boot */
-	static unsigned long jiffies_p = 0;
-
-	/*
-	 * cache volatile jiffies temporarily; we have IRQs turned off. 
-	 */
-	unsigned long jiffies_t;
-
-	/* timer count may underflow right here */
-	outb_p(0x00, 0x43);	/* latch the count ASAP */
-
-	count = inb_p(0x40);	/* read the latched count */
-
-	/*
-	 * We do this guaranteed double memory access instead of a _p 
-	 * postfix in the previous port access. Wheee, hackady hack
-	 */
- 	jiffies_t = jiffies;
-
-	count |= inb_p(0x40) << 8;
-
-	/* Detect timer underflows.  If we haven't had a timer tick since 
-	   the last time we were called, and time is apparently going
-	   backwards, the counter must have wrapped during this routine. */
-	if ((jiffies_t == jiffies_p) && (count > count_p))
-		count -= (mSEC_10_from_14/6);
-	else
-		jiffies_p = jiffies_t;
-
-	count_p = count;
-
-	count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
-	count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
-
-	return count;
-}
-
-static irqreturn_t
-isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	if (machine_is_netwinder())
-		do_leds();
-
-	do_timer(regs);
-	do_set_rtc();
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-static unsigned long __init get_isa_cmos_time(void)
-{
-	unsigned int year, mon, day, hour, min, sec;
-	int i;
-
-	// check to see if the RTC makes sense.....
-	if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
-		return mktime(1970, 1, 1, 0, 0, 0);
-
-	/* The Linux interpretation of the CMOS clock register contents:
-	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
-	 * RTC registers show the second which has precisely just started.
-	 * Let's hope other operating systems interpret the RTC the same way.
-	 */
-	/* read RTC exactly on falling edge of update flag */
-	for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
-		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
-			break;
-
-	for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
-		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
-			break;
-
-	do { /* Isn't this overkill ? UIP above should guarantee consistency */
-		sec  = CMOS_READ(RTC_SECONDS);
-		min  = CMOS_READ(RTC_MINUTES);
-		hour = CMOS_READ(RTC_HOURS);
-		day  = CMOS_READ(RTC_DAY_OF_MONTH);
-		mon  = CMOS_READ(RTC_MONTH);
-		year = CMOS_READ(RTC_YEAR);
-	} while (sec != CMOS_READ(RTC_SECONDS));
-
-	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-		BCD_TO_BIN(sec);
-		BCD_TO_BIN(min);
-		BCD_TO_BIN(hour);
-		BCD_TO_BIN(day);
-		BCD_TO_BIN(mon);
-		BCD_TO_BIN(year);
-	}
-	if ((year += 1900) < 1970)
-		year += 100;
-	return mktime(year, mon, day, hour, min, sec);
-}
-
-static int
-set_isa_cmos_time(void)
-{
-	int retval = 0;
-	int real_seconds, real_minutes, cmos_minutes;
-	unsigned char save_control, save_freq_select;
-	unsigned long nowtime = xtime.tv_sec;
-
-	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
-	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
-
-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
-	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
-	cmos_minutes = CMOS_READ(RTC_MINUTES);
-	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-		BCD_TO_BIN(cmos_minutes);
-
-	/*
-	 * since we're only adjusting minutes and seconds,
-	 * don't interfere with hour overflow. This avoids
-	 * messing with unknown time zones but requires your
-	 * RTC not to be off by more than 15 minutes
-	 */
-	real_seconds = nowtime % 60;
-	real_minutes = nowtime / 60;
-	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-		real_minutes += 30;		/* correct for half hour time zone */
-	real_minutes %= 60;
-
-	if (abs(real_minutes - cmos_minutes) < 30) {
-		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-			BIN_TO_BCD(real_seconds);
-			BIN_TO_BCD(real_minutes);
-		}
-		CMOS_WRITE(real_seconds,RTC_SECONDS);
-		CMOS_WRITE(real_minutes,RTC_MINUTES);
-	} else
-		retval = -1;
-
-	/* The following flags have to be released exactly in this order,
-	 * otherwise the DS12887 (popular MC146818A clone with integrated
-	 * battery and quartz) will not reset the oscillator and will not
-	 * update precisely 500 ms later. You won't find this mentioned in
-	 * the Dallas Semiconductor data sheets, but who believes data
-	 * sheets anyway ...                           -- Markus Kuhn
-	 */
-	CMOS_WRITE(save_control, RTC_CONTROL);
-	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-
-	return retval;
-}
-
-
-static unsigned long timer1_latch;
-
-static unsigned long timer1_gettimeoffset (void)
-{
-	unsigned long value = timer1_latch - *CSR_TIMER1_VALUE;
-
-	return ((tick_nsec / 1000) * value) / timer1_latch;
-}
-
-static irqreturn_t
-timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	*CSR_TIMER1_CLR = 0;
-
-	/* Do the LEDs things */
-	do_leds();
-	do_timer(regs);
-	do_set_rtc();
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Set up timer interrupt.
- */
-void __init time_init(void)
-{
-	int irq;
-
-	if (machine_is_co285() ||
-	    machine_is_personal_server())
-		/*
-		 * Add-in 21285s shouldn't access the RTC
-		 */
-		rtc_base = 0;
-	else
-		rtc_base = 0x70;
-
-	if (rtc_base) {
-		int reg_d, reg_b;
-
-		/*
-		 * Probe for the RTC.
-		 */
-		reg_d = CMOS_READ(RTC_REG_D);
-
-		/*
-		 * make sure the divider is set
-		 */
-		CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
-
-		/*
-		 * Set control reg B
-		 *   (24 hour mode, update enabled)
-		 */
-		reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
-		reg_b |= 2;
-		CMOS_WRITE(reg_b, RTC_REG_B);
-
-		if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
-		    CMOS_READ(RTC_REG_B) == reg_b) {
-			struct timespec tv;
-
-			/*
-			 * We have a RTC.  Check the battery
-			 */
-			if ((reg_d & 0x80) == 0)
-				printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
-
-			tv.tv_nsec = 0;
-			tv.tv_sec = get_isa_cmos_time();
-			do_settimeofday(&tv);
-			set_rtc = set_isa_cmos_time;
-		} else
-			rtc_base = 0;
-	}
-
-	if (machine_is_ebsa285() ||
-	    machine_is_co285() ||
-	    machine_is_personal_server()) {
-		gettimeoffset = timer1_gettimeoffset;
-
-		timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
-
-		*CSR_TIMER1_CLR  = 0;
-		*CSR_TIMER1_LOAD = timer1_latch;
-		*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
-
-		timer_irq.handler = timer1_interrupt;
-		irq = IRQ_TIMER1;
-	} else {
-		/* enable PIT timer */
-		/* set for periodic (4) and LSB/MSB write (0x30) */
-		outb(0x34, 0x43);
-		outb((mSEC_10_from_14/6) & 0xFF, 0x40);
-		outb((mSEC_10_from_14/6) >> 8, 0x40);
-
-		gettimeoffset = isa_gettimeoffset;
-		timer_irq.handler = isa_timer_interrupt;
-		irq = IRQ_ISA_TIMER;
-	}
-	setup_irq(irq, &timer_irq);
-}
diff -Nru a/include/asm-arm/arch-epxa10db/time.h b/include/asm-arm/arch-epxa10db/time.h
--- a/include/asm-arm/arch-epxa10db/time.h	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,60 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-epxa10db/time.h
- *
- *  Copyright (C) 2001 Altera Corporation
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <asm/system.h>
-#include <asm/leds.h>
-#include <asm/arch/hardware.h>
-#define TIMER00_TYPE (volatile unsigned int*)
-#include <asm/arch/timer00.h>
-
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-excalibur_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-
-	// ...clear the interrupt
-	*TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))|=TIMER0_CR_CI_MSK;
-
-	do_leds();
-	do_timer(regs);
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-void __init time_init(void)
-{
-	timer_irq.handler = excalibur_timer_interrupt;
-
-	/* 
-	 * Make irqs happen for the system timer
-	 */
-	setup_irq(IRQ_TIMER0, &timer_irq);
-
-	/* Start the timer */
-	*TIMER0_LIMIT(IO_ADDRESS(EXC_TIMER00_BASE))=(unsigned int)(EXC_AHB2_CLK_FREQUENCY/200);
-	*TIMER0_PRESCALE(IO_ADDRESS(EXC_TIMER00_BASE))=1;
-	*TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))=TIMER0_CR_IE_MSK | TIMER0_CR_S_MSK;
-}
diff -Nru a/include/asm-arm/arch-integrator/impd1.h b/include/asm-arm/arch-integrator/impd1.h
--- a/include/asm-arm/arch-integrator/impd1.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-arm/arch-integrator/impd1.h	2004-06-23 19:04:27 -07:00
@@ -14,6 +14,5 @@
 
 struct device;
 
-void impd1_set_vco(struct device *dev, int vconr, unsigned long period);
 void impd1_tweak_control(struct device *dev, u32 mask, u32 val);
 
diff -Nru a/include/asm-arm/arch-integrator/platform.h b/include/asm-arm/arch-integrator/platform.h
--- a/include/asm-arm/arch-integrator/platform.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-arm/arch-integrator/platform.h	2004-06-23 19:04:27 -07:00
@@ -457,6 +457,10 @@
 #define mSEC_25                         (mSEC_1 * 25)
 #define SEC_1                           (mSEC_1 * 1000)
 
+#ifndef __ASSEMBLY__
+extern void integrator_time_init(unsigned long, unsigned int);
+#endif
+
 #define INTEGRATOR_CSR_BASE             0x10000000
 #define INTEGRATOR_CSR_SIZE             0x10000000
 
diff -Nru a/include/asm-arm/arch-iop3xx/time.h b/include/asm-arm/arch-iop3xx/time.h
--- a/include/asm-arm/arch-iop3xx/time.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,12 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop80310/time.h
- *
- * Author:  Nicolas Pitre
- * Copyright:   (C) 2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
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	2004-06-23 19:04:25 -07:00
+++ b/include/asm-arm/arch-ixp4xx/platform.h	2004-06-23 19:04:25 -07:00
@@ -58,6 +58,7 @@
  */
 extern void ixp4xx_map_io(void);
 extern void ixp4xx_init_irq(void);
+extern void ixp4xx_init_time(void);
 extern void ixp4xx_pci_preinit(void);
 struct pci_sys_data;
 extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
diff -Nru a/include/asm-arm/arch-ixp4xx/time.h b/include/asm-arm/arch-ixp4xx/time.h
--- a/include/asm-arm/arch-ixp4xx/time.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,7 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ixp4xx/time.h
- *
- * We implement timer code in arch/arm/mach-ixp4xx/time.c
- *
- */
-
diff -Nru a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h
--- a/include/asm-arm/arch-lh7a40x/memory.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-arm/arch-lh7a40x/memory.h	2004-06-23 19:04:26 -07:00
@@ -6,14 +6,14 @@
  *  modify it under the terms of the GNU General Public License
  *  version 2 as published by the Free Software Foundation.
  *
+ *
+ *  Refer to <file:Documentation/arm/Sharp-LH/SDRAM> for more information.
+ *
  */
 
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-
-#define BANKS_PER_NODE 1	/* Define as either 1 or 2 */
-
 /*
  * Physical DRAM offset.
  */
@@ -30,57 +30,30 @@
 #define __bus_to_virt(x)	 __phys_to_virt(x)
 
 #ifdef CONFIG_DISCONTIGMEM
-/*
- * Because of the wide memory address space between physical RAM
- * banks, it's convenient to use Linux's NUMA support to represent our
- * memory map.  Assuming all memory nodes have equal access
- * characteristics, we then have a generic discontiguous memory setup.
- *
- * Of course, all this isn't mandatory for implementations with only
- * one used memory bank.  For those, simply undefine
- * CONFIG_DISCONTIGMEM.  However, keep in mind that a featurefull
- * system will need more than 4MiB of RAM.
- *
- * The contiguous memory blocks are small enough that it pays to
- * aggregate two banks into one node.  Setting BANKS_PER_NODE to 2
- * puts pairs of banks into a node.
- *
- * A typical layout would start like this:
- *
- *  node 0: 0xc0000000
- *          0xc1000000
- *  node 1: 0xc4000000
- *          0xc5000000
- *  node 2: 0xc8000000
- *          0xc9000000
- *
- * The proximity of the pairs of blocks makes it feasible to combine them.
- *
- */
 
 /*
  * Given a kernel address, find the home node of the underlying memory.
  */
 
-#if BANKS_PER_NODE==1
-#define KVADDR_TO_NID(addr) \
+# ifdef CONFIG_LH7A40X_ONE_BANK_PER_NODE
+#  define KVADDR_TO_NID(addr) \
   (  ((((unsigned long) (addr) - PAGE_OFFSET) >> 24) &  1)\
    | ((((unsigned long) (addr) - PAGE_OFFSET) >> 25) & ~1))
-#else  /* 2 banks per node */
-#define KVADDR_TO_NID(addr) \
-       ((unsigned long) (addr) - PAGE_OFFSET) >> 26)
-#endif
+# else  /* 2 banks per node */
+#  define KVADDR_TO_NID(addr) \
+      (((unsigned long) (addr) - PAGE_OFFSET) >> 26)
+# endif
 
 /*
  * Given a page frame number, convert it to a node id.
  */
 
-#if BANKS_PER_NODE==1
-#define PFN_TO_NID(pfn) \
+# ifdef CONFIG_LH7A40X_ONE_BANK_PER_NODE
+#  define PFN_TO_NID(pfn) \
   (((((pfn) - PHYS_PFN_OFFSET) >> (24 - PAGE_SHIFT)) &  1)\
  | ((((pfn) - PHYS_PFN_OFFSET) >> (25 - PAGE_SHIFT)) & ~1))
-#else  /* 2 banks per node */
-#define PFN_TO_NID(addr) \
+# else  /* 2 banks per node */
+#  define PFN_TO_NID(pfn) \
     (((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT))
 #endif
 
@@ -88,13 +61,13 @@
  * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
  * and return the mem_map of that node.
  */
-#define ADDR_TO_MAPBASE(kaddr)	NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
+# define ADDR_TO_MAPBASE(kaddr)	NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
 
 /*
  * Given a page frame number, find the owning node of the memory
  * and return the mem_map of that node.
  */
-#define PFN_TO_MAPBASE(pfn)	NODE_MEM_MAP(PFN_TO_NID(pfn))
+# define PFN_TO_MAPBASE(pfn)	NODE_MEM_MAP(PFN_TO_NID(pfn))
 
 /*
  * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
@@ -102,17 +75,17 @@
  * node's mem_map.
  */
 
-#if BANKS_PER_NODE==1
-#define LOCAL_MAP_NR(addr) \
+# ifdef CONFIG_LH7A40X_ONE_BANK_PER_NODE
+#  define LOCAL_MAP_NR(addr) \
        (((unsigned long)(addr) & 0x003fffff) >> PAGE_SHIFT)
-#else  /* 2 banks per node */
-#define LOCAL_MAP_NR(addr) \
+# else  /* 2 banks per node */
+#  define LOCAL_MAP_NR(addr) \
        (((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT)
-#endif
+# endif
 
 #else
 
-#define PFN_TO_NID(addr)	(0)
+# define PFN_TO_NID(addr)	(0)
 
 #endif
 
diff -Nru a/include/asm-arm/arch-lh7a40x/time.h b/include/asm-arm/arch-lh7a40x/time.h
--- a/include/asm-arm/arch-lh7a40x/time.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,53 +0,0 @@
-/* include/asm-arm/arch-lh7a40x/time.h
- *
- *  Copyright (C) 2004 Logic Product Development
- *
- *  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.
- *
- */
-
-#if HZ < 100
-# define TIMER_CONTROL	TIMER_CONTROL1
-# define TIMER_LOAD	TIMER_LOAD1
-# define TIMER_CONSTANT	(508469/HZ)
-# define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
-# define TIMER_EOI	TIMER_EOI1
-# define TIMER_IRQ	IRQ_T1UI
-#else
-# define TIMER_CONTROL	TIMER_CONTROL3
-# define TIMER_LOAD	TIMER_LOAD3
-# define TIMER_CONSTANT	(3686400/HZ)
-# define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC)
-# define TIMER_EOI	TIMER_EOI3
-# define TIMER_IRQ	IRQ_T3UI
-#endif
-
-static irqreturn_t
-lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	TIMER_EOI = 0;
-	do_profile (regs);
-	do_leds();
-	do_set_rtc();
-	do_timer (regs);
-
-	return IRQ_HANDLED;
-}
-
-void __init time_init(void)
-{
-				/* Stop/disable all timers */
-	TIMER_CONTROL1 = 0;
-	TIMER_CONTROL2 = 0;
-	TIMER_CONTROL3 = 0;
-
-	timer_irq.handler = lh7a40x_timer_interrupt;
-	timer_irq.flags |= SA_INTERRUPT;
-	setup_irq (TIMER_IRQ, &timer_irq);
-
-	TIMER_LOAD = TIMER_CONSTANT;
-	TIMER_CONTROL = TIMER_MODE;
-}
-
diff -Nru a/include/asm-arm/arch-nexuspci/dma.h b/include/asm-arm/arch-nexuspci/dma.h
--- a/include/asm-arm/arch-nexuspci/dma.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,20 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/dma.h
- *
- * Architecture DMA routines
- *
- * Copyright (C) 1998, 1999 Philip Blundell
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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 is the maximum DMA address that can be DMAd to.
- */
-#define MAX_DMA_ADDRESS		0xffffffff
-#define MAX_DMA_CHANNELS	0
diff -Nru a/include/asm-arm/arch-nexuspci/hardware.h b/include/asm-arm/arch-nexuspci/hardware.h
--- a/include/asm-arm/arch-nexuspci/hardware.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,76 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/hardware.h
- *
- * Copyright (C) 1998, 1999, 2000 FutureTV Labs Ltd.
- *
- * This file contains the hardware definitions of the FTV PCI card.
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-/*    Logical    Physical
- * 0xffe00000	0x20000000	INTCONT
- * 0xffd00000	0x30000000	Status
- * 0xffc00000	0x60000000	PLX registers
- * 0xfe000000	0xC0000000	PCI I/O
- * 0xfd000000	0x70000000	cache flush
- * 0xfc000000	0x80000000	PCI/ISA memory
- * 0xe0000000	0x10000000	SCC2691 DUART
- */
-
-/*
- * Mapping areas
- */
-#define INTCONT_BASE		0xffe00000
-#define STATUS_BASE		0xffd00000
-#define PLX_BASE		0xffc00000
-#define PCIO_BASE		0xfe000000
-#define FLUSH_BASE		0xfd000000
-#define DUART_BASE		0xe0000000
-#define PCIMEM_BASE		0xfc000000
-
-#define PLX_IO_START		0xC0000000
-#define PLX_MEM_START		0x80000000
-#define PLX_START		0x60000000
-#define STATUS_START		0x30000000
-#define INTCONT_START		0x20000000
-#define DUART_START		0x10000000
-
-/*
- * RAM definitions
- */
-#define RAM_BASE		0x40000000
-#define FLUSH_BASE_PHYS		0x70000000
-
-/*
- * Miscellaneous INTCONT bits
- */
-#define INTCONT_FIQ_PLX		0x00
-#define INTCONT_FIQ_D		0x02
-#define INTCONT_FIQ_C		0x04
-#define INTCONT_FIQ_B		0x06
-#define INTCONT_FIQ_A		0x08
-#define INTCONT_FIQ_SYSERR	0x0a
-#define INTCONT_IRQ_DUART	0x0c
-#define INTCONT_IRQ_PLX		0x0e
-#define INTCONT_IRQ_D		0x10
-#define INTCONT_IRQ_C		0x12
-#define INTCONT_IRQ_B		0x14
-#define INTCONT_IRQ_A		0x16
-#define INTCONT_IRQ_SYSERR	0x1e
-
-#define INTCONT_WATCHDOG	0x18
-#define INTCONT_LED		0x1a
-#define INTCONT_PCI_RESET	0x1c
-
-#define UNCACHEABLE_ADDR	STATUS_BASE
-
-#endif
diff -Nru a/include/asm-arm/arch-nexuspci/io.h b/include/asm-arm/arch-nexuspci/io.h
--- a/include/asm-arm/arch-nexuspci/io.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,58 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/io.h
- *
- * Copyright (C) 1997-1999 Russell King
- * Copyright (C) 2000 FutureTV Labs Ltd.
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffff
-
-/*
- * Translation of various region addresses to virtual addresses
- */
-#define __io(a)			(PCIO_BASE + (a))
-#if 1
-#define __mem_pci(a)		((unsigned long)(a))
-#define __mem_isa(a)		(PCIMEM_BASE + (unsigned long)(a))
-#else
-
-static inline unsigned long ___mem_pci(unsigned long a)
-{
-	/* PCI addresses must have been ioremapped */
-	if (a <= 0xc0000000 || a >= 0xe0000000)
-		*((int *)0) = 0;
-	return a;
-}
-
-static inline unsigned long ___mem_isa(unsigned long a)
-{
-	BUG_ON(a >= 16*1048576);
-	return PCIMEM_BASE + a;
-}
-#define __mem_pci(a)		___mem_pci((unsigned long)(a))
-#define __mem_isa(a)		___mem_isa((unsigned long)(a))
-#endif
-
-/*
- * ioremap support - validate a PCI memory address,
- * and convert a PCI memory address to a physical
- * address for the page tables.
- */
-#define iomem_valid_addr(iomem,sz)	\
-	((iomem) < 0x80000000 && (iomem) + (sz) <= 0x80000000)
-#define iomem_to_phys(iomem)	((iomem) + PLX_MEM_START)
-
-#define __arch_ioremap(off,sz,nocache)				\
- ({								\
-	unsigned long _off = (off), _size = (sz);		\
-	void *_ret = (void *)0;					\
-	if (iomem_valid_addr(_off, _size))			\
-		_ret = __ioremap(iomem_to_phys(_off),_size,0);	\
-	_ret;							\
- })
-
-#define __arch_iounmap __iounmap
-
-#endif
diff -Nru a/include/asm-arm/arch-nexuspci/irqs.h b/include/asm-arm/arch-nexuspci/irqs.h
--- a/include/asm-arm/arch-nexuspci/irqs.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,34 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/irqs.h
- *
- * Copyright (C) 1997, 1998, 2000 Philip Blundell
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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 hardware is capable of routing any interrupt source (except the
- * DUART) to either IRQ or FIQ.  We ignore FIQ and use IRQ exclusively
- * for simplicity.  
- */
-
-#define IRQ_DUART		0
-#define IRQ_PLX 		1
-#define IRQ_PCI_D		2
-#define IRQ_PCI_C		3
-#define IRQ_PCI_B		4
-#define IRQ_PCI_A	        5
-#define IRQ_SYSERR		6	/* only from IOSLAVE rev B */
-
-#define FIRST_IRQ		IRQ_DUART
-#define LAST_IRQ		IRQ_SYSERR
-
-/* timer is part of the DUART */
-#define IRQ_TIMER		IRQ_DUART
-
-#define irq_canonicalize(i)	(i)
diff -Nru a/include/asm-arm/arch-nexuspci/memory.h b/include/asm-arm/arch-nexuspci/memory.h
--- a/include/asm-arm/arch-nexuspci/memory.h	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,23 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/memory.h
- *
- * Copyright (c) 1997, 1998, 2000 FutureTV Labs Ltd.
- * Copyright (c) 1999 Russell King
- *
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PHYS_OFFSET	(0x40000000UL)
-#define BUS_OFFSET	(0xe0000000UL)
-
-/*
- * On the PCI bus the DRAM appears at address 0xe0000000
- */
-#define __virt_to_bus(x) ((unsigned long)(x) - PAGE_OFFSET + BUS_OFFSET)
-#define __bus_to_virt(x) ((unsigned long)(x) + PAGE_OFFSET - BUS_OFFSET)
-
-#endif
diff -Nru a/include/asm-arm/arch-nexuspci/param.h b/include/asm-arm/arch-nexuspci/param.h
--- a/include/asm-arm/arch-nexuspci/param.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,3 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-nexuspci/param.h
- */
diff -Nru a/include/asm-arm/arch-nexuspci/system.h b/include/asm-arm/arch-nexuspci/system.h
--- a/include/asm-arm/arch-nexuspci/system.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,24 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/system.h
- *
- * Copyright (c) 1996, 97, 98, 99, 2000 FutureTV Labs Ltd.
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef __ASM_ARCH_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H
-
-static inline void arch_idle(void)
-{
-	cpu_do_idle();
-}
-
-#define arch_reset(mode)	do { } while (0)
-
-#endif
diff -Nru a/include/asm-arm/arch-nexuspci/time.h b/include/asm-arm/arch-nexuspci/time.h
--- a/include/asm-arm/arch-nexuspci/time.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,62 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/time.h
- *
- * Copyright (c) 1997, 1998, 1999, 2000 FutureTV Labs Ltd.
- *
- * The FTV PCI card has no real-time clock.  We get timer ticks from the
- * SCC chip.
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-static irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	static int count = 25;
-	unsigned char stat = __raw_readb(DUART_BASE + 0x14);
-	if (!(stat & 0x10))
-		return;		/* Not for us */
-
-	/* Reset counter */
-	__raw_writeb(0x90, DUART_BASE + 8);
-
-	if (--count == 0) {
-		static int state = 1;
-		state ^= 1;
-		__raw_writeb(0x1a + state, INTCONT_BASE);
-		__raw_writeb(0x18 + state, INTCONT_BASE);
-		count = 50;
-	}
-
-	/* Wait for slow rise time */
-	__raw_readb(DUART_BASE + 0x14);
-	__raw_readb(DUART_BASE + 0x14);
-	__raw_readb(DUART_BASE + 0x14);
-	__raw_readb(DUART_BASE + 0x14);
-	__raw_readb(DUART_BASE + 0x14);
-	__raw_readb(DUART_BASE + 0x14);
-
-	do_timer(regs);
-
-	return IRQ_HANDLED;
-}
-
-void __init time_init(void)
-{
-	int tick = 3686400 / 16 / 2 / 100;
-
-	__raw_writeb(tick & 0xff, DUART_BASE + 0x1c);
-	__raw_writeb(tick >> 8, DUART_BASE + 0x18);
-	__raw_writeb(0x80, DUART_BASE + 8);
-	__raw_writeb(0x10, DUART_BASE + 0x14);
-
-	timer_irq.handler = timer_interrupt;
-	timer_irq.flags = SA_SHIRQ;
-
-	setup_irq(IRQ_TIMER, &timer_irq);
-}
diff -Nru a/include/asm-arm/arch-nexuspci/timex.h b/include/asm-arm/arch-nexuspci/timex.h
--- a/include/asm-arm/arch-nexuspci/timex.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,8 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/timex.h
- *
- * NexusPCI StrongARM card timex specifications
- *
- * Copyright (C) 1998 Philip Blundell
- */
-
diff -Nru a/include/asm-arm/arch-nexuspci/uncompress.h b/include/asm-arm/arch-nexuspci/uncompress.h
--- a/include/asm-arm/arch-nexuspci/uncompress.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,66 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/uncompress.h
- *
- * Copyright (C) 1998, 1999, 2000 Philip Blundell
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-/*
- * Write a character to the UART
- */
-void _ll_write_char(char c)
-{
-	while (!(__raw_readb(DUART_START + 0x4) & 0x4))
-		;
-	__raw_writeb(c, DUART_START + 0xc);
-}
-
-/*
- * This does not append a newline
- */
-static void puts(const char *s)
-{
-	while (*s) {
-		if (*s == '\n')
-			_ll_write_char('\r');
-		_ll_write_char(*(s++));
-	}
-}
-
-/*
- * Set up for decompression
- */
-static void arch_decomp_setup(void)
-{
-	/* LED off */
-	__raw_writel(INTCONT_LED, INTCONT_START);
-
-	/* Set up SCC */
-	__raw_writeb(42, DUART_START + 8);
-	__raw_writeb(48, DUART_START + 8);
-	__raw_writeb(16, DUART_START + 8);
-	__raw_writeb(0x93, DUART_START);
-	__raw_writeb(0x17, DUART_START);
-	__raw_writeb(0xbb, DUART_START + 4);
-	__raw_writeb(0x78, DUART_START + 16);
-	__raw_writeb(0xa0, DUART_START + 8);
-	__raw_writeb(5, DUART_START + 8);
-}
-
-/*
- * Stroke the watchdog so we don't get reset during decompression.
- */
-static inline void arch_decomp_wdog(void)
-{
-	__raw_writel(INTCONT_WATCHDOG, INTCONT_START);
-	__raw_writel(INTCONT_WATCHDOG | 1, INTCONT_START);
-}
diff -Nru a/include/asm-arm/arch-nexuspci/vmalloc.h b/include/asm-arm/arch-nexuspci/vmalloc.h
--- a/include/asm-arm/arch-nexuspci/vmalloc.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,15 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/vmalloc.h
- */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_END       (PAGE_OFFSET + 0x20000000)
diff -Nru a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h
--- a/include/asm-arm/arch-omap/memory.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-arm/arch-omap/memory.h	2004-06-23 19:04:26 -07:00
@@ -57,12 +57,28 @@
 
 /*
  * OMAP-1510 bus address is translated into a Local Bus address if the
- * OMAP bus type is lbus. See dmadev_uses_omap_lbus().
+ * OMAP bus type is lbus. We do the address translation based on the
+ * device overriding the defaults used in the dma-mapping API.
  */
 #ifdef CONFIG_ARCH_OMAP1510
-#define bus_to_lbus(x)	((x) + (OMAP1510_LB_OFFSET - PHYS_OFFSET))
-#define lbus_to_bus(x)	((x) - (OMAP1510_LB_OFFSET - PHYS_OFFSET))
-#endif
+
+#define virt_to_lbus(x)		((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
+#define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
+#define is_lbus_device(dev)	(cpu_is_omap1510() && dev->coherent_dma_mask == 0x0fffffff)
+
+#define __arch_page_to_dma(dev, page)	({is_lbus_device(dev) ? \
+					(dma_addr_t)virt_to_lbus(page_address(page)) : \
+					(dma_addr_t)__virt_to_bus(page_address(page));})
+
+#define __arch_dma_to_virt(dev, addr)	({is_lbus_device(dev) ? \
+					lbus_to_virt(addr) : \
+					__bus_to_virt(addr);})
+
+#define __arch_virt_to_dma(dev, addr)	({is_lbus_device(dev) ? \
+					virt_to_lbus(addr) : \
+					__virt_to_bus(addr);})
+
+#endif	/* CONFIG_ARCH_OMAP1510 */
 
 #define PHYS_TO_NID(addr) (0)
 #endif
diff -Nru a/include/asm-arm/arch-omap/time.h b/include/asm-arm/arch-omap/time.h
--- a/include/asm-arm/arch-omap/time.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,212 +0,0 @@
-/*
- * linux/include/asm-arm/arch-omap/time.h
- *
- * 32kHz timer definition
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: Greg Lonnon <glonnon@ridgerun.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#if !defined(__ASM_ARCH_OMAP_TIME_H)
-#define __ASM_ARCH_OMAP_TIME_H
-
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <asm/system.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/leds.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/arch/clocks.h>
-
-#ifndef __instrument
-#define __instrument
-#define __noinstrument __attribute__ ((no_instrument_function))
-#endif
-
-typedef struct {
-	u32 cntl;     /* CNTL_TIMER, R/W */
-	u32 load_tim; /* LOAD_TIM,   W */
-	u32 read_tim; /* READ_TIM,   R */
-} mputimer_regs_t;
-
-#define mputimer_base(n) \
-    ((volatile mputimer_regs_t*)IO_ADDRESS(OMAP_MPUTIMER_BASE + \
-				 (n)*OMAP_MPUTIMER_OFFSET))
-
-static inline unsigned long timer32k_read(int reg) {
-	unsigned long val;
-	val = omap_readw(reg + OMAP_32kHz_TIMER_BASE);
-	return val;
-}
-static inline void timer32k_write(int reg,int val) {
-	omap_writew(val, reg + OMAP_32kHz_TIMER_BASE);
-}
-
-/*
- * How long is the timer interval? 100 HZ, right...
- * IRQ rate = (TVR + 1) / 32768 seconds
- * TVR = 32768 * IRQ_RATE -1
- * IRQ_RATE =  1/100
- * TVR = 326
- */
-#define TIMER32k_PERIOD 326
-//#define TIMER32k_PERIOD 0x7ff
-
-static inline void start_timer32k(void) {
-	timer32k_write(TIMER32k_CR,
-		       TIMER32k_TSS | TIMER32k_TRB |
-		       TIMER32k_INT | TIMER32k_ARL);
-}
-
-#ifdef CONFIG_MACH_OMAP_PERSEUS2
-/*
- * After programming PTV with 0 and setting the MPUTIM_CLOCK_ENABLE
- * (external clock enable)  bit, the timer count rate is 6.5 MHz (13
- * MHZ input/2). !! The divider by 2 is undocumented !!
- */
-#define MPUTICKS_PER_SEC (13000000/2)
-#else
-/*
- * After programming PTV with 0, the timer count rate is 6 MHz.
- * WARNING! this must be an even number, or machinecycles_to_usecs
- * below will break.
- */
-#define MPUTICKS_PER_SEC  (12000000/2)
-#endif
-
-static int mputimer_started[3] = {0,0,0};
-
-static inline void __noinstrument start_mputimer(int n,
-						 unsigned long load_val)
-{
-	volatile mputimer_regs_t* timer = mputimer_base(n);
-
-	mputimer_started[n] = 0;
-	timer->cntl = MPUTIM_CLOCK_ENABLE;
-	udelay(1);
-
-	timer->load_tim = load_val;
-        udelay(1);
-	timer->cntl = (MPUTIM_CLOCK_ENABLE | MPUTIM_AR | MPUTIM_ST);
-	mputimer_started[n] = 1;
-}
-
-static inline unsigned long __noinstrument
-read_mputimer(int n)
-{
-	volatile mputimer_regs_t* timer = mputimer_base(n);
-	return (mputimer_started[n] ? timer->read_tim : 0);
-}
-
-void __noinstrument start_mputimer1(unsigned long load_val)
-{
-	start_mputimer(0, load_val);
-}
-void __noinstrument start_mputimer2(unsigned long load_val)
-{
-	start_mputimer(1, load_val);
-}
-void __noinstrument start_mputimer3(unsigned long load_val)
-{
-	start_mputimer(2, load_val);
-}
-
-unsigned long __noinstrument read_mputimer1(void)
-{
-	return read_mputimer(0);
-}
-unsigned long __noinstrument read_mputimer2(void)
-{
-	return read_mputimer(1);
-}
-unsigned long __noinstrument read_mputimer3(void)
-{
-	return read_mputimer(2);
-}
-
-unsigned long __noinstrument do_getmachinecycles(void)
-{
-	return 0 - read_mputimer(0);
-}
-
-unsigned long __noinstrument machinecycles_to_usecs(unsigned long mputicks)
-{
-	/* Round up to nearest usec */
-	return ((mputicks * 1000) / (MPUTICKS_PER_SEC / 2 / 1000) + 1) >> 1;
-}
-
-/*
- * This marks the time of the last system timer interrupt
- * that was *processed by the ISR* (timer 2).
- */
-static unsigned long systimer_mark;
-
-static unsigned long omap1510_gettimeoffset(void)
-{
-	/* Return elapsed usecs since last system timer ISR */
-	return machinecycles_to_usecs(do_getmachinecycles() - systimer_mark);
-}
-
-static irqreturn_t
-omap1510_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long now, ilatency;
-
-	/*
-	 * Mark the time at which the timer interrupt ocurred using
-	 * timer1. We need to remove interrupt latency, which we can
-	 * retrieve from the current system timer2 counter. Both the
-	 * offset timer1 and the system timer2 are counting at 6MHz,
-	 * so we're ok.
-	 */
-	now = 0 - read_mputimer1();
-	ilatency = MPUTICKS_PER_SEC / 100 - read_mputimer2();
-	systimer_mark = now - ilatency;
-
-	do_leds();
-	do_timer(regs);
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-void __init time_init(void)
-{
-	/* Since we don't call request_irq, we must init the structure */
-	gettimeoffset = omap1510_gettimeoffset;
-
-	timer_irq.handler = omap1510_timer_interrupt;
-	timer_irq.flags = SA_INTERRUPT;
-#ifdef OMAP1510_USE_32KHZ_TIMER
-	timer32k_write(TIMER32k_CR, 0x0);
-	timer32k_write(TIMER32k_TVR,TIMER32k_PERIOD);
-	setup_irq(INT_OS_32kHz_TIMER, &timer_irq);
-	start_timer32k();
-#else
-	setup_irq(INT_TIMER2, &timer_irq);
-	start_mputimer2(MPUTICKS_PER_SEC / 100 - 1);
-#endif
-}
-
-#endif
diff -Nru a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
--- a/include/asm-arm/arch-pxa/hardware.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-arm/arch-pxa/hardware.h	2004-06-23 19:04:25 -07:00
@@ -83,6 +83,11 @@
 extern void pxa_gpio_mode( int gpio_mode );
 
 /*
+ * Routine to enable or disable CKEN
+ */
+extern void pxa_set_cken(int clock, int enable);
+
+/*
  * return current memory and LCD clock frequency in units of 10kHz
  */
 extern unsigned int get_memclk_frequency_10khz(void);
diff -Nru a/include/asm-arm/arch-pxa/time.h b/include/asm-arm/arch-pxa/time.h
--- a/include/asm-arm/arch-pxa/time.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,105 +0,0 @@
-/*
- * linux/include/asm-arm/arch-pxa/time.h
- *
- * Author:	Nicolas Pitre
- * Created:	Jun 15, 2001
- * Copyright:	MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-
-static inline unsigned long pxa_get_rtc_time(void)
-{
-	return RCNR;
-}
-
-static int pxa_set_rtc(void)
-{
-	unsigned long current_time = xtime.tv_sec;
-
-	if (RTSR & RTSR_ALE) {
-		/* make sure not to forward the clock over an alarm */
-		unsigned long alarm = RTAR;
-		if (current_time >= alarm && alarm >= RCNR)
-			return -ERESTARTSYS;
-	}
-	RCNR = current_time;
-	return 0;
-}
-
-/* IRQs are disabled before entering here from do_gettimeofday() */
-static unsigned long pxa_gettimeoffset (void)
-{
-	long ticks_to_match, elapsed, usec;
-
-	/* Get ticks before next timer match */
-	ticks_to_match = OSMR0 - OSCR;
-
-	/* We need elapsed ticks since last match */
-	elapsed = LATCH - ticks_to_match;
-
-	/* don't get fooled by the workaround in pxa_timer_interrupt() */
-	if (elapsed <= 0)
-		return 0;
-
-	/* Now convert them to usec */
-	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
-
-	return usec;
-}
-
-static irqreturn_t
-pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	int next_match;
-
-	do_profile(regs);
-
-	/* Loop until we get ahead of the free running timer.
-	 * This ensures an exact clock tick count and time accuracy.
-	 * IRQs are disabled inside the loop to ensure coherence between
-	 * lost_ticks (updated in do_timer()) and the match reg value, so we
-	 * can use do_gettimeofday() from interrupt handlers.
-	 *
-	 * HACK ALERT: it seems that the PXA timer regs aren't updated right
-	 * away in all cases when a write occurs.  We therefore compare with
-	 * 8 instead of 0 in the while() condition below to avoid missing a
-	 * match if OSCR has already reached the next OSMR value.
-	 * Experience has shown that up to 6 ticks are needed to work around
-	 * this problem, but let's use 8 to be conservative.  Note that this
-	 * affect things only when the timer IRQ has been delayed by nearly
-	 * exactly one tick period which should be a pretty rare event.
-	 */
-	do {
-		do_leds();
-		do_set_rtc();
-		do_timer(regs);
-		OSSR = OSSR_M0;  /* Clear match on timer 0 */
-		next_match = (OSMR0 += LATCH);
-	} while( (signed long)(next_match - OSCR) <= 8 );
-
-	return IRQ_HANDLED;
-}
-
-void __init time_init(void)
-{
-	struct timespec tv;
-
-	gettimeoffset = pxa_gettimeoffset;
-	set_rtc = pxa_set_rtc;
-
-	tv.tv_nsec = 0;
-	tv.tv_sec = pxa_get_rtc_time();
-	do_settimeofday(&tv);
-
-	timer_irq.handler = pxa_timer_interrupt;
-	OSMR0 = 0;		/* set initial match at 0 */
-	OSSR = 0xf;		/* clear status on all timers */
-	setup_irq(IRQ_OST0, &timer_irq);
-	OIER |= OIER_E0;	/* enable match on timer 0 to cause interrupts */
-	OSCR = 0;		/* initialize free-running timer, force first match */
-}
-
diff -Nru a/include/asm-arm/arch-rpc/time.h b/include/asm-arm/arch-rpc/time.h
--- a/include/asm-arm/arch-rpc/time.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,37 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-rpc/time.h
- *
- *  Copyright (C) 1996-2000 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
- * published by the Free Software Foundation.
- *
- *  Changelog:
- *   24-Sep-1996 RMK	Created
- *   10-Oct-1996 RMK	Brought up to date with arch-sa110eval
- *   04-Dec-1997 RMK	Updated for new arch/arm/time.c
- */
-extern void ioctime_init(void);
-
-static irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	do_timer(regs);
-	do_set_rtc();
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Set up timer interrupt.
- */
-void __init time_init(void)
-{
-	ioctime_init();
-
-	timer_irq.handler = timer_interrupt;
-
-	setup_irq(IRQ_TIMER, &timer_irq);
-}
diff -Nru a/include/asm-arm/arch-s3c2410/time.h b/include/asm-arm/arch-s3c2410/time.h
--- a/include/asm-arm/arch-s3c2410/time.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,173 +0,0 @@
-/* linux/include/asm-arm/arch-s3c2410/time.h
- *
- *  Copyright (C) 2003 Simtec Electronics <linux@simtec.co.uk>
- *    Ben Dooks, <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/system.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#include <asm/io.h>
-#include <asm/arch/map.h>
-#include <asm/arch/regs-timer.h>
-
-extern unsigned long (*gettimeoffset)(void);
-
-static unsigned long timer_startval;
-static unsigned long timer_ticks_usec;
-
-#ifdef CONFIG_S3C2410_RTC
-extern void s3c2410_rtc_check();
-#endif
-
-/* with an 12MHz clock, we get 12 ticks per-usec
- */
-
-
-/***
- * Returns microsecond  since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
- * IRQs are disabled before entering here from do_gettimeofday()
- */
-static unsigned long s3c2410_gettimeoffset (void)
-{
-	unsigned long tdone;
-	unsigned long usec;
-
-	/* work out how many ticks have gone since last timer interrupt */
-
-	tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4));
-
-	/* currently, tcnt is in 12MHz units, but this may change
-	 * for non-bast machines...
-	 */
-
-	usec = tdone / timer_ticks_usec;
-
-	return usec;
-}
-
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-s3c2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	do_leds();
-	do_timer(regs);
-
-	do_set_rtc();
-	//s3c2410_rtc_check();
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-
-/* currently we only use timer4, as it is the only timer which has no
- * other function that can be exploited externally
-*/
-
-void __init time_init (void)
-{
-	unsigned long tcon;
-	unsigned long tcnt;
-	unsigned long tcfg1;
-	unsigned long tcfg0;
-
-	gettimeoffset = s3c2410_gettimeoffset;
-	timer_irq.handler = s3c2410_timer_interrupt;
-
-	tcnt = 0xffff;  /* default value for tcnt */
-
-	/* read the current timer configuration bits */
-
-	tcon = __raw_readl(S3C2410_TCON);
-	tcfg1 = __raw_readl(S3C2410_TCFG1);
-	tcfg0 = __raw_readl(S3C2410_TCFG0);
-
-	/* configure the system for whichever machine is in use */
-
-	if (machine_is_bast() || machine_is_vr1000()) {
-		timer_ticks_usec = 12;	      /* timer is at 12MHz */
-		tcnt = (timer_ticks_usec * (1000*1000)) / HZ;
-	}
-
-	/* for the h1940, we use the pclk from the core to generate
-	 * the timer values. since 67.5MHz is not a value we can directly
-	 * generate the timer value from, we need to pre-scale and
-	 * divied before using it.
-	 *
-	 * overall divsior to get 200Hz is 337500
-	 *   we can fit tcnt if we pre-scale by 6, producing a tick rate
-	 *   of 11.25MHz, and a tcnt of 56250.
-	 */
-
-	if (machine_is_h1940() || machine_is_smdk2410() ) {
-		timer_ticks_usec = s3c2410_pclk / (1000*1000);
-		timer_ticks_usec /= 6;
-
-		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
-		tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
-
-		tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
-		tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
-
-		tcnt = (s3c2410_pclk / 6) / HZ;
-	}
-
-
-	printk("setup_timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx\n",
-	       tcon, tcnt, tcfg0, tcfg1);
-
-	/* check to see if timer is within 16bit range... */
-	if (tcnt > 0xffff) {
-		panic("setup_timer: HZ is too small, cannot configure timer!");
-		return;
-	}
-
-	__raw_writel(tcfg1, S3C2410_TCFG1);
-	__raw_writel(tcfg0, S3C2410_TCFG0);
-
-	timer_startval = tcnt;
-	__raw_writel(tcnt, S3C2410_TCNTB(4));
-
-	/* ensure timer is stopped... */
-
-	tcon &= ~(7<<20);
-	tcon |= S3C2410_TCON_T4RELOAD;
-	tcon |= S3C2410_TCON_T4MANUALUPD;
-
-	__raw_writel(tcon, S3C2410_TCON);
-	__raw_writel(tcnt, S3C2410_TCNTB(4));
-	__raw_writel(tcnt, S3C2410_TCMPB(4));
-
-	setup_irq(IRQ_TIMER4, &timer_irq);
-
-	/* start the timer running */
-	tcon |= S3C2410_TCON_T4START;
-	tcon &= ~S3C2410_TCON_T4MANUALUPD;
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-
-
diff -Nru a/include/asm-arm/arch-sa1100/time.h b/include/asm-arm/arch-sa1100/time.h
--- a/include/asm-arm/arch-sa1100/time.h	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,111 +0,0 @@
-/*
- * linux/include/asm-arm/arch-sa1100/time.h
- *
- * Copyright (C) 1998 Deborah Wallach.
- * Twiddles  (C) 1999 	Hugo Fiennes <hugo@empeg.com>
- * 
- * 2000/03/29 (C) Nicolas Pitre <nico@cam.org>
- *	Rewritten: big cleanup, much simpler, better HZ accuracy.
- *
- */
-
-
-#define RTC_DEF_DIVIDER		(32768 - 1)
-#define RTC_DEF_TRIM            0
-
-static unsigned long __init sa1100_get_rtc_time(void)
-{
-	/*
-	 * According to the manual we should be able to let RTTR be zero
-	 * and then a default diviser for a 32.768KHz clock is used.
-	 * Apparently this doesn't work, at least for my SA1110 rev 5.
-	 * If the clock divider is uninitialized then reset it to the
-	 * default value to get the 1Hz clock.
-	 */
-	if (RTTR == 0) {
-		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-		printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n");
-		/* The current RTC value probably doesn't make sense either */
-		RCNR = 0;
-		return 0;
-	}
-	return RCNR;
-}
-
-static int sa1100_set_rtc(void)
-{
-	unsigned long current_time = xtime.tv_sec;
-
-	if (RTSR & RTSR_ALE) {
-		/* make sure not to forward the clock over an alarm */
-		unsigned long alarm = RTAR;
-		if (current_time >= alarm && alarm >= RCNR)
-			return -ERESTARTSYS;
-	}
-	RCNR = current_time;
-	return 0;
-}
-
-/* IRQs are disabled before entering here from do_gettimeofday() */
-static unsigned long sa1100_gettimeoffset (void)
-{
-	unsigned long ticks_to_match, elapsed, usec;
-
-	/* Get ticks before next timer match */
-	ticks_to_match = OSMR0 - OSCR;
-
-	/* We need elapsed ticks since last match */
-	elapsed = LATCH - ticks_to_match;
-
-	/* Now convert them to usec */
-	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
-
-	return usec;
-}
-
-/*
- * We will be entered with IRQs enabled.
- *
- * Loop until we get ahead of the free running timer.
- * This ensures an exact clock tick count and time accuracy.
- * IRQs are disabled inside the loop to ensure coherence between
- * lost_ticks (updated in do_timer()) and the match reg value, so we
- * can use do_gettimeofday() from interrupt handlers.
- */
-static irqreturn_t
-sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned int next_match;
-
-	do {
-		do_leds();
-		do_timer(regs);
-		OSSR = OSSR_M0;  /* Clear match on timer 0 */
-		next_match = (OSMR0 += LATCH);
-		do_set_rtc();
-	} while ((signed long)(next_match - OSCR) <= 0);
-
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-void __init time_init(void)
-{
-	struct timespec tv;
-
-	gettimeoffset = sa1100_gettimeoffset;
-	set_rtc = sa1100_set_rtc;
-
-	tv.tv_nsec = 0;
-	tv.tv_sec = sa1100_get_rtc_time();
-	do_settimeofday(&tv);
-
-	timer_irq.handler = sa1100_timer_interrupt;
-	OSMR0 = 0;		/* set initial match at 0 */
-	OSSR = 0xf;		/* clear status on all timers */
-	setup_irq(IRQ_OST0, &timer_irq);
-	OIER |= OIER_E0;	/* enable match on timer 0 to cause interrupts */
-	OSCR = 0;		/* initialize free-running timer, force first match */
-}
-
diff -Nru a/include/asm-arm/arch-shark/time.h b/include/asm-arm/arch-shark/time.h
--- a/include/asm-arm/arch-shark/time.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,39 +0,0 @@
-/*
- * linux/include/asm-arm/arch-shark/time.h
- *
- * by Alexander Schulz
- *
- * derived from include/asm-arm/arch-ebsa110/time.h
- * Copyright (c) 1996,1997,1998 Russell King.
- */
-
-#include <asm/leds.h>
-#include <asm/param.h>
-
-#define IRQ_TIMER 0
-#define HZ_TIME ((1193180 + HZ/2) / HZ)
-
-static irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	do_leds();
-	do_timer(regs);
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-void __init time_init(void)
-{
-        unsigned long flags;
-
-	outb(0x34, 0x43);               /* binary, mode 0, LSB/MSB, Ch 0 */
-	outb(HZ_TIME & 0xff, 0x40);     /* LSB of count */
-	outb(HZ_TIME >> 8, 0x40);
-
-	timer_irq.handler = timer_interrupt;
-	setup_irq(IRQ_TIMER, &timer_irq);
-}
diff -Nru a/include/asm-arm/arch-tbox/dma.h b/include/asm-arm/arch-tbox/dma.h
--- a/include/asm-arm/arch-tbox/dma.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,37 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/dma.h
- *
- * Architecture DMA routines.  We have to contend with the bizarre DMA
- * machine built into the Tbox hardware.
- *
- * Copyright (C) 1998 Philip Blundell
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-/*
- * DMA channel definitions.  Some of these are physically strange but
- * we sort it out inside dma.c so the user never has to care.  The
- * exception is the double-buffering which we can't really abstract
- * away sensibly.
- */
-#define DMA_VIDEO			0
-#define DMA_MPEG_B			1
-#define DMA_AUDIO_B			2
-#define DMA_ASHRX_B			3
-#define DMA_ASHTX			4
-#define DMA_MPEG			5
-#define DMA_AUDIO			6
-#define DMA_ASHRX			7
-
-#define MAX_DMA_CHANNELS		0	/* XXX */
-
-/*
- * This is the maximum DMA address that can be DMAd to.
- */
-#define MAX_DMA_ADDRESS		0xffffffff
diff -Nru a/include/asm-arm/arch-tbox/hardware.h b/include/asm-arm/arch-tbox/hardware.h
--- a/include/asm-arm/arch-tbox/hardware.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,60 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/hardware.h
- *
- * Copyright (C) 1998, 1999, 2000 Philip Blundell
- * Copyright (C) 2000 FutureTV Labs Ltd
- *
- * This file contains the hardware definitions of the Tbox
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-/*    Logical    Physical
- * 0xfff00000	0x00100000	I/O
- * 0xfff00000	0x00100000	  Expansion CS0
- * 0xfff10000	0x00110000	  DMA
- * 0xfff20000	0x00120000	  C-Cube
- * 0xfff30000	0x00130000	  FPGA 1
- * 0xfff40000	0x00140000	  UART 2
- * 0xfff50000	0x00150000	  UART 1
- * 0xfff60000	0x00160000	  CS8900
- * 0xfff70000	0x00170000	  INTCONT
- * 0xfff80000	0x00180000	  RAMDAC
- * 0xfff90000	0x00190000	  Control 0
- * 0xfffa0000	0x001a0000	  Control 1
- * 0xfffb0000	0x001b0000	  Control 2
- * 0xfffc0000	0x001c0000	  FPGA 2
- * 0xfffd0000	0x001d0000	  INTRESET
- * 0xfffe0000	0x001e0000	  C-Cube DMA throttle
- * 0xffff0000	0x001f0000	  Expansion CS1
- * 0xffe00000	0x82000000	cache flush
- */
-
-/*
- * Mapping areas
- */
-#define IO_BASE			0xfff00000
-#define IO_START		0x00100000
-#define FLUSH_BASE		0xffe00000
-
-#define INTCONT			0xfff70000
-
-#define FPGA1CONT		0xffff3000
-
-/*
- * RAM definitions
- */
-#define RAM_BASE		0x80000000
-#define FLUSH_BASE_PHYS		0x82000000
-
-#define UNCACHEABLE_ADDR	INTCONT
-
-#endif
diff -Nru a/include/asm-arm/arch-tbox/io.h b/include/asm-arm/arch-tbox/io.h
--- a/include/asm-arm/arch-tbox/io.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,40 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/io.h
- *
- * Copyright (C) 1996-1999 Russell King
- * Copyright (C) 1998, 1999 Philip Blundell
- *
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(_x)		((_x) << 2)
-
-/*
- * Generic virtual read/write
- */
-static inline unsigned int __arch_getw(unsigned long a)
-{
-	unsigned int value;
-	__asm__ __volatile__("ldr%?h	%0, [%1, #0]	@ getw"
-		: "=&r" (value)
-		: "r" (a));
-	return value;
-}
-
-static inline void __arch_putw(unsigned int value, unsigned long a)
-{
-	__asm__ __volatile__("str%?h	%0, [%1, #0]	@ putw"
-		: : "r" (value), "r" (a));
-}
-
-/* Idem, for devices on the upper byte lanes */
-#define inb_u(p)		__arch_getb(__io_pc(p) + 2)
-#define inw_u(p)		__arch_getw(__io_pc(p) + 2)
-
-#define outb_u(v,p)		__arch_putb(v,__io_pc(p) + 2)
-#define outw_u(v,p)		__arch_putw(v,__io_pc(p) + 2)
-
-#endif
diff -Nru a/include/asm-arm/arch-tbox/irqs.h b/include/asm-arm/arch-tbox/irqs.h
--- a/include/asm-arm/arch-tbox/irqs.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,29 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/irqs.h
- *
- * Copyright (C) 1998, 2000 Philip Blundell
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define IRQ_MPEGDMA		0
-#define IRQ_ASHTX		1
-#define IRQ_ASHRX		2
-#define IRQ_VSYNC		3
-#define IRQ_HSYNC		4
-#define IRQ_MPEG		5
-#define IRQ_UART2		6
-#define IRQ_UART1		7
-#define IRQ_ETHERNET		8
-#define IRQ_TIMER		9
-#define IRQ_AUDIODMA		10
-/* bit 11 used for video field ident */
-#define IRQ_EXPMODCS0		12
-#define IRQ_EXPMODCS1		13
-
-#define irq_canonicalize(i)	(i)
diff -Nru a/include/asm-arm/arch-tbox/memory.h b/include/asm-arm/arch-tbox/memory.h
--- a/include/asm-arm/arch-tbox/memory.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,21 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/memory.h
- *
- * Copyright (c) 1996-1999 Russell King.
- * Copyright (c) 1998-1999 Phil Blundell
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PHYS_OFFSET		(0x80000000UL)
-
-/*
- * Bus view is the same as physical view
- */
-#define __virt_to_bus(x)	__virt_to_phys(x)
-#define __bus_to_virt(x)	__phys_to_virt(x)
-
-#endif
diff -Nru a/include/asm-arm/arch-tbox/param.h b/include/asm-arm/arch-tbox/param.h
--- a/include/asm-arm/arch-tbox/param.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,4 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-tbox/param.h
- */
-#define __KERNEL_HZ 1000
diff -Nru a/include/asm-arm/arch-tbox/serial.h b/include/asm-arm/arch-tbox/serial.h
--- a/include/asm-arm/arch-tbox/serial.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,32 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/serial.h
- *
- * Copyright (c) 1996 Russell King.
- * Copyright (c) 1998 Phil Blundell
- *
- * Changelog:
- *  15-10-1996	RMK	Created
- *  09-06-1998  PJB	tbox version
- */
-#ifndef __ASM_ARCH_SERIAL_H
-#define __ASM_ARCH_SERIAL_H
-
-/*
- * This assumes you have a 1.8432 MHz clock for your UART.
- *
- * It'd be nice if someone built a serial card with a 24.576 MHz
- * clock, since the 16550A is capable of handling a top speed of 1.5
- * megabits/second; but this requires the faster clock.
- */
-#define BASE_BAUD (1843200 / 16)
-
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
-     /* UART CLK        PORT  IRQ     FLAGS        */
-#define STD_SERIAL_PORT_DEFNS \
-	{ 0, BASE_BAUD, 0xffff4000 >> 2, 6, STD_COM_FLAGS }, /* ttyS0 */ \
-	{ 0, BASE_BAUD, 0xffff5000 >> 2, 7, STD_COM_FLAGS }, /* ttyS1 */
-
-#define EXTRA_SERIAL_PORT_DEFNS
-
-#endif
diff -Nru a/include/asm-arm/arch-tbox/system.h b/include/asm-arm/arch-tbox/system.h
--- a/include/asm-arm/arch-tbox/system.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,16 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/system.h
- *
- * Copyright (c) 1996-1999 Russell King.
- */
-#ifndef __ASM_ARCH_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H
-
-static inline void arch_idle(void)
-{
-	cpu_do_idle();
-}
-
-#define arch_reset(mode)	do { } while (0)
-
-#endif
diff -Nru a/include/asm-arm/arch-tbox/time.h b/include/asm-arm/arch-tbox/time.h
--- a/include/asm-arm/arch-tbox/time.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,39 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/time.h
- *
- * Copyright (c) 1997, 1999 Phil Blundell.
- * Copyright (c) 2000 FutureTV Labs Ltd
- *
- * Tbox has no real-time clock -- we get millisecond ticks to update
- * our soft copy.
- */
-
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/io.h>
-#include <asm/hardware.h>
-
-#define update_rtc()
-
-static irqreturn_t
-timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
-{
-	/* Clear irq */
-	__raw_writel(1, FPGA1CONT + 0xc); 
-	__raw_writel(0, FPGA1CONT + 0xc);
-
-	do_timer(regs);
-
-	return IRQ_HANDLED;
-}
-
-void __init time_init(void)
-{
-	timer_irq.handler = timer_interrupt;
-	setup_irq(IRQ_TIMER, &timer_irq);
-}
diff -Nru a/include/asm-arm/arch-tbox/timex.h b/include/asm-arm/arch-tbox/timex.h
--- a/include/asm-arm/arch-tbox/timex.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,8 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/timex.h
- *
- * Tbox timex specifications
- *
- * Copyright (C) 1999 Philip Blundell
- */
-
diff -Nru a/include/asm-arm/arch-tbox/uncompress.h b/include/asm-arm/arch-tbox/uncompress.h
--- a/include/asm-arm/arch-tbox/uncompress.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,42 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/uncompress.h
- *  from linux/include/asm-arm/arch-ebsa110/uncompress.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- * Copyright (C) 1998, 1999 Phil Blundell
- */
-
-#include <asm/io.h>
-
-#define UARTBASE 0x00400000
-
-/*
- * This does not append a newline
- */
-static void puts(const char *s)
-{
-  while (*s)
-  {
-    char c = *(s++);
-    while (!(__raw_readb(UARTBASE + 0x14) & 0x20));
-    __raw_writeb(c, UARTBASE);
-    if (c == 10) {
-      while (!(__raw_readb(UARTBASE + 0x14) & 0x20));
-      __raw_writeb(13, UARTBASE);
-    }
-  }
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-
-/*
- * Stroke the watchdog so we don't get reset during decompression.
- */
-#define arch_decomp_wdog()				\
-	do {						\
-	__raw_writel(1, 0xa00000);			\
-	__raw_writel(0, 0xa00000);			\
-	} while (0)
diff -Nru a/include/asm-arm/arch-tbox/vmalloc.h b/include/asm-arm/arch-tbox/vmalloc.h
--- a/include/asm-arm/arch-tbox/vmalloc.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,15 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/vmalloc.h
- */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff -Nru a/include/asm-arm/arch-versatile/time.h b/include/asm-arm/arch-versatile/time.h
--- a/include/asm-arm/arch-versatile/time.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,158 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-versatile/time.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/system.h>
-#include <asm/leds.h>
-
-/*
- * Where is the timer (VA)?
- */
-#define TIMER0_VA_BASE		 IO_ADDRESS(VERSATILE_TIMER0_1_BASE)
-#define TIMER1_VA_BASE		(IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20)
-#define TIMER2_VA_BASE		 IO_ADDRESS(VERSATILE_TIMER2_3_BASE)
-#define TIMER3_VA_BASE		(IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20)
-#define VA_IC_BASE		 IO_ADDRESS(VERSATILE_VIC_BASE) 
-
-/*
- * How long is the timer interval?
- */
-#define TIMER_INTERVAL	(TICKS_PER_uSEC * mSEC_10)
-#if TIMER_INTERVAL >= 0x100000
-#define TIMER_RELOAD	(TIMER_INTERVAL >> 8)		/* Divide by 256 */
-#define TIMER_CTRL	0x88				/* Enable, Clock / 256 */
-#define TICKS2USECS(x)	(256 * (x) / TICKS_PER_uSEC)
-#elif TIMER_INTERVAL >= 0x10000
-#define TIMER_RELOAD	(TIMER_INTERVAL >> 4)		/* Divide by 16 */
-#define TIMER_CTRL	0x84				/* Enable, Clock / 16 */
-#define TICKS2USECS(x)	(16 * (x) / TICKS_PER_uSEC)
-#else
-#define TIMER_RELOAD	(TIMER_INTERVAL)
-#define TIMER_CTRL	0x80				/* Enable */
-#define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
-#endif
-
-#define TIMER_CTRL_IE	(1 << 5)	/* Interrupt Enable */
-
-/*
- * What does it look like?
- */
-typedef struct TimerStruct {
-	unsigned long TimerLoad;
-	unsigned long TimerValue;
-	unsigned long TimerControl;
-	unsigned long TimerClear;
-} TimerStruct_t;
-
-extern unsigned long (*gettimeoffset)(void);
-
-/*
- * Returns number of ms since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
- */
-static unsigned long versatile_gettimeoffset(void)
-{
-	volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE;
-	unsigned long ticks1, ticks2, status;
-
-	/*
-	 * Get the current number of ticks.  Note that there is a race
-	 * condition between us reading the timer and checking for
-	 * an interrupt.  We get around this by ensuring that the
-	 * counter has not reloaded between our two reads.
-	 */
-	ticks2 = timer0->TimerValue & 0xffff;
-	do {
-		ticks1 = ticks2;
-		status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS);
-		ticks2 = timer0->TimerValue & 0xffff;
-	} while (ticks2 > ticks1);
-
-	/*
-	 * Number of ticks since last interrupt.
-	 */
-	ticks1 = TIMER_RELOAD - ticks2;
-
-	/*
-	 * Interrupt pending?  If so, we've reloaded once already.
-	 *
-	 * FIXME: Need to check this is effectively timer 0 that expires
-	 */
-	if (status & IRQMASK_TIMERINT0_1)
-		ticks1 += TIMER_RELOAD;
-
-	/*
-	 * Convert the ticks to usecs
-	 */
-	return TICKS2USECS(ticks1);
-}
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-
-	// ...clear the interrupt
-	timer0->TimerClear = 1;
-
-	do_leds();
-	do_timer(regs);
-	do_profile(regs);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-void __init time_init(void)
-{
-	volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-	volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
-	volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
-	volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE;
-
-	/* 
-	 * set clock frequency: 
-	 *	VERSATILE_REFCLK is 32KHz
-	 *	VERSATILE_TIMCLK is 1MHz
-	 */
-	*(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= 
-	  ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
-	   (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel));
-
-	timer_irq.handler = versatile_timer_interrupt;
-
-	/*
-	 * Initialise to a known state (all timers off)
-	 */
-	timer0->TimerControl = 0;
-	timer1->TimerControl = 0;
-	timer2->TimerControl = 0;
-	timer3->TimerControl = 0;
-
-	timer0->TimerLoad    = TIMER_RELOAD;
-	timer0->TimerValue   = TIMER_RELOAD;
-	timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE;  /* periodic + IE */
-
-	/* 
-	 * Make irqs happen for the system timer
-	 */
-	setup_irq(IRQ_TIMERINT0_1, &timer_irq);
-	gettimeoffset = versatile_gettimeoffset;
-}
diff -Nru a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
--- a/include/asm-arm/checksum.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-arm/checksum.h	2004-06-23 19:04:28 -07:00
@@ -9,6 +9,8 @@
 #ifndef __ASM_ARM_CHECKSUM_H
 #define __ASM_ARM_CHECKSUM_H
 
+#include <linux/in6.h>
+
 /*
  * computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit)
diff -Nru a/include/asm-arm/cpu-multi32.h b/include/asm-arm/cpu-multi32.h
--- a/include/asm-arm/cpu-multi32.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-arm/cpu-multi32.h	2004-06-23 19:04:25 -07:00
@@ -7,9 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef __ASSEMBLY__
-
-#include <asm/memory.h>
 #include <asm/page.h>
 
 struct mm_struct;
@@ -64,16 +61,4 @@
 #define cpu_do_idle()			processor._do_idle()
 #define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz)
 #define cpu_set_pte(ptep, pte)		processor.set_pte(ptep, pte)
-
-#define cpu_switch_mm(pgd,mm)	processor.switch_mm(__virt_to_phys((unsigned long)(pgd)),mm)
-
-#define cpu_get_pgd()	\
-	({						\
-		unsigned long pg;			\
-		__asm__("mrc	p15, 0, %0, c2, c0, 0"	\
-			 : "=r" (pg) : : "cc");		\
-		pg &= ~0x3fff;				\
-		(pgd_t *)phys_to_virt(pg);		\
-	})
-
-#endif
+#define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
diff -Nru a/include/asm-arm/cpu-single.h b/include/asm-arm/cpu-single.h
--- a/include/asm-arm/cpu-single.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-arm/cpu-single.h	2004-06-23 19:04:25 -07:00
@@ -27,12 +27,9 @@
 #define cpu_reset			__cpu_fn(CPU_NAME,_reset)
 #define cpu_do_idle			__cpu_fn(CPU_NAME,_do_idle)
 #define cpu_dcache_clean_area		__cpu_fn(CPU_NAME,_dcache_clean_area)
-#define cpu__switch_mm			__cpu_fn(CPU_NAME,_switch_mm)
+#define cpu_do_switch_mm		__cpu_fn(CPU_NAME,_switch_mm)
 #define cpu_set_pte			__cpu_fn(CPU_NAME,_set_pte)
 
-#ifndef __ASSEMBLY__
-
-#include <asm/memory.h>
 #include <asm/page.h>
 
 struct mm_struct;
@@ -42,20 +39,6 @@
 extern void cpu_proc_fin(void);
 extern int cpu_do_idle(void);
 extern void cpu_dcache_clean_area(void *, int);
-extern void cpu__switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
+extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
 extern void cpu_set_pte(pte_t *ptep, pte_t pte);
-
 extern volatile void cpu_reset(unsigned long addr);
-
-#define cpu_switch_mm(pgd,mm) cpu__switch_mm(__virt_to_phys((unsigned long)(pgd)),mm)
-
-#define cpu_get_pgd()	\
-	({						\
-		unsigned long pg;			\
-		__asm__("mrc	p15, 0, %0, c2, c0, 0"	\
-			 : "=r" (pg) : : "cc");		\
-		pg &= ~0x3fff;				\
-		(pgd_t *)phys_to_virt(pg);		\
-	})
-
-#endif
diff -Nru a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
--- a/include/asm-arm/dma-mapping.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-arm/dma-mapping.h	2004-06-23 19:04:25 -07:00
@@ -124,7 +124,7 @@
 	       enum dma_data_direction dir)
 {
 	consistent_sync(cpu_addr, size, dir);
-	return __virt_to_bus((unsigned long)cpu_addr);
+	return virt_to_dma(dev, (unsigned long)cpu_addr);
 }
 #else
 extern dma_addr_t dma_map_single(struct device *,void *, size_t, enum dma_data_direction);
@@ -231,7 +231,7 @@
 	for (i = 0; i < nents; i++, sg++) {
 		char *virt;
 
-		sg->dma_address = page_to_bus(sg->page) + sg->offset;
+		sg->dma_address = page_to_dma(dev, sg->page) + sg->offset;
 		virt = page_address(sg->page) + sg->offset;
 		consistent_sync(virt, sg->length, dir);
 	}
@@ -288,14 +288,14 @@
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size,
 			enum dma_data_direction dir)
 {
-	consistent_sync((void *)__bus_to_virt(handle), size, dir);
+	consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
 }
 
 static inline void
 dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
 			   enum dma_data_direction dir)
 {
-	consistent_sync((void *)__bus_to_virt(handle), size, dir);
+	consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
 }
 #else
 extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction);
diff -Nru a/include/asm-arm/fcntl.h b/include/asm-arm/fcntl.h
--- a/include/asm-arm/fcntl.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-arm/fcntl.h	2004-06-23 19:04:26 -07:00
@@ -20,6 +20,7 @@
 #define O_NOFOLLOW	0100000	/* don't follow links */
 #define O_DIRECT	0200000	/* direct disk access hint - currently ignored */
 #define O_LARGEFILE	0400000
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
--- a/include/asm-arm/fpstate.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-arm/fpstate.h	2004-06-23 19:04:28 -07:00
@@ -13,6 +13,36 @@
 
 #define FP_SIZE 35
 
+#ifndef __ASSEMBLY__
+
+/*
+ * VFP storage area has:
+ *  - FPEXC, FPSCR, FPINST and FPINST2.
+ *  - 16 double precision data registers
+ *  - an implementation-dependant word of state for FLDMX/FSTMX
+ * 
+ *  FPEXC will always be non-zero once the VFP has been used in this process.
+ */
+
+struct vfp_hard_struct {
+	__u64 fpregs[16];
+	__u32 fpmx_state;
+	__u32 fpexc;
+	__u32 fpscr;
+	/*
+	 * VFP implementation specific state
+	 */
+	__u32 fpinst;
+	__u32 fpinst2;
+};
+
+union vfp_state {
+	struct vfp_hard_struct	hard;
+};
+
+extern void vfp_flush_thread(union vfp_state *);
+extern void vfp_release_thread(union vfp_state *);
+
 struct fp_hard_struct {
 	unsigned int save[FP_SIZE];		/* as yet undefined */
 };
@@ -25,5 +55,7 @@
 	struct fp_hard_struct	hard;
 	struct fp_soft_struct	soft;
 };
+
+#endif
 
 #endif
diff -Nru a/include/asm-arm/hardware/clock.h b/include/asm-arm/hardware/clock.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/hardware/clock.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,121 @@
+/*
+ *  linux/include/asm-arm/hardware/clock.h
+ *
+ *  Copyright (C) 2004 ARM Limited.
+ *  Written by Deep Blue Solutions Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASMARM_CLOCK_H
+#define ASMARM_CLOCK_H
+
+struct device;
+
+/*
+ * The base API.
+ */
+
+
+/*
+ * struct clk - an machine class defined object / cookie.
+ */
+struct clk;
+
+/**
+ * clk_get - lookup and obtain a reference to a clock producer.
+ * @dev: device for clock "consumer"
+ * @id: device ID
+ *
+ * Returns a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno.
+ */
+struct clk *clk_get(struct device *dev, const char *id);
+
+/**
+ * clk_enable - inform the system when the clock source should be running.
+ * @clk: clock source
+ *
+ * If the clock can not be enabled/disabled, this should return success.
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_enable(struct clk *clk);
+
+/**
+ * clk_disable - inform the system when the clock source is no longer required.
+ * @clk: clock source
+ */
+void clk_disable(struct clk *clk);
+
+/**
+ * clk_use - increment the use count
+ * @clk: clock source
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_use(struct clk *clk);
+
+/**
+ * clk_unuse - decrement the use count
+ * @clk: clock source
+ */
+void clk_unuse(struct clk *clk);
+
+/**
+ * clk_get_rate - obtain the current clock rate for a clock source.
+ *		  This is only valid once the clock source has been enabled.
+ * @clk: clock source
+ */
+unsigned long clk_get_rate(struct clk *clk);
+
+/**
+ * clk_put	- "free" the clock source
+ * @clk: clock source
+ */
+void clk_put(struct clk *clk);
+
+
+/*
+ * The remaining APIs are optional for machine class support.
+ */
+
+
+/**
+ * clk_round_rate - adjust a rate to the exact rate a clock can provide
+ * @clk: clock source
+ * @rate: desired clock rate in kHz
+ *
+ * Returns rounded clock rate, or negative errno.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate);
+ 
+/**
+ * clk_set_rate - set the clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired clock rate in kHz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate);
+ 
+/**
+ * clk_set_parent - set the parent clock source for this clock
+ * @clk: clock source
+ * @parent: parent clock source
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent);
+                                                                                
+/**
+ * clk_get_parent - get the parent clock source for this clock
+ * @clk: clock source
+ *
+ * Returns struct clk corresponding to parent clock source, or
+ * valid IS_ERR() condition containing errno.
+ */
+struct clk *clk_get_parent(struct clk *clk);
+
+#endif
diff -Nru a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h
--- a/include/asm-arm/mach/arch.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-arm/mach/arch.h	2004-06-23 19:04:28 -07:00
@@ -45,6 +45,7 @@
 					 struct meminfo *);
 	void			(*map_io)(void);/* IO mapping function	*/
 	void			(*init_irq)(void);
+	void			(*init_time)(void);
 	void			(*init_machine)(void);
 };
 
@@ -86,6 +87,9 @@
 
 #define INITIRQ(_func)				\
 	.init_irq	= _func,
+
+#define INITTIME(_func)				\
+	.init_time	= _func,
 
 #define INIT_MACHINE(_func)			\
 	.init_machine	= _func,
diff -Nru a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/mach/time.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,20 @@
+/*
+ * linux/include/asm-arm/mach/time.h
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_MACH_TIME_H
+#define __ASM_ARM_MACH_TIME_H
+
+extern void (*init_arch_time)(void);
+
+extern int (*set_rtc)(void);
+extern unsigned long(*gettimeoffset)(void);
+
+void timer_tick(struct pt_regs *);
+
+#endif
diff -Nru a/include/asm-arm/memory.h b/include/asm-arm/memory.h
--- a/include/asm-arm/memory.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-arm/memory.h	2004-06-23 19:04:28 -07:00
@@ -159,9 +159,18 @@
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 
 /*
+ * Optional device DMA address remapping. Do _not_ use directly!
  * We should really eliminate virt_to_bus() here - it's deprecated.
  */
-#define page_to_bus(page)	(virt_to_bus(page_address(page)))
+#ifndef __arch_page_to_dma
+#define page_to_dma(dev, page)		((dma_addr_t)__virt_to_bus(page_address(page)))
+#define dma_to_virt(dev, addr)		(__bus_to_virt(addr))
+#define virt_to_dma(dev, addr)		(__virt_to_bus(addr))
+#else
+#define page_to_dma(dev, page)		(__arch_page_to_dma(dev, page))
+#define dma_to_virt(dev, addr)		(__arch_dma_to_virt(dev, addr))
+#define virt_to_dma(dev, addr)		(__arch_virt_to_dma(dev, addr))
+#endif
 
 #endif
 
diff -Nru a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h
--- a/include/asm-arm/proc-fns.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-arm/proc-fns.h	2004-06-23 19:04:27 -07:00
@@ -148,11 +148,27 @@
 # endif
 #endif
 
+#ifndef __ASSEMBLY__
+
 #ifndef MULTI_CPU
 #include "asm/cpu-single.h"
 #else
 #include "asm/cpu-multi32.h"
 #endif
 
+#include <asm/memory.h>
+
+#define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm)
+
+#define cpu_get_pgd()	\
+	({						\
+		unsigned long pg;			\
+		__asm__("mrc	p15, 0, %0, c2, c0, 0"	\
+			 : "=r" (pg) : : "cc");		\
+		pg &= ~0x3fff;				\
+		(pgd_t *)phys_to_virt(pg);		\
+	})
+
+#endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* __ASM_PROCFNS_H */
diff -Nru a/include/asm-arm/resource.h b/include/asm-arm/resource.h
--- a/include/asm-arm/resource.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-arm/resource.h	2004-06-23 19:04:28 -07:00
@@ -16,8 +16,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 #ifdef __KERNEL__
 
@@ -40,6 +42,8 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
+	{ MAX_SIGPENDING, MAX_SIGPENDING},	\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX},		\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
--- a/include/asm-arm/thread_info.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-arm/thread_info.h	2004-06-23 19:04:26 -07:00
@@ -12,12 +12,13 @@
 
 #ifdef __KERNEL__
 
+#include <asm/fpstate.h>
+
 #ifndef __ASSEMBLY__
 
 struct task_struct;
 struct exec_domain;
 
-#include <asm/fpstate.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
 #include <asm/domain.h>
@@ -53,7 +54,8 @@
 	struct cpu_context_save	cpu_context;	/* cpu context */
 	__u8			used_cp[16];	/* thread used copro */
 	union fp_state		fpstate;
-	struct restart_block    restart_block;
+	union vfp_state		vfpstate;
+	struct restart_block	restart_block;
 };
 
 #define INIT_THREAD_INFO(tsk)						\
@@ -110,6 +112,7 @@
 #define TI_CPU_SAVE	28
 #define TI_USED_CP	76
 #define TI_FPSTATE	(TI_USED_CP+16)
+#define TI_VFPSTATE	(TI_FPSTATE+FP_SIZE*4)
 
 #endif
 
diff -Nru a/include/asm-arm/vfp.h b/include/asm-arm/vfp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/vfp.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,78 @@
+/*
+ * linux/include/asm-arm/vfp.h
+ *
+ * VFP register definitions.
+ * First, the standard VFP set.
+ */
+
+#define FPSID			cr0
+#define FPSCR			cr1
+#define FPEXC			cr8
+
+/* FPSID bits */
+#define FPSID_IMPLEMENTER_BIT	(24)
+#define FPSID_IMPLEMENTER_MASK	(0xff << FPSID_IMPLEMENTER_BIT)
+#define FPSID_SOFTWARE		(1<<23)
+#define FPSID_FORMAT_BIT	(21)
+#define FPSID_FORMAT_MASK	(0x3  << FPSID_FORMAT_BIT)
+#define FPSID_NODOUBLE		(1<<20)
+#define FPSID_ARCH_BIT		(16)
+#define FPSID_ARCH_MASK		(0xF  << FPSID_ARCH_BIT)
+#define FPSID_PART_BIT		(8)
+#define FPSID_PART_MASK		(0xFF << FPSID_PART_BIT)
+#define FPSID_VARIANT_BIT	(4)
+#define FPSID_VARIANT_MASK	(0xF  << FPSID_VARIANT_BIT)
+#define FPSID_REV_BIT		(0)
+#define FPSID_REV_MASK		(0xF  << FPSID_REV_BIT)
+
+/* FPEXC bits */
+#define FPEXC_EXCEPTION		(1<<31)
+#define FPEXC_ENABLE		(1<<30)
+
+/* FPSCR bits */
+#define FPSCR_DEFAULT_NAN	(1<<25)
+#define FPSCR_FLUSHTOZERO	(1<<24)
+#define FPSCR_ROUND_NEAREST	(0<<22)
+#define FPSCR_ROUND_PLUSINF	(1<<22)
+#define FPSCR_ROUND_MINUSINF	(2<<22)
+#define FPSCR_ROUND_TOZERO	(3<<22)
+#define FPSCR_RMODE_BIT		(22)
+#define FPSCR_RMODE_MASK	(3 << FPSCR_RMODE_BIT)
+#define FPSCR_STRIDE_BIT	(20)
+#define FPSCR_STRIDE_MASK	(3 << FPSCR_STRIDE_BIT)
+#define FPSCR_LENGTH_BIT	(16)
+#define FPSCR_LENGTH_MASK	(7 << FPSCR_LENGTH_BIT)
+#define FPSCR_IOE		(1<<8)
+#define FPSCR_DZE		(1<<9)
+#define FPSCR_OFE		(1<<10)
+#define FPSCR_UFE		(1<<11)
+#define FPSCR_IXE		(1<<12)
+#define FPSCR_IDE		(1<<15)
+#define FPSCR_IOC		(1<<0)
+#define FPSCR_DZC		(1<<1)
+#define FPSCR_OFC		(1<<2)
+#define FPSCR_UFC		(1<<3)
+#define FPSCR_IXC		(1<<4)
+#define FPSCR_IDC		(1<<7)
+
+/*
+ * VFP9-S specific.
+ */
+#define FPINST			cr9
+#define FPINST2			cr10
+
+/* FPEXC bits */
+#define FPEXC_FPV2		(1<<28)
+#define FPEXC_LENGTH_BIT	(8)
+#define FPEXC_LENGTH_MASK	(7 << FPEXC_LENGTH_BIT)
+#define FPEXC_INV		(1 << 7)
+#define FPEXC_UFC		(1 << 3)
+#define FPEXC_OFC		(1 << 2)
+#define FPEXC_IOC		(1 << 0)
+
+/* Bit patterns for decoding the packaged operation descriptors */
+#define VFPOPDESC_LENGTH_BIT	(9)
+#define VFPOPDESC_LENGTH_MASK	(0x07 << VFPOPDESC_LENGTH_BIT)
+#define VFPOPDESC_UNUSED_BIT	(24)
+#define VFPOPDESC_UNUSED_MASK	(0xFF << VFPOPDESC_UNUSED_BIT)
+#define VFPOPDESC_OPDESC_MASK	(~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK))
diff -Nru a/include/asm-arm/vfpmacros.h b/include/asm-arm/vfpmacros.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/vfpmacros.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,25 @@
+/*
+ * linux/include/asm-arm/vfpmacros.h
+ *
+ * Assembler-only file containing VFP macros and register definitions.
+ */
+#include "vfp.h"
+
+@ Macros to allow building with old toolkits (with no VFP support)
+	.macro	VFPFMRX, rd, sysreg, cond
+	MRC\cond	p10, 7, \rd, \sysreg, cr0, 0	@ FMRX	\rd, \sysreg
+	.endm
+
+	.macro	VFPFMXR, sysreg, rd, cond
+	MCR\cond	p10, 7, \rd, \sysreg, cr0, 0	@ FMXR	\sysreg, \rd
+	.endm
+
+	@ read all the working registers back into the VFP
+	.macro	VFPFLDMIA, base
+	LDC	p11, cr0, [\base],#33*4		    @ FLDMIAX \base!, {d0-d15}
+	.endm
+
+	@ write all the working registers out of the VFP
+	.macro	VFPFSTMIA, base
+	STC	p11, cr0, [\base],#33*4		    @ FSTMIAX \base!, {d0-d15}
+	.endm
diff -Nru a/include/asm-arm26/fcntl.h b/include/asm-arm26/fcntl.h
--- a/include/asm-arm26/fcntl.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-arm26/fcntl.h	2004-06-23 19:04:28 -07:00
@@ -20,6 +20,7 @@
 #define O_NOFOLLOW	0100000	/* don't follow links */
 #define O_DIRECT	0200000	/* direct disk access hint - currently ignored */
 #define O_LARGEFILE	0400000
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-arm26/resource.h b/include/asm-arm26/resource.h
--- a/include/asm-arm26/resource.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-arm26/resource.h	2004-06-23 19:04:25 -07:00
@@ -16,8 +16,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 #ifdef __KERNEL__
 
@@ -40,6 +42,8 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
+	{ MAX_SIGPENDING, MAX_SIGPENDING},	\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX},		\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-arm26/tlb.h b/include/asm-arm26/tlb.h
--- a/include/asm-arm26/tlb.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-arm26/tlb.h	2004-06-23 19:04:29 -07:00
@@ -1,6 +1,7 @@
 #ifndef __ASMARM_TLB_H
 #define __ASMARM_TLB_H
 
+#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 
 /*
diff -Nru a/include/asm-cris/fcntl.h b/include/asm-cris/fcntl.h
--- a/include/asm-cris/fcntl.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-cris/fcntl.h	2004-06-23 19:04:25 -07:00
@@ -22,6 +22,7 @@
 #define O_LARGEFILE	0100000
 #define O_DIRECTORY	0200000	/* must be a directory */
 #define O_NOFOLLOW	0400000 /* don't follow links */
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get f_flags */
diff -Nru a/include/asm-cris/resource.h b/include/asm-cris/resource.h
--- a/include/asm-cris/resource.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-cris/resource.h	2004-06-23 19:04:27 -07:00
@@ -15,9 +15,11 @@
 #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 */
-#define RLIMIT_LOCKS   10              /* maximum file locks held */
+#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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -38,8 +40,10 @@
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },               \
-        { RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
--- a/include/asm-generic/tlb.h	2004-06-23 19:04:24 -07:00
+++ b/include/asm-generic/tlb.h	2004-06-23 19:04:24 -07:00
@@ -15,6 +15,7 @@
 
 #include <linux/config.h>
 #include <linux/swap.h>
+#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 
 /*
diff -Nru a/include/asm-h8300/fcntl.h b/include/asm-h8300/fcntl.h
--- a/include/asm-h8300/fcntl.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-h8300/fcntl.h	2004-06-23 19:04:28 -07:00
@@ -20,6 +20,7 @@
 #define O_NOFOLLOW	0100000	/* don't follow links */
 #define O_DIRECT	0200000	/* direct disk access hint - currently ignored */
 #define O_LARGEFILE	0400000
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-h8300/io.h b/include/asm-h8300/io.h
--- a/include/asm-h8300/io.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-h8300/io.h	2004-06-23 19:04:27 -07:00
@@ -35,27 +35,38 @@
 
 static inline unsigned short _swapw(volatile unsigned short v)
 {
-	unsigned short r,t;
-	__asm__("mov.b %w2,%x1\n\t"
-		"mov.b %x2,%w1\n\t"
-		"mov.w %1,%0"
-		:"=r"(r),"=r"(t)
-		:"r"(v));
+#ifndef H8300_IO_NOSWAP
+	unsigned short r;
+	__asm__("xor.b %w0,%x0\n\t"
+		"xor.b %x0,%w0\n\t"
+		"xor.b %w0,%x0"
+		:"=r"(r)
+		:"0"(v));
 	return r;
-}
-
-static inline unsigned int _swapl(volatile unsigned long v)
-{
-	unsigned int r,t;
-	__asm__("mov.b %w2,%x1\n\t"
-		"mov.b %x2,%w1\n\t"
-		"mov.w %f1,%e0\n\t"
-		"mov.w %e2,%f1\n\t"
-		"mov.b %w1,%x0\n\t"
-		"mov.b %x1,%w0"
-		:"=r"(r),"=r"(t)
-		:"r"(v));
+#else
+	return v;
+#endif
+}
+
+static inline unsigned long _swapl(volatile unsigned long v)
+{
+#ifndef H8300_IO_NOSWAP
+	unsigned long r;
+	__asm__("xor.b %w0,%x0\n\t"
+		"xor.b %x0,%w0\n\t"
+		"xor.b %w0,%x0\n\t"
+		"xor.w %e0,%f0\n\t"
+		"xor.w %f0,%e0\n\t"
+		"xor.w %e0,%f0\n\t"
+		"xor.b %w0,%x0\n\t"
+		"xor.b %x0,%w0\n\t"
+		"xor.b %w0,%x0"
+		:"=r"(r)
+		:"0"(v));
 	return r;
+#else
+	return v;
+#endif
 }
 
 #define readb(addr) \
@@ -109,12 +120,28 @@
 
 static inline void io_outsl(unsigned int addr, const void *buf, int len)
 {
-	volatile unsigned int *ap = (volatile unsigned int *) addr;
+	volatile unsigned long *ap = (volatile unsigned long *) addr;
 	unsigned long *bp = (unsigned long *) buf;
 	while (len--)
 		*ap = _swapl(*bp++);
 }
 
+static inline void io_outsw_noswap(unsigned int addr, const void *buf, int len)
+{
+	volatile unsigned short *ap = (volatile unsigned short *) addr;
+	unsigned short *bp = (unsigned short *) buf;
+	while (len--)
+		*ap = *bp++;
+}
+
+static inline void io_outsl_noswap(unsigned int addr, const void *buf, int len)
+{
+	volatile unsigned long *ap = (volatile unsigned long *) addr;
+	unsigned long *bp = (unsigned long *) buf;
+	while (len--)
+		*ap = *bp++;
+}
+
 static inline void io_insb(unsigned int addr, void *buf, int len)
 {
 	volatile unsigned char  *ap_b;
@@ -142,12 +169,28 @@
 
 static inline void io_insl(unsigned int addr, void *buf, int len)
 {
-	volatile unsigned int *ap = (volatile unsigned int *) addr;
+	volatile unsigned long *ap = (volatile unsigned long *) addr;
 	unsigned long *bp = (unsigned long *) buf;
 	while (len--)
 		*bp++ = _swapl(*ap);
 }
 
+static inline void io_insw_noswap(unsigned int addr, void *buf, int len)
+{
+	volatile unsigned short *ap = (volatile unsigned short *) addr;
+	unsigned short *bp = (unsigned short *) buf;
+	while (len--)
+		*bp++ = *ap;
+}
+
+static inline void io_insl_noswap(unsigned int addr, void *buf, int len)
+{
+	volatile unsigned long *ap = (volatile unsigned long *) addr;
+	unsigned long *bp = (unsigned long *) buf;
+	while (len--)
+		*bp++ = *ap;
+}
+
 /*
  *	make the short names macros so specific devices
  *	can override them as required
@@ -160,7 +203,8 @@
 #define inb(addr)    ((h8300_buswidth(addr))?readw((addr) & ~1) & 0xff:readb(addr))
 #define inw(addr)    _swapw(readw(addr))
 #define inl(addr)    _swapl(readl(addr))
-#define outb(x,addr) ((void)((h8300_buswidth(addr) && ((addr) & 1))?writew(x,(addr) & ~1):writeb(x,addr)))
+#define outb(x,addr) ((void)((h8300_buswidth(addr) && \
+                      ((addr) & 1))?writew(x,(addr) & ~1):writeb(x,addr)))
 #define outw(x,addr) ((void) writew(_swapw(x),addr))
 #define outl(x,addr) ((void) writel(_swapl(x),addr))
 
@@ -227,7 +271,7 @@
 	return *(volatile unsigned short*)addr;
 }
 
-static __inline__ unsigned int ctrl_inl(unsigned long addr)
+static __inline__ unsigned long ctrl_inl(unsigned long addr)
 {
 	return *(volatile unsigned long*)addr;
 }
@@ -242,7 +286,7 @@
 	*(volatile unsigned short*)addr = b;
 }
 
-static __inline__ void ctrl_outl(unsigned int b, unsigned long addr)
+static __inline__ void ctrl_outl(unsigned long b, unsigned long addr)
 {
         *(volatile unsigned long*)addr = b;
 }
diff -Nru a/include/asm-h8300/resource.h b/include/asm-h8300/resource.h
--- a/include/asm-h8300/resource.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-h8300/resource.h	2004-06-23 19:04:25 -07:00
@@ -16,8 +16,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -39,7 +41,9 @@
 	{      INR_OPEN,     INR_OPEN  },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
-        { RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-i386/apic.h b/include/asm-i386/apic.h
--- a/include/asm-i386/apic.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-i386/apic.h	2004-06-23 19:04:29 -07:00
@@ -41,6 +41,8 @@
 	do { } while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY );
 }
 
+int get_physical_broadcast(void);
+
 #ifdef CONFIG_X86_GOOD_APIC
 # define FORCE_READ_AROUND_WRITE 0
 # define apic_read_around(x)
diff -Nru a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
--- a/include/asm-i386/bitops.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/bitops.h	2004-06-23 19:04:27 -07:00
@@ -34,7 +34,7 @@
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
-static __inline__ void set_bit(int nr, volatile unsigned long * addr)
+static inline void set_bit(int nr, volatile unsigned long * addr)
 {
 	__asm__ __volatile__( LOCK_PREFIX
 		"btsl %1,%0"
@@ -51,7 +51,7 @@
  * If it's called on the same region of memory simultaneously, the effect
  * may be that only one operation succeeds.
  */
-static __inline__ void __set_bit(int nr, volatile unsigned long * addr)
+static inline void __set_bit(int nr, volatile unsigned long * addr)
 {
 	__asm__(
 		"btsl %1,%0"
@@ -69,7 +69,7 @@
  * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
  * in order to ensure changes are visible on other processors.
  */
-static __inline__ void clear_bit(int nr, volatile unsigned long * addr)
+static inline void clear_bit(int nr, volatile unsigned long * addr)
 {
 	__asm__ __volatile__( LOCK_PREFIX
 		"btrl %1,%0"
@@ -77,7 +77,7 @@
 		:"Ir" (nr));
 }
 
-static __inline__ void __clear_bit(int nr, volatile unsigned long * addr)
+static inline void __clear_bit(int nr, volatile unsigned long * addr)
 {
 	__asm__ __volatile__(
 		"btrl %1,%0"
@@ -96,7 +96,7 @@
  * If it's called on the same region of memory simultaneously, the effect
  * may be that only one operation succeeds.
  */
-static __inline__ void __change_bit(int nr, volatile unsigned long * addr)
+static inline void __change_bit(int nr, volatile unsigned long * addr)
 {
 	__asm__ __volatile__(
 		"btcl %1,%0"
@@ -113,7 +113,7 @@
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
-static __inline__ void change_bit(int nr, volatile unsigned long * addr)
+static inline void change_bit(int nr, volatile unsigned long * addr)
 {
 	__asm__ __volatile__( LOCK_PREFIX
 		"btcl %1,%0"
@@ -129,7 +129,7 @@
  * This operation is atomic and cannot be reordered.  
  * It also implies a memory barrier.
  */
-static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
+static inline int test_and_set_bit(int nr, volatile unsigned long * addr)
 {
 	int oldbit;
 
@@ -149,7 +149,7 @@
  * If two examples of this operation race, one can appear to succeed
  * but actually fail.  You must protect multiple accesses with a lock.
  */
-static __inline__ int __test_and_set_bit(int nr, volatile unsigned long * addr)
+static inline int __test_and_set_bit(int nr, volatile unsigned long * addr)
 {
 	int oldbit;
 
@@ -168,7 +168,7 @@
  * This operation is atomic and cannot be reordered.  
  * It also implies a memory barrier.
  */
-static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
+static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
 {
 	int oldbit;
 
@@ -188,7 +188,7 @@
  * If two examples of this operation race, one can appear to succeed
  * but actually fail.  You must protect multiple accesses with a lock.
  */
-static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
@@ -200,7 +200,7 @@
 }
 
 /* WARNING: non atomic and it can be reordered! */
-static __inline__ int __test_and_change_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
 {
 	int oldbit;
 
@@ -219,7 +219,7 @@
  * This operation is atomic and cannot be reordered.  
  * It also implies a memory barrier.
  */
-static __inline__ int test_and_change_bit(int nr, volatile unsigned long* addr)
+static inline int test_and_change_bit(int nr, volatile unsigned long* addr)
 {
 	int oldbit;
 
@@ -244,7 +244,7 @@
 	return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
 }
 
-static __inline__ int variable_test_bit(int nr, const volatile unsigned long * addr)
+static inline int variable_test_bit(int nr, const volatile unsigned long * addr)
 {
 	int oldbit;
 
@@ -270,7 +270,7 @@
  * Returns the bit-number of the first zero bit, not the number of the byte
  * containing a bit.
  */
-static __inline__ int find_first_zero_bit(const unsigned long *addr, unsigned size)
+static inline int find_first_zero_bit(const unsigned long *addr, unsigned size)
 {
 	int d0, d1, d2;
 	int res;
@@ -295,6 +295,14 @@
 }
 
 /**
+ * find_next_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+int find_next_zero_bit(const unsigned long *addr, int size, int offset);
+
+/**
  * find_first_bit - find the first set bit in a memory region
  * @addr: The address to start the search at
  * @size: The maximum size to search
@@ -302,7 +310,7 @@
  * Returns the bit-number of the first set bit, not the number of the byte
  * containing a bit.
  */
-static __inline__ int find_first_bit(const unsigned long *addr, unsigned size)
+static inline int find_first_bit(const unsigned long *addr, unsigned size)
 {
 	int d0, d1;
 	int res;
@@ -323,70 +331,12 @@
 }
 
 /**
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static __inline__ int find_next_zero_bit(const unsigned long *addr, int size, int offset)
-{
-	unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
-	int set = 0, bit = offset & 31, res;
-	
-	if (bit) {
-		/*
-		 * Look for zero in the first 32 bits.
-		 */
-		__asm__("bsfl %1,%0\n\t"
-			"jne 1f\n\t"
-			"movl $32, %0\n"
-			"1:"
-			: "=r" (set)
-			: "r" (~(*p >> bit)));
-		if (set < (32 - bit))
-			return set + offset;
-		set = 32 - bit;
-		p++;
-	}
-	/*
-	 * No zero yet, search remaining full bytes for a zero
-	 */
-	res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
-	return (offset + set + res);
-}
-
-/**
  * find_next_bit - find the first set bit in a memory region
  * @addr: The address to base the search on
  * @offset: The bitnumber to start searching at
  * @size: The maximum size to search
  */
-static __inline__ int find_next_bit(const unsigned long *addr, int size, int offset)
-{
-	const unsigned long *p = addr + (offset >> 5);
-	int set = 0, bit = offset & 31, res;
-
-	if (bit) {
-		/*
-		 * Look for nonzero in the first 32 bits:
-		 */
-		__asm__("bsfl %1,%0\n\t"
-			"jne 1f\n\t"
-			"movl $32, %0\n"
-			"1:"
-			: "=r" (set)
-			: "r" (*p >> bit));
-		if (set < (32 - bit))
-			return set + offset;
-		set = 32 - bit;
-		p++;
-	}
-	/*
-	 * No set bit yet, search remaining full words for a bit
-	 */
-	res = find_first_bit (p, size - 32 * (p - addr));
-	return (offset + set + res);
-}
+int find_next_bit(const unsigned long *addr, int size, int offset);
 
 /**
  * ffz - find first zero in word.
@@ -394,7 +344,7 @@
  *
  * Undefined if no zero exists, so code should check against ~0UL first.
  */
-static __inline__ unsigned long ffz(unsigned long word)
+static inline unsigned long ffz(unsigned long word)
 {
 	__asm__("bsfl %1,%0"
 		:"=r" (word)
@@ -408,7 +358,7 @@
  *
  * Undefined if no bit exists, so code should check against 0 first.
  */
-static __inline__ unsigned long __ffs(unsigned long word)
+static inline unsigned long __ffs(unsigned long word)
 {
 	__asm__("bsfl %1,%0"
 		:"=r" (word)
@@ -451,7 +401,7 @@
  * the libc and compiler builtin ffs routines, therefore
  * differs in spirit from the above ffz (man ffs).
  */
-static __inline__ int ffs(int x)
+static inline int ffs(int x)
 {
 	int r;
 
diff -Nru a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
--- a/include/asm-i386/checksum.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-i386/checksum.h	2004-06-23 19:04:28 -07:00
@@ -172,8 +172,10 @@
  *	Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user(const char *src, char *dst,
-				    int len, int sum, int *err_ptr)
+static __inline__ unsigned int csum_and_copy_to_user(const char *src, 
+						     char __user *dst,
+						     int len, int sum, 
+						     int *err_ptr)
 {
 	if (access_ok(VERIFY_WRITE, dst, len))
 		return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
diff -Nru a/include/asm-i386/delay.h b/include/asm-i386/delay.h
--- a/include/asm-i386/delay.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-i386/delay.h	2004-06-23 19:04:25 -07:00
@@ -16,7 +16,7 @@
 extern void __delay(unsigned long loops);
 
 #define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
+	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
 	__udelay(n))
 	
 #define ndelay(n) (__builtin_constant_p(n) ? \
diff -Nru a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h
--- a/include/asm-i386/dma-mapping.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-i386/dma-mapping.h	2004-06-23 19:04:29 -07:00
@@ -1,6 +1,9 @@
 #ifndef _ASM_I386_DMA_MAPPING_H
 #define _ASM_I386_DMA_MAPPING_H
 
+#include <linux/device.h>
+#include <linux/mm.h>
+
 #include <asm/cache.h>
 #include <asm/io.h>
 #include <asm/scatterlist.h>
diff -Nru a/include/asm-i386/fcntl.h b/include/asm-i386/fcntl.h
--- a/include/asm-i386/fcntl.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/fcntl.h	2004-06-23 19:04:27 -07:00
@@ -20,6 +20,7 @@
 #define O_LARGEFILE	0100000
 #define O_DIRECTORY	0200000	/* must be a directory */
 #define O_NOFOLLOW	0400000 /* don't follow links */
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-i386/genapic.h b/include/asm-i386/genapic.h
--- a/include/asm-i386/genapic.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/genapic.h	2004-06-23 19:04:27 -07:00
@@ -25,7 +25,6 @@
 	cpumask_t (*target_cpus)(void);
 	int int_delivery_mode;
 	int int_dest_mode; 
-	int apic_broadcast_id; 
 	int ESR_DISABLE;
 	int apic_destination_logical;
 	unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid);
@@ -78,7 +77,6 @@
 	.probe = aprobe, \
 	.int_delivery_mode = INT_DELIVERY_MODE, \
 	.int_dest_mode = INT_DEST_MODE, \
-	.apic_broadcast_id = APIC_BROADCAST_ID, \
 	.no_balance_irq = NO_BALANCE_IRQ, \
 	.no_ioapic_check = NO_IOAPIC_CHECK, \
 	.ESR_DISABLE = esr_disable, \
diff -Nru a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
--- a/include/asm-i386/hpet.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/hpet.h	2004-06-23 19:04:27 -07:00
@@ -57,9 +57,12 @@
 #define HPET_ID_LEGSUP	0x00008000
 #define HPET_ID_NUMBER	0x00001f00
 #define HPET_ID_REV	0x000000ff
+#define	HPET_ID_NUMBER_SHIFT	8
 
 #define HPET_CFG_ENABLE	0x001
 #define HPET_CFG_LEGACY	0x002
+#define	HPET_LEGACY_8254	2
+#define	HPET_LEGACY_RTC		8
 
 #define HPET_TN_ENABLE		0x004
 #define HPET_TN_PERIODIC	0x008
diff -Nru a/include/asm-i386/ide.h b/include/asm-i386/ide.h
--- a/include/asm-i386/ide.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-i386/ide.h	2004-06-23 19:04:25 -07:00
@@ -28,9 +28,6 @@
 static __inline__ int ide_default_irq(unsigned long base)
 {
 	switch (base) {
-#ifdef CONFIG_X86_PC9800
-		case 0x640: return 9;
-#endif
 		case 0x1f0: return 14;
 		case 0x170: return 15;
 		case 0x1e8: return 11;
@@ -45,47 +42,16 @@
 static __inline__ unsigned long ide_default_io_base(int index)
 {
 	switch (index) {
-#ifdef CONFIG_X86_PC9800
-		case 0:
-		case 1:	return 0x640;
-#else
 		case 0:	return 0x1f0;
 		case 1:	return 0x170;
 		case 2: return 0x1e8;
 		case 3: return 0x168;
 		case 4: return 0x1e0;
 		case 5: return 0x160;
-#endif
 		default:
 			return 0;
 	}
 }
-
-#ifdef CONFIG_X86_PC9800
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
-	 unsigned long ctrl_port, int *irq)
-{
-	unsigned long reg = data_port;
-	int i;
-
-	unsigned long increment = data_port == 0x640 ? 2 : 1;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += increment;
-	}
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else if (data_port == 0x640) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = 0x74c;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-	}
-	if (irq != NULL)
-		*irq = 0;
-	hw->io_ports[IDE_IRQ_OFFSET] = 0;
-}
-#endif
 
 #define IDE_ARCH_OBSOLETE_INIT
 #define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
diff -Nru a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h
--- a/include/asm-i386/io_apic.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/io_apic.h	2004-06-23 19:04:27 -07:00
@@ -188,15 +188,6 @@
 	*(IO_APIC_BASE(apic)+4) = value;
 }
 
-/*
- * Synchronize the IO-APIC and the CPU by doing
- * a dummy read from the IO-APIC
- */
-static inline void io_apic_sync(unsigned int apic)
-{
-	(void) *(IO_APIC_BASE(apic)+4);
-}
-
 /* 1 if "noapic" boot option passed */
 extern int skip_ioapic_setup;
 
diff -Nru a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h
--- a/include/asm-i386/mach-bigsmp/mach_apic.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-i386/mach-bigsmp/mach_apic.h	2004-06-23 19:04:28 -07:00
@@ -39,7 +39,6 @@
 #define INT_DELIVERY_MODE dest_Fixed
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
-#define APIC_BROADCAST_ID     (0xff)
 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
 {
 	return 0;
diff -Nru a/include/asm-i386/mach-bigsmp/mach_mpspec.h b/include/asm-i386/mach-bigsmp/mach_mpspec.h
--- a/include/asm-i386/mach-bigsmp/mach_mpspec.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-i386/mach-bigsmp/mach_mpspec.h	2004-06-23 19:04:28 -07:00
@@ -1,11 +1,6 @@
 #ifndef __ASM_MACH_MPSPEC_H
 #define __ASM_MACH_MPSPEC_H
 
-/*
- * a maximum of 16 APICs with the current APIC ID architecture.
- */
-#define MAX_APICS 16
-
 #define MAX_IRQ_SOURCES 256
 
 #define MAX_MP_BUSSES 32
diff -Nru a/include/asm-i386/mach-default/mach_apic.h b/include/asm-i386/mach-default/mach_apic.h
--- a/include/asm-i386/mach-default/mach_apic.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-i386/mach-default/mach_apic.h	2004-06-23 19:04:29 -07:00
@@ -2,6 +2,7 @@
 #define __ASM_MACH_APIC_H
 
 #include <mach_apicdef.h>
+#include <asm/smp.h>
 
 #define APIC_DFR_VALUE	(APIC_DFR_FLAT)
 
@@ -23,12 +24,6 @@
 #define INT_DELIVERY_MODE dest_LowestPrio
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
-/*
- * this isn't really broadcast, just a (potentially inaccurate) upper
- * bound for valid physical APIC id's
- */
-#define APIC_BROADCAST_ID      0x0F
-
 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
 {
 	return physid_isset(apicid, bitmap);
@@ -85,7 +80,10 @@
 
 static inline int cpu_present_to_apicid(int mps_cpu)
 {
-	return  mps_cpu;
+	if (mps_cpu < get_physical_broadcast())
+		return  mps_cpu;
+	else
+		return BAD_APICID;
 }
 
 static inline physid_mask_t apicid_to_cpu_present(int phys_apicid)
diff -Nru a/include/asm-i386/mach-default/mach_mpspec.h b/include/asm-i386/mach-default/mach_mpspec.h
--- a/include/asm-i386/mach-default/mach_mpspec.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-i386/mach-default/mach_mpspec.h	2004-06-23 19:04:28 -07:00
@@ -1,11 +1,6 @@
 #ifndef __ASM_MACH_MPSPEC_H
 #define __ASM_MACH_MPSPEC_H
 
-/*
- * a maximum of 16 APICs with the current APIC ID architecture.
- */
-#define MAX_APICS 16
-
 #define MAX_IRQ_SOURCES 256
 
 #define MAX_MP_BUSSES 32
diff -Nru a/include/asm-i386/mach-default/setup_arch_post.h b/include/asm-i386/mach-default/setup_arch_post.h
--- a/include/asm-i386/mach-default/setup_arch_post.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-i386/mach-default/setup_arch_post.h	2004-06-23 19:04:28 -07:00
@@ -6,7 +6,7 @@
  *	use of all of the static functions.
  **/
 
-static inline char * __init machine_specific_memory_setup(void)
+static char * __init machine_specific_memory_setup(void)
 {
 	char *who;
 
diff -Nru a/include/asm-i386/mach-es7000/mach_apic.h b/include/asm-i386/mach-es7000/mach_apic.h
--- a/include/asm-i386/mach-es7000/mach_apic.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-i386/mach-es7000/mach_apic.h	2004-06-23 19:04:25 -07:00
@@ -38,7 +38,6 @@
 #define WAKE_SECONDARY_VIA_INIT
 #endif
 
-#define APIC_BROADCAST_ID	(0xff)
 #define NO_IOAPIC_CHECK (1)
 
 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
diff -Nru a/include/asm-i386/mach-es7000/mach_mpspec.h b/include/asm-i386/mach-es7000/mach_mpspec.h
--- a/include/asm-i386/mach-es7000/mach_mpspec.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-i386/mach-es7000/mach_mpspec.h	2004-06-23 19:04:26 -07:00
@@ -1,11 +1,6 @@
 #ifndef __ASM_MACH_MPSPEC_H
 #define __ASM_MACH_MPSPEC_H
 
-/*
- * a maximum of 256 APICs with the current APIC ID architecture.
- */
-#define MAX_APICS 256
-
 #define MAX_IRQ_SOURCES 256
 
 #define MAX_MP_BUSSES 32
diff -Nru a/include/asm-i386/mach-generic/mach_apic.h b/include/asm-i386/mach-generic/mach_apic.h
--- a/include/asm-i386/mach-generic/mach_apic.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-i386/mach-generic/mach_apic.h	2004-06-23 19:04:26 -07:00
@@ -6,7 +6,6 @@
 #define esr_disable (genapic->ESR_DISABLE)
 #define NO_BALANCE_IRQ (genapic->no_balance_irq)
 #define NO_IOAPIC_CHECK	(genapic->no_ioapic_check)
-#define APIC_BROADCAST_ID (genapic->apic_broadcast_id)
 #define INT_DELIVERY_MODE (genapic->int_delivery_mode)
 #define INT_DEST_MODE (genapic->int_dest_mode)
 #undef APIC_DEST_LOGICAL
diff -Nru a/include/asm-i386/mach-generic/mach_mpspec.h b/include/asm-i386/mach-generic/mach_mpspec.h
--- a/include/asm-i386/mach-generic/mach_mpspec.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/mach-generic/mach_mpspec.h	2004-06-23 19:04:27 -07:00
@@ -1,11 +1,6 @@
 #ifndef __ASM_MACH_MPSPEC_H
 #define __ASM_MACH_MPSPEC_H
 
-/*
- * a maximum of 256 APICs with the current APIC ID architecture.
- */
-#define MAX_APICS 256
-
 #define MAX_IRQ_SOURCES 256
 
 /* Summit or generic (i.e. installer) kernels need lots of bus entries. */
diff -Nru a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h
--- a/include/asm-i386/mach-numaq/mach_apic.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-i386/mach-numaq/mach_apic.h	2004-06-23 19:04:26 -07:00
@@ -22,7 +22,6 @@
 #define INT_DELIVERY_MODE dest_LowestPrio
 #define INT_DEST_MODE 0     /* physical delivery on LOCAL quad */
  
-#define APIC_BROADCAST_ID      0x0F
 #define check_apicid_used(bitmap, apicid) physid_isset(apicid, bitmap)
 #define check_apicid_present(bit) physid_isset(bit, phys_cpu_present_map)
 #define apicid_cluster(apicid) (apicid & 0xF0)
diff -Nru a/include/asm-i386/mach-numaq/mach_mpspec.h b/include/asm-i386/mach-numaq/mach_mpspec.h
--- a/include/asm-i386/mach-numaq/mach_mpspec.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/mach-numaq/mach_mpspec.h	2004-06-23 19:04:27 -07:00
@@ -1,11 +1,6 @@
 #ifndef __ASM_MACH_MPSPEC_H
 #define __ASM_MACH_MPSPEC_H
 
-/*
- * a maximum of 256 APICs with the current APIC ID architecture.
- */
-#define MAX_APICS 256
-
 #define MAX_IRQ_SOURCES 512
 
 #define MAX_MP_BUSSES 32
diff -Nru a/include/asm-i386/mach-pc9800/apm.h b/include/asm-i386/mach-pc9800/apm.h
--- a/include/asm-i386/mach-pc9800/apm.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,82 +0,0 @@
-/*
- *  include/asm-i386/mach-pc9800/apm.h
- *
- *  Machine specific APM BIOS functions for NEC PC9800.
- *  Split out from apm.c by Osamu Tomita <tomita@cinet.co.jp>
- */
-
-#ifndef _ASM_APM_H
-#define _ASM_APM_H
-
-#include <linux/apm_bios.h>
-
-#ifdef APM_ZERO_SEGS
-#	define APM_DO_ZERO_SEGS \
-		"pushl %%ds\n\t" \
-		"pushl %%es\n\t" \
-		"xorl %%edx, %%edx\n\t" \
-		"mov %%dx, %%ds\n\t" \
-		"mov %%dx, %%es\n\t" \
-		"mov %%dx, %%fs\n\t" \
-		"mov %%dx, %%gs\n\t"
-#	define APM_DO_POP_SEGS \
-		"popl %%es\n\t" \
-		"popl %%ds\n\t"
-#else
-#	define APM_DO_ZERO_SEGS
-#	define APM_DO_POP_SEGS
-#endif
-
-static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
-					u32 *eax, u32 *ebx, u32 *ecx,
-					u32 *edx, u32 *esi)
-{
-	/*
-	 * N.B. We do NOT need a cld after the BIOS call
-	 * because we always save and restore the flags.
-	 */
-	__asm__ __volatile__(APM_DO_ZERO_SEGS
-		"pushl %%edi\n\t"
-		"pushl %%ebp\n\t"
-		"pushfl\n\t"
-		"lcall *%%cs:apm_bios_entry\n\t"
-		"setc %%al\n\t"
-		"popl %%ebp\n\t"
-		"popl %%edi\n\t"
-		APM_DO_POP_SEGS
-		: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx),
-		  "=S" (*esi)
-		: "a" (func), "b" (ebx_in), "c" (ecx_in)
-		: "memory", "cc");
-}
-
-static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in,
-						u32 ecx_in, u32 *eax)
-{
-	int	cx, dx, si;
-	u8	error;
-
-	/*
-	 * N.B. We do NOT need a cld after the BIOS call
-	 * because we always save and restore the flags.
-	 */
-	__asm__ __volatile__(APM_DO_ZERO_SEGS
-		"pushl %%edi\n\t"
-		"pushl %%ebp\n\t"
-		"pushfl\n\t"
-		"lcall *%%cs:apm_bios_entry\n\t"
-		"setc %%bl\n\t"
-		"popl %%ebp\n\t"
-		"popl %%edi\n\t"
-		APM_DO_POP_SEGS
-		: "=a" (*eax), "=b" (error), "=c" (cx), "=d" (dx),
-		  "=S" (si)
-		: "a" (func), "b" (ebx_in), "c" (ecx_in)
-		: "memory", "cc");
-	if (func == APM_FUNC_VERSION)
-		*eax = (*eax & 0xff00) | ((*eax & 0x00f0) >> 4);
-
-	return error;
-}
-
-#endif /* _ASM_APM_H */
diff -Nru a/include/asm-i386/mach-pc9800/bios_ebda.h b/include/asm-i386/mach-pc9800/bios_ebda.h
--- a/include/asm-i386/mach-pc9800/bios_ebda.h	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,14 +0,0 @@
-#ifndef _MACH_BIOS_EBDA_H
-#define _MACH_BIOS_EBDA_H
-
-/*
- * PC-9800 has no EBDA.
- * Its BIOS uses 0x40E for other purpose,
- * Not pointer to 4K EBDA area.
- */
-static inline unsigned int get_bios_ebda(void)
-{
-	return 0;	/* 0 means none */
-}
-
-#endif /* _MACH_BIOS_EBDA_H */
diff -Nru a/include/asm-i386/mach-pc9800/do_timer.h b/include/asm-i386/mach-pc9800/do_timer.h
--- a/include/asm-i386/mach-pc9800/do_timer.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,82 +0,0 @@
-/* defines for inline arch setup functions */
-
-#include <asm/apic.h>
-
-/**
- * do_timer_interrupt_hook - hook into timer tick
- * @regs:	standard registers from interrupt
- *
- * Description:
- *	This hook is called immediately after the timer interrupt is ack'd.
- *	It's primary purpose is to allow architectures that don't possess
- *	individual per CPU clocks (like the CPU APICs supply) to broadcast the
- *	timer interrupt as a means of triggering reschedules etc.
- **/
-
-static inline void do_timer_interrupt_hook(struct pt_regs *regs)
-{
-	do_timer(regs);
-/*
- * In the SMP case we use the local APIC timer interrupt to do the
- * profiling, except when we simulate SMP mode on a uniprocessor
- * system, in that case we have to call the local interrupt handler.
- */
-#ifndef CONFIG_X86_LOCAL_APIC
-	x86_do_profile(regs);
-#else
-	if (!using_apic_timer)
-		smp_local_timer_interrupt(regs);
-#endif
-}
-
-
-/* you can safely undefine this if you don't have the Neptune chipset */
-
-#define BUGGY_NEPTUN_TIMER
-
-/**
- * do_timer_overflow - process a detected timer overflow condition
- * @count:	hardware timer interrupt count on overflow
- *
- * Description:
- *	This call is invoked when the jiffies count has not incremented but
- *	the hardware timer interrupt has.  It means that a timer tick interrupt
- *	came along while the previous one was pending, thus a tick was missed
- **/
-static inline int do_timer_overflow(int count)
-{
-	int i;
-
-	spin_lock(&i8259A_lock);
-	/*
-	 * This is tricky when I/O APICs are used;
-	 * see do_timer_interrupt().
-	 */
-	i = inb(0x00);
-	spin_unlock(&i8259A_lock);
-	
-	/* assumption about timer being IRQ0 */
-	if (i & 0x01) {
-		/*
-		 * We cannot detect lost timer interrupts ... 
-		 * well, that's why we call them lost, don't we? :)
-		 * [hmm, on the Pentium and Alpha we can ... sort of]
-		 */
-		count -= LATCH;
-	} else {
-#ifdef BUGGY_NEPTUN_TIMER
-		/*
-		 * for the Neptun bug we know that the 'latch'
-		 * command doesn't latch the high and low value
-		 * of the counter atomically. Thus we have to 
-		 * substract 256 from the counter 
-		 * ... funny, isnt it? :)
-		 */
-		
-		count -= 256;
-#else
-		printk("do_slow_gettimeoffset(): hardware timer problem?\n");
-#endif
-	}
-	return count;
-}
diff -Nru a/include/asm-i386/mach-pc9800/io_ports.h b/include/asm-i386/mach-pc9800/io_ports.h
--- a/include/asm-i386/mach-pc9800/io_ports.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,30 +0,0 @@
-/*
- *  arch/i386/mach-pc9800/io_ports.h
- *
- *  Machine specific IO port address definition for PC-9800.
- *  Written by Osamu Tomita <tomita@cinet.co.jp>
- */
-#ifndef _MACH_IO_PORTS_H
-#define _MACH_IO_PORTS_H
-
-/* i8253A PIT registers */
-#define PIT_MODE		0x77
-#define PIT_CH0			0x71
-#define PIT_CH2			0x75
-
-/* i8259A PIC registers */
-#define PIC_MASTER_CMD		0x00
-#define PIC_MASTER_IMR		0x02
-#define PIC_MASTER_ISR		PIC_MASTER_CMD
-#define PIC_MASTER_POLL		PIC_MASTER_ISR
-#define PIC_MASTER_OCW3		PIC_MASTER_ISR
-#define PIC_SLAVE_CMD		0x08
-#define PIC_SLAVE_IMR		0x0a
-
-/* i8259A PIC related values */
-#define PIC_CASCADE_IR		7
-#define MASTER_ICW4_DEFAULT	0x1d
-#define SLAVE_ICW4_DEFAULT	0x09
-#define PIC_ICW4_AEOI		0x02
-
-#endif /* !_MACH_IO_PORTS_H */
diff -Nru a/include/asm-i386/mach-pc9800/irq_vectors.h b/include/asm-i386/mach-pc9800/irq_vectors.h
--- a/include/asm-i386/mach-pc9800/irq_vectors.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,99 +0,0 @@
-/*
- * This file should contain #defines for all of the interrupt vector
- * numbers used by this architecture.
- *
- * In addition, there are some standard defines:
- *
- *	FIRST_EXTERNAL_VECTOR:
- *		The first free place for external interrupts
- *
- *	SYSCALL_VECTOR:
- *		The IRQ vector a syscall makes the user to kernel transition
- *		under.
- *
- *	TIMER_IRQ:
- *		The IRQ number the timer interrupt comes in at.
- *
- *	NR_IRQS:
- *		The total number of interrupt vectors (including all the
- *		architecture specific interrupts) needed.
- *
- *	NR_IRQ_VECTORS:
- *		The total number of IO APIC vector inputs
- *
- */			
-#ifndef _ASM_IRQ_VECTORS_H
-#define _ASM_IRQ_VECTORS_H
-
-/*
- * IDT vectors usable for external interrupt sources start
- * at 0x20:
- */
-#define FIRST_EXTERNAL_VECTOR	0x20
-
-#define SYSCALL_VECTOR		0x80
-
-/*
- * Vectors 0x20-0x2f are used for ISA interrupts.
- */
-
-/*
- * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
- *
- *  some of the following vectors are 'rare', they are merged
- *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
- *  TLB, reschedule and local APIC vectors are performance-critical.
- *
- *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
- */
-#define SPURIOUS_APIC_VECTOR	0xff
-#define ERROR_APIC_VECTOR	0xfe
-#define INVALIDATE_TLB_VECTOR	0xfd
-#define RESCHEDULE_VECTOR	0xfc
-#define CALL_FUNCTION_VECTOR	0xfb
-
-#define THERMAL_APIC_VECTOR	0xf0
-/*
- * Local APIC timer IRQ vector is on a different priority level,
- * to work around the 'lost local interrupt if more than 2 IRQ
- * sources per level' errata.
- */
-#define LOCAL_TIMER_VECTOR	0xef
-
-/*
- * First APIC vector available to drivers: (vectors 0x30-0xee)
- * we start at 0x31 to spread out vectors evenly between priority
- * levels. (0x80 is the syscall vector)
- */
-#define FIRST_DEVICE_VECTOR	0x31
-#define FIRST_SYSTEM_VECTOR	0xef
-
-#define TIMER_IRQ 0
-
-/*
- * 16 8259A IRQ's, 208 potential APIC interrupt sources.
- * Right now the APIC is mostly only used for SMP.
- * 256 vectors is an architectural limit. (we can have
- * more than 256 devices theoretically, but they will
- * have to use shared interrupts)
- * Since vectors 0x00-0x1f are used/reserved for the CPU,
- * the usable vector space is 0x20-0xff (224 vectors)
- */
-#ifdef CONFIG_X86_IO_APIC
-#define NR_IRQS 224
-#else
-#define NR_IRQS 16
-#endif
-
-#define NR_VECTORS 256
-#define NR_IRQ_VECTORS NR_IRQS
-
-#define FPU_IRQ			8
-
-#define	FIRST_VM86_IRQ		2
-#define LAST_VM86_IRQ		15
-#define invalid_vm86_irq(irq)	((irq) < 2 || (irq) == 7 || (irq) > 15)
-
-#endif /* _ASM_IRQ_VECTORS_H */
-
-
diff -Nru a/include/asm-i386/mach-pc9800/mach_reboot.h b/include/asm-i386/mach-pc9800/mach_reboot.h
--- a/include/asm-i386/mach-pc9800/mach_reboot.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,21 +0,0 @@
-/*
- *  arch/i386/mach-pc9800/mach_reboot.h
- *
- *  Machine specific reboot functions for PC-9800.
- *  Written by Osamu Tomita <tomita@cinet.co.jp>
- */
-#ifndef _MACH_REBOOT_H
-#define _MACH_REBOOT_H
-
-#ifdef CMOS_WRITE
-#undef CMOS_WRITE
-#define CMOS_WRITE(a,b)	do{}while(0)
-#endif
-
-static inline void mach_reboot(void)
-{
-	outb(0, 0xf0);		/* signal CPU reset */
-	mdelay(1);
-}
-
-#endif /* !_MACH_REBOOT_H */
diff -Nru a/include/asm-i386/mach-pc9800/mach_time.h b/include/asm-i386/mach-pc9800/mach_time.h
--- a/include/asm-i386/mach-pc9800/mach_time.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,100 +0,0 @@
-/*
- *  include/asm-i386/mach-pc9800/mach_time.h
- *
- *  Machine specific set RTC function for PC-9800.
- *  Written by Osamu Tomita <tomita@cinet.co.jp>
- */
-#ifndef _MACH_TIME_H
-#define _MACH_TIME_H
-
-#include <linux/bcd.h>
-#include <linux/upd4990a.h>
-
-/* for check timing call set_rtc_mmss() */
-/* used in arch/i386/time.c::do_timer_interrupt() */
-/*
- * Because PC-9800's RTC (NEC uPD4990A) does not allow setting
- * time partially, we always have to read-modify-write the
- * entire time (including year) so that set_rtc_mmss() will
- * take quite much time to execute.  You may want to relax
- * RTC resetting interval (currently ~11 minuts)...
- */
-#define USEC_AFTER	1000000
-#define USEC_BEFORE	0
-
-static inline int mach_set_rtc_mmss(unsigned long nowtime)
-{
-	int retval = 0;
-	int real_seconds, real_minutes, cmos_minutes;
-	struct upd4990a_raw_data data;
-
-	upd4990a_get_time(&data, 1);
-	cmos_minutes = BCD2BIN(data.min);
-
-	/*
-	 * since we're only adjusting minutes and seconds,
-	 * don't interfere with hour overflow. This avoids
-	 * messing with unknown time zones but requires your
-	 * RTC not to be off by more than 15 minutes
-	 */
-	real_seconds = nowtime % 60;
-	real_minutes = nowtime / 60;
-	if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
-		real_minutes += 30;	/* correct for half hour time zone */
-	real_minutes %= 60;
-
-	if (abs(real_minutes - cmos_minutes) < 30) {
-		u8 temp_seconds = (real_seconds / 10) * 16 + real_seconds % 10;
-		u8 temp_minutes = (real_minutes / 10) * 16 + real_minutes % 10;
-
-		if (data.sec != temp_seconds || data.min != temp_minutes) {
-			data.sec = temp_seconds;
-			data.min = temp_minutes;
-			upd4990a_set_time(&data, 1);
-		}
-	} else {
-		printk(KERN_WARNING
-		       "set_rtc_mmss: can't update from %d to %d\n",
-		       cmos_minutes, real_minutes);
-		retval = -1;
-	}
-
-	/* uPD4990A users' manual says we should issue Register Hold
-	 * command after reading time, or future Time Read command
-	 * may not work.  When we have set the time, this also starts
-	 * the clock.
-	 */
-	upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
-
-	return retval;
-}
-
-static inline unsigned long mach_get_cmos_time(void)
-{
-	int i;
-	u8 prev, cur;
-	unsigned int year;
-	struct upd4990a_raw_data data;
-
-	/* Connect uPD4990A's DATA OUT pin to its 1Hz reference clock. */
-	upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
-
-	/* Catch rising edge of reference clock.  */
-	prev = ~UPD4990A_READ_DATA();
-	for (i = 0; i < 1800000; i++) { /* may take up to 1 second... */
-		__asm__ ("outb %%al,%0" : : "N" (0x5f)); /* 0.6usec delay */
-		cur = UPD4990A_READ_DATA();
-		if (!(prev & cur & 1))
-			break;
-		prev = ~cur;
-	}
-
-	upd4990a_get_time(&data, 0);
-
-	if ((year = BCD2BIN(data.year) + 1900) < 1995)
-		year += 100;
-	return mktime(year, data.mon, BCD2BIN(data.mday), BCD2BIN(data.hour),
-			BCD2BIN(data.min), BCD2BIN(data.sec));
-}
-
-#endif /* !_MACH_TIME_H */
diff -Nru a/include/asm-i386/mach-pc9800/mach_timer.h b/include/asm-i386/mach-pc9800/mach_timer.h
--- a/include/asm-i386/mach-pc9800/mach_timer.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,31 +0,0 @@
-/*
- *  include/asm-i386/mach-pc9800/mach_timer.h
- *
- *  Machine specific calibrate_tsc() for PC-9800.
- *  Written by Osamu Tomita <tomita@cinet.co.jp>
- */
-/* ------ Calibrate the TSC ------- 
- * PC-9800:
- *  CTC cannot be used because some models (especially
- *  note-machines) may disable clock to speaker channel (#1)
- *  unless speaker is enabled.  We use ARTIC instead.
- */
-#ifndef _MACH_TIMER_H
-#define _MACH_TIMER_H
-
-#define CALIBRATE_LATCH	(5 * 307200/HZ) /* 0.050sec * 307200Hz = 15360 */
-
-static inline void mach_prepare_counter(void)
-{
-	/* ARTIC can't be stopped nor reset. So we wait roundup. */
-	while (inw(0x5c));
-}
-
-static inline void mach_countup(unsigned long *count)
-{
-	do {
-		*count = inw(0x5c);
-	} while (*count < CALIBRATE_LATCH);
-}
-
-#endif /* !_MACH_TIMER_H */
diff -Nru a/include/asm-i386/mach-pc9800/mach_traps.h b/include/asm-i386/mach-pc9800/mach_traps.h
--- a/include/asm-i386/mach-pc9800/mach_traps.h	2004-06-23 19:04:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,27 +0,0 @@
-/*
- *  include/asm-i386/mach-pc9800/mach_traps.h
- *
- *  Machine specific NMI handling for PC-9800.
- *  Written by Osamu Tomita <tomita@cinet.co.jp>
- */
-#ifndef _MACH_TRAPS_H
-#define _MACH_TRAPS_H
-
-static inline void clear_mem_error(unsigned char reason)
-{
-	outb(0x08, 0x37);
-	outb(0x09, 0x37);
-}
-
-static inline unsigned char get_nmi_reason(void)
-{
-	return (inb(0x33) & 6) ? 0x80 : 0;
-}
-
-static inline void reassert_nmi(void)
-{
-	outb(0x09, 0x50);	/* disable NMI once */
-	outb(0x09, 0x52);	/* re-enable it */
-}
-
-#endif /* !_MACH_TRAPS_H */
diff -Nru a/include/asm-i386/mach-pc9800/mach_wakecpu.h b/include/asm-i386/mach-pc9800/mach_wakecpu.h
--- a/include/asm-i386/mach-pc9800/mach_wakecpu.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,45 +0,0 @@
-#ifndef __ASM_MACH_WAKECPU_H
-#define __ASM_MACH_WAKECPU_H
-
-/* 
- * This file copes with machines that wakeup secondary CPUs by the
- * INIT, INIT, STARTUP sequence.
- */
-
-#define WAKE_SECONDARY_VIA_INIT
-
-/*
- * On PC-9800, continuation on warm reset is done by loading
- * %ss:%sp from 0x0000:0404 and executing 'lret', so:
- */
-#define TRAMPOLINE_LOW phys_to_virt(0x4fa)
-#define TRAMPOLINE_HIGH phys_to_virt(0x4fc)
-
-#define boot_cpu_apicid boot_cpu_physical_apicid
-
-static inline void wait_for_init_deassert(atomic_t *deassert)
-{
-	while (!atomic_read(deassert));
-	return;
-}
-
-/* Nothing to do for most platforms, since cleared by the INIT cycle */
-static inline void smp_callin_clear_local_apic(void)
-{
-}
-
-static inline void store_NMI_vector(unsigned short *high, unsigned short *low)
-{
-}
-
-static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
-{
-}
-
-#if APIC_DEBUG
- #define inquire_remote_apic(apicid) __inquire_remote_apic(apicid)
-#else
- #define inquire_remote_apic(apicid) {}
-#endif
-
-#endif /* __ASM_MACH_WAKECPU_H */
diff -Nru a/include/asm-i386/mach-pc9800/pci-functions.h b/include/asm-i386/mach-pc9800/pci-functions.h
--- a/include/asm-i386/mach-pc9800/pci-functions.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,20 +0,0 @@
-/*
- *	PCI BIOS function codes for the PC9800. Different to
- *	standard PC systems
- */
-
-/* Note: PC-9800 confirms PCI 2.1 on only few models */
-
-#define PCIBIOS_PCI_FUNCTION_ID 	0xccXX
-#define PCIBIOS_PCI_BIOS_PRESENT 	0xcc81
-#define PCIBIOS_FIND_PCI_DEVICE		0xcc82
-#define PCIBIOS_FIND_PCI_CLASS_CODE	0xcc83
-/*      PCIBIOS_GENERATE_SPECIAL_CYCLE	0xcc86	(not supported by bios) */
-#define PCIBIOS_READ_CONFIG_BYTE	0xcc88
-#define PCIBIOS_READ_CONFIG_WORD	0xcc89
-#define PCIBIOS_READ_CONFIG_DWORD	0xcc8a
-#define PCIBIOS_WRITE_CONFIG_BYTE	0xcc8b
-#define PCIBIOS_WRITE_CONFIG_WORD	0xcc8c
-#define PCIBIOS_WRITE_CONFIG_DWORD	0xcc8d
-#define PCIBIOS_GET_ROUTING_OPTIONS	0xcc8e	/* PCI 2.1 only */
-#define PCIBIOS_SET_PCI_HW_INT		0xcc8f	/* PCI 2.1 only */
diff -Nru a/include/asm-i386/mach-pc9800/setup_arch_post.h b/include/asm-i386/mach-pc9800/setup_arch_post.h
--- a/include/asm-i386/mach-pc9800/setup_arch_post.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,29 +0,0 @@
-/**
- * machine_specific_memory_setup - Hook for machine specific memory setup.
- *
- * Description:
- *	This is included late in kernel/setup.c so that it can make
- *	use of all of the static functions.
- **/
-
-static inline char * __init machine_specific_memory_setup(void)
-{
-	char *who;
-	unsigned long low_mem_size, lower_high, higher_high;
-
-
-	who = "BIOS (common area)";
-
-	low_mem_size = ((*(unsigned char *)__va(PC9800SCA_BIOS_FLAG) & 7) + 1) << 17;
-	add_memory_region(0, low_mem_size, 1);
-	lower_high = (__u32) *(__u8 *) bus_to_virt(PC9800SCA_EXPMMSZ) << 17;
-	higher_high = (__u32) *(__u16 *) bus_to_virt(PC9800SCA_MMSZ16M) << 20;
-	if (lower_high != 0x00f00000UL) {
-		add_memory_region(HIGH_MEMORY, lower_high, 1);
-		add_memory_region(0x01000000UL, higher_high, 1);
-	}
-	else
-		add_memory_region(HIGH_MEMORY, lower_high + higher_high, 1);
-
-	return who;
-}
diff -Nru a/include/asm-i386/mach-pc9800/setup_arch_pre.h b/include/asm-i386/mach-pc9800/setup_arch_pre.h
--- a/include/asm-i386/mach-pc9800/setup_arch_pre.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,36 +0,0 @@
-/* Hook to call BIOS initialisation function */
-
-/* no action for generic */
-
-#define ARCH_SETUP arch_setup_pc9800();
-
-#include <linux/timex.h>
-#include <asm/io.h>
-#include <asm/pc9800.h>
-#include <asm/pc9800_sca.h>
-
-int CLOCK_TICK_RATE;
-extern unsigned long tick_usec;	/* ACTHZ          period (usec) */
-extern unsigned long tick_nsec;	/* USER_HZ period (nsec) */
-unsigned char pc9800_misc_flags;
-/* (bit 0) 1:High Address Video ram exists 0:otherwise */
-
-#ifdef CONFIG_SMP
-#define MPC_TABLE_SIZE 512
-#define MPC_TABLE ((char *) (PARAM+0x400))
-char mpc_table[MPC_TABLE_SIZE];
-#endif
-
-static  inline void arch_setup_pc9800(void)
-{
-	CLOCK_TICK_RATE = PC9800_8MHz_P() ? 1996800 : 2457600;
-	printk(KERN_DEBUG "CLOCK_TICK_RATE = %d\n", CLOCK_TICK_RATE);
-	tick_usec = TICK_USEC; 		/* USER_HZ period (usec) */
-	tick_nsec = TICK_NSEC;		/* ACTHZ period (nsec) */
-
-	pc9800_misc_flags = PC9800_MISC_FLAGS;
-#ifdef CONFIG_SMP
-	if ((*(u32 *)(MPC_TABLE)) == 0x504d4350)
-		memcpy(mpc_table, MPC_TABLE, *(u16 *)(MPC_TABLE + 4));
-#endif /* CONFIG_SMP */
-}
diff -Nru a/include/asm-i386/mach-pc9800/smpboot_hooks.h b/include/asm-i386/mach-pc9800/smpboot_hooks.h
--- a/include/asm-i386/mach-pc9800/smpboot_hooks.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,52 +0,0 @@
-/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
- * which needs to alter them. */
-
-static inline void smpboot_clear_io_apic_irqs(void)
-{
-	io_apic_irqs = 0;
-}
-
-static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
-{
-	/* reset code is stored in 8255 on PC-9800. */
-	outb(0x0e, 0x37);	/* SHUT0 = 0 */
-	local_flush_tlb();
-	Dprintk("1.\n");
-	*((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4;
-	Dprintk("2.\n");
-	*((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf;
-	Dprintk("3.\n");
-	/*
-	 * On PC-9800, continuation on warm reset is done by loading
-	 * %ss:%sp from 0x0000:0404 and executing 'lret', so:
-	 */
-	/* 0x3f0 is on unused interrupt vector and should be safe... */
-	*((volatile unsigned long *) phys_to_virt(0x404)) = 0x000003f0;
-	Dprintk("4.\n");
-}
-
-static inline void smpboot_restore_warm_reset_vector(void)
-{
-	/*
-	 * Install writable page 0 entry to set BIOS data area.
-	 */
-	local_flush_tlb();
-
-	/*
-	 * Paranoid:  Set warm reset code and vector here back
-	 * to default values.
-	 */
-	outb(0x0f, 0x37);	/* SHUT0 = 1 */
-
-	*((volatile long *) phys_to_virt(0x404)) = 0;
-}
-
-static inline void smpboot_setup_io_apic(void)
-{
-	/*
-	 * Here we can be sure that there is an IO-APIC in the system. Let's
-	 * go and set it up:
-	 */
-	if (!skip_ioapic_setup && nr_ioapics)
-		setup_IO_APIC();
-}
diff -Nru a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
--- a/include/asm-i386/mach-summit/mach_apic.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/mach-summit/mach_apic.h	2004-06-23 19:04:27 -07:00
@@ -27,7 +27,6 @@
 #define INT_DELIVERY_MODE (dest_Fixed)
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
-#define APIC_BROADCAST_ID     (0xFF)
 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
 {
 	return 0;
diff -Nru a/include/asm-i386/mach-summit/mach_mpspec.h b/include/asm-i386/mach-summit/mach_mpspec.h
--- a/include/asm-i386/mach-summit/mach_mpspec.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-i386/mach-summit/mach_mpspec.h	2004-06-23 19:04:26 -07:00
@@ -1,11 +1,6 @@
 #ifndef __ASM_MACH_MPSPEC_H
 #define __ASM_MACH_MPSPEC_H
 
-/*
- * a maximum of 256 APICs with the current APIC ID architecture.
- */
-#define MAX_APICS 256
-
 #define MAX_IRQ_SOURCES 256
 
 /* Maximum 256 PCI busses, plus 1 ISA bus in each of 4 cabinets. */
diff -Nru a/include/asm-i386/mach-visws/mach_apic.h b/include/asm-i386/mach-visws/mach_apic.h
--- a/include/asm-i386/mach-visws/mach_apic.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-i386/mach-visws/mach_apic.h	2004-06-23 19:04:25 -07:00
@@ -19,7 +19,6 @@
  #define TARGET_CPUS cpumask_of_cpu(0)
 #endif
 
-#define APIC_BROADCAST_ID      0x0F
 #define check_apicid_used(bitmap, apicid)	physid_isset(apicid, bitmap)
 #define check_apicid_present(bit)		physid_isset(bit, phys_cpu_present_map)
 
@@ -61,7 +60,10 @@
 
 static inline int cpu_present_to_apicid(int mps_cpu)
 {
-	return mps_cpu;
+	if (mps_cpu < get_physical_broadcast())
+		return mps_cpu;
+	else
+		return BAD_APICID;
 }
 
 static inline physid_mask_t apicid_to_cpu_present(int apicid)
diff -Nru a/include/asm-i386/mach-visws/setup_arch_post.h b/include/asm-i386/mach-visws/setup_arch_post.h
--- a/include/asm-i386/mach-visws/setup_arch_post.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/mach-visws/setup_arch_post.h	2004-06-23 19:04:27 -07:00
@@ -10,7 +10,7 @@
 
 long long mem_size __initdata = 0;
 
-static inline char * __init machine_specific_memory_setup(void)
+static char * __init machine_specific_memory_setup(void)
 {
 	long long gfx_mem_size = 8 * MB;
 
diff -Nru a/include/asm-i386/mach-voyager/setup_arch_post.h b/include/asm-i386/mach-voyager/setup_arch_post.h
--- a/include/asm-i386/mach-voyager/setup_arch_post.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-i386/mach-voyager/setup_arch_post.h	2004-06-23 19:04:26 -07:00
@@ -3,7 +3,7 @@
  * This is included late in kernel/setup.c so that it can make use of all of
  * the static functions. */
 
-static inline char * __init machine_specific_memory_setup(void)
+static char * __init machine_specific_memory_setup(void)
 {
 	char *who;
 
diff -Nru a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
--- a/include/asm-i386/mpspec.h	2004-06-23 19:04:24 -07:00
+++ b/include/asm-i386/mpspec.h	2004-06-23 19:04:24 -07:00
@@ -33,7 +33,7 @@
 extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_parse_prt (void);
+extern void mp_register_gsi (u32 gsi, int edge_level, int active_high_low);
 #endif /*CONFIG_ACPI_BOOT*/
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
diff -Nru a/include/asm-i386/mpspec_def.h b/include/asm-i386/mpspec_def.h
--- a/include/asm-i386/mpspec_def.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-i386/mpspec_def.h	2004-06-23 19:04:26 -07:00
@@ -14,6 +14,7 @@
 #define SMP_MAGIC_IDENT	(('_'<<24)|('P'<<16)|('M'<<8)|'_')
 
 #define MAX_MPC_ENTRY 1024
+#define MAX_APICS      256
 
 struct intel_mp_floating
 {
diff -Nru a/include/asm-i386/msi.h b/include/asm-i386/msi.h
--- a/include/asm-i386/msi.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-i386/msi.h	2004-06-23 19:04:27 -07:00
@@ -16,7 +16,7 @@
 #ifdef CONFIG_SMP
 #define MSI_TARGET_CPU		logical_smp_processor_id()
 #else
-#define MSI_TARGET_CPU		TARGET_CPUS
+#define MSI_TARGET_CPU	cpu_to_logical_apicid(first_cpu(cpu_online_map))
 #endif
 
 #endif /* ASM_MSI_H */
diff -Nru a/include/asm-i386/pc9800.h b/include/asm-i386/pc9800.h
--- a/include/asm-i386/pc9800.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,27 +0,0 @@
-/*
- *  PC-9800 machine types.
- *
- *  Copyright (C) 1999	TAKAI Kosuke <tak@kmc.kyoto-u.ac.jp>
- *			(Linux/98 Project)
- */
-
-#ifndef _ASM_PC9800_H_
-#define _ASM_PC9800_H_
-
-#include <asm/pc9800_sca.h>
-#include <asm/types.h>
-
-#define __PC9800SCA(type, pa)	(*(type *) phys_to_virt(pa))
-#define __PC9800SCA_TEST_BIT(pa, n)	\
-	((__PC9800SCA(u8, pa) & (1U << (n))) != 0)
-
-#define PC9800_HIGHRESO_P()	__PC9800SCA_TEST_BIT(PC9800SCA_BIOS_FLAG, 3)
-#define PC9800_8MHz_P()		__PC9800SCA_TEST_BIT(PC9800SCA_BIOS_FLAG, 7)
-
-				/* 0x2198 is 98 21 on memory... */
-#define PC9800_9821_P()		(__PC9800SCA(u16, PC9821SCA_ROM_ID) == 0x2198)
-
-/* Note PC9821_...() are valid only when PC9800_9821_P() was true. */
-#define PC9821_IDEIF_DOUBLE_P()	__PC9800SCA_TEST_BIT(PC9821SCA_ROM_FLAG4, 4)
-
-#endif
diff -Nru a/include/asm-i386/pc9800_sca.h b/include/asm-i386/pc9800_sca.h
--- a/include/asm-i386/pc9800_sca.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,25 +0,0 @@
-/*
- *  System-common area definitions for NEC PC-9800 series
- *
- *  Copyright (C) 1999	TAKAI Kousuke <tak@kmc.kyoto-u.ac.jp>,
- *			Kyoto University Microcomputer Club.
- */
-
-#ifndef _ASM_I386_PC9800SCA_H_
-#define _ASM_I386_PC9800SCA_H_
-
-#define PC9800SCA_EXPMMSZ		(0x0401)	/* B */
-#define PC9800SCA_SCSI_PARAMS		(0x0460)	/* 8 * 4B */
-#define PC9800SCA_DISK_EQUIPS		(0x0482)	/* B */
-#define PC9800SCA_XROM_ID		(0x04C0)	/* 52B */
-#define PC9800SCA_BIOS_FLAG		(0x0501)	/* B */
-#define PC9800SCA_MMSZ16M		(0x0594)	/* W */
-
-/* PC-9821 have additional system common area in their BIOS-ROM segment. */
-
-#define PC9821SCA__BASE			(0xF8E8 << 4)
-#define PC9821SCA_ROM_ID		(PC9821SCA__BASE + 0x00)
-#define PC9821SCA_ROM_FLAG4		(PC9821SCA__BASE + 0x05)
-#define PC9821SCA_RSFLAGS		(PC9821SCA__BASE + 0x11)	/* B */
-
-#endif /* !_ASM_I386_PC9800SCA_H_ */
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
--- a/include/asm-i386/pgtable.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-i386/pgtable.h	2004-06-23 19:04:28 -07:00
@@ -220,8 +220,20 @@
 static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte_low |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte_low |= _PAGE_RW; return pte; }
 
-static inline  int ptep_test_and_clear_dirty(pte_t *ptep)	{ return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); }
-static inline  int ptep_test_and_clear_young(pte_t *ptep)	{ return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); }
+static inline int ptep_test_and_clear_dirty(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)
+{
+	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); }
 
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-i386/processor.h	2004-06-23 19:04:25 -07:00
@@ -259,14 +259,8 @@
 
 /*
  * Bus types (default is ISA, but people can check others with these..)
- * pc98 indicates PC98 systems (CBUS)
  */
 extern int MCA_bus;
-#ifdef CONFIG_X86_PC9800
-#define pc98 1
-#else
-#define pc98 0
-#endif
 
 static inline void __monitor(const void *eax, unsigned long ecx,
 		unsigned long edx)
diff -Nru a/include/asm-i386/resource.h b/include/asm-i386/resource.h
--- a/include/asm-i386/resource.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-i386/resource.h	2004-06-23 19:04:25 -07:00
@@ -16,8 +16,11 @@
 #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 RLIM_NLIMITS	11
 
 /*
  * SuS says limits have to be unsigned.
@@ -39,7 +42,9 @@
 	{      INR_OPEN,     INR_OPEN  },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
-        { RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-i386/serial.h b/include/asm-i386/serial.h
--- a/include/asm-i386/serial.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-i386/serial.h	2004-06-23 19:04:28 -07:00
@@ -47,19 +47,12 @@
 
 #define C_P(card,port) (((card)<<6|(port)<<3) + 1)
 
-#ifndef CONFIG_X86_PC9800
 #define STD_SERIAL_PORT_DEFNS			\
 	/* UART CLK   PORT IRQ     FLAGS        */			\
 	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
 	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
 	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
 	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
-#else
-#define STD_SERIAL_PORT_DEFNS			\
-	/* UART CLK   PORT IRQ     FLAGS        */			\
-	{ 0, BASE_BAUD, 0x30, 4, STD_COM_FLAGS },	/* ttyS0 */	\
-	{ 0, BASE_BAUD, 0x238, 5, STD_COM_FLAGS },	/* ttyS1 */
-#endif /* CONFIG_X86_PC9800 */
 
 
 #ifdef CONFIG_SERIAL_MANY_PORTS
diff -Nru a/include/asm-i386/std_resources.h b/include/asm-i386/std_resources.h
--- a/include/asm-i386/std_resources.h	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,14 +0,0 @@
-/*
- * include/asm-i386/std_resources.h
- */
-
-#ifndef __ASM_I386_STD_RESOURCES_H
-#define __ASM_I386_STD_RESOURCES_H
-
-#include <linux/init.h>
-
-void probe_roms(void) __init;
-void request_graphics_resource(void) __init;
-void request_standard_io_resources(void) __init;
-
-#endif
diff -Nru a/include/asm-i386/timex.h b/include/asm-i386/timex.h
--- a/include/asm-i386/timex.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-i386/timex.h	2004-06-23 19:04:26 -07:00
@@ -9,14 +9,10 @@
 #include <linux/config.h>
 #include <asm/msr.h>
 
-#ifdef CONFIG_X86_PC9800
-   extern int CLOCK_TICK_RATE;
-#else
 #ifdef CONFIG_X86_ELAN
 #  define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
 #else
 #  define CLOCK_TICK_RATE 1193182 /* Underlying HZ */
-#endif
 #endif
 
 #define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
diff -Nru a/include/asm-ia64/fcntl.h b/include/asm-ia64/fcntl.h
--- a/include/asm-ia64/fcntl.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-ia64/fcntl.h	2004-06-23 19:04:27 -07:00
@@ -28,6 +28,7 @@
 #define O_LARGEFILE	0100000
 #define O_DIRECTORY	0200000	/* must be a directory */
 #define O_NOFOLLOW	0400000 /* don't follow links */
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h
--- a/include/asm-ia64/gcc_intrin.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ia64/gcc_intrin.h	2004-06-23 19:04:26 -07:00
@@ -489,10 +489,16 @@
 #define ia64_ptce(addr)	asm volatile ("ptc.e %0" :: "r"(addr))
 
 #define ia64_ptcga(addr, size)							\
-	asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory")
-
-#define ia64_ptcl(addr, size)						\
-	asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory")
+do {										\
+	asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory");	\
+	ia64_dv_serialize_data();						\
+} while (0)
+
+#define ia64_ptcl(addr, size)							\
+do {										\
+	asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory");	\
+	ia64_dv_serialize_data();						\
+} while (0)
 
 #define ia64_ptri(addr, size)						\
 	asm volatile ("ptr.i %0,%1" :: "r"(addr), "r"(size) : "memory")
@@ -581,7 +587,7 @@
 
 #define ia64_intrin_local_irq_restore(x)			\
 do {								\
-	asm volatile ("     cmp.ne p6,p7=%0,r0;;"		\
+	asm volatile (";;   cmp.ne p6,p7=%0,r0;;"		\
 		      "(p6) ssm psr.i;"				\
 		      "(p7) rsm psr.i;;"			\
 		      "(p6) srlz.d"				\
diff -Nru a/include/asm-ia64/ia32.h b/include/asm-ia64/ia32.h
--- a/include/asm-ia64/ia32.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-ia64/ia32.h	2004-06-23 19:04:29 -07:00
@@ -6,7 +6,8 @@
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 
-#define IA32_NR_syscalls		283 /* length of syscall table */
+#define IA32_NR_syscalls		283	/* length of syscall table */
+#define IA32_PAGE_SHIFT			12	/* 4KB pages */
 
 #ifndef __ASSEMBLY__
 
@@ -24,6 +25,13 @@
 /* Declare this unconditionally, so we don't get warnings for unreachable code.  */
 extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
 			      sigset_t *set, struct pt_regs *regs);
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+extern int ia32_copy_partial_page_list (struct task_struct *, unsigned long);
+extern void ia32_drop_partial_page_list (struct task_struct *);
+#else
+# define ia32_copy_partial_page_list(a1, a2)	0
+# define ia32_drop_partial_page_list(a1)	do { ; } while (0)
+#endif
 
 #endif /* !__ASSEMBLY__ */
 
diff -Nru a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
--- a/include/asm-ia64/iosapic.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-ia64/iosapic.h	2004-06-23 19:04:27 -07:00
@@ -60,7 +60,6 @@
 				    unsigned int gsi_base);
 extern int gsi_to_vector (unsigned int gsi);
 extern int gsi_to_irq (unsigned int gsi);
-extern void __init iosapic_parse_prt (void);
 extern void iosapic_enable_intr (unsigned int vector);
 extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
 				  unsigned long trigger);
diff -Nru a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h
--- a/include/asm-ia64/irq.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-ia64/irq.h	2004-06-23 19:04:29 -07:00
@@ -30,6 +30,12 @@
 extern void enable_irq (unsigned int);
 extern void set_irq_affinity_info (unsigned int irq, int dest, int redir);
 
+#ifdef CONFIG_SMP
+extern void move_irq(int irq);
+#else
+#define move_irq(irq)
+#endif
+
 struct irqaction;
 struct pt_regs;
 int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
--- a/include/asm-ia64/pgtable.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ia64/pgtable.h	2004-06-23 19:04:26 -07:00
@@ -297,11 +297,7 @@
  * works bypasses the caches, but does allow for consecutive writes to
  * be combined into single (but larger) write transactions.
  */
-#ifdef CONFIG_MCKINLEY_A0_SPECIFIC
-# define pgprot_writecombine(prot)	prot
-#else
-# define pgprot_writecombine(prot)	__pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC)
-#endif
+#define pgprot_writecombine(prot)	__pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC)
 
 static inline unsigned long
 pgd_index (unsigned long address)
@@ -346,6 +342,8 @@
 ptep_test_and_clear_young (pte_t *ptep)
 {
 #ifdef CONFIG_SMP
+	if (!pte_young(*ptep))
+		return 0;
 	return test_and_clear_bit(_PAGE_A_BIT, ptep);
 #else
 	pte_t pte = *ptep;
@@ -360,6 +358,8 @@
 ptep_test_and_clear_dirty (pte_t *ptep)
 {
 #ifdef CONFIG_SMP
+	if (!pte_dirty(*ptep))
+		return 0;
 	return test_and_clear_bit(_PAGE_D_BIT, ptep);
 #else
 	pte_t pte = *ptep;
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ia64/processor.h	2004-06-23 19:04:26 -07:00
@@ -230,6 +230,7 @@
 
 #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
 
+struct partial_page_list;
 #endif
 
 struct thread_struct {
@@ -251,6 +252,7 @@
 	__u64 fdr;			/* IA32 fp except. data reg */
 	__u64 old_k1;			/* old value of ar.k1 */
 	__u64 old_iob;			/* old IOBase value */
+	struct partial_page_list *ppl;	/* partial page list for 4K page size issue */
         /* cached TLS descriptors. */
 	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
 
@@ -260,7 +262,8 @@
 				.fir =		0,			\
 				.fdr =		0,			\
 				.old_k1 =	0,			\
-				.old_iob =	0,
+				.old_iob =	0,			\
+				.ppl =		0,
 #else
 # define INIT_THREAD_IA32
 #endif /* CONFIG_IA32_SUPPORT */
diff -Nru a/include/asm-ia64/resource.h b/include/asm-ia64/resource.h
--- a/include/asm-ia64/resource.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ia64/resource.h	2004-06-23 19:04:28 -07:00
@@ -23,8 +23,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -47,6 +49,8 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 # endif /* __KERNEL__ */
diff -Nru a/include/asm-ia64/sn/module.h b/include/asm-ia64/sn/module.h
--- a/include/asm-ia64/sn/module.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ia64/sn/module.h	2004-06-23 19:04:26 -07:00
@@ -180,7 +180,7 @@
 };
 
 /* module.c */
-extern module_t	       *modules[MODULE_MAX];	/* Indexed by cmoduleid_t   */
+extern module_t	       *sn_modules[MODULE_MAX];	/* Indexed by cmoduleid_t   */
 extern int		nummodules;
 
 extern module_t	       *module_lookup(moduleid_t id);
diff -Nru a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
--- a/include/asm-ia64/sn/sn_sal.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-ia64/sn/sn_sal.h	2004-06-23 19:04:29 -07:00
@@ -33,6 +33,7 @@
 #define  SN_SAL_NO_FAULT_ZONE_VIRTUAL		   0x02000010
 #define  SN_SAL_NO_FAULT_ZONE_PHYSICAL		   0x02000011
 #define  SN_SAL_PRINT_ERROR			   0x02000012
+#define  SN_SAL_SET_ERROR_HANDLING_FEATURES	   0x0200001a	// reentrant
 #define  SN_SAL_CONSOLE_PUTC                       0x02000021
 #define  SN_SAL_CONSOLE_GETC                       0x02000022
 #define  SN_SAL_CONSOLE_PUTS                       0x02000023
@@ -92,6 +93,19 @@
 #define SALRET_INVALID_ARG	-2
 #define SALRET_ERROR		-3
 
+/*
+ * SN_SAL_SET_ERROR_HANDLING_FEATURES bit settings
+ */
+enum 
+{
+	/* if "rz always" is set, have the mca slaves call os_init_slave */
+	SN_SAL_EHF_MCA_SLV_TO_OS_INIT_SLV=0,
+	/* do not rz on tlb checks, even if "rz always" is set */
+	SN_SAL_EHF_NO_RZ_TLBC,
+	/* do not rz on PIO reads to I/O space, even if "rz always" is set */
+	SN_SAL_EHF_NO_RZ_IO_READ,
+};
+
 
 /**
  * sn_sal_rev_major - get the major SGI SAL revision number
@@ -668,6 +682,26 @@
 	if (rv.status)
 	    	return rv.v0;
 	return 0;
+}
+
+/*
+ * Tell the prom how the OS wants to handle specific error features.
+ * It takes an array of 7 u64.
+ */
+static inline u64
+ia64_sn_set_error_handling_features(const u64 *feature_bits)
+{
+	struct ia64_sal_retval rv = {0, 0, 0, 0};
+
+	SAL_CALL_REENTRANT(rv, SN_SAL_SET_ERROR_HANDLING_FEATURES,
+			feature_bits[0],
+			feature_bits[1],
+			feature_bits[2],
+			feature_bits[3],
+			feature_bits[4],
+			feature_bits[5],
+			feature_bits[6]);
+	return rv.status;
 }
 
 #endif /* _ASM_IA64_SN_SN_SAL_H */
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ia64/system.h	2004-06-23 19:04:26 -07:00
@@ -171,7 +171,7 @@
 # define local_irq_restore(x)	__local_irq_restore(x)
 #endif /* !CONFIG_IA64_DEBUG_IRQ */
 
-#define local_irq_enable()	({ ia64_ssm(IA64_PSR_I); ia64_srlz_d(); })
+#define local_irq_enable()	({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); })
 #define local_save_flags(flags)	({ ia64_stop(); (flags) = ia64_getreg(_IA64_REG_PSR); })
 
 #define irqs_disabled()				\
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ia64/unistd.h	2004-06-23 19:04:25 -07:00
@@ -266,6 +266,8 @@
 
 #define NR_syscalls			256 /* length of syscall table */
 
+#define __ARCH_WANT_SYS_RT_SIGACTION
+
 #ifdef CONFIG_IA32_SUPPORT
 # define __ARCH_WANT_SYS_FADVISE64
 # define __ARCH_WANT_SYS_GETPGRP
@@ -275,7 +277,6 @@
 # define __ARCH_WANT_SYS_OLDUMOUNT
 # define __ARCH_WANT_SYS_SIGPENDING
 # define __ARCH_WANT_SYS_SIGPROCMASK
-# define __ARCH_WANT_SYS_RT_SIGACTION
 #endif
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
diff -Nru a/include/asm-m68k/atomic.h b/include/asm-m68k/atomic.h
--- a/include/asm-m68k/atomic.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-m68k/atomic.h	2004-06-23 19:04:25 -07:00
@@ -1,6 +1,8 @@
 #ifndef __ARCH_M68K_ATOMIC__
 #define __ARCH_M68K_ATOMIC__
 
+#include <asm/system.h>	/* local_irq_XXX() */
+
 /*
  * Atomic operations that C can't guarantee us.  Useful for
  * resource counting etc..
@@ -16,38 +18,124 @@
 #define atomic_read(v)		((v)->counter)
 #define atomic_set(v, i)	(((v)->counter) = i)
 
-static __inline__ void atomic_add(int i, atomic_t *v)
+static inline void atomic_add(int i, atomic_t *v)
+{
+	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : "id" (i));
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : "id" (i));
+}
+
+static inline void atomic_inc(atomic_t *v)
+{
+	__asm__ __volatile__("addql #1,%0" : "+m" (*v));
+}
+
+static inline void atomic_dec(atomic_t *v)
+{
+	__asm__ __volatile__("subql #1,%0" : "+m" (*v));
+}
+
+static inline int atomic_dec_and_test(atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
+	return c != 0;
+}
+
+static inline int atomic_inc_and_test(atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
+	return c != 0;
+}
+
+#ifdef CONFIG_RMW_INSNS
+static inline int atomic_add_return(int i, atomic_t *v)
 {
-	__asm__ __volatile__("addl %1,%0" : "=m" (*v) : "id" (i), "0" (*v));
+	int t, tmp;
+
+	__asm__ __volatile__(
+			"1:	movel %2,%1\n"
+			"	addl %3,%1\n"
+			"	casl %2,%1,%0\n"
+			"	jne 1b"
+			: "+m" (*v), "=&d" (t), "=&d" (tmp)
+			: "g" (i), "2" (atomic_read(v)));
+	return t;
 }
 
-static __inline__ void atomic_sub(int i, atomic_t *v)
+static inline int atomic_sub_return(int i, atomic_t *v)
 {
-	__asm__ __volatile__("subl %1,%0" : "=m" (*v) : "id" (i), "0" (*v));
+	int t, tmp;
+
+	__asm__ __volatile__(
+			"1:	movel %2,%1\n"
+			"	subl %3,%1\n"
+			"	casl %2,%1,%0\n"
+			"	jne 1b"
+			: "+m" (*v), "=&d" (t), "=&d" (tmp)
+			: "g" (i), "2" (atomic_read(v)));
+	return t;
+}
+#else /* !CONFIG_RMW_INSNS */
+static inline int atomic_add_return(int i, atomic_t * v)
+{
+	unsigned long flags;
+	int t;
+
+	local_irq_save(flags);
+	t = atomic_read(v);
+	t += i;
+	atomic_set(v, t);
+	local_irq_restore(flags);
+
+	return t;
 }
 
-static __inline__ void atomic_inc(volatile atomic_t *v)
+static inline int atomic_sub_return(int i, atomic_t * v)
 {
-	__asm__ __volatile__("addql #1,%0" : "=m" (*v): "0" (*v));
+	unsigned long flags;
+	int t;
+
+	local_irq_save(flags);
+	t = atomic_read(v);
+	t -= i;
+	atomic_set(v, t);
+	local_irq_restore(flags);
+
+	return t;
 }
+#endif /* !CONFIG_RMW_INSNS */
+
+#define atomic_dec_return(v)	atomic_sub_return(1, (v))
+#define atomic_inc_return(v)	atomic_add_return(1, (v))
 
-static __inline__ void atomic_dec(volatile atomic_t *v)
+static inline int atomic_sub_and_test(int i, atomic_t *v)
 {
-	__asm__ __volatile__("subql #1,%0" : "=m" (*v): "0" (*v));
+	char c;
+	__asm__ __volatile__("subl %2,%1; seq %0" : "=d" (c), "+m" (*v): "g" (i));
+	return c != 0;
 }
 
-static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
+static inline int atomic_add_negative(int i, atomic_t *v)
 {
 	char c;
-	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "=m" (*v): "1" (*v));
+	__asm__ __volatile__("addl %2,%1; smi %0" : "=d" (c), "+m" (*v): "g" (i));
 	return c != 0;
 }
 
-#define atomic_clear_mask(mask, v) \
-	__asm__ __volatile__("andl %1,%0" : "=m" (*v) : "id" (~(mask)),"0"(*v))
+static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
+{
+	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
+}
 
-#define atomic_set_mask(mask, v) \
-	__asm__ __volatile__("orl %1,%0" : "=m" (*v) : "id" (mask),"0"(*v))
+static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
+{
+	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
+}
 
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()	barrier()
diff -Nru a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h
--- a/include/asm-m68k/bitops.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-m68k/bitops.h	2004-06-23 19:04:29 -07:00
@@ -23,25 +23,24 @@
 
 #define __test_and_set_bit(nr,vaddr) test_and_set_bit(nr,vaddr)
 
-static inline int __constant_test_and_set_bit(int nr,
-					      volatile unsigned long *vaddr)
+static inline int __constant_test_and_set_bit(int nr, unsigned long *vaddr)
 {
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
 	char retval;
 
 	__asm__ __volatile__ ("bset %2,%1; sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
-	     : "di" (nr & 7));
+			: "=d" (retval), "+m" (*p)
+			: "di" (nr & 7));
 
 	return retval;
 }
 
-static inline int __generic_test_and_set_bit(int nr,
-					     volatile unsigned long *vaddr)
+static inline int __generic_test_and_set_bit(int nr, unsigned long *vaddr)
 {
 	char retval;
 
-	__asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
-	     : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
+	__asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
+			: "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
 
 	return retval;
 }
@@ -53,16 +52,17 @@
 
 #define __set_bit(nr,vaddr) set_bit(nr,vaddr)
 
-static inline void __constant_set_bit(int nr, volatile unsigned long *vaddr)
+static inline void __constant_set_bit(int nr, unsigned long *vaddr)
 {
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
 	__asm__ __volatile__ ("bset %1,%0"
-	     : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
+			: "+m" (*p) : "di" (nr & 7));
 }
 
-static inline void __generic_set_bit(int nr, volatile unsigned long *vaddr)
+static inline void __generic_set_bit(int nr, unsigned long *vaddr)
 {
-	__asm__ __volatile__ ("bfset %1@{%0:#1}"
-	     : : "d" (nr^31), "a" (vaddr) : "memory");
+	__asm__ __volatile__ ("bfset %1{%0:#1}"
+			: : "d" (nr^31), "o" (*vaddr) : "memory");
 }
 
 #define test_and_clear_bit(nr,vaddr) \
@@ -72,25 +72,24 @@
 
 #define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr)
 
-static inline int __constant_test_and_clear_bit(int nr,
-						volatile unsigned long *vaddr)
+static inline int __constant_test_and_clear_bit(int nr, unsigned long *vaddr)
 {
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
 	char retval;
 
 	__asm__ __volatile__ ("bclr %2,%1; sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
-	     : "di" (nr & 7));
+			: "=d" (retval), "+m" (*p)
+			: "di" (nr & 7));
 
 	return retval;
 }
 
-static inline int __generic_test_and_clear_bit(int nr,
-					       volatile unsigned long *vaddr)
+static inline int __generic_test_and_clear_bit(int nr, unsigned long *vaddr)
 {
 	char retval;
 
-	__asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
-	     : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
+	__asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
+			: "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
 
 	return retval;
 }
@@ -107,16 +106,17 @@
    __generic_clear_bit(nr, vaddr))
 #define __clear_bit(nr,vaddr) clear_bit(nr,vaddr)
 
-static inline void __constant_clear_bit(int nr, volatile unsigned long *vaddr)
+static inline void __constant_clear_bit(int nr, unsigned long *vaddr)
 {
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
 	__asm__ __volatile__ ("bclr %1,%0"
-	     : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
+			: "+m" (*p) : "di" (nr & 7));
 }
 
-static inline void __generic_clear_bit(int nr, volatile unsigned long *vaddr)
+static inline void __generic_clear_bit(int nr, unsigned long *vaddr)
 {
-	__asm__ __volatile__ ("bfclr %1@{%0:#1}"
-	     : : "d" (nr^31), "a" (vaddr) : "memory");
+	__asm__ __volatile__ ("bfclr %1{%0:#1}"
+			: : "d" (nr^31), "o" (*vaddr) : "memory");
 }
 
 #define test_and_change_bit(nr,vaddr) \
@@ -127,25 +127,24 @@
 #define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr)
 #define __change_bit(nr,vaddr) change_bit(nr,vaddr)
 
-static inline int __constant_test_and_change_bit(int nr,
-						 volatile unsigned long *vaddr)
+static inline int __constant_test_and_change_bit(int nr, unsigned long *vaddr)
 {
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
 	char retval;
 
 	__asm__ __volatile__ ("bchg %2,%1; sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
-	     : "di" (nr & 7));
+			: "=d" (retval), "+m" (*p)
+			: "di" (nr & 7));
 
 	return retval;
 }
 
-static inline int __generic_test_and_change_bit(int nr,
-						volatile unsigned long *vaddr)
+static inline int __generic_test_and_change_bit(int nr, unsigned long *vaddr)
 {
 	char retval;
 
-	__asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0"
-	     : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
+	__asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0"
+			: "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
 
 	return retval;
 }
@@ -155,21 +154,22 @@
    __constant_change_bit(nr, vaddr) : \
    __generic_change_bit(nr, vaddr))
 
-static inline void __constant_change_bit(int nr, volatile unsigned long *vaddr)
+static inline void __constant_change_bit(int nr, unsigned long *vaddr)
 {
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
 	__asm__ __volatile__ ("bchg %1,%0"
-	     : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
+			: "+m" (*p) : "di" (nr & 7));
 }
 
-static inline void __generic_change_bit(int nr, volatile unsigned long *vaddr)
+static inline void __generic_change_bit(int nr, unsigned long *vaddr)
 {
-	__asm__ __volatile__ ("bfchg %1@{%0:#1}"
-	     : : "d" (nr^31), "a" (vaddr) : "memory");
+	__asm__ __volatile__ ("bfchg %1{%0:#1}"
+			: : "d" (nr^31), "o" (*vaddr) : "memory");
 }
 
-static inline int test_bit(int nr, const volatile unsigned long *vaddr)
+static inline int test_bit(int nr, const unsigned long *vaddr)
 {
-	return ((1UL << (nr & 31)) & (((const volatile unsigned long *) vaddr)[nr >> 5])) != 0;
+	return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0;
 }
 
 static inline int find_first_zero_bit(const unsigned long *vaddr,
@@ -364,76 +364,27 @@
 	return ((p - addr) << 4) + (res ^ 31);
 }
 
-static inline int minix_test_and_set_bit(int nr, volatile void *vaddr)
-{
-	char retval;
-
-	__asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
-	     : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *)vaddr) : "memory");
-
-	return retval;
-}
-
-#define minix_set_bit(nr,addr)	((void)minix_test_and_set_bit(nr,addr))
-
-static inline int minix_test_and_clear_bit(int nr, volatile void *vaddr)
-{
-	char retval;
-
-	__asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
-	     : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *) vaddr) : "memory");
-
-	return retval;
-}
+#define minix_test_and_set_bit(nr, addr)	test_and_set_bit((nr) ^ 16, (unsigned long *)(addr))
+#define minix_set_bit(nr,addr)			set_bit((nr) ^ 16, (unsigned long *)(addr))
+#define minix_test_and_clear_bit(nr, addr)	test_and_clear_bit((nr) ^ 16, (unsigned long *)(addr))
 
-static inline int minix_test_bit(int nr, const volatile void *vaddr)
+static inline int minix_test_bit(int nr, const void *vaddr)
 {
-	return ((1U << (nr & 15)) & (((const volatile unsigned short *) vaddr)[nr >> 4])) != 0;
+	const unsigned short *p = vaddr;
+	return (p[nr >> 4] & (1U << (nr & 15))) != 0;
 }
 
 /* Bitmap functions for the ext2 filesystem. */
 
-static inline int ext2_set_bit(int nr, volatile void *vaddr)
-{
-	char retval;
-
-	__asm__ __volatile__ ("bfset %2{%1,#1}; sne %0"
-	     : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory");
-
-	return retval;
-}
-
-static inline int ext2_clear_bit(int nr, volatile void *vaddr)
-{
-	char retval;
-
-	__asm__ __volatile__ ("bfclr %2{%1,#1}; sne %0"
-	     : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory");
-
-	return retval;
-}
-
-#define ext2_set_bit_atomic(lock, nr, addr)		\
-	({						\
-		int ret;				\
-		spin_lock(lock);			\
-		ret = ext2_set_bit((nr), (addr));	\
-		spin_unlock(lock);			\
-		ret;					\
-	})
-
-#define ext2_clear_bit_atomic(lock, nr, addr)		\
-	({						\
-		int ret;				\
-		spin_lock(lock);			\
-		ret = ext2_clear_bit((nr), (addr));	\
-		spin_unlock(lock);			\
-		ret;					\
-	})
+#define ext2_set_bit(nr, addr)			test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
+#define ext2_set_bit_atomic(lock, nr, addr)	test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
+#define ext2_clear_bit(nr, addr)		test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
+#define ext2_clear_bit_atomic(lock, nr, addr)	test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
 
-static inline int ext2_test_bit(int nr, const volatile void *vaddr)
+static inline int ext2_test_bit(int nr, const void *vaddr)
 {
-	return ((1U << (nr & 7)) & (((const volatile unsigned char *) vaddr)[nr >> 3])) != 0;
+	const unsigned char *p = vaddr;
+	return (p[nr >> 3] & (1U << (nr & 7))) != 0;
 }
 
 static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size)
diff -Nru a/include/asm-m68k/fcntl.h b/include/asm-m68k/fcntl.h
--- a/include/asm-m68k/fcntl.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-m68k/fcntl.h	2004-06-23 19:04:26 -07:00
@@ -20,6 +20,7 @@
 #define O_NOFOLLOW	0100000	/* don't follow links */
 #define O_DIRECT	0200000	/* direct disk access hint - currently ignored */
 #define O_LARGEFILE	0400000
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-m68k/io.h b/include/asm-m68k/io.h
--- a/include/asm-m68k/io.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-m68k/io.h	2004-06-23 19:04:27 -07:00
@@ -120,7 +120,7 @@
  * be compiled in so the case statement will be optimised away
  */
 
-static inline u8 *isa_itb(long addr)
+static inline u8 *isa_itb(unsigned long addr)
 {
   switch(ISA_TYPE)
     {
@@ -136,7 +136,7 @@
     default: return 0; /* avoid warnings, just in case */
     }
 }
-static inline u16 *isa_itw(long addr)
+static inline u16 *isa_itw(unsigned long addr)
 {
   switch(ISA_TYPE)
     {
@@ -152,7 +152,7 @@
     default: return 0; /* avoid warnings, just in case */
     }
 }
-static inline u8 *isa_mtb(long addr)
+static inline u8 *isa_mtb(unsigned long addr)
 {
   switch(ISA_TYPE)
     {
@@ -168,7 +168,7 @@
     default: return 0; /* avoid warnings, just in case */
     }
 }
-static inline u16 *isa_mtw(long addr)
+static inline u16 *isa_mtw(unsigned long addr)
 {
   switch(ISA_TYPE)
     {
@@ -191,10 +191,14 @@
 #define isa_outb(val,port) out_8(isa_itb(port),(val))
 #define isa_outw(val,port) (ISA_SEX ? out_be16(isa_itw(port),(val)) : out_le16(isa_itw(port),(val)))
 
-#define isa_readb(p)       in_8(isa_mtb(p))
-#define isa_readw(p)       (ISA_SEX ? in_be16(isa_mtw(p)) : in_le16(isa_mtw(p)))
-#define isa_writeb(val,p)  out_8(isa_mtb(p),(val))
-#define isa_writew(val,p)  (ISA_SEX ? out_be16(isa_mtw(p),(val)) : out_le16(isa_mtw(p),(val)))
+#define isa_readb(p)       in_8(isa_mtb((unsigned long)(p)))
+#define isa_readw(p)       \
+	(ISA_SEX ? in_be16(isa_mtw((unsigned long)(p)))	\
+		 : in_le16(isa_mtw((unsigned long)(p))))
+#define isa_writeb(val,p)  out_8(isa_mtb((unsigned long)(p)),(val))
+#define isa_writew(val,p)  \
+	(ISA_SEX ? out_be16(isa_mtw((unsigned long)(p)),(val))	\
+		 : out_le16(isa_mtw((unsigned long)(p)),(val)))
 
 static inline void isa_delay(void)
 {
@@ -215,17 +219,21 @@
 
 #define isa_inb_p(p)      ({u8 v=isa_inb(p);isa_delay();v;})
 #define isa_outb_p(v,p)   ({isa_outb((v),(p));isa_delay();})
+#define isa_inw_p(p)      ({u16 v=isa_inw(p);isa_delay();v;})
+#define isa_outw_p(v,p)   ({isa_outw((v),(p));isa_delay();})
+#define isa_inl_p(p)      ({u32 v=isa_inl(p);isa_delay();v;})
+#define isa_outl_p(v,p)   ({isa_outl((v),(p));isa_delay();})
 
-#define isa_insb(port, buf, nr) raw_insb(isa_itb(port), (buf), (nr))
-#define isa_outsb(port, buf, nr) raw_outsb(isa_itb(port), (buf), (nr))
+#define isa_insb(port, buf, nr) raw_insb(isa_itb(port), (u8 *)(buf), (nr))
+#define isa_outsb(port, buf, nr) raw_outsb(isa_itb(port), (u8 *)(buf), (nr))
 
 #define isa_insw(port, buf, nr)     \
-       (ISA_SEX ? raw_insw(isa_itw(port), (buf), (nr)) :    \
-                  raw_insw_swapw(isa_itw(port), (buf), (nr)))
+       (ISA_SEX ? raw_insw(isa_itw(port), (u16 *)(buf), (nr)) :    \
+                  raw_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
 
 #define isa_outsw(port, buf, nr)    \
-       (ISA_SEX ? raw_outsw(isa_itw(port), (buf), (nr)) :  \
-                  raw_outsw_swapw(isa_itw(port), (buf), (nr)))
+       (ISA_SEX ? raw_outsw(isa_itw(port), (u16 *)(buf), (nr)) :  \
+                  raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
 #endif  /* CONFIG_ISA */
 
 
@@ -235,9 +243,13 @@
 #define outb    isa_outb
 #define outb_p  isa_outb_p
 #define inw     isa_inw
+#define inw_p   isa_inw_p
 #define outw    isa_outw
+#define outw_p  isa_outw_p
 #define inl     isa_inw
+#define inl_p   isa_inw_p
 #define outl    isa_outw
+#define outl_p  isa_outw_p
 #define insb    isa_insb
 #define insw    isa_insw
 #define outsb   isa_outsb
@@ -281,10 +293,16 @@
 #define inb(port) ((port)<1024 ? isa_inb(port) : in_8(port))
 #define inb_p(port) ((port)<1024 ? isa_inb_p(port) : in_8(port))
 #define inw(port) ((port)<1024 ? isa_inw(port) : in_le16(port))
+#define inw_p(port) ((port)<1024 ? isa_inw_p(port) : in_le16(port))
+#define inl(port) ((port)<1024 ? isa_inl(port) : in_le32(port))
+#define inl_p(port) ((port)<1024 ? isa_inl_p(port) : in_le32(port))
 
 #define outb(val,port) ((port)<1024 ? isa_outb((val),(port)) : out_8((port),(val)))
 #define outb_p(val,port) ((port)<1024 ? isa_outb_p((val),(port)) : out_8((port),(val)))
 #define outw(val,port) ((port)<1024 ? isa_outw((val),(port)) : out_le16((port),(val)))
+#define outw_p(val,port) ((port)<1024 ? isa_outw_p((val),(port)) : out_le16((port),(val)))
+#define outl(val,port) ((port)<1024 ? isa_outl((val),(port)) : out_le32((port),(val)))
+#define outl_p(val,port) ((port)<1024 ? isa_outl_p((val),(port)) : out_le32((port),(val)))
 #endif
 #endif /* CONFIG_PCI */
 
diff -Nru a/include/asm-m68k/page.h b/include/asm-m68k/page.h
--- a/include/asm-m68k/page.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-m68k/page.h	2004-06-23 19:04:29 -07:00
@@ -52,15 +52,13 @@
 
 static inline void clear_page(void *page)
 {
-	unsigned long data, tmp;
-	void *sp = page;
+	unsigned long tmp;
+	unsigned long *sp = page;
 
-	data = 0;
-
-	*((unsigned long *)(page))++ = 0;
-	*((unsigned long *)(page))++ = 0;
-	*((unsigned long *)(page))++ = 0;
-	*((unsigned long *)(page))++ = 0;
+	*sp++ = 0;
+	*sp++ = 0;
+	*sp++ = 0;
+	*sp++ = 0;
 
 	__asm__ __volatile__("1:\t"
 			     ".chip 68040\n\t"
@@ -69,8 +67,8 @@
 			     "subqw  #8,%2\n\t"
 			     "subqw  #8,%2\n\t"
 			     "dbra   %1,1b\n\t"
-			     : "=a" (page), "=d" (tmp)
-			     : "a" (sp), "0" (page),
+			     : "=a" (sp), "=d" (tmp)
+			     : "a" (page), "0" (sp),
 			       "1" ((PAGE_SIZE - 16) / 16 - 1));
 }
 
diff -Nru a/include/asm-m68k/resource.h b/include/asm-m68k/resource.h
--- a/include/asm-m68k/resource.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-m68k/resource.h	2004-06-23 19:04:25 -07:00
@@ -16,8 +16,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -39,7 +41,9 @@
 	{      INR_OPEN,     INR_OPEN  },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
-        { RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-m68k/string.h b/include/asm-m68k/string.h
--- a/include/asm-m68k/string.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-m68k/string.h	2004-06-23 19:04:27 -07:00
@@ -290,9 +290,7 @@
 static inline void * __memset_page(void * s,int c,size_t count)
 {
   unsigned long data, tmp;
-  void *xs, *sp;
-
-  xs = sp = s;
+  void *xs = s;
 
   c = c & 255;
   data = c | (c << 8);
@@ -303,10 +301,11 @@
   if (((unsigned long) s) & 0x0f)
 	  __memset_g(s, c, count);
   else{
-	  *((unsigned long *)(s))++ = data;
-	  *((unsigned long *)(s))++ = data;
-	  *((unsigned long *)(s))++ = data;
-	  *((unsigned long *)(s))++ = data;
+	  unsigned long *sp = s;
+	  *sp++ = data;
+	  *sp++ = data;
+	  *sp++ = data;
+	  *sp++ = data;
 
 	  __asm__ __volatile__("1:\t"
 			       ".chip 68040\n\t"
@@ -315,8 +314,8 @@
 			       "subqw  #8,%2\n\t"
 			       "subqw  #8,%2\n\t"
 			       "dbra   %1,1b\n\t"
-			       : "=a" (s), "=d" (tmp)
-			       : "a" (sp), "0" (s), "1" ((count - 16) / 16 - 1)
+			       : "=a" (sp), "=d" (tmp)
+			       : "a" (s), "0" (sp), "1" ((count - 16) / 16 - 1)
 			       );
   }
 
diff -Nru a/include/asm-m68k/ucontext.h b/include/asm-m68k/ucontext.h
--- a/include/asm-m68k/ucontext.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-m68k/ucontext.h	2004-06-23 19:04:25 -07:00
@@ -6,10 +6,8 @@
 typedef greg_t gregset_t[NGREG];
 
 typedef struct fpregset {
-	int f_pcr;
-	int f_psr;
-	int f_fpiaddr;
-	int f_fpregs[8][3];
+	int f_fpcntl[3];
+	int f_fpregs[8*3];
 } fpregset_t;
 
 struct mcontext {
diff -Nru a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
--- a/include/asm-mips/checksum.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-mips/checksum.h	2004-06-23 19:04:25 -07:00
@@ -41,7 +41,8 @@
  * Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-static inline unsigned int csum_and_copy_to_user (const char *src, char *dst,
+static inline unsigned int csum_and_copy_to_user (const char *src, 
+						  char __user *dst,
 						  int len, int sum,
 						  int *err_ptr)
 {
diff -Nru a/include/asm-mips/fcntl.h b/include/asm-mips/fcntl.h
--- a/include/asm-mips/fcntl.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-mips/fcntl.h	2004-06-23 19:04:28 -07:00
@@ -26,6 +26,7 @@
 #define O_DIRECT	0x8000	/* direct disk access hint */
 #define O_DIRECTORY	0x10000	/* must be a directory */
 #define O_NOFOLLOW	0x20000	/* don't follow links */
+#define O_NOATIME	0x40000
 
 #define O_NDELAY	O_NONBLOCK
 
diff -Nru a/include/asm-mips/resource.h b/include/asm-mips/resource.h
--- a/include/asm-mips/resource.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-mips/resource.h	2004-06-23 19:04:28 -07:00
@@ -23,8 +23,10 @@
 #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 11			/* Number of limit flavors.  */
+#define RLIM_NLIMITS 13			/* Number of limit flavors.  */
 
 #ifdef __KERNEL__
 
@@ -54,6 +56,8 @@
 	{ 0,             0             },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-parisc/checksum.h b/include/asm-parisc/checksum.h
--- a/include/asm-parisc/checksum.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-parisc/checksum.h	2004-06-23 19:04:25 -07:00
@@ -191,8 +191,10 @@
  *	Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
-				    int len, int sum, int *err_ptr)
+static __inline__ unsigned int csum_and_copy_to_user (const char *src, 
+						      char __user *dst,
+						      int len, int sum, 
+						      int *err_ptr)
 {
 	/* code stolen from include/asm-mips64 */
 	sum = csum_partial(src, len, sum);
diff -Nru a/include/asm-parisc/fcntl.h b/include/asm-parisc/fcntl.h
--- a/include/asm-parisc/fcntl.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-parisc/fcntl.h	2004-06-23 19:04:27 -07:00
@@ -19,6 +19,7 @@
 #define O_NOCTTY	00400000 /* not fcntl */
 #define O_DSYNC		01000000 /* HPUX only */
 #define O_RSYNC		02000000 /* HPUX only */
+#define O_NOATIME	04000000
 
 #define FASYNC		00020000 /* fcntl, for BSD compatibility */
 #define O_DIRECT	00040000 /* direct disk access hint - currently ignored */
diff -Nru a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
--- a/include/asm-parisc/pgtable.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-parisc/pgtable.h	2004-06-23 19:04:28 -07:00
@@ -417,6 +417,8 @@
 static inline int ptep_test_and_clear_young(pte_t *ptep)
 {
 #ifdef CONFIG_SMP
+	if (!pte_young(*ptep))
+		return 0;
 	return test_and_clear_bit(xlate_pabit(_PAGE_ACCESSED_BIT), ptep);
 #else
 	pte_t pte = *ptep;
@@ -430,6 +432,8 @@
 static inline int ptep_test_and_clear_dirty(pte_t *ptep)
 {
 #ifdef CONFIG_SMP
+	if (!pte_dirty(*ptep))
+		return 0;
 	return test_and_clear_bit(xlate_pabit(_PAGE_DIRTY_BIT), ptep);
 #else
 	pte_t pte = *ptep;
diff -Nru a/include/asm-parisc/resource.h b/include/asm-parisc/resource.h
--- a/include/asm-parisc/resource.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-parisc/resource.h	2004-06-23 19:04:27 -07:00
@@ -16,8 +16,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -40,6 +42,8 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/elf.h b/include/asm-ppc/elf.h
--- a/include/asm-ppc/elf.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc/elf.h	2004-06-23 19:04:25 -07:00
@@ -52,6 +52,7 @@
 #define ELF_NGREG	48	/* includes nip, msr, lr, etc. */
 #define ELF_NFPREG	33	/* includes fpscr */
 #define ELF_NVRREG	33	/* includes vscr */
+#define ELF_NEVRREG	34	/* includes acc (as 2) */
 
 /*
  * These are used to set parameters in the core dumps.
diff -Nru a/include/asm-ppc/fcntl.h b/include/asm-ppc/fcntl.h
--- a/include/asm-ppc/fcntl.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-ppc/fcntl.h	2004-06-23 19:04:27 -07:00
@@ -20,6 +20,7 @@
 #define O_NOFOLLOW      0100000	/* don't follow links */
 #define O_LARGEFILE     0200000
 #define O_DIRECT	0400000	/* direct disk access hint */
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-ppc/fsl_ocp.h b/include/asm-ppc/fsl_ocp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc/fsl_ocp.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,54 @@
+/*
+ * include/asm-ppc/fsl_ocp.h
+ *
+ * Definitions for the on-chip peripherals on Freescale PPC processors
+ *
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright 2004 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_FS_OCP_H__
+#define __ASM_FS_OCP_H__
+
+/* A table of information for supporting the Gianfar Ethernet Controller
+ * This helps identify which enet controller we are dealing with,
+ * and what type of enet controller it is
+ */
+struct ocp_gfar_data {
+	uint interruptTransmit;
+	uint interruptError;
+	uint interruptReceive;
+	uint interruptPHY;
+	uint flags;
+	uint phyid;
+	uint phyregidx;
+	unsigned char mac_addr[6];
+};
+
+/* Flags in the flags field */
+#define GFAR_HAS_COALESCE		0x20
+#define GFAR_HAS_RMON			0x10
+#define GFAR_HAS_MULTI_INTR		0x08
+#define GFAR_FIRM_SET_MACADDR		0x04
+#define GFAR_HAS_PHY_INTR		0x02	/* if not set use a timer */
+#define GFAR_HAS_GIGABIT		0x01
+
+/* Data structure for I2C support.  Just contains a couple flags
+ * to distinguish various I2C implementations*/
+struct ocp_fs_i2c_data {
+	uint flags;
+};
+
+/* Flags for I2C */
+#define FS_I2C_SEPARATE_DFSRR	0x02
+#define FS_I2C_32BIT		0x01
+
+#endif	/* __ASM_FS_OCP_H__ */
+#endif	/* __KERNEL__ */
diff -Nru a/include/asm-ppc/immap_85xx.h b/include/asm-ppc/immap_85xx.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc/immap_85xx.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,126 @@
+/*
+ * include/asm-ppc/immap_85xx.h
+ *
+ * MPC85xx Internal Memory Map
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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_IMMAP_85XX_H__
+#define __ASM_IMMAP_85XX_H__
+
+/* Eventually this should define all the IO block registers in 85xx */
+
+/* PCI Registers */
+typedef struct ccsr_pci {
+	uint	cfg_addr;	/* 0x.000 - PCI Configuration Address Register */
+	uint	cfg_data;	/* 0x.004 - PCI Configuration Data Register */
+	uint	int_ack;	/* 0x.008 - PCI Interrupt Acknowledge Register */
+	char	res1[3060];
+	uint	potar0;		/* 0x.c00 - PCI Outbound Transaction Address Register 0 */
+	uint	potear0;	/* 0x.c04 - PCI Outbound Translation Extended Address Register 0 */
+	uint	powbar0;	/* 0x.c08 - PCI Outbound Window Base Address Register 0 */
+	char	res2[4];
+	uint	powar0;		/* 0x.c10 - PCI Outbound Window Attributes Register 0 */
+	char	res3[12];
+	uint	potar1;		/* 0x.c20 - PCI Outbound Transaction Address Register 1 */
+	uint	potear1;	/* 0x.c24 - PCI Outbound Translation Extended Address Register 1 */
+	uint	powbar1;	/* 0x.c28 - PCI Outbound Window Base Address Register 1 */
+	char	res4[4];
+	uint	powar1;		/* 0x.c30 - PCI Outbound Window Attributes Register 1 */
+	char	res5[12];
+	uint	potar2;		/* 0x.c40 - PCI Outbound Transaction Address Register 2 */
+	uint	potear2;	/* 0x.c44 - PCI Outbound Translation Extended Address Register 2 */
+	uint	powbar2;	/* 0x.c48 - PCI Outbound Window Base Address Register 2 */
+	char	res6[4];
+	uint	powar2;		/* 0x.c50 - PCI Outbound Window Attributes Register 2 */
+	char	res7[12];
+	uint	potar3;		/* 0x.c60 - PCI Outbound Transaction Address Register 3 */
+	uint	potear3;	/* 0x.c64 - PCI Outbound Translation Extended Address Register 3 */
+	uint	powbar3;	/* 0x.c68 - PCI Outbound Window Base Address Register 3 */
+	char	res8[4];
+	uint	powar3;		/* 0x.c70 - PCI Outbound Window Attributes Register 3 */
+	char	res9[12];
+	uint	potar4;		/* 0x.c80 - PCI Outbound Transaction Address Register 4 */
+	uint	potear4;	/* 0x.c84 - PCI Outbound Translation Extended Address Register 4 */
+	uint	powbar4;	/* 0x.c88 - PCI Outbound Window Base Address Register 4 */
+	char	res10[4];
+	uint	powar4;		/* 0x.c90 - PCI Outbound Window Attributes Register 4 */
+	char	res11[268];
+	uint	pitar3;		/* 0x.da0 - PCI Inbound Translation Address Register 3  */
+	char	res12[4];
+	uint	piwbar3;	/* 0x.da8 - PCI Inbound Window Base Address Register 3 */
+	uint	piwbear3;	/* 0x.dac - PCI Inbound Window Base Extended Address Register 3 */
+	uint	piwar3;		/* 0x.db0 - PCI Inbound Window Attributes Register 3 */
+	char	res13[12];
+	uint	pitar2;		/* 0x.dc0 - PCI Inbound Translation Address Register 2  */
+	char	res14[4];
+	uint	piwbar2;	/* 0x.dc8 - PCI Inbound Window Base Address Register 2 */
+	uint	piwbear2;	/* 0x.dcc - PCI Inbound Window Base Extended Address Register 2 */
+	uint	piwar2;		/* 0x.dd0 - PCI Inbound Window Attributes Register 2 */
+	char	res15[12];
+	uint	pitar1;		/* 0x.de0 - PCI Inbound Translation Address Register 1  */
+	char	res16[4];
+	uint	piwbar1;	/* 0x.de8 - PCI Inbound Window Base Address Register 1 */
+	char	res17[4];
+	uint	piwar1;		/* 0x.df0 - PCI Inbound Window Attributes Register 1 */
+	char	res18[12];
+	uint	err_dr;		/* 0x.e00 - PCI Error Detect Register */
+	uint	err_cap_dr;	/* 0x.e04 - PCI Error Capture Disable Register */
+	uint	err_en;		/* 0x.e08 - PCI Error Enable Register */
+	uint	err_attrib;	/* 0x.e0c - PCI Error Attributes Capture Register */
+	uint	err_addr;	/* 0x.e10 - PCI Error Address Capture Register */
+	uint	err_ext_addr;	/* 0x.e14 - PCI Error Extended Address Capture Register */
+	uint	err_dl;		/* 0x.e18 - PCI Error Data Low Capture Register */
+	uint	err_dh;		/* 0x.e1c - PCI Error Data High Capture Register */
+	uint	gas_timr;	/* 0x.e20 - PCI Gasket Timer Register */
+	uint	pci_timr;	/* 0x.e24 - PCI Timer Register */
+	char	res19[472];
+} ccsr_pci_t;
+
+/* Global Utility Registers */
+typedef struct ccsr_guts {
+	uint	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
+	uint	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
+	uint	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
+	uint	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
+	uint	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
+	char	res1[12];
+	uint	gpporcr;	/* 0x.0020 - General-Purpose POR Configuration Register */
+	char	res2[12];
+	uint	gpiocr;		/* 0x.0030 - GPIO Control Register */
+	char	res3[12];
+	uint	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
+	char	res4[12];
+	uint	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
+	char	res5[12];
+	uint	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
+	char	res6[12];
+	uint	devdisr;	/* 0x.0070 - Device Disable Control */
+	char	res7[12];
+	uint	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
+	char	res8[12];
+	uint	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
+	char	res9[12];
+	uint	pvr;		/* 0x.00a0 - Processor Version Register */
+	uint	svr;		/* 0x.00a4 - System Version Register */
+	char	res10[3416];
+	uint	clkocr;		/* 0x.0e00 - Clock Out Select Register */
+	char	res11[12];
+	uint	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
+	char	res12[12];
+	uint	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
+	char	res13[61916];
+} ccsr_guts_t;
+
+#endif /* __ASM_IMMAP_85XX_H__ */
+#endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/io.h b/include/asm-ppc/io.h
--- a/include/asm-ppc/io.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ppc/io.h	2004-06-23 19:04:28 -07:00
@@ -30,6 +30,8 @@
 #include <asm/mpc8xx.h>
 #elif defined(CONFIG_8260)
 #include <asm/mpc8260.h>
+#elif defined(CONFIG_85xx)
+#include <asm/mpc85xx.h>
 #elif defined(CONFIG_APUS)
 #define _IO_BASE	0
 #define _ISA_MEM_BASE	0
diff -Nru a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
--- a/include/asm-ppc/mmu.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ppc/mmu.h	2004-06-23 19:04:28 -07:00
@@ -379,6 +379,74 @@
 #define PPC44x_TLB_SW		0x00000002      /* Super write */
 #define PPC44x_TLB_SR		0x00000001      /* Super read */
 
+/* Book-E defined page sizes */
+#define BOOKE_PAGESZ_1K		0
+#define BOOKE_PAGESZ_4K		1
+#define BOOKE_PAGESZ_16K	2
+#define BOOKE_PAGESZ_64K	3
+#define BOOKE_PAGESZ_256K	4
+#define BOOKE_PAGESZ_1M		5
+#define BOOKE_PAGESZ_4M		6
+#define BOOKE_PAGESZ_16M	7
+#define BOOKE_PAGESZ_64M	8
+#define BOOKE_PAGESZ_256M	9
+#define BOOKE_PAGESZ_1GB	10
+#define BOOKE_PAGESZ_4GB	11
+#define BOOKE_PAGESZ_16GB	12
+#define BOOKE_PAGESZ_64GB	13
+#define BOOKE_PAGESZ_256GB	14
+#define BOOKE_PAGESZ_1TB	15
+
+/*
+ * Freescale Book-E MMU support
+ */
+
+#define MAS0_TLBSEL	0x10000000
+#define MAS0_ESEL	0x000F0000
+#define MAS0_NV		0x00000001
+
+#define MAS1_VALID 	0x80000000
+#define MAS1_IPROT	0x40000000
+#define MAS1_TID 	0x03FF0000
+#define MAS1_TS		0x00001000
+#define MAS1_TSIZE(x)	(x << 8)
+
+#define MAS2_EPN	0xFFFFF000
+#define MAS2_SHAREN	0x00000200
+#define MAS2_X0		0x00000040
+#define MAS2_X1		0x00000020
+#define MAS2_W		0x00000010
+#define MAS2_I		0x00000008
+#define MAS2_M		0x00000004
+#define MAS2_G		0x00000002
+#define MAS2_E		0x00000001
+
+#define MAS3_RPN	0xFFFFF000
+#define MAS3_U0		0x00000200
+#define MAS3_U1		0x00000100
+#define MAS3_U2		0x00000080
+#define MAS3_U3		0x00000040
+#define MAS3_UX		0x00000020
+#define MAS3_SX		0x00000010
+#define MAS3_UW		0x00000008
+#define MAS3_SW		0x00000004
+#define MAS3_UR		0x00000002
+#define MAS3_SR		0x00000001
+
+#define MAS4_TLBSELD	0x10000000
+#define MAS4_TIDDSEL	0x00030000
+#define MAS4_DSHAREN	0x00001000
+#define MAS4_TSIZED(x)	(x << 8)
+#define MAS4_X0D	0x00000040
+#define MAS4_X1D	0x00000020
+#define MAS4_WD		0x00000010
+#define MAS4_ID		0x00000008
+#define MAS4_MD		0x00000004
+#define MAS4_GD		0x00000002
+#define MAS4_ED		0x00000001
+
+#define MAS6_SPID	0x00FF0000
+#define MAS6_SAS	0x00000001
 
 #endif /* _PPC_MMU_H_ */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h
--- a/include/asm-ppc/mmu_context.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-ppc/mmu_context.h	2004-06-23 19:04:27 -07:00
@@ -63,6 +63,11 @@
 #define LAST_CONTEXT    	255
 #define FIRST_CONTEXT    	1
 
+#elif CONFIG_E500
+#define NO_CONTEXT      	256
+#define LAST_CONTEXT    	255
+#define FIRST_CONTEXT    	1
+
 #else
 
 /* PPC 6xx, 7xx CPUs */
diff -Nru a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc/mpc85xx.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,128 @@
+/*
+ * include/asm-ppc/mpc85xx.h
+ *
+ * MPC85xx definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 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_MPC85xx_H__
+#define __ASM_MPC85xx_H__
+
+#include <linux/config.h>
+#include <asm/mmu.h>
+
+#ifdef CONFIG_85xx
+
+#ifdef CONFIG_MPC8540_ADS
+#include <platforms/85xx/mpc8540_ads.h>
+#endif
+
+#define _IO_BASE        isa_io_base
+#define _ISA_MEM_BASE   isa_mem_base
+#define PCI_DRAM_OFFSET pci_dram_offset
+
+/*
+ * The "residual" board information structure the boot loader passes
+ * into the kernel.
+ */
+extern unsigned char __res[];
+
+/* Internal IRQs on MPC85xx OpenPIC */
+/* Not all of these exist on all MPC85xx implementations */
+
+#ifndef MPC85xx_OPENPIC_IRQ_OFFSET
+#define MPC85xx_OPENPIC_IRQ_OFFSET	64
+#endif
+
+/* The 32 internal sources */
+#define MPC85xx_IRQ_L2CACHE	( 0 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_ECM		( 1 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DDR		( 2 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_LBIU	( 3 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA0	( 4 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA1	( 5 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA2	( 6 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA3	( 7 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PCI1	( 8 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PCI2	( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_ERROR	( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_BELL	(10 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_TX	(11 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_RX	(12 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_TX	(13 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_RX	(14 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_ERROR	(18 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_TX	(19 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_RX	(20 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_ERROR	(24 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_FEC		(25 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DUART	(26 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_IIC1	(27 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PERFMON	(28 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_CPM		(30 + MPC85xx_OPENPIC_IRQ_OFFSET)
+
+/* The 12 external interrupt lines */
+#define MPC85xx_IRQ_EXT0        (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT1        (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT2        (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT3        (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT4        (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT5        (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT6        (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT7        (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT8        (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT9        (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT10       (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT11       (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
+
+/* Offset from CCSRBAR */
+#define MPC85xx_CPM_OFFSET	(0x80000)
+#define MPC85xx_CPM_SIZE	(0x40000)
+#define MPC85xx_DMA_OFFSET	(0x21000)
+#define MPC85xx_DMA_SIZE	(0x01000)
+#define MPC85xx_ENET1_OFFSET	(0x24000)
+#define MPC85xx_ENET1_SIZE	(0x01000)
+#define MPC85xx_ENET2_OFFSET	(0x25000)
+#define MPC85xx_ENET2_SIZE	(0x01000)
+#define MPC85xx_ENET3_OFFSET	(0x26000)
+#define MPC85xx_ENET3_SIZE	(0x01000)
+#define MPC85xx_GUTS_OFFSET	(0xe0000)
+#define MPC85xx_GUTS_SIZE	(0x01000)
+#define MPC85xx_IIC1_OFFSET	(0x03000)
+#define MPC85xx_IIC1_SIZE	(0x01000)
+#define MPC85xx_OPENPIC_OFFSET	(0x40000)
+#define MPC85xx_OPENPIC_SIZE	(0x40000)
+#define MPC85xx_PCI1_OFFSET	(0x08000)
+#define MPC85xx_PCI1_SIZE	(0x01000)
+#define MPC85xx_PCI2_OFFSET	(0x09000)
+#define MPC85xx_PCI2_SIZE	(0x01000)
+#define MPC85xx_PERFMON_OFFSET	(0xe1000)
+#define MPC85xx_PERFMON_SIZE	(0x01000)
+#define MPC85xx_UART0_OFFSET	(0x04500)
+#define MPC85xx_UART0_SIZE	(0x00100)
+#define MPC85xx_UART1_OFFSET	(0x04600)
+#define MPC85xx_UART1_SIZE	(0x00100)
+
+#define MPC85xx_CCSRBAR_SIZE	(1024*1024)
+
+/* Let modules/drivers get at CCSRBAR */
+extern phys_addr_t get_ccsrbar(void);
+
+#ifdef MODULE
+#define CCSRBAR get_ccsrbar()
+#else
+#define CCSRBAR BOARD_CCSRBAR
+#endif
+
+#endif /* CONFIG_85xx */
+#endif /* __ASM_MPC85xx_H__ */
+#endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/ocp.h b/include/asm-ppc/ocp.h
--- a/include/asm-ppc/ocp.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ppc/ocp.h	2004-06-23 19:04:26 -07:00
@@ -202,6 +202,10 @@
 #include <asm/ibm_ocp.h>
 #endif
 
+#ifdef CONFIG_FSL_OCP
+#include <asm/fsl_ocp.h>
+#endif
+
 #endif				/* CONFIG_PPC_OCP */
 #endif				/* __OCP_H__ */
 #endif				/* __KERNEL__ */
diff -Nru a/include/asm-ppc/ocp_ids.h b/include/asm-ppc/ocp_ids.h
--- a/include/asm-ppc/ocp_ids.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ppc/ocp_ids.h	2004-06-23 19:04:28 -07:00
@@ -45,6 +45,7 @@
 
 /* Memory devices 0x0090 - 0x009F */
 #define OCP_FUNC_MAL		0x0090
+#define OCP_FUNC_DMA		0x0091
 
 /* Display 0x00A0 - 0x00AF */
 
@@ -62,7 +63,7 @@
 
 /* Network 0x0200 - 0x02FF */
 #define OCP_FUNC_EMAC		0x0200
-#define OCP_FUNC_ENET		0x0201	/* TSEC & FEC */
+#define OCP_FUNC_GFAR		0x0201	/* TSEC & FEC */
 
 /* Bridge devices 0xE00 - 0xEFF */
 #define OCP_FUNC_OPB		0x0E00
diff -Nru a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
--- a/include/asm-ppc/pgtable.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ppc/pgtable.h	2004-06-23 19:04:26 -07:00
@@ -222,6 +222,43 @@
 /* ERPN in a PTE never gets cleared, ignore it */
 #define _PTE_NONE_MASK	0xffffffff00000000ULL
 
+#elif defined(CONFIG_E500)
+
+/*
+   MMU Assist Register 3:
+
+   32 33 34 35 36  ... 50 51 52 53 54 55 56 57 58 59 60 61 62 63
+   RPN......................  0  0 U0 U1 U2 U3 UX SX UW SW UR SR
+
+   - PRESENT *must* be in the bottom three bits because swap cache
+     entries use the top 29 bits.
+
+   - FILE *must* be in the bottom three bits because swap cache
+     entries use the top 29 bits.
+*/
+
+/* Definitions for e500 core */
+#define _PAGE_PRESENT	0x001	/* S: PTE contains a translation */
+#define _PAGE_USER	0x002	/* S: User page (maps to UR) */
+#define _PAGE_FILE	0x002	/* S: when !present: nonlinear file mapping */
+#define _PAGE_ACCESSED	0x004	/* S: Page referenced */
+#define _PAGE_HWWRITE	0x008	/* H: Dirty & RW, set in exception */
+#define _PAGE_RW	0x010	/* S: Write permission */
+#define _PAGE_HWEXEC	0x020	/* H: UX permission */
+
+#define _PAGE_ENDIAN	0x040	/* H: E bit */
+#define _PAGE_GUARDED	0x080	/* H: G bit */
+#define _PAGE_COHERENT	0x100	/* H: M bit */
+#define _PAGE_NO_CACHE	0x200	/* H: I bit */
+#define _PAGE_WRITETHRU	0x400	/* H: W bit */
+#define _PAGE_DIRTY	0x800	/* S: Page dirty */
+
+#define _PMD_PRESENT	0
+#define _PMD_PRESENT_MASK (PAGE_MASK)
+#define _PMD_BAD	(~PAGE_MASK)
+
+#define NUM_TLBCAMS	(16)
+
 #elif defined(CONFIG_8xx)
 /* Definitions for 8xx embedded chips. */
 #define _PAGE_PRESENT	0x0001	/* Page is valid */
diff -Nru a/include/asm-ppc/pmac_feature.h b/include/asm-ppc/pmac_feature.h
--- a/include/asm-ppc/pmac_feature.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc/pmac_feature.h	2004-06-23 19:04:25 -07:00
@@ -273,6 +273,12 @@
  */
 #define PMAC_FTR_ENABLE_MPIC		PMAC_FTR_DEF(19)
 
+/* PMAC_FTR_AACK_DELAY_ENABLE	(NULL, int enable, 0)
+ *
+ * Enable/disable the AACK delay on the northbridge for systems using DFS
+ */
+#define PMAC_FTR_AACK_DELAY_ENABLE     	PMAC_FTR_DEF(20)
+
 
 /* Don't use those directly, they are for the sake of pmac_setup.c */
 extern long pmac_do_feature_call(unsigned int selector, ...);
diff -Nru a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h
--- a/include/asm-ppc/ppc_asm.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc/ppc_asm.h	2004-06-23 19:04:25 -07:00
@@ -59,6 +59,20 @@
 #define REST_16VR(n,b,base)	REST_8VR(n,b,base); REST_8VR(n+8,b,base)
 #define REST_32VR(n,b,base)	REST_16VR(n,b,base); REST_16VR(n+16,b,base)
 
+#define SAVE_EVR(n,s,base)	evmergehi s,s,n; stw s,THREAD_EVR0+4*(n)(base)
+#define SAVE_2EVR(n,s,base)	SAVE_EVR(n,s,base); SAVE_EVR(n+1,s,base)
+#define SAVE_4EVR(n,s,base)	SAVE_2EVR(n,s,base); SAVE_2EVR(n+2,s,base)
+#define SAVE_8EVR(n,s,base)	SAVE_4EVR(n,s,base); SAVE_4EVR(n+4,s,base)
+#define SAVE_16EVR(n,s,base)	SAVE_8EVR(n,s,base); SAVE_8EVR(n+8,s,base)
+#define SAVE_32EVR(n,s,base)	SAVE_16EVR(n,s,base); SAVE_16EVR(n+16,s,base)
+
+#define REST_EVR(n,s,base)	lwz s,THREAD_EVR0+4*(n)(base); evmergelo n,s,n
+#define REST_2EVR(n,s,base)	REST_EVR(n,s,base); REST_EVR(n+1,s,base)
+#define REST_4EVR(n,s,base)	REST_2EVR(n,s,base); REST_2EVR(n+2,s,base)
+#define REST_8EVR(n,s,base)	REST_4EVR(n,s,base); REST_4EVR(n+4,s,base)
+#define REST_16EVR(n,s,base)	REST_8EVR(n,s,base); REST_8EVR(n+8,s,base)
+#define REST_32EVR(n,s,base)	REST_16EVR(n,s,base); REST_16EVR(n+16,s,base)
+
 #ifdef CONFIG_PPC601_SYNC_FIX
 #define SYNC				\
 BEGIN_FTR_SECTION			\
@@ -107,7 +121,14 @@
 	bdnz	0b
 #endif
 
-#if !defined(CONFIG_44x)
+#ifdef CONFIG_BOOKE
+#define tophys(rd,rs)				\
+	addis	rd,rs,0
+
+#define tovirt(rd,rs)				\
+	addis	rd,rs,0
+
+#else  /* CONFIG_BOOKE */
 /*
  * On APUS (Amiga PowerPC cpu upgrade board), we don't know the
  * physical base address of RAM at compile time.
@@ -125,15 +146,7 @@
 	.align  1;				\
 	.long   0b;				\
 	.previous
-#else  /* CONFIG_44x */
-
-#define tophys(rd,rs)				\
-	mr	rd,rs
-
-#define tovirt(rd,rs)				\
-	mr	rd,rs
-
-#endif /* CONFIG_44x */
+#endif  /* CONFIG_BOOKE */
 
 /*
  * On 64-bit cpus, we use the rfid instruction instead of rfi, but
@@ -288,6 +301,39 @@
 #define	vr29	29
 #define	vr30	30
 #define	vr31	31
+
+#define	evr0	0
+#define	evr1	1
+#define	evr2	2
+#define	evr3	3
+#define	evr4	4
+#define	evr5	5
+#define	evr6	6
+#define	evr7	7
+#define	evr8	8
+#define	evr9	9
+#define	evr10	10
+#define	evr11	11
+#define	evr12	12
+#define	evr13	13
+#define	evr14	14
+#define	evr15	15
+#define	evr16	16
+#define	evr17	17
+#define	evr18	18
+#define	evr19	19
+#define	evr20	20
+#define	evr21	21
+#define	evr22	22
+#define	evr23	23
+#define	evr24	24
+#define	evr25	25
+#define	evr26	26
+#define	evr27	27
+#define	evr28	28
+#define	evr29	29
+#define	evr30	30
+#define	evr31	31
 
 /* some stab codes */
 #define N_FUN	36
diff -Nru a/include/asm-ppc/ppcboot.h b/include/asm-ppc/ppcboot.h
--- a/include/asm-ppc/ppcboot.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ppc/ppcboot.h	2004-06-23 19:04:28 -07:00
@@ -52,7 +52,7 @@
 	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_8260)
+#if defined(CONFIG_8xx) || defined(CONFIG_8260) || defined(CONFIG_85xx)
 	unsigned long	bi_immr_base;	/* base of IMMR register */
 #endif
 	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS) */
@@ -79,7 +79,7 @@
 #if defined(CONFIG_HYMOD)
 	hymod_conf_t	bi_hymod_conf;	/* hymod configuration information */
 #endif
-#if defined(CONFIG_EVB64260)
+#if defined(CONFIG_EVB64260) || defined(CONFIG_85xx)
 	/* the board has three onboard ethernet ports */
 	unsigned char	bi_enet1addr[6];
 	unsigned char	bi_enet2addr[6];
diff -Nru a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h
--- a/include/asm-ppc/processor.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc/processor.h	2004-06-23 19:04:25 -07:00
@@ -40,6 +40,14 @@
 	.globl n;\
 n:
 
+/*
+ * this is the minimum allowable io space due to the location
+ * of the io areas on prep (first one at 0x80000000) but
+ * as soon as I get around to remapping the io areas with the BATs
+ * to match the mac we can raise this. -- Cort
+ */
+#define TASK_SIZE	(CONFIG_TASK_SIZE)
+
 #ifndef __ASSEMBLY__
 #ifdef CONFIG_PPC_MULTIPLATFORM
 extern int _machine;
@@ -79,14 +87,7 @@
 /* Lazy FPU handling on uni-processor */
 extern struct task_struct *last_task_used_math;
 extern struct task_struct *last_task_used_altivec;
-
-/*
- * this is the minimum allowable io space due to the location
- * of the io areas on prep (first one at 0x80000000) but
- * as soon as I get around to remapping the io areas with the BATs
- * to match the mac we can raise this. -- Cort
- */
-#define TASK_SIZE	(CONFIG_TASK_SIZE)
+extern struct task_struct *last_task_used_spe;
 
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
@@ -104,7 +105,7 @@
 	void		*pgdir;		/* root of page-table tree */
 	int		fpexc_mode;	/* floating-point exception mode */
 	signed long	last_syscall;
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) || defined (CONFIG_BOOKE)
 	unsigned long	dbcr0;		/* debug control register values */
 	unsigned long	dbcr1;
 #endif
@@ -119,6 +120,12 @@
 	unsigned long	vrsave;
 	int		used_vr;	/* set if process has used altivec */
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+	unsigned long	evr[32];	/* upper 32-bits of SPE regs */
+	u64		acc;		/* Accumulator */
+	unsigned long	spefscr;	/* SPE & eFP status */
+	int		used_spe;	/* set if process has used spe */
+#endif /* CONFIG_SPE */
 };
 
 #define ARCH_MIN_TASKALIGN 16
@@ -189,6 +196,8 @@
 }
 
 #define spin_lock_prefetch(x)	prefetchw(x)
+
+extern int emulate_altivec(struct pt_regs *regs);
 
 #endif /* !__ASSEMBLY__ */
 
diff -Nru a/include/asm-ppc/ptrace.h b/include/asm-ppc/ptrace.h
--- a/include/asm-ppc/ptrace.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-ppc/ptrace.h	2004-06-23 19:04:27 -07:00
@@ -131,4 +131,9 @@
 #define PTRACE_GETVRREGS	18
 #define PTRACE_SETVRREGS	19
 
+/* Get/set all the upper 32-bits of the SPE registers, accumulator, and
+ * spefscr, in one go */
+#define PTRACE_GETEVRREGS	20
+#define PTRACE_SETEVRREGS	21
+
 #endif
diff -Nru a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h
--- a/include/asm-ppc/reg.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ppc/reg.h	2004-06-23 19:04:28 -07:00
@@ -174,6 +174,7 @@
 
 #define SPRN_HID1	0x3F1		/* Hardware Implementation Register 1 */
 #define HID1_EMCP	(1<<31)		/* 7450 Machine Check Pin Enable */
+#define HID1_DFS	(1<<22)		/* 7447A Dynamic Frequency Scaling */
 #define HID1_PC0	(1<<16)		/* 7450 PLL_CFG[0] */
 #define HID1_PC1	(1<<15)		/* 7450 PLL_CFG[1] */
 #define HID1_PC2	(1<<14)		/* 7450 PLL_CFG[2] */
@@ -294,6 +295,9 @@
 #define SPRN_SPRG7	0x117	/* Special Purpose Register General 7 */
 #define SPRN_SRR0	0x01A	/* Save/Restore Register 0 */
 #define SPRN_SRR1	0x01B	/* Save/Restore Register 1 */
+#ifndef SPRN_SVR
+#define SPRN_SVR	0x11E	/* System Version Register */
+#endif
 #define SPRN_THRM1	0x3FC		/* Thermal Management Register 1 */
 /* these bits were defined in inverted endian sense originally, ugh, confusing */
 #define THRM1_TIN	(1 << 31)
@@ -400,6 +404,7 @@
 #define SRR1	SPRN_SRR1	/* Save and Restore Register 1 */
 #define SRR2	SPRN_SRR2	/* Save and Restore Register 2 */
 #define SRR3	SPRN_SRR3	/* Save and Restore Register 3 */
+#define SVR	SPRN_SVR	/* System Version Register */
 #define ICTC	SPRN_ICTC	/* Instruction Cache Throttling Control Reg */
 #define THRM1	SPRN_THRM1	/* Thermal Management Register 1 */
 #define THRM2	SPRN_THRM2	/* Thermal Management Register 2 */
@@ -462,6 +467,8 @@
 #define PVR_7400	0x000C0000
 #define PVR_7410	0x800C0000
 #define PVR_7450	0x80000000
+#define PVR_8540	0x80200000
+#define PVR_8560	0x80200000
 /*
  * For the 8xx processors, all of them report the same PVR family for
  * the PowerPC core. The various versions of these processors must be
@@ -475,6 +482,12 @@
 #define PVR_8240	0x00810100
 #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
 
 /* Segment Registers */
 #define SR0	0
diff -Nru a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
--- a/include/asm-ppc/reg_booke.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ppc/reg_booke.h	2004-06-23 19:04:28 -07:00
@@ -43,13 +43,23 @@
 	mtdcr(base ## _CFGADDR, base ## _ ## reg);	\
 	mtdcr(base ## _CFGDATA, data);		\
 } while (0)
+
+/* Performance Monitor Registers */
+#define mfpmr(rn)	({unsigned int rval; \
+			asm volatile("mfpmr %0," __stringify(rn) \
+				     : "=r" (rval)); rval;})
+#define mtpmr(rn, v)	asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v))
 #endif /* __ASSEMBLY__ */
 
 
 /* Machine State Register (MSR) Fields */
+#define MSR_UCLE	(1<<26)	/* User-mode cache lock enable */
+#define MSR_SPE		(1<<25)	/* Enable SPE */
 #define MSR_DWE		(1<<10)	/* Debug Wait Enable */
+#define MSR_UBLE	(1<<10)	/* BTB lock enable (e500) */
 #define MSR_IS		MSR_IR	/* Instruction Space */
 #define MSR_DS		MSR_DR	/* Data Space */
+#define MSR_PMM		(1<<2)	/* Performance monitor mark bit */
 
 /* Default MSR for kernel mode. */
 #if defined (CONFIG_40x)
@@ -91,20 +101,28 @@
 #define SPRN_IVOR13	0x19D	/* Interrupt Vector Offset Register 13 */
 #define SPRN_IVOR14	0x19E	/* Interrupt Vector Offset Register 14 */
 #define SPRN_IVOR15	0x19F	/* Interrupt Vector Offset Register 15 */
+#define SPRN_SPEFSCR	0x200	/* SPE & Embedded FP Status & Control */
+#define SPRN_BBEAR	0x201	/* Branch Buffer Entry Address Register */
+#define SPRN_BBTAR	0x202	/* Branch Buffer Target Address Register */
+#define SPRN_IVOR32	0x210	/* Interrupt Vector Offset Register 32 */
+#define SPRN_IVOR33	0x211	/* Interrupt Vector Offset Register 33 */
+#define SPRN_IVOR34	0x212	/* Interrupt Vector Offset Register 34 */
+#define SPRN_IVOR35	0x213	/* Interrupt Vector Offset Register 35 */
 #define SPRN_MCSRR0	0x23A	/* Machine Check Save and Restore Register 0 */
 #define SPRN_MCSRR1	0x23B	/* Machine Check Save and Restore Register 1 */
 #define SPRN_MCSR	0x23C	/* Machine Check Status Register */
-#ifdef CONFIG_440A
-#define  MCSR_MCS	0x80000000 /* Machine Check Summary */
-#define  MCSR_IB	0x40000000 /* Instruction PLB Error */
-#define  MCSR_DRB	0x20000000 /* Data Read PLB Error */
-#define  MCSR_DWB	0x10000000 /* Data Write PLB Error */
-#define  MCSR_TLBP	0x08000000 /* TLB Parity Error */
-#define  MCSR_ICP	0x04000000 /* I-Cache Parity Error */
-#define  MCSR_DCSP	0x02000000 /* D-Cache Search Parity Error */
-#define  MCSR_DCFP	0x01000000 /* D-Cache Flush Parity Error */
-#define  MCSR_IMPE	0x00800000 /* Imprecise Machine Check Exception */
-#endif
+#define SPRN_MCAR	0x23D	/* Machine Check Address Register */
+#define SPRN_MAS0	0x270	/* MMU Assist Register 0 */
+#define SPRN_MAS1	0x271	/* MMU Assist Register 1 */
+#define SPRN_MAS2	0x272	/* MMU Assist Register 2 */
+#define SPRN_MAS3	0x273	/* MMU Assist Register 3 */
+#define SPRN_MAS4	0x274	/* MMU Assist Register 4 */
+#define SPRN_MAS5	0x275	/* MMU Assist Register 5 */
+#define SPRN_MAS6	0x276	/* MMU Assist Register 6 */
+#define SPRN_PID1	0x279	/* Process ID Register 1 */
+#define SPRN_PID2	0x27A	/* Process ID Register 2 */
+#define SPRN_TLB0CFG	0x2B0	/* TLB 0 Config Register */
+#define SPRN_TLB1CFG	0x2B1	/* TLB 1 Config Register */
 #define SPRN_ZPR	0x3B0	/* Zone Protection Register (40x) */
 #define SPRN_MMUCR	0x3B2	/* MMU Control Register */
 #define SPRN_CCR0	0x3B3	/* Core Configuration Register */
@@ -115,9 +133,12 @@
 #define SPRN_DCMP	0x3D1	/* Data TLB Compare Register */
 #define SPRN_ICDBDR	0x3D3	/* Instruction Cache Debug Data Register */
 #define SPRN_EVPR	0x3D6	/* Exception Vector Prefix Register */
+#define SPRN_L1CSR0	0x3F2	/* L1 Cache Control and Status Register 0 */
+#define SPRN_L1CSR1	0x3F3	/* L1 Cache Control and Status Register 1 */
 #define SPRN_PIT	0x3DB	/* Programmable Interval Timer */
 #define SPRN_DCCR	0x3FA	/* Data Cache Cacheability Register */
 #define SPRN_ICCR	0x3FB	/* Instruction Cache Cacheability Register */
+#define SPRN_SVR	0x3FF	/* System Version Register */
 
 /*
  * SPRs which have conflicting definitions on true Book E versus classic,
@@ -125,6 +146,7 @@
  */
 #ifdef CONFIG_BOOKE
 #define SPRN_PID	0x030	/* Process ID */
+#define SPRN_PID0	SPRN_PID/* Process ID Register 0 */
 #define SPRN_CSRR0	0x03A	/* Critical Save and Restore Register 0 */
 #define SPRN_CSRR1	0x03B	/* Critical Save and Restore Register 1 */
 #define SPRN_DEAR	0x03D	/* Data Error Address Register */
@@ -157,6 +179,34 @@
 #define SPRN_CSRR1	SPRN_SRR3 /* Critical Save and Restore Register 1 */
 #endif
 
+/* Bit definitions for the MCSR. */
+#ifdef CONFIG_440A
+#define MCSR_MCS	0x80000000 /* Machine Check Summary */
+#define MCSR_IB		0x40000000 /* Instruction PLB Error */
+#define MCSR_DRB	0x20000000 /* Data Read PLB Error */
+#define MCSR_DWB	0x10000000 /* Data Write PLB Error */
+#define MCSR_TLBP	0x08000000 /* TLB Parity Error */
+#define MCSR_ICP	0x04000000 /* I-Cache Parity Error */
+#define MCSR_DCSP	0x02000000 /* D-Cache Search Parity Error */
+#define MCSR_DCFP	0x01000000 /* D-Cache Flush Parity Error */
+#define MCSR_IMPE	0x00800000 /* Imprecise Machine Check Exception */
+#endif
+#ifdef CONFIG_E500
+#define MCSR_MCP 	0x80000000UL /* Machine Check Input Pin */
+#define MCSR_ICPERR 	0x40000000UL /* I-Cache Parity Error */
+#define MCSR_DCP_PERR 	0x20000000UL /* D-Cache Push Parity Error */
+#define MCSR_DCPERR 	0x10000000UL /* D-Cache Parity Error */
+#define MCSR_GL_CI 	0x00010000UL /* Guarded Load or Cache-Inhibited stwcx. */
+#define MCSR_BUS_IAERR 	0x00000080UL /* Instruction Address Error */
+#define MCSR_BUS_RAERR 	0x00000040UL /* Read Address Error */
+#define MCSR_BUS_WAERR 	0x00000020UL /* Write Address Error */
+#define MCSR_BUS_IBERR 	0x00000010UL /* Instruction Data Error */
+#define MCSR_BUS_RBERR 	0x00000008UL /* Read Data Bus Error */
+#define MCSR_BUS_WBERR 	0x00000004UL /* Write Data Bus Error */
+#define MCSR_BUS_IPERR 	0x00000002UL /* Instruction parity Error */
+#define MCSR_BUS_RPERR 	0x00000001UL /* Read parity Error */
+#endif
+
 /* Bit definitions for the DBSR. */
 /*
  * DBSR bits which have conflicting definitions on true Book E versus IBM 40x.
@@ -165,11 +215,27 @@
 #define DBSR_IC		0x08000000	/* Instruction Completion */
 #define DBSR_BT		0x04000000	/* Branch Taken */
 #define DBSR_TIE	0x01000000	/* Trap Instruction Event */
+#define DBSR_IAC1	0x00800000	/* Instr Address Compare 1 Event */
+#define DBSR_IAC2	0x00400000	/* Instr Address Compare 2 Event */
+#define DBSR_IAC3	0x00200000	/* Instr Address Compare 3 Event */
+#define DBSR_IAC4	0x00100000	/* Instr Address Compare 4 Event */
+#define DBSR_DAC1R	0x00080000	/* Data Addr Compare 1 Read Event */
+#define DBSR_DAC1W	0x00040000	/* Data Addr Compare 1 Write Event */
+#define DBSR_DAC2R	0x00020000	/* Data Addr Compare 2 Read Event */
+#define DBSR_DAC2W	0x00010000	/* Data Addr Compare 2 Write Event */
 #endif
 #ifdef CONFIG_40x
 #define DBSR_IC		0x80000000	/* Instruction Completion */
 #define DBSR_BT		0x40000000	/* Branch taken */
 #define DBSR_TIE	0x10000000	/* Trap Instruction debug Event */
+#define DBSR_IAC1	0x00800000	/* Instruction Address Compare 1 Event */
+#define DBSR_IAC2	0x00400000	/* Instruction Address Compare 2 Event */
+#define DBSR_IAC3	0x00200000	/* Instruction Address Compare 3 Event */
+#define DBSR_IAC4	0x00100000	/* Instruction Address Compare 4 Event */
+#define DBSR_DAC1R	0x00080000	/* Data Address Compare 1 Read Event */
+#define DBSR_DAC1W	0x00040000	/* Data Address Compare 1 Write Event */
+#define DBSR_DAC2R	0x00020000	/* Data Address Compare 2 Read Event */
+#define DBSR_DAC2W	0x00010000	/* Data Address Compare 2 Write Event */
 #endif
 
 /* Bit definitions related to the ESR. */
@@ -184,6 +250,9 @@
 #define ESR_DST		0x00800000	/* Storage Exception - Data miss */
 #define ESR_DIZ		0x00400000	/* Storage Exception - Zone fault */
 #define ESR_ST		0x00800000	/* Store Operation */
+#define ESR_DLK		0x00200000	/* Data Cache Locking */
+#define ESR_ILK		0x00100000	/* Instr. Cache Locking */
+#define ESR_BO		0x00020000	/* Byte Ordering */
 
 /* Bit definitions related to the DBCR0. */
 #define DBCR0_EDM	0x80000000	/* External Debug Mode */
@@ -258,9 +327,48 @@
 #define ICCR_NOCACHE	0		/* Noncacheable */
 #define ICCR_CACHE	1		/* Cacheable */
 
+/* Bit definitions for L1CSR0. */
+#define L1CSR0_DCFI	0x00000002	/* Data Cache Flash Invalidate */
+#define L1CSR0_DCE	0x00000001	/* Data Cache Enable */
+
+/* Bit definitions for L1CSR0. */
+#define L1CSR1_ICLFR	0x00000100	/* Instr Cache Lock Bits Flash Reset */
+#define L1CSR1_ICFI	0x00000002	/* Instr Cache Flash Invalidate */
+#define L1CSR1_ICE	0x00000001	/* Instr Cache Enable */
+
 /* Bit definitions for SGR. */
 #define SGR_NORMAL	0		/* Speculative fetching allowed. */
 #define SGR_GUARDED	1		/* Speculative fetching disallowed. */
+
+/* Bit definitions for SPEFSCR. */
+#define SPEFSCR_SOVH	0x80000000	/* Summary integer overflow high */
+#define SPEFSCR_OVH	0x40000000	/* Integer overflow high */
+#define SPEFSCR_FGH	0x20000000	/* Embedded FP guard bit high */
+#define SPEFSCR_FXH	0x10000000	/* Embedded FP sticky bit high */
+#define SPEFSCR_FINVH	0x08000000	/* Embedded FP invalid operation high */
+#define SPEFSCR_FDBZH	0x04000000	/* Embedded FP div by zero high */
+#define SPEFSCR_FUNFH	0x02000000	/* Embedded FP underflow high */
+#define SPEFSCR_FOVFH	0x01000000	/* Embedded FP overflow high */
+#define SPEFSCR_FINXS	0x00200000	/* Embedded FP inexact sticky */
+#define SPEFSCR_FINVS	0x00100000	/* Embedded FP invalid op. sticky */
+#define SPEFSCR_FDBZS	0x00080000	/* Embedded FP div by zero sticky */
+#define SPEFSCR_FUNFS	0x00040000	/* Embedded FP underflow sticky */
+#define SPEFSCR_FOVFS	0x00020000	/* Embedded FP overflow sticky */
+#define SPEFSCR_MODE	0x00010000	/* Embedded FP mode */
+#define SPEFSCR_SOV	0x00008000	/* Integer summary overflow */
+#define SPEFSCR_OV	0x00004000	/* Integer overflow */
+#define SPEFSCR_FG	0x00002000	/* Embedded FP guard bit */
+#define SPEFSCR_FX	0x00001000	/* Embedded FP sticky bit */
+#define SPEFSCR_FINV	0x00000800	/* Embedded FP invalid operation */
+#define SPEFSCR_FDBZ	0x00000400	/* Embedded FP div by zero */
+#define SPEFSCR_FUNF	0x00000200	/* Embedded FP underflow */
+#define SPEFSCR_FOVF	0x00000100	/* Embedded FP overflow */
+#define SPEFSCR_FINXE	0x00000040	/* Embedded FP inexact enable */
+#define SPEFSCR_FINVE	0x00000020	/* Embedded FP invalid op. enable */
+#define SPEFSCR_FDBZE	0x00000010	/* Embedded FP div by zero enable */
+#define SPEFSCR_FUNFE	0x00000008	/* Embedded FP underflow enable */
+#define SPEFSCR_FOVFE	0x00000004	/* Embedded FP overflow enable */
+#define SPEFSCR_FRMC 	0x00000003	/* Embedded FP rounding mode control */
 
 /* Short-hand for various SPRs. */
 #ifdef CONFIG_BOOKE
diff -Nru a/include/asm-ppc/resource.h b/include/asm-ppc/resource.h
--- a/include/asm-ppc/resource.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ppc/resource.h	2004-06-23 19:04:26 -07:00
@@ -12,8 +12,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 #ifdef __KERNEL__
 
@@ -37,6 +39,8 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
--- a/include/asm-ppc/serial.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ppc/serial.h	2004-06-23 19:04:28 -07:00
@@ -30,6 +30,8 @@
 #include <platforms/spruce.h>
 #elif defined(CONFIG_4xx)
 #include <asm/ibm4xx.h>
+#elif defined(CONFIG_85xx)
+#include <asm/mpc85xx.h>
 #else
 
 /*
diff -Nru a/include/asm-ppc/system.h b/include/asm-ppc/system.h
--- a/include/asm-ppc/system.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ppc/system.h	2004-06-23 19:04:26 -07:00
@@ -76,6 +76,8 @@
 extern void enable_kernel_fp(void);
 extern void giveup_altivec(struct task_struct *);
 extern void load_up_altivec(struct task_struct *);
+extern void giveup_spe(struct task_struct *);
+extern void load_up_spe(struct task_struct *);
 extern int fix_alignment(struct pt_regs *);
 extern void cvt_fd(float *from, double *to, unsigned long *fpscr);
 extern void cvt_df(double *from, float *to, unsigned long *fpscr);
diff -Nru a/include/asm-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h
--- a/include/asm-ppc/tlbflush.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc/tlbflush.h	2004-06-23 19:04:25 -07:00
@@ -39,6 +39,28 @@
 				unsigned long end)
 	{ __tlbia(); }
 
+#elif defined(CONFIG_FSL_BOOKE)
+
+/* TODO: determine if flush_tlb_range & flush_tlb_kernel_range
+ * are best implemented as tlbia vs specific tlbie's */
+
+#define __tlbia()	_tlbia()
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+	{ __tlbia(); }
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+				unsigned long vmaddr)
+	{ _tlbie(vmaddr); }
+static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
+					 unsigned long vmaddr)
+	{ _tlbie(vmaddr); }
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				unsigned long start, unsigned long end)
+	{ __tlbia(); }
+static inline void flush_tlb_kernel_range(unsigned long start,
+				unsigned long end)
+	{ __tlbia(); }
+
 #elif defined(CONFIG_8xx)
 #define __tlbia()	asm volatile ("tlbia; sync" : : : "memory")
 
diff -Nru a/include/asm-ppc/uninorth.h b/include/asm-ppc/uninorth.h
--- a/include/asm-ppc/uninorth.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ppc/uninorth.h	2004-06-23 19:04:28 -07:00
@@ -142,6 +142,12 @@
  */
 #define UNI_N_HWINIT_STATE_CPU1_FLAG	0x10000000
 
+/* This register controls AACK delay, which is set when 2004 iBook/PowerBook
+ * is in low speed mode.
+ */
+#define UNI_N_AACK_DELAY		0x0100
+#define UNI_N_AACK_DELAY_ENABLE		0x00000001
+
 /* Uninorth 1.5 rev. has additional perf. monitor registers at 0xf00-0xf50 */
 
 
diff -Nru a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h
--- a/include/asm-ppc64/eeh.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-ppc64/eeh.h	2004-06-23 19:04:28 -07:00
@@ -55,6 +55,7 @@
  * device (including config space i/o).  Call eeh_add_device_late
  * to finish the eeh setup for this device.
  */
+struct device_node;
 void eeh_add_device_early(struct device_node *);
 void eeh_add_device_late(struct pci_dev *);
 
diff -Nru a/include/asm-ppc64/fcntl.h b/include/asm-ppc64/fcntl.h
--- a/include/asm-ppc64/fcntl.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc64/fcntl.h	2004-06-23 19:04:25 -07:00
@@ -27,6 +27,7 @@
 #define O_NOFOLLOW      0100000	/* don't follow links */
 #define O_LARGEFILE     0200000
 #define O_DIRECT	0400000	/* direct disk access hint */
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h
--- a/include/asm-ppc64/hardirq.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc64/hardirq.h	2004-06-23 19:04:25 -07:00
@@ -82,9 +82,11 @@
 
 #ifdef CONFIG_PREEMPT
 # define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
+# define preemptible()	(preempt_count() == 0 && !irqs_disabled())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
 # define in_atomic()	(preempt_count() != 0)
+# define preemptible()	0
 # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
 #endif
 #define irq_exit()							\
diff -Nru a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h
--- a/include/asm-ppc64/paca.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ppc64/paca.h	2004-06-23 19:04:26 -07:00
@@ -136,23 +136,21 @@
 	u8  rsvd6[0x500 - 0x8];
 
 /*=====================================================================================
- * CACHE_LINE_31 0x0F00 - 0x0F7F Exception stack
+ * CACHE_LINE_31-32 0x0F00 - 0x0FFF Exception register save areas
  *=====================================================================================
  */
-	u8 exception_stack[N_EXC_STACK*EXC_FRAME_SIZE];
+	u64 exgen[8];		/* used for most interrupts/exceptions */
+	u64 exmc[8];		/* used for machine checks */
+	u64 exslb[8];		/* used for SLB/segment table misses
+				 * on the linear mapping */
+	u64 exdsi[8];		/* used for linear mapping hash table misses */
 
 /*=====================================================================================
- * CACHE_LINE_32 0x0F80 - 0x0FFF Reserved
+ * Page 2 used as a stack when we detect a bad kernel stack pointer,
+ * and early in SMP boots before relocation is enabled.
  *=====================================================================================
  */
-	u8 rsvd7[0x80];                  /* Give the stack some rope ... */
-
-/*=====================================================================================
- * Page 2 Reserved for guard page.  Also used as a stack early in SMP boots before
- *        relocation is enabled.
- *=====================================================================================
- */
-	u8 guard[0x1000];               /* ... and then hang 'em         */ 
+	u8 guard[0x1000];
 };
 
 #endif /* _PPC64_PACA_H */
diff -Nru a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h
--- a/include/asm-ppc64/pgalloc.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc64/pgalloc.h	2004-06-23 19:04:25 -07:00
@@ -101,33 +101,7 @@
 
 DECLARE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
 
-static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage)
-{
-	/* This is safe as we are holding page_table_lock */
-        cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
-	struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
-
-	if (atomic_read(&tlb->mm->mm_users) < 2 ||
-	    cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
-		pte_free(ptepage);
-		return;
-	}
-
-	if (*batchp == NULL) {
-		*batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);
-		if (*batchp == NULL) {
-			pte_free_now(ptepage);
-			return;
-		}
-		(*batchp)->index = 0;
-	}
-	(*batchp)->pages[(*batchp)->index++] = ptepage;
-	if ((*batchp)->index == PTE_FREELIST_SIZE) {
-		pte_free_submit(*batchp);
-		*batchp = NULL;
-	}
-}
-
+void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage);
 #define __pmd_free_tlb(tlb, pmd)	__pte_free_tlb(tlb, virt_to_page(pmd))
 
 #define check_pgt_cache()	do { } while (0)
diff -Nru a/include/asm-ppc64/ppc_asm.h b/include/asm-ppc64/ppc_asm.h
--- a/include/asm-ppc64/ppc_asm.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-ppc64/ppc_asm.h	2004-06-23 19:04:26 -07:00
@@ -28,6 +28,9 @@
 #define REST_8GPRS(n, base)	REST_4GPRS(n, base); REST_4GPRS(n+4, base)
 #define REST_10GPRS(n, base)	REST_8GPRS(n, base); REST_2GPRS(n+8, base)
 
+#define SAVE_NVGPRS(base)	SAVE_8GPRS(14, base); SAVE_10GPRS(22, base)
+#define REST_NVGPRS(base)	REST_8GPRS(14, base); REST_10GPRS(22, base)
+
 #define SAVE_FPR(n, base)	stfd	n,THREAD_FPR0+8*(n)(base)
 #define SAVE_2FPRS(n, base)	SAVE_FPR(n, base); SAVE_FPR(n+1, base)
 #define SAVE_4FPRS(n, base)	SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
@@ -53,11 +56,6 @@
 #define REST_8VRS(n,b,base)	REST_4VRS(n,b,base); REST_4VRS(n+4,b,base)
 #define REST_16VRS(n,b,base)	REST_8VRS(n,b,base); REST_8VRS(n+8,b,base)
 #define REST_32VRS(n,b,base)	REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
-
-#define CHECKANYINT(ra,rb)			\
-	mfspr	rb,SPRG3;		/* Get Paca address */\
-	ld	ra,PACALPPACA+LPPACAANYINT(rb); /* Get pending interrupt flags */\
-	cmpldi	0,ra,0;
 
 /* Macros to adjust thread priority for Iseries hardware multithreading */
 #define HMT_LOW		or 1,1,1
diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
--- a/include/asm-ppc64/processor.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc64/processor.h	2004-06-23 19:04:25 -07:00
@@ -543,8 +543,7 @@
 	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	saved_msr;	/* Save MSR across signal handlers */
-	unsigned long	saved_softe;	/* Ditto for Soft Enable/Disable */
+	unsigned long	pad[3];		/* was saved_msr, saved_softe */
 #ifdef CONFIG_ALTIVEC
 	/* Complete AltiVec register set */
 	vector128	vr[32] __attribute((aligned(16)));
diff -Nru a/include/asm-ppc64/ptrace.h b/include/asm-ppc64/ptrace.h
--- a/include/asm-ppc64/ptrace.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-ppc64/ptrace.h	2004-06-23 19:04:27 -07:00
@@ -71,6 +71,18 @@
 #define instruction_pointer(regs) ((regs)->nip)
 #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
 
+#define force_successful_syscall_return()   \
+		(current_thread_info()->syscall_noerror = 1)
+
+/*
+ * We use the least-significant bit of the trap field to indicate
+ * whether we have saved the full set of registers, or only a
+ * partial set.  A 1 there means the partial set.
+ */
+#define FULL_REGS(regs)		(((regs)->trap & 1) == 0)
+#define TRAP(regs)		((regs)->trap & ~0xF)
+#define CHECK_FULL_REGS(regs)	BUG_ON(regs->trap & 1)
+
 /*
  * Offsets used by 'ptrace' system call interface.
  */
diff -Nru a/include/asm-ppc64/resource.h b/include/asm-ppc64/resource.h
--- a/include/asm-ppc64/resource.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-ppc64/resource.h	2004-06-23 19:04:27 -07:00
@@ -21,8 +21,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 #ifdef __KERNEL__
 
@@ -46,6 +48,8 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
--- a/include/asm-ppc64/system.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-ppc64/system.h	2004-06-23 19:04:29 -07:00
@@ -111,12 +111,23 @@
 extern int _get_PVR(void);
 extern void giveup_fpu(struct task_struct *);
 extern void disable_kernel_fp(void);
+extern void flush_fp_to_thread(struct task_struct *);
 extern void enable_kernel_fp(void);
 extern void giveup_altivec(struct task_struct *);
 extern void disable_kernel_altivec(void);
 extern void enable_kernel_altivec(void);
+extern int emulate_altivec(struct pt_regs *);
 extern void cvt_fd(float *from, double *to, unsigned long *fpscr);
 extern void cvt_df(double *from, float *to, unsigned long *fpscr);
+
+#ifdef CONFIG_ALTIVEC
+extern void flush_altivec_to_thread(struct task_struct *);
+#else
+static inline void flush_altivec_to_thread(struct task_struct *t)
+{
+}
+#endif
+
 extern int abs(int);
 
 extern struct task_struct *__switch_to(struct task_struct *,
@@ -276,6 +287,15 @@
      (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,		 \
 				    (unsigned long)_n_, sizeof(*(ptr))); \
   })
+
+/*
+ * We handle most unaligned accesses in hardware. On the other hand 
+ * unaligned DMA can be very expensive on some ppc64 IO chips (it does
+ * powers of 2 writes until it reaches sufficient alignment).
+ *
+ * Based on this we disable the IP header alignment in network drivers.
+ */
+#define NET_IP_ALIGN   0
 
 #endif /* __KERNEL__ */
 #endif
diff -Nru a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
--- a/include/asm-ppc64/thread_info.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-ppc64/thread_info.h	2004-06-23 19:04:25 -07:00
@@ -13,6 +13,7 @@
 #ifndef __ASSEMBLY__
 #include <linux/config.h>
 #include <asm/processor.h>
+#include <asm/page.h>
 #include <linux/stringify.h>
 
 /*
@@ -23,8 +24,10 @@
 	struct exec_domain *exec_domain;	/* execution domain */
 	unsigned long	flags;			/* low level flags */
 	int		cpu;			/* cpu we're on */
-	int		preempt_count;		/* not used at present */
+	int		preempt_count;
 	struct restart_block restart_block;
+	/* set by force_successful_syscall_return */
+	unsigned char	syscall_noerror;
 };
 
 /*
@@ -73,7 +76,7 @@
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
-	__asm__("clrrdi %0,1,14" : "=r"(ti));
+	__asm__("clrrdi %0,1,%1" : "=r"(ti) : "i" (THREAD_SHIFT));
 	return ti;
 }
 
diff -Nru a/include/asm-s390/fcntl.h b/include/asm-s390/fcntl.h
--- a/include/asm-s390/fcntl.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-s390/fcntl.h	2004-06-23 19:04:25 -07:00
@@ -27,6 +27,7 @@
 #define O_LARGEFILE	0100000
 #define O_DIRECTORY	0200000	/* must be a directory */
 #define O_NOFOLLOW	0400000 /* don't follow links */
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
--- a/include/asm-s390/pgtable.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-s390/pgtable.h	2004-06-23 19:04:28 -07:00
@@ -654,9 +654,11 @@
 	__pte;                                                            \
 })
 
-#define arch_set_page_uptodate(__page)					  \
+#define SetPageUptodate(_page) \
 	do {								  \
-		asm volatile ("sske %0,%1" : : "d" (0),			  \
+		struct page *__page = (_page);				  \
+		if (!test_and_set_bit(PG_uptodate, &__page->flags))	  \
+			asm volatile ("sske %0,%1" : : "d" (0),		  \
 			      "a" (__pa((__page-mem_map) << PAGE_SHIFT)));\
 	} while (0)
 
diff -Nru a/include/asm-s390/resource.h b/include/asm-s390/resource.h
--- a/include/asm-s390/resource.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-s390/resource.h	2004-06-23 19:04:26 -07:00
@@ -24,8 +24,10 @@
 #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 RLIM_NLIMITS	11
+#define RLIMIT_SIGPENDING 11		/* max number of pending signals */
+#define RLIMIT_MSGQUEUE 12		/* maximum bytes in POSIX mqueues */
+
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -48,6 +50,8 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h
--- a/include/asm-sh/checksum.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-sh/checksum.h	2004-06-23 19:04:25 -07:00
@@ -201,8 +201,10 @@
  *	Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
-				    int len, int sum, int *err_ptr)
+static __inline__ unsigned int csum_and_copy_to_user (const char *src, 
+						      char __user *dst,
+						      int len, int sum,
+						      int *err_ptr)
 {
 	if (access_ok(VERIFY_WRITE, dst, len))
 		return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
diff -Nru a/include/asm-sh/fcntl.h b/include/asm-sh/fcntl.h
--- a/include/asm-sh/fcntl.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-sh/fcntl.h	2004-06-23 19:04:28 -07:00
@@ -20,6 +20,7 @@
 #define O_LARGEFILE	0100000
 #define O_DIRECTORY	0200000	/* must be a directory */
 #define O_NOFOLLOW	0400000 /* don't follow links */
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-sh/resource.h b/include/asm-sh/resource.h
--- a/include/asm-sh/resource.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-sh/resource.h	2004-06-23 19:04:27 -07:00
@@ -16,8 +16,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 #ifdef __KERNEL__
 
@@ -40,6 +42,8 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-sparc/checksum.h b/include/asm-sparc/checksum.h
--- a/include/asm-sparc/checksum.h	2004-06-23 19:04:24 -07:00
+++ b/include/asm-sparc/checksum.h	2004-06-23 19:04:24 -07:00
@@ -91,7 +91,7 @@
   }
   
 static inline unsigned int 
-csum_partial_copy_to_user(const char *src, char *dst, int len, 
+csum_partial_copy_to_user(const char *src, char __user *dst, int len, 
 			  unsigned int sum, int *err)
 {
 	if (!access_ok (VERIFY_WRITE, dst, len)) {
diff -Nru a/include/asm-sparc/fcntl.h b/include/asm-sparc/fcntl.h
--- a/include/asm-sparc/fcntl.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-sparc/fcntl.h	2004-06-23 19:04:28 -07:00
@@ -21,6 +21,7 @@
 #define O_NOFOLLOW	0x20000	/* don't follow links */
 #define O_LARGEFILE	0x40000
 #define O_DIRECT        0x100000 /* direct disk access hint */
+#define O_NOATIME	0x200000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-sparc/resource.h b/include/asm-sparc/resource.h
--- a/include/asm-sparc/resource.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-sparc/resource.h	2004-06-23 19:04:25 -07:00
@@ -19,11 +19,13 @@
 #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_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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -44,7 +46,9 @@
     {INR_OPEN, INR_OPEN}, {0, 0},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
-    {RLIM_INFINITY, RLIM_INFINITY}	\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {MAX_SIGPENDING, MAX_SIGPENDING},	\
+    {MQ_BYTES_MAX, MQ_BYTES_MAX},	\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h
--- a/include/asm-sparc64/bug.h	2004-06-23 19:04:27 -07:00
+++ b/include/asm-sparc64/bug.h	2004-06-23 19:04:27 -07:00
@@ -3,6 +3,8 @@
 #ifndef _SPARC64_BUG_H
 #define _SPARC64_BUG_H
 
+#include <linux/compiler.h>
+
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 extern void do_BUG(const char *file, int line);
 #define BUG() do {					\
diff -Nru a/include/asm-sparc64/checksum.h b/include/asm-sparc64/checksum.h
--- a/include/asm-sparc64/checksum.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-sparc64/checksum.h	2004-06-23 19:04:26 -07:00
@@ -66,8 +66,9 @@
  */
 #define HAVE_CSUM_COPY_USER
 extern unsigned int csum_partial_copy_user_sparc64(const char *src, char *dst, int len, unsigned int sum);
+
 static __inline__ unsigned int 
-csum_and_copy_to_user(const char *src, char *dst, int len, 
+csum_and_copy_to_user(const char *src, char __user *dst, int len, 
 		      unsigned int sum, int *err)
 {
 	__asm__ __volatile__ ("stx	%0, [%%sp + 0x7ff + 128]"
diff -Nru a/include/asm-sparc64/fcntl.h b/include/asm-sparc64/fcntl.h
--- a/include/asm-sparc64/fcntl.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-sparc64/fcntl.h	2004-06-23 19:04:28 -07:00
@@ -21,6 +21,7 @@
 #define O_NOFOLLOW	0x20000	/* don't follow links */
 #define O_LARGEFILE	0x40000
 #define O_DIRECT        0x100000 /* direct disk access hint */
+#define O_NOATIME	0x200000
 
 
 #define F_DUPFD		0	/* dup */
diff -Nru a/include/asm-sparc64/resource.h b/include/asm-sparc64/resource.h
--- a/include/asm-sparc64/resource.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-sparc64/resource.h	2004-06-23 19:04:25 -07:00
@@ -19,11 +19,13 @@
 #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_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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -43,7 +45,9 @@
     {INR_OPEN, INR_OPEN}, {0, 0},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
-    {RLIM_INFINITY, RLIM_INFINITY}	\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {MAX_SIGPENDING, MAX_SIGPENDING},	\
+    {MQ_BYTES_MAX, MQ_BYTES_MAX},	\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-v850/fcntl.h b/include/asm-v850/fcntl.h
--- a/include/asm-v850/fcntl.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-v850/fcntl.h	2004-06-23 19:04:26 -07:00
@@ -20,6 +20,7 @@
 #define O_NOFOLLOW     0100000	/* don't follow links */
 #define O_DIRECT       0200000	/* direct disk access hint - currently ignored */
 #define O_LARGEFILE    0400000
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-v850/resource.h b/include/asm-v850/resource.h
--- a/include/asm-v850/resource.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-v850/resource.h	2004-06-23 19:04:25 -07:00
@@ -16,8 +16,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -39,7 +41,9 @@
 	{      INR_OPEN,     INR_OPEN  },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
-        { RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-x86_64/fcntl.h b/include/asm-x86_64/fcntl.h
--- a/include/asm-x86_64/fcntl.h	2004-06-23 19:04:25 -07:00
+++ b/include/asm-x86_64/fcntl.h	2004-06-23 19:04:25 -07:00
@@ -20,6 +20,7 @@
 #define O_LARGEFILE	0100000
 #define O_DIRECTORY	0200000	/* must be a directory */
 #define O_NOFOLLOW	0400000 /* don't follow links */
+#define O_NOATIME	01000000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get close_on_exec */
diff -Nru a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h
--- a/include/asm-x86_64/mpspec.h	2004-06-23 19:04:26 -07:00
+++ b/include/asm-x86_64/mpspec.h	2004-06-23 19:04:26 -07:00
@@ -189,7 +189,7 @@
 extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_parse_prt (void);
+extern void mp_register_gsi (u32 gsi, int edge_level, int active_high_low);
 #endif /*CONFIG_X86_IO_APIC*/
 #endif
 
diff -Nru a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
--- a/include/asm-x86_64/pgtable.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-x86_64/pgtable.h	2004-06-23 19:04:28 -07:00
@@ -262,8 +262,21 @@
 extern inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 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)	{ return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep); }
-static inline  int ptep_test_and_clear_young(pte_t *ptep)	{ return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep); }
+
+static inline int ptep_test_and_clear_dirty(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)
+{
+	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); }
 
diff -Nru a/include/asm-x86_64/resource.h b/include/asm-x86_64/resource.h
--- a/include/asm-x86_64/resource.h	2004-06-23 19:04:28 -07:00
+++ b/include/asm-x86_64/resource.h	2004-06-23 19:04:28 -07:00
@@ -16,8 +16,10 @@
 #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	11
+#define RLIM_NLIMITS	13
 
 /*
  * SuS says limits have to be unsigned.
@@ -39,7 +41,9 @@
 	{      INR_OPEN,     INR_OPEN  },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
-        { RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
--- a/include/asm-x86_64/uaccess.h	2004-06-23 19:04:29 -07:00
+++ b/include/asm-x86_64/uaccess.h	2004-06-23 19:04:29 -07:00
@@ -33,16 +33,6 @@
 
 #define segment_eq(a,b)	((a).seg == (b).seg)
 
-#ifdef __CHECKER__
-#define CHECK_UPTR(ptr) do {				\
-	__typeof__(*(ptr)) *__dummy_check_uptr =	\
-		(void __user *)&__dummy_check_uptr;	\
-} while(0)
-#else
-#define CHECK_UPTR(ptr)
-#endif
-
-
 #define __addr_ok(addr) (!((unsigned long)(addr) & (current_thread_info()->addr_limit.seg)))
 
 /*
@@ -50,7 +40,7 @@
  */
 #define __range_not_ok(addr,size) ({ \
 	unsigned long flag,sum; \
-	CHECK_UPTR(addr);	\
+	__chk_user_ptr(addr); \
 	asm("# range_ok\n\r" \
 		"addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0"  \
 		:"=&r" (flag), "=r" (sum) \
@@ -114,7 +104,7 @@
 #define get_user(x,ptr)							\
 ({	long __val_gu;							\
 	int __ret_gu; 							\
-	CHECK_UPTR(ptr);						\
+	__chk_user_ptr(ptr);						\
 	switch(sizeof (*(ptr))) {					\
 	case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;		\
 	case 2:  __get_user_x(2,__ret_gu,__val_gu,ptr); break;		\
@@ -150,7 +140,6 @@
 #define __put_user_nocheck(x,ptr,size)			\
 ({							\
 	int __pu_err;					\
-	CHECK_UPTR(ptr);				\
 	__put_user_size((x),(ptr),(size),__pu_err);	\
 	__pu_err;					\
 })
@@ -168,6 +157,7 @@
 #define __put_user_size(x,ptr,size,retval)				\
 do {									\
 	retval = 0;							\
+	__chk_user_ptr(ptr);						\
 	switch (size) {							\
 	  case 1: __put_user_asm(x,ptr,retval,"b","b","iq",-EFAULT); break;\
 	  case 2: __put_user_asm(x,ptr,retval,"w","w","ir",-EFAULT); break;\
@@ -206,7 +196,6 @@
 ({								\
 	int __gu_err;						\
 	long __gu_val;						\
-	CHECK_UPTR(ptr);					\
 	__get_user_size(__gu_val,(ptr),(size),__gu_err);	\
 	(x) = (__typeof__(*(ptr)))__gu_val;			\
 	__gu_err;						\
@@ -217,6 +206,7 @@
 #define __get_user_size(x,ptr,size,retval)				\
 do {									\
 	retval = 0;							\
+	__chk_user_ptr(ptr);						\
 	switch (size) {							\
 	  case 1: __get_user_asm(x,ptr,retval,"b","b","=q",-EFAULT); break;\
 	  case 2: __get_user_asm(x,ptr,retval,"w","w","=r",-EFAULT); break;\
@@ -257,28 +247,28 @@
 { 
        int ret = 0;
 	if (!__builtin_constant_p(size))
-		return copy_user_generic(dst,(void *)src,size);
+		return copy_user_generic(dst,(__force void *)src,size);
 	switch (size) { 
-	case 1:__get_user_asm(*(u8*)dst,(u8 *)src,ret,"b","b","=q",1); 
+	case 1:__get_user_asm(*(u8*)dst,(u8 __user *)src,ret,"b","b","=q",1); 
 		return ret;
-	case 2:__get_user_asm(*(u16*)dst,(u16*)src,ret,"w","w","=r",2);
+	case 2:__get_user_asm(*(u16*)dst,(u16 __user *)src,ret,"w","w","=r",2);
 		return ret;
-	case 4:__get_user_asm(*(u32*)dst,(u32*)src,ret,"l","k","=r",4);
+	case 4:__get_user_asm(*(u32*)dst,(u32 __user *)src,ret,"l","k","=r",4);
 		return ret;
-	case 8:__get_user_asm(*(u64*)dst,(u64*)src,ret,"q","","=r",8);
+	case 8:__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",8);
 		return ret; 
 	case 10:
-	       	__get_user_asm(*(u64*)dst,(u64*)src,ret,"q","","=r",16);
+	       	__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16);
 		if (unlikely(ret)) return ret;
-		__get_user_asm(*(u16*)(8+(char*)dst),(u16*)(8+(char*)src),ret,"w","w","=r",2);
+		__get_user_asm(*(u16*)(8+(char*)dst),(u16 __user *)(8+(char __user *)src),ret,"w","w","=r",2);
 		return ret; 
 	case 16:
-		__get_user_asm(*(u64*)dst,(u64*)src,ret,"q","","=r",16);
+		__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16);
 		if (unlikely(ret)) return ret;
-		__get_user_asm(*(u64*)(8+(char*)dst),(u64*)(8+(char*)src),ret,"q","","=r",8);
+		__get_user_asm(*(u64*)(8+(char*)dst),(u64 __user *)(8+(char __user *)src),ret,"q","","=r",8);
 		return ret; 
 	default:
-		return copy_user_generic(dst,(void *)src,size); 
+		return copy_user_generic(dst,(__force void *)src,size); 
 	}
 }	
 
@@ -286,30 +276,30 @@
 { 
        int ret = 0;
 	if (!__builtin_constant_p(size))
-		return copy_user_generic((void *)dst,src,size);
+		return copy_user_generic((__force void *)dst,src,size);
 	switch (size) { 
-	case 1:__put_user_asm(*(u8*)src,(u8 *)dst,ret,"b","b","iq",1); 
+	case 1:__put_user_asm(*(u8*)src,(u8 __user *)dst,ret,"b","b","iq",1); 
 		return ret;
-	case 2:__put_user_asm(*(u16*)src,(u16*)dst,ret,"w","w","ir",2);
+	case 2:__put_user_asm(*(u16*)src,(u16 __user *)dst,ret,"w","w","ir",2);
 		return ret;
-	case 4:__put_user_asm(*(u32*)src,(u32*)dst,ret,"l","k","ir",4);
+	case 4:__put_user_asm(*(u32*)src,(u32 __user *)dst,ret,"l","k","ir",4);
 		return ret;
-	case 8:__put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",8);
+	case 8:__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",8);
 		return ret; 
 	case 10:
-		__put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",10);
+		__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",10);
 		if (unlikely(ret)) return ret;
 		asm("":::"memory");
-		__put_user_asm(4[(u16*)src],4+(u16*)dst,ret,"w","w","ir",2);
+		__put_user_asm(4[(u16*)src],4+(u16 __user *)dst,ret,"w","w","ir",2);
 		return ret; 
 	case 16:
-		__put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",16);
+		__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",16);
 		if (unlikely(ret)) return ret;
 		asm("":::"memory");
-		__put_user_asm(1[(u64*)src],1+(u64*)dst,ret,"q","","ir",8);
+		__put_user_asm(1[(u64*)src],1+(u64 __user *)dst,ret,"q","","ir",8);
 		return ret; 
 	default:
-		return copy_user_generic((void *)dst,src,size); 
+		return copy_user_generic((__force void *)dst,src,size); 
 	}
 }	
 
@@ -318,39 +308,39 @@
 { 
        int ret = 0;
 	if (!__builtin_constant_p(size))
-		return copy_user_generic((void *)dst,(void *)src,size);
+		return copy_user_generic((__force void *)dst,(__force void *)src,size);
 	switch (size) { 
 	case 1: { 
 		u8 tmp;
-		__get_user_asm(tmp,(u8 *)src,ret,"b","b","=q",1); 
+		__get_user_asm(tmp,(u8 __user *)src,ret,"b","b","=q",1); 
 		if (likely(!ret))
-			__put_user_asm(tmp,(u8 *)dst,ret,"b","b","iq",1); 
+			__put_user_asm(tmp,(u8 __user *)dst,ret,"b","b","iq",1); 
 		return ret;
 	}
 	case 2: { 
 		u16 tmp;
-		__get_user_asm(tmp,(u16 *)src,ret,"w","w","=r",2); 
+		__get_user_asm(tmp,(u16 __user *)src,ret,"w","w","=r",2); 
 		if (likely(!ret))
-			__put_user_asm(tmp,(u16 *)dst,ret,"w","w","ir",2); 
+			__put_user_asm(tmp,(u16 __user *)dst,ret,"w","w","ir",2); 
 		return ret;
 	}
 
 	case 4: { 
 		u32 tmp;
-		__get_user_asm(tmp,(u32 *)src,ret,"l","k","=r",4); 
+		__get_user_asm(tmp,(u32 __user *)src,ret,"l","k","=r",4); 
 		if (likely(!ret))
-			__put_user_asm(tmp,(u32 *)dst,ret,"l","k","ir",4); 
+			__put_user_asm(tmp,(u32 __user *)dst,ret,"l","k","ir",4); 
 		return ret;
 	}
 	case 8: { 
 		u64 tmp;
-		__get_user_asm(tmp,(u64 *)src,ret,"q","","=r",8); 
+		__get_user_asm(tmp,(u64 __user *)src,ret,"q","","=r",8); 
 		if (likely(!ret))
-			__put_user_asm(tmp,(u64 *)dst,ret,"q","","ir",8); 
+			__put_user_asm(tmp,(u64 __user *)dst,ret,"q","","ir",8); 
 		return ret;
 	}
 	default:
-		return copy_user_generic((void *)dst,(void *)src,size); 
+		return copy_user_generic((__force void *)dst,(__force void *)src,size); 
 	}
 }	
 
diff -Nru a/include/linux/802_11.h b/include/linux/802_11.h
--- a/include/linux/802_11.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,191 +0,0 @@
-#ifndef IEEE_802_11
-#define IEEE_802_11  
-
-#include <linux/types.h>
-
-enum ieee_802_11_link_status_failure_reason {
-	reserved0, Unspecified=1, Previous_not_valid, 
-	Sender_Quits_ESS_or_IBSS,
-	Due_Inactivity, AP_Overload, 
-	Class_2_from_NonAuth,
-	Class_3_from_NonAuth,
-	Sender_Quits_BSS,
-	Association_requester_not_authenticated,
-	Reserved10 
-};
-	
-	
-#define IEEE_802_11_LINK_STATUS_FAILURE_REASON_STRINGS \
-{	\
-        {reserved0,		0xff," Reserved reason "},\
-        {Unspecified,		0xff," Unspecified Reason "},\
-        {Previous_not_valid,	0xff," Previous Authentication no longer valid "},\
-        {Sender_Quits_ESS_or_IBSS,0xff," Deauthenticated because sending station is leaving (has left) IBSS or ESS "},\
-        {Due_Inactivity,	0xff," Disassociated due to inactivity "},\
-        {AP_Overload,		0xff," Disassociated because AP is unable to handle all currently associated stations "},\
-        {Class_2_from_NonAuth,	0xff," Class 2 frame received from non-Authenticated station"},\
-        {Class_3_from_NonAuth,	0xff," Class 3 frame received from non­Associated station"},\
-        {Sender_Quits_BSS,	0xff," Disassociated because sending station is leaving (has left) BSS"},\
-        {Association_requester_not_authenticated,0xff," Station requesting (Re)Association is not Authenticated with responding station"},\
-        {Reserved10,		0xff," Reserved"},\
-	{0,0,NULL}\
-};
-
-
-
-struct ieee_802_11_header {
-	u16	frame_control;// needs to be subtyped
-	u16	duration;
-	u8	mac1[6];
-	u8	mac2[6];
-	u8	mac3[6];
-	u16	SeqCtl;
-	u8	mac4[6];
-	u16	gapLen;
-	u8	gap[8];
-};
-
-
-struct ieee_802_3_header {
-
-	u16	status;
-	u16	payload_length;
-	u8	dst_mac[6];
-	u8	src_mac[6];
-	
-};
-
-#define P80211_OUI_LEN 3
-
-struct ieee_802_11_snap_header { 
-
-	u8    dsap;   /* always 0xAA */
-	u8    ssap;   /* always 0xAA */
-	u8    ctrl;   /* always 0x03 */
-	u8    oui[P80211_OUI_LEN];    /* organizational universal id */
-
-} __attribute__ ((packed));
-
-#define P80211_LLC_OUI_LEN 3
-
-struct ieee_802_11_802_1H_header {
-
-	u8    dsap;   
-	u8    ssap;   /* always 0xAA */
-	u8    ctrl;   /* always 0x03 */
-	u8    oui[P80211_OUI_LEN];    /* organizational universal id */
-	u16    unknown1;      /* packet type ID fields */
-	u16    unknown2;		/* here is something like length in some cases */
-} __attribute__ ((packed));
-
-struct ieee_802_11_802_2_header {
-
-	u8    dsap;   
-	u8    ssap;   /* always 0xAA */
-	u8    ctrl;   /* always 0x03 */
-	u8    oui[P80211_OUI_LEN];    /* organizational universal id */
-	u8    type;      /* packet type ID field. i guess,  */
-
-} __attribute__ ((packed));
-
-
-
-// following is incoplete and may be incorrect and need reorganization
-
-#define ieee_802_11_frame_type_Management	0x00
-#define ieee_802_11_frame_type_Control		0x01
-#define ieee_802_11_frame_type_Data		0x10
-#define ieee_802_11_frame_type_Reserved		0x11
-
-#define ieee_802_11_frame_subtype_Association_Req	0x0 // Association Request
-#define ieee_802_11_frame_subtype_Association_Resp	0x1 // Association Response
-#define ieee_802_11_frame_subtype_Reassociation_Req	0x2 // Reassociation Request
-#define ieee_802_11_frame_subtype_Reassociation_Resp	0x3 // Reassociation Response
-#define ieee_802_11_frame_subtype_Probe_Req		0x4 // Probe Request
-#define ieee_802_11_frame_subtype_Probe_Resp		0x5 // Probe Response
-#define ieee_802_11_frame_subtype_Beacon 		0x8 // Beacon
-#define ieee_802_11_frame_subtype_ATIM 			0x9 // ATIM
-#define ieee_802_11_frame_subtype_Disassociation 	0xA // Disassociation
-#define ieee_802_11_frame_subtype_Authentication 	0xB // Authentication
-#define ieee_802_11_frame_subtype_Deauthentication 	0xC // Deauthentication
-#define ieee_802_11_frame_subtype_PS_Poll 		0xA // PS-Poll
-#define ieee_802_11_frame_subtype_RTS 			0xB // RTS
-#define ieee_802_11_frame_subtype_CTS 			0xC // CTS
-#define ieee_802_11_frame_subtype_ACK 			0xD // ACK
-#define ieee_802_11_frame_subtype_CFEnd 		0xE // CF-End
-#define ieee_802_11_frame_subtype_CFEnd_CFAck 		0xF // CF-End + CF-Ack
-#define ieee_802_11_frame_subtype_Data 			0x0 // Data
-#define ieee_802_11_frame_subtype_Data_CFAck 		0x1 // Data + CF-Ack
-#define ieee_802_11_frame_subtype_Data_CF_Poll 		0x2 // Data + CF-Poll
-#define ieee_802_11_frame_subtype_Data_CF_AckCF_Poll 	0x3 // Data + CF-Ack + CF-Poll
-#define ieee_802_11_frame_subtype_NullFunction 		0x4 // Null Function (no data)
-#define ieee_802_11_frame_subtype_CF_Ack 		0x5 // CF-Ack (no data)
-#define ieee_802_11_frame_subtype_CF_Poll 		0x6 // CF-Poll (no data)
-#define ieee_802_11_frame_subtype_CF_AckCF_Poll 	0x7 // CF-Ack + CF-Poll (no data)
-
-
-#define ieee_802_11_frame_subtype_strings {\
-	{ ieee_802_11_frame_subtype_Association_Req,	0xF,"f  Association Request"},\
-	{ ieee_802_11_frame_subtype_Association_Resp,	0xF,"1  Association Response"},\
-	{ ieee_802_11_frame_subtype_Reassociation_Req,	0xF,"2  Reassociation Request"},\
-	{ ieee_802_11_frame_subtype_Reassociation_Resp,	0xF,"3  Reassociation Response"},\
-	{ ieee_802_11_frame_subtype_Probe_Req	,	0xF,"4  Probe Request"},\
-	{ ieee_802_11_frame_subtype_Probe_Resp	,	0xF,"5  Probe Response"},\
-	{ ieee_802_11_frame_subtype_Beacon 	,	0xF,"8  Beacon"},\
-	{ ieee_802_11_frame_subtype_ATIM 	,	0xF,"9  ATIM"},\
-	{ ieee_802_11_frame_subtype_Disassociation,	0xF,"A  Disassociation"},\
-	{ ieee_802_11_frame_subtype_Authentication,	0xF,"B  Authentication"},\
-	{ ieee_802_11_frame_subtype_Deauthentication,	0xF,"C  Deauthentication"},\
-	{ ieee_802_11_frame_subtype_PS_Poll 	,	0xF,"A  PS-Poll"},\
-	{ ieee_802_11_frame_subtype_RTS 	,	0xF,"B  RTS"},\
-	{ ieee_802_11_frame_subtype_CTS 	,	0xF,"C  CTS"},\
-	{ ieee_802_11_frame_subtype_ACK 	,	0xF,"D  ACK"},\
-	{ ieee_802_11_frame_subtype_CFEnd	,	0xF,"E  CF-End"},\
-	{ ieee_802_11_frame_subtype_CFEnd_CFAck ,	0xF,"F  CF-End + CF-Ack"},\
-	{ ieee_802_11_frame_subtype_Data 	,	0xF,"0  Data"},\
-	{ ieee_802_11_frame_subtype_Data_CFAck 	,	0xF,"1  Data + CF-Ack"},\
-	{ ieee_802_11_frame_subtype_Data_CFPoll ,	0xF,"2  Data + CF-Poll"},\
-	{ ieee_802_11_frame_subtype_Data_CFAck_CFPoll,	0xF,"3  Data + CF-Ack + CF-Poll"},\
-	{ ieee_802_11_frame_subtype_Null_Function ,	0xF,"4  Null Function (no data)"},\
-	{ ieee_802_11_frame_subtype_CFAck ,		0xF,"5  CF-Ack (no data)"},\
-	{ ieee_802_11_frame_subtype_CFPoll ,		0xF,"6  CF-Poll (no data)"},\
-	{ ieee_802_11_frame_subtype_CFAck_CFPoll,	0xF,"y7  CF-Ack + CF-Poll (no data)"},\
-	{ 0,0,NULL}\
-}
-struct ieee_802_11_frame_subtype_class {
-	u8	subtype;
-	u8	mask;
-	u8	class;
-	u8	type;
-};
-#define ieee_802_11_frame_subtype_classes {\
-	{ ieee_802_11_frame_subtype_Association_Req,	0xF,2,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_Association_Resp,	0xF,2,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_Reassociation_Req,	0xF,2,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_Reassociation_Resp,	0xF,2,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_Probe_Req	,	0xF,1,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_Probe_Resp	,	0xF,1,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_Beacon 	,	0xF,1,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_ATIM 	,	0xF,1,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_Disassociation,	0xF,2,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_Authentication,	0xF,1,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_Deauthentication,	0xF,3,ieee_802_11_frame_type_Management},\
-	{ ieee_802_11_frame_subtype_PS-Poll 	,	0xF,3,ieee_802_11_frame_type_Control},\
-	{ ieee_802_11_frame_subtype_RTS 	,	0xF,1,ieee_802_11_frame_type_Control},\
-	{ ieee_802_11_frame_subtype_CTS 	,	0xF,1,ieee_802_11_frame_type_Control},\
-	{ ieee_802_11_frame_subtype_ACK 	,	0xF,1,ieee_802_11_frame_type_Control},\
-	{ ieee_802_11_frame_subtype_CFEnd	,	0xF,1,ieee_802_11_frame_type_Control},\
-	{ ieee_802_11_frame_subtype_CFEnd_CFAck ,	0xF,1,ieee_802_11_frame_type_Control},\
-	{ ieee_802_11_frame_subtype_Data 	,	0xF,3,ieee_802_11_frame_type_Data},\
-	{ ieee_802_11_frame_subtype_Data_CFAck 	,	0xF,3,ieee_802_11_frame_type_Data},\
-	{ ieee_802_11_frame_subtype_Data_CF_Poll 	0xF,3,ieee_802_11_frame_type_Data},\
-	{ ieee_802_11_frame_subtype_Data_CF_AckCF_Poll,	0xF,3,ieee_802_11_frame_type_Data},\
-	{ ieee_802_11_frame_subtype_NullFunction 	0xF,1,ieee_802_11_frame_type_Data},\
-	{ ieee_802_11_frame_subtype_CF_Ack ,		0xF,1,ieee_802_11_frame_type_Data},\
-	{ ieee_802_11_frame_subtype_CF_Poll ,		0xF,1,ieee_802_11_frame_type_Data},\
-	{ ieee_802_11_frame_subtype_CF_AckCF_Poll,	0xF,1,ieee_802_11_frame_type_Data},\
-	{ 0,0,NULL}\
-}
-
-
-#endif
diff -Nru a/include/linux/acct.h b/include/linux/acct.h
--- a/include/linux/acct.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/acct.h	2004-06-23 19:04:25 -07:00
@@ -16,14 +16,18 @@
 #define _LINUX_ACCT_H
 
 #include <linux/types.h>
+#include <asm/param.h>
 
 /* 
  *  comp_t is a 16-bit "floating" point number with a 3-bit base 8
- *  exponent and a 13-bit fraction. See linux/kernel/acct.c for the
- *  specific encoding system used.
+ *  exponent and a 13-bit fraction.
+ *  comp2_t is 24-bit with 5-bit base 2 exponent and 20 bit fraction
+ *  (leading 1 not stored).
+ *  See linux/kernel/acct.c for the specific encoding systems used.
  */
 
 typedef __u16	comp_t;
+typedef __u32	comp2_t;
 
 /*
  *   accounting file record
@@ -36,27 +40,59 @@
 
 struct acct
 {
-	char		ac_flag;		/* Accounting Flags */
-/*
- *	No binary format break with 2.0 - but when we hit 32bit uid we'll
- *	have to bite one
- */
-	__u16		ac_uid;			/* Accounting Real User ID */
-	__u16		ac_gid;			/* Accounting Real Group ID */
-	__u16		ac_tty;			/* Accounting Control Terminal */
-	__u32		ac_btime;		/* Accounting Process Creation Time */
-	comp_t		ac_utime;		/* Accounting User Time */
-	comp_t		ac_stime;		/* Accounting System Time */
-	comp_t		ac_etime;		/* Accounting Elapsed Time */
-	comp_t		ac_mem;			/* Accounting Average Memory Usage */
-	comp_t		ac_io;			/* Accounting Chars Transferred */
-	comp_t		ac_rw;			/* Accounting Blocks Read or Written */
-	comp_t		ac_minflt;		/* Accounting Minor Pagefaults */
-	comp_t		ac_majflt;		/* Accounting Major Pagefaults */
-	comp_t		ac_swaps;		/* Accounting Number of Swaps */
-	__u32		ac_exitcode;		/* Accounting Exitcode */
-	char		ac_comm[ACCT_COMM + 1];	/* Accounting Command Name */
-	char		ac_pad[10];		/* Accounting Padding Bytes */
+	char		ac_flag;		/* Flags */
+	char		ac_version;		/* Always set to ACCT_VERSION */
+	/* for binary compatibility back until 2.0 */
+	__u16		ac_uid16;		/* LSB of Real User ID */
+	__u16		ac_gid16;		/* LSB of Real Group ID */
+	__u16		ac_tty;			/* Control Terminal */
+	__u32		ac_btime;		/* Process Creation Time */
+	comp_t		ac_utime;		/* User Time */
+	comp_t		ac_stime;		/* System Time */
+	comp_t		ac_etime;		/* Elapsed Time */
+	comp_t		ac_mem;			/* Average Memory Usage */
+	comp_t		ac_io;			/* Chars Transferred */
+	comp_t		ac_rw;			/* Blocks Read or Written */
+	comp_t		ac_minflt;		/* Minor Pagefaults */
+	comp_t		ac_majflt;		/* Major Pagefaults */
+	comp_t		ac_swaps;		/* Number of Swaps */
+/* m68k had no padding here. */
+#if !defined(CONFIG_M68K) || !defined(__KERNEL__)
+	__u16		ac_ahz;			/* AHZ */
+#endif
+	__u32		ac_exitcode;		/* Exitcode */
+	char		ac_comm[ACCT_COMM + 1];	/* Command Name */
+	__u8		ac_etime_hi;		/* Elapsed Time MSB */
+	__u16		ac_etime_lo;		/* Elapsed Time LSB */
+	__u32		ac_uid;			/* Real User ID */
+	__u32		ac_gid;			/* Real Group ID */
+};
+
+struct acct_v3
+{
+	char		ac_flag;		/* Flags */
+	char		ac_version;		/* Always set to ACCT_VERSION */
+	__u16		ac_tty;			/* Control Terminal */
+	__u32		ac_exitcode;		/* Exitcode */
+	__u32		ac_uid;			/* Real User ID */
+	__u32		ac_gid;			/* Real Group ID */
+	__u32		ac_pid;			/* Process ID */
+	__u32		ac_ppid;		/* Parent Process ID */
+	__u32		ac_btime;		/* Process Creation Time */
+#ifdef __KERNEL__
+	__u32		ac_etime;		/* Elapsed Time */
+#else
+	float		ac_etime;		/* Elapsed Time */
+#endif
+	comp_t		ac_utime;		/* User Time */
+	comp_t		ac_stime;		/* System Time */
+	comp_t		ac_mem;			/* Average Memory Usage */
+	comp_t		ac_io;			/* Chars Transferred */
+	comp_t		ac_rw;			/* Blocks Read or Written */
+	comp_t		ac_minflt;		/* Minor Pagefaults */
+	comp_t		ac_majflt;		/* Major Pagefaults */
+	comp_t		ac_swaps;		/* Number of Swaps */
+	char		ac_comm[ACCT_COMM];	/* Command Name */
 };
 
 /*
@@ -68,8 +104,7 @@
 #define ACOMPAT		0x04	/* ... used compatibility mode (VAX only not used) */
 #define ACORE		0x08	/* ... dumped core */
 #define AXSIG		0x10	/* ... was killed by a signal */
-
-#define AHZ		100
+#define ABYTESEX	0x80	/* always set, allows to detect byteorder */
 
 #ifdef __KERNEL__
 
@@ -84,6 +119,66 @@
 #define acct_process(x)		do { } while (0)
 #endif
 
+/*
+ * ACCT_VERSION numbers as yet defined:
+ * 0: old format (until 2.6.7) with 16 bit uid/gid
+ * 1: extended variant (binary compatible on M68K)
+ * 2: extended variant (binary compatible on everything except M68K)
+ * 3: new binary incompatible format (64 bytes)
+ * 4: new binary incompatible format (128 bytes)
+ * 5: new binary incompatible format (128 bytes, second half)
+ *
+ */
+
+#ifdef CONFIG_BSD_PROCESS_ACCT_V3
+#define ACCT_VERSION	3
+#define AHZ		100
+typedef struct acct_v3 acct_t;
+#else
+#ifdef CONFIG_M68K
+#define ACCT_VERSION	1
+#else
+#define ACCT_VERSION	2
+#endif
+#define AHZ		(USER_HZ)
+typedef struct acct acct_t;
+#endif
+
+#else
+#define ACCT_VERSION	2
+#define AHZ		(HZ)
 #endif	/* __KERNEL */
+
+#ifdef __KERNEL__
+/*
+ * Yet another set of HZ to *HZ helper functions.
+ * See <linux/times.h> for the original.
+ */
+
+static inline u32 jiffies_to_AHZ(unsigned long x)
+{
+#if (TICK_NSEC % (NSEC_PER_SEC / AHZ)) == 0
+	return x / (HZ / USER_HZ);
+#else
+        u64 tmp = (u64)x * TICK_NSEC;
+        do_div(tmp, (NSEC_PER_SEC / AHZ));
+        return (long)tmp;
+#endif
+}
+
+static inline u64 jiffies_64_to_AHZ(u64 x)
+{
+#if (TICK_NSEC % (NSEC_PER_SEC / AHZ)) == 0
+#if HZ != AHZ
+	do_div(x, HZ / AHZ);
+#endif
+#else
+	x *= TICK_NSEC;
+	do_div(x, (NSEC_PER_SEC / AHZ));
+#endif
+       return x;
+}
+
+#endif  /* __KERNEL */
 
 #endif	/* _LINUX_ACCT_H */
diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h
--- a/include/linux/acpi.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/acpi.h	2004-06-23 19:04:25 -07:00
@@ -413,6 +413,8 @@
 
 #endif 	/*!CONFIG_ACPI_BOOT*/
 
+unsigned int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low);
+int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
 #ifdef CONFIG_ACPI_PCI
 
@@ -437,8 +439,6 @@
 struct pci_dev;
 
 int acpi_pci_irq_enable (struct pci_dev *dev);
-int acpi_pci_irq_init (void);
-int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
 struct acpi_pci_driver {
 	struct acpi_pci_driver *next;
diff -Nru a/include/linux/acpi_serial.h b/include/linux/acpi_serial.h
--- a/include/linux/acpi_serial.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,107 +0,0 @@
-/*
- *  linux/include/linux/acpi_serial.h
- *
- *  Copyright (C) 2000  Hewlett-Packard Co.
- *  Copyright (C) 2000  Khalid Aziz <khalid_aziz@hp.com>
- *
- *  Definitions for ACPI defined serial ports (headless console and 
- *  debug ports)
- *
- */
-
-#include <linux/serial.h>
-
-extern void setup_serial_acpi(void *);
-
-#define ACPI_SIG_LEN		4
-
-/* ACPI table signatures */
-#define ACPI_SPCRT_SIGNATURE	"SPCR"
-#define ACPI_DBGPT_SIGNATURE	"DBGP"
-
-/* Interface type as defined in ACPI serial port tables */
-#define ACPI_SERIAL_INTFC_16550	0
-#define ACPI_SERIAL_INTFC_16450	1
-
-/* Interrupt types for ACPI serial port tables */
-#define ACPI_SERIAL_INT_PCAT	0x01
-#define ACPI_SERIAL_INT_APIC	0x02
-#define ACPI_SERIAL_INT_SAPIC	0x04
-
-/* Baud rates as defined in ACPI serial port tables */
-#define ACPI_SERIAL_BAUD_9600		3
-#define ACPI_SERIAL_BAUD_19200		4
-#define ACPI_SERIAL_BAUD_57600		6
-#define ACPI_SERIAL_BAUD_115200		7
-
-/* Parity as defined in ACPI serial port tables */
-#define ACPI_SERIAL_PARITY_NONE		0
-
-/* Flow control methods as defined in ACPI serial port tables */
-#define ACPI_SERIAL_FLOW_DCD	0x01
-#define ACPI_SERIAL_FLOW_RTS	0x02
-#define ACPI_SERIAL_FLOW_XON	0x04
-
-/* Terminal types as defined in ACPI serial port tables */
-#define ACPI_SERIAL_TERM_VT100		0
-#define ACPI_SERIAL_TERM_VT100X	1
-
-/* PCI Flags as defined by SPCR table */
-#define ACPI_SERIAL_PCIFLAG_PNP	0x00000001
-
-/* Space ID as defined in base address structure in ACPI serial port tables */
-#define ACPI_SERIAL_MEM_SPACE		0
-#define ACPI_SERIAL_IO_SPACE		1
-#define ACPI_SERIAL_PCICONF_SPACE	2
-
-/* 
- * Generic Register Address Structure - as defined by Microsoft 
- * in http://www.microsoft.com/hwdev/onnow/download/LFreeACPI.doc
- *
-*/
-typedef struct {
-	u8  space_id;
-	u8  bit_width;
-	u8  bit_offset;
-	u8  resv;
-	u32 addrl;
-	u32 addrh;
-} gen_regaddr;
-
-/* Space ID for generic register address structure */
-#define REGADDR_SPACE_SYSMEM	0
-#define REGADDR_SPACE_SYSIO	1
-#define REGADDR_SPACE_PCICONFIG	2
-
-/* Serial Port Console Redirection and Debug Port Table formats */
-typedef struct {
-	u8 signature[4];
-	u32 length;
-	u8  rev;
-	u8  chksum;
-	u8  oemid[6];
-	u8  oem_tabid[8];
-	u32 oem_rev;
-	u8  creator_id[4];
-	u32 creator_rev;
-	u8  intfc_type;
-	u8  resv1[3];
-	gen_regaddr base_addr;
-	u8  int_type;
-	u8  irq;
-	u8  global_int[4];
-	u8  baud;
-	u8  parity;
-	u8  stop_bits;
-	u8  flow_ctrl;
-	u8  termtype;
-	u8  language;
-	u16 pci_dev_id;
-	u16 pci_vendor_id;
-	u8  pci_bus;
-	u8  pci_dev;
-	u8  pci_func;
-	u8  pci_flags[4];
-	u8  pci_seg;
-	u32 resv2;
-} acpi_ser_t;
diff -Nru a/include/linux/adb_mouse.h b/include/linux/adb_mouse.h
--- a/include/linux/adb_mouse.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,23 +0,0 @@
-#ifndef _LINUX_ADB_MOUSE_H
-#define _LINUX_ADB_MOUSE_H
-
-/*
- * linux/include/linux/mac_mouse.h
- * header file for Macintosh ADB mouse driver
- * 27-10-97 Michael Schmitz
- * copied from:
- * header file for Atari Mouse driver
- * by Robert de Vries (robert@and.nl) on 19Jul93
- */
-
-struct mouse_status {
-	char		buttons;
-	short		dx;
-	short		dy;
-	int		ready;
-	int		active;
-	struct wait_queue *wait;
-	struct fasync_struct *fasyncptr;
-};
-
-#endif
diff -Nru a/include/linux/affs_fs.h b/include/linux/affs_fs.h
--- a/include/linux/affs_fs.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/affs_fs.h	2004-06-23 19:04:25 -07:00
@@ -36,7 +36,8 @@
 extern u32	affs_count_free_blocks(struct super_block *s);
 extern void	affs_free_block(struct super_block *sb, u32 block);
 extern u32	affs_alloc_block(struct inode *inode, u32 goal);
-extern int	affs_init_bitmap(struct super_block *sb);
+extern int	affs_init_bitmap(struct super_block *sb, int *flags);
+extern void	affs_free_bitmap(struct super_block *sb);
 
 /* namei.c */
 
diff -Nru a/include/linux/affs_fs_sb.h b/include/linux/affs_fs_sb.h
--- a/include/linux/affs_fs_sb.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/affs_fs_sb.h	2004-06-23 19:04:25 -07:00
@@ -47,7 +47,6 @@
 #define SF_OFS		0x0200		/* Old filesystem */
 #define SF_PREFIX	0x0400		/* Buffer for prefix is allocated */
 #define SF_VERBOSE	0x0800		/* Talk about fs when mounting */
-#define SF_READONLY	0x1000		/* Don't allow to remount rw */
 
 /* short cut to get to the affs specific sb data */
 static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)
diff -Nru a/include/linux/atapi.h b/include/linux/atapi.h
--- a/include/linux/atapi.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,370 +0,0 @@
-/**** vi:set ts=8 sts=8 sw=8:************************************************
- *
- * Copyright (C) 2002 Marcin Dalecki <martin@dalecki.de>
- *
- * 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 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.
- */
-
-#include <linux/types.h>
-#include <asm/byteorder.h>
-
-/*
- * With each packet command, we allocate a buffer.
- * This is used for several packet
- * commands (Not for READ/WRITE commands).
- */
-#define IDEFLOPPY_PC_BUFFER_SIZE	256
-#define IDETAPE_PC_BUFFER_SIZE		256
-
-/*
- * Packet flags bits.
- */
-
-#define	PC_ABORT		0	/* set when an error is considered normal - we won't retry */
-#define PC_WAIT_FOR_DSC		1	/* 1 when polling for DSC on a media access command */
-#define PC_DMA_RECOMMENDED	2	/* 1 when we prefer to use DMA if possible */
-#define	PC_DMA_IN_PROGRESS	3	/* 1 while DMA in progress */
-#define	PC_DMA_ERROR		4	/* 1 when encountered problem during DMA */
-#define	PC_WRITING		5	/* data direction */
-#define	PC_SUPPRESS_ERROR	6	/* suppress error reporting */
-#define PC_TRANSFORM		7	/* transform SCSI commands */
-
-/* This struct get's shared between different drivers.
- */
-struct atapi_packet_command {
-	u8 c[12];			/* Actual packet bytes */
-	char *buffer;			/* Data buffer */
-	int buffer_size;		/* Size of our data buffer */
-	char *current_position;		/* Pointer into the above buffer */
-	int request_transfer;		/* Bytes to transfer */
-	int actually_transferred;	/* Bytes actually transferred */
-
-	unsigned long flags;		/* Status/Action bit flags: long for set_bit */
-
-	/* FIXME: the following is ugly as hell, but the only way we can start
-	 * actually to unify the code.
-	 */
-	/* driver specific data. */
-	/* floppy/tape */
-	int retries;				/* On each retry, we increment retries */
-	int error;				/* Error code */
-	char *b_data;				/* Pointer which runs on the buffers */
-	unsigned int b_count;			/* Missing/Available data on the current buffer */
-	u8 pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE];	/* Temporary buffer */
-	/* Called when this packet command is completed */
-	void (*callback) (struct ata_device *, struct request *);
-
-	/* only tape */
-	struct bio *bio;
-
-	/* only scsi */
-	struct {
-		unsigned int b_count;			/* Bytes transferred from current entry */
-		struct scatterlist *sg;			/* Scatter gather table */
-		struct scsi_cmnd *scsi_cmd;		/* SCSI command */
-		void (*done)(struct scsi_cmnd *);	/* Scsi completion routine */
-		unsigned long timeout;			/* Command timeout */
-	} s;
-};
-
-/*
- *	ATAPI Status Register.
- */
-typedef union {
-	u8 all			: 8;
-	struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-		u8 check	: 1;	/* Error occurred */
-		u8 idx		: 1;	/* Reserved */
-		u8 corr		: 1;	/* Correctable error occurred */
-		u8 drq		: 1;	/* Data is request by the device */
-		u8 dsc		: 1;	/* Media access command finished / Buffer availability */
-		u8 reserved5	: 1;	/* Reserved */
-		u8 drdy		: 1;	/* Ignored for ATAPI commands (ready to accept ATA command) */
-		u8 bsy		: 1;	/* The device has access to the command block */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-		u8 bsy		: 1;
-		u8 drdy		: 1;
-		u8 reserved5	: 1;
-		u8 dsc		: 1;
-		u8 drq		: 1;
-		u8 corr		: 1;
-		u8 idx		: 1;
-		u8 check	: 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	} b;
-} atapi_status_reg_t;
-
-/*
- *	ATAPI error register.
- */
-typedef union {
-	u8 all			: 8;
-	struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-		u8 ili		: 1;	/* Illegal Length Indication */
-		u8 eom		: 1;	/* End Of Media Detected */
-		u8 abrt		: 1;	/* Aborted command - As defined by ATA */
-		u8 mcr		: 1;	/* Media Change Requested - As defined by ATA */
-		u8 sense_key	: 4;	/* Sense key of the last failed packet command */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-		u8 sense_key	: 4;
-		u8 mcr		: 1;
-		u8 abrt		: 1;
-		u8 eom		: 1;
-		u8 ili		: 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	} b;
-} atapi_error_reg_t;
-
-/* Currently unused, but please do not remove.  --bkz */
-/*
- *	ATAPI Feature Register.
- */
-typedef union {
-	u8 all			: 8;
-	struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-		u8 dma		: 1;	/* Using DMA or PIO */
-		u8 reserved321	: 3;	/* Reserved */
-		u8 reserved654	: 3;	/* Reserved (Tag Type) */
-		u8 reserved7	: 1;	/* Reserved */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-		u8 reserved7	: 1;
-		u8 reserved654	: 3;
-		u8 reserved321	: 3;
-		u8 dma		: 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	} b;
-} atapi_feature_reg_t;
-
-/*
- *	ATAPI Byte Count Register.
- */
-typedef union {
-	u16 all			: 16;
-	struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-		u8 low;			/* LSB */
-		u8 high;		/* MSB */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-		u8 high;
-		u8 low;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	} b;
-} atapi_bcount_reg_t;
-
-/*
- *	ATAPI Interrupt Reason Register.
- */
-typedef union {
-	u8 all			: 8;
-	struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-		u8 cod		: 1;	/* Information transferred is command (1) or data (0) */
-		u8 io		: 1;	/* The device requests us to read (1) or write (0) */
-		u8 reserved	: 6;	/* Reserved */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-		u8 reserved	: 6;
-		u8 io		: 1;
-		u8 cod		: 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	} b;
-} atapi_ireason_reg_t;
-
-/* Currently unused, but please do not remove.  --bkz */
-/*
- *	ATAPI Drive Select Register.
- */
-typedef union {
-	u8 all			:8;
-	struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-		u8 sam_lun	:3;	/* Logical unit number */
-		u8 reserved3	:1;	/* Reserved */
-		u8 drv		:1;	/* The responding drive will be drive 0 (0) or drive 1 (1) */
-		u8 one5		:1;	/* Should be set to 1 */
-		u8 reserved6	:1;	/* Reserved */
-		u8 one7		:1;	/* Should be set to 1 */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-		u8 one7		:1;
-		u8 reserved6	:1;
-		u8 one5		:1;
-		u8 drv		:1;
-		u8 reserved3	:1;
-		u8 sam_lun	:3;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	} b;
-} atapi_drivesel_reg_t;
-
-/* Currently unused, but please do not remove.  --bkz */
-/*
- *	ATAPI Device Control Register.
- */
-typedef union {
-	u8 all			: 8;
-	struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-		u8 zero0	: 1;	/* Should be set to zero */
-		u8 nien		: 1;	/* Device interrupt is disabled (1) or enabled (0) */
-		u8 srst		: 1;	/* ATA software reset. ATAPI devices should use the new ATAPI srst. */
-		u8 one3		: 1;	/* Should be set to 1 */
-		u8 reserved4567	: 4;	/* Reserved */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-		u8 reserved4567	: 4;
-		u8 one3		: 1;
-		u8 srst		: 1;
-		u8 nien		: 1;
-		u8 zero0	: 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	} b;
-} atapi_control_reg_t;
-
-/*
- *	The following is used to format the general configuration word
- *	of the ATAPI IDENTIFY DEVICE command.
- */
-struct atapi_id_gcw {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 packet_size		: 2;	/* Packet Size */
-	u8 reserved234		: 3;	/* Reserved */
-	u8 drq_type		: 2;	/* Command packet DRQ type */
-	u8 removable		: 1;	/* Removable media */
-	u8 device_type		: 5;	/* Device type */
-	u8 reserved13		: 1;	/* Reserved */
-	u8 protocol		: 2;	/* Protocol type */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-	u8 protocol		: 2;
-	u8 reserved13		: 1;
-	u8 device_type		: 5;
-	u8 removable		: 1;
-	u8 drq_type		: 2;
-	u8 reserved234		: 3;
-	u8 packet_size		: 2;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-};
-
-/*
- *	INQUIRY packet command - Data Format.
- */
-typedef struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8	device_type	: 5;	/* Peripheral Device Type */
-	u8	reserved0_765	: 3;	/* Peripheral Qualifier - Reserved */
-	u8	reserved1_6t0	: 7;	/* Reserved */
-	u8	rmb		: 1;	/* Removable Medium Bit */
-	u8	ansi_version	: 3;	/* ANSI Version */
-	u8	ecma_version	: 3;	/* ECMA Version */
-	u8	iso_version	: 2;	/* ISO Version */
-	u8	response_format : 4;	/* Response Data Format */
-	u8	reserved3_45	: 2;	/* Reserved */
-	u8	reserved3_6	: 1;	/* TrmIOP - Reserved */
-	u8	reserved3_7	: 1;	/* AENC - Reserved */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-	u8	reserved0_765	: 3;
-	u8	device_type	: 5;
-	u8	rmb		: 1;
-	u8	reserved1_6t0	: 7;
-	u8	iso_version	: 2;
-	u8	ecma_version	: 3;
-	u8	ansi_version	: 3;
-	u8	reserved3_7	: 1;
-	u8	reserved3_6	: 1;
-	u8	reserved3_45	: 2;
-	u8	response_format : 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	u8	additional_length;	/* Additional Length (total_length-4) */
-	u8	rsv5, rsv6, rsv7;	/* Reserved */
-	u8	vendor_id[8];		/* Vendor Identification */
-	u8	product_id[16];		/* Product Identification */
-	u8	revision_level[4];	/* Revision Level */
-	u8	vendor_specific[20];	/* Vendor Specific - Optional */
-	u8	reserved56t95[40];	/* Reserved - Optional */
-					/* Additional information may be returned */
-} atapi_inquiry_result_t;
-
-/*
- *	REQUEST SENSE packet command result - Data Format.
- */
-typedef struct atapi_request_sense {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8	error_code	: 7;	/* Error Code (0x70 - current or 0x71 - deferred) */
-	u8	valid		: 1;	/* The information field conforms to standard */
-	u8	reserved1	: 8;	/* Reserved (Segment Number) */
-	u8	sense_key	: 4;	/* Sense Key */
-	u8	reserved2_4	: 1;	/* Reserved */
-	u8	ili		: 1;	/* Incorrect Length Indicator */
-	u8	eom		: 1;	/* End Of Medium */
-	u8	filemark	: 1;	/* Filemark */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-	u8	valid		: 1;
-	u8	error_code	: 7;
-	u8	reserved1	: 8;
-	u8	filemark	: 1;
-	u8	eom		: 1;
-	u8	ili		: 1;
-	u8	reserved2_4	: 1;
-	u8	sense_key	: 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	u32	information __attribute__ ((packed));
-	u8	asl;			/* Additional sense length (n-7) */
-	u32	command_specific;	/* Additional command specific information */
-	u8	asc;			/* Additional Sense Code */
-	u8	ascq;			/* Additional Sense Code Qualifier */
-	u8	replaceable_unit_code;	/* Field Replaceable Unit Code */
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8	sk_specific1	: 7;	/* Sense Key Specific */
-	u8	sksv		: 1;	/* Sense Key Specific information is valid */
-#elif defined(__BIG_ENDIAN_BITFIELD)
-	u8	sksv		: 1;	/* Sense Key Specific information is valid */
-	u8	sk_specific1	: 7;	/* Sense Key Specific */
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-	u8	sk_specific[2];		/* Sense Key Specific */
-	u8	pad[2];			/* Padding to 20 bytes */
-} atapi_request_sense_result_t;
-
-
-extern void atapi_init_pc(struct atapi_packet_command *pc);
-
-extern void atapi_discard_data(struct ata_device *, unsigned int);
-extern void atapi_write_zeros(struct ata_device *, unsigned int);
-
-extern void atapi_read(struct ata_device *, u8 *, unsigned int);
-extern void atapi_write(struct ata_device *, u8 *, unsigned int);
-
-typedef enum {
-	ide_wait,	/* insert rq at end of list, and wait for it */
-	ide_preempt,	/* insert rq in front of current request */
-	ide_end		/* insert rq at end of list, but don't wait for it */
-} ide_action_t;
-
-extern int ide_do_drive_cmd(struct ata_device *, struct request *, ide_action_t);
diff -Nru a/include/linux/atm.h b/include/linux/atm.h
--- a/include/linux/atm.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/atm.h	2004-06-23 19:04:28 -07:00
@@ -20,6 +20,7 @@
 #include <linux/socket.h>
 #include <linux/types.h>
 #endif
+#include <linux/compiler.h>
 #include <linux/atmapi.h>
 #include <linux/atmsap.h>
 #include <linux/atmioc.h>
diff -Nru a/include/linux/binfmts.h b/include/linux/binfmts.h
--- a/include/linux/binfmts.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/binfmts.h	2004-06-23 19:04:27 -07:00
@@ -35,8 +35,12 @@
 	char * interp;		/* Name of the binary really executed. Most
 				   of the time same as filename, but could be
 				   different for binfmt_{misc,script} */
+	unsigned long interp_flags;
 	unsigned long loader, exec;
 };
+
+#define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
+#define BINPRM_FLAGS_ENFORCE_NONDUMP (1 << BINPRM_FLAGS_ENFORCE_NONDUMP_BIT)
 
 /*
  * This structure defines the functions that are used to load the binary formats that
diff -Nru a/include/linux/bio.h b/include/linux/bio.h
--- a/include/linux/bio.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/bio.h	2004-06-23 19:04:28 -07:00
@@ -25,6 +25,15 @@
 
 /* Platforms may set this to teach the BIO layer about IOMMU hardware. */
 #include <asm/io.h>
+
+#if defined(BIO_VMERGE_MAX_SIZE) && defined(BIO_VMERGE_BOUNDARY)
+#define BIOVEC_VIRT_START_SIZE(x) (bvec_to_phys(x) & (BIO_VMERGE_BOUNDARY - 1))
+#define BIOVEC_VIRT_OVERSIZE(x)	((x) > BIO_VMERGE_MAX_SIZE)
+#else
+#define BIOVEC_VIRT_START_SIZE(x)	0
+#define BIOVEC_VIRT_OVERSIZE(x)		0
+#endif
+
 #ifndef BIO_VMERGE_BOUNDARY
 #define BIO_VMERGE_BOUNDARY	0
 #endif
@@ -81,6 +90,15 @@
 	unsigned short		bi_hw_segments;
 
 	unsigned int		bi_size;	/* residual I/O count */
+
+	/*
+	 * To keep track of the max hw size, we account for the
+	 * sizes of the first and last virtually mergeable segments
+	 * in this bio
+	 */
+	unsigned int		bi_hw_front_size;
+	unsigned int		bi_hw_back_size;
+
 	unsigned int		bi_max_vecs;	/* max bvl_vecs we can hold */
 
 	struct bio_vec		*bi_io_vec;	/* the actual vec list */
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/blkdev.h	2004-06-23 19:04:26 -07:00
@@ -592,6 +592,7 @@
 extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
 extern void blk_dump_rq_flags(struct request *, char *);
 extern void generic_unplug_device(request_queue_t *);
+extern inline void __generic_unplug_device(request_queue_t *);
 extern long nr_blockdev_pages(void);
 
 int blk_get_queue(request_queue_t *);
diff -Nru a/include/linux/bootmem.h b/include/linux/bootmem.h
--- a/include/linux/bootmem.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/bootmem.h	2004-06-23 19:04:28 -07:00
@@ -67,4 +67,12 @@
 	__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0)
 #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 
+extern void *__init alloc_large_system_hash(const char *tablename,
+					    unsigned long bucketsize,
+					    unsigned long numentries,
+					    int scale,
+					    int consider_highmem,
+					    unsigned int *_hash_shift,
+					    unsigned int *_hash_mask);
+
 #endif /* _LINUX_BOOTMEM_H */
diff -Nru a/include/linux/cciss_ioctl.h b/include/linux/cciss_ioctl.h
--- a/include/linux/cciss_ioctl.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/cciss_ioctl.h	2004-06-23 19:04:26 -07:00
@@ -206,7 +206,35 @@
 #define CCISS_REGNEWDISK  _IOW(CCISS_IOC_MAGIC, 13, int)
 
 #define CCISS_REGNEWD	   _IO(CCISS_IOC_MAGIC, 14)
+#define CCISS_RESCANDISK   _IO(CCISS_IOC_MAGIC, 16)
 #define CCISS_GETLUNINFO   _IOR(CCISS_IOC_MAGIC, 17, LogvolInfo_struct)
 #define CCISS_BIG_PASSTHRU _IOWR(CCISS_IOC_MAGIC, 18, BIG_IOCTL_Command_struct)
 
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+
+/* 32 bit compatible ioctl structs */
+typedef struct _IOCTL32_Command_struct {
+  LUNAddr_struct	   LUN_info;
+  RequestBlock_struct      Request;
+  ErrorInfo_struct  	   error_info;
+  WORD			   buf_size;  /* size in bytes of the buf */
+  __u32			   buf; /* 32 bit pointer to data buffer */
+} IOCTL32_Command_struct;
+
+typedef struct _BIG_IOCTL32_Command_struct {
+  LUNAddr_struct	   LUN_info;
+  RequestBlock_struct      Request;
+  ErrorInfo_struct  	   error_info;
+  DWORD			   malloc_size; /* < MAX_KMALLOC_SIZE in cciss.c */
+  DWORD			   buf_size;    /* size in bytes of the buf */
+  				        /* < malloc_size * MAXSGENTRIES */
+  __u32 		buf;	/* 32 bit pointer to data buffer */
+} BIG_IOCTL32_Command_struct;
+
+#define CCISS_PASSTHRU32   _IOWR(CCISS_IOC_MAGIC, 11, IOCTL32_Command_struct)
+#define CCISS_BIG_PASSTHRU32 _IOWR(CCISS_IOC_MAGIC, 18, BIG_IOCTL32_Command_struct)
+
+#endif /* CONFIG_COMPAT */
+#endif /* __KERNEL__ */
 #endif  
diff -Nru a/include/linux/cpu.h b/include/linux/cpu.h
--- a/include/linux/cpu.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/cpu.h	2004-06-23 19:04:25 -07:00
@@ -27,6 +27,7 @@
 
 struct cpu {
 	int node_id;		/* The node which contains the CPU */
+	int no_control;		/* Should the sysfs control file be created? */
 	struct sys_device sysdev;
 };
 
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/device.h	2004-06-23 19:04:28 -07:00
@@ -54,6 +54,9 @@
 	struct kset		drivers;
 	struct kset		devices;
 
+	struct bus_attribute	* bus_attrs;
+	struct device_attribute	* dev_attrs;
+
 	int		(*match)(struct device * dev, struct device_driver * drv);
 	struct device * (*add)	(struct device * parent, char * bus_id);
 	int		(*hotplug) (struct device *dev, char **envp, 
@@ -90,11 +93,7 @@
 };
 
 #define BUS_ATTR(_name,_mode,_show,_store)	\
-struct bus_attribute bus_attr_##_name = { 		\
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
-	.show	= _show,				\
-	.store	= _store,				\
-};
+struct bus_attribute bus_attr_##_name = __ATTR(_name,_mode,_show,_store)
 
 extern int bus_create_file(struct bus_type *, struct bus_attribute *);
 extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
@@ -131,11 +130,7 @@
 };
 
 #define DRIVER_ATTR(_name,_mode,_show,_store)	\
-struct driver_attribute driver_attr_##_name = { 		\
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
-	.show	= _show,				\
-	.store	= _store,				\
-};
+struct driver_attribute driver_attr_##_name = __ATTR(_name,_mode,_show,_store)
 
 extern int driver_create_file(struct device_driver *, struct driver_attribute *);
 extern void driver_remove_file(struct device_driver *, struct driver_attribute *);
@@ -151,6 +146,9 @@
 	struct list_head	children;
 	struct list_head	interfaces;
 
+	struct class_attribute		* class_attrs;
+	struct class_device_attribute	* class_dev_attrs;
+
 	int	(*hotplug)(struct class_device *dev, char **envp, 
 			   int num_envp, char *buffer, int buffer_size);
 
@@ -172,11 +170,7 @@
 };
 
 #define CLASS_ATTR(_name,_mode,_show,_store)			\
-struct class_attribute class_attr_##_name = { 			\
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
-	.show	= _show,					\
-	.store	= _store,					\
-};
+struct class_attribute class_attr_##_name = __ATTR(_name,_mode,_show,_store) 
 
 extern int class_create_file(struct class *, const struct class_attribute *);
 extern void class_remove_file(struct class *, const struct class_attribute *);
@@ -224,11 +218,8 @@
 };
 
 #define CLASS_DEVICE_ATTR(_name,_mode,_show,_store)		\
-struct class_device_attribute class_device_attr_##_name = { 	\
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
-	.show	= _show,					\
-	.store	= _store,					\
-};
+struct class_device_attribute class_device_attr_##_name = 	\
+	__ATTR(_name,_mode,_show,_store)
 
 extern int class_device_create_file(struct class_device *, 
 				    const struct class_device_attribute *);
@@ -342,11 +333,7 @@
 };
 
 #define DEVICE_ATTR(_name,_mode,_show,_store) \
-struct device_attribute dev_attr_##_name = { 		\
-	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
-	.show	= _show,				\
-	.store	= _store,				\
-};
+struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store)
 
 
 extern int device_create_file(struct device *device, struct device_attribute * entry);
@@ -389,6 +376,10 @@
 
 extern struct bus_type platform_bus_type;
 extern struct device platform_bus;
+
+extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int);
+extern int platform_get_irq(struct platform_device *, unsigned int);
+extern int platform_add_devices(struct platform_device **, int);
 
 /* drivers/base/power.c */
 extern void device_shutdown(void);
diff -Nru a/include/linux/dmi.h b/include/linux/dmi.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/dmi.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,47 @@
+#ifndef __DMI_H__
+#define __DMI_H__
+
+enum dmi_field {
+	DMI_NONE,
+	DMI_BIOS_VENDOR,
+	DMI_BIOS_VERSION,
+	DMI_BIOS_DATE,
+	DMI_SYS_VENDOR,
+	DMI_PRODUCT_NAME,
+	DMI_PRODUCT_VERSION,
+	DMI_BOARD_VENDOR,
+	DMI_BOARD_NAME,
+	DMI_BOARD_VERSION,
+	DMI_STRING_MAX,
+};
+
+/*
+ *	DMI callbacks for problem boards
+ */
+struct dmi_strmatch {
+	u8 slot;
+	char *substr;
+};
+
+struct dmi_system_id {
+	int (*callback)(struct dmi_system_id *);
+	char *ident;
+	struct dmi_strmatch matches[4];
+	void *driver_data;
+};
+
+#define DMI_MATCH(a,b)	{ a, b }
+
+#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
+
+extern int dmi_check_system(struct dmi_system_id *list);
+extern char * dmi_get_system_info(int field);
+
+#else
+
+static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
+static inline char * dmi_get_system_info(int field) { return NULL; }
+
+#endif
+
+#endif	/* __DMI_H__ */
diff -Nru a/include/linux/ds1286.h b/include/linux/ds1286.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/ds1286.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1998, 1999, 2003 Ralf Baechle
+ *
+ * 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_DS1286_H
+#define __LINUX_DS1286_H
+
+#include <asm/ds1286.h>
+
+/**********************************************************************
+ * register summary
+ **********************************************************************/
+#define RTC_HUNDREDTH_SECOND	0
+#define RTC_SECONDS		1
+#define RTC_MINUTES		2
+#define RTC_MINUTES_ALARM	3
+#define RTC_HOURS		4
+#define RTC_HOURS_ALARM		5
+#define RTC_DAY			6
+#define RTC_DAY_ALARM		7
+#define RTC_DATE		8
+#define RTC_MONTH		9
+#define RTC_YEAR		10
+#define RTC_CMD			11
+#define RTC_WHSEC		12
+#define RTC_WSEC		13
+#define RTC_UNUSED		14
+
+/* RTC_*_alarm is always true if 2 MSBs are set */
+# define RTC_ALARM_DONT_CARE 	0xC0
+
+
+/*
+ * Bits in the month register
+ */
+#define RTC_EOSC		0x80
+#define RTC_ESQW		0x40
+
+/*
+ * Bits in the Command register
+ */
+#define RTC_TDF			0x01
+#define RTC_WAF			0x02
+#define RTC_TDM			0x04
+#define RTC_WAM			0x08
+#define RTC_PU_LVL		0x10
+#define RTC_IBH_LO		0x20
+#define RTC_IPSW		0x40
+#define RTC_TE			0x80
+
+#endif /* __LINUX_DS1286_H */
diff -Nru a/include/linux/errqueue.h b/include/linux/errqueue.h
--- a/include/linux/errqueue.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/errqueue.h	2004-06-23 19:04:26 -07:00
@@ -22,6 +22,10 @@
 #ifdef __KERNEL__
 
 #include <linux/config.h>
+#include <net/ip.h>
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#include <linux/ipv6.h>
+#endif
 
 #define SKB_EXT_ERR(skb) ((struct sock_exterr_skb *) ((skb)->cb))
 
diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
--- a/include/linux/ext3_fs.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/ext3_fs.h	2004-06-23 19:04:27 -07:00
@@ -689,6 +689,7 @@
 extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
 						    unsigned int block_group,
 						    struct buffer_head ** bh);
+extern int ext3_should_retry_alloc(struct super_block *sb, int *retries);
 
 /* dir.c */
 extern int ext3_check_dir_entry(const char *, struct inode *,
diff -Nru a/include/linux/fb.h b/include/linux/fb.h
--- a/include/linux/fb.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/fb.h	2004-06-23 19:04:26 -07:00
@@ -125,7 +125,8 @@
 	unsigned long mmio_start;	/* Start of Memory Mapped I/O   */
 					/* (physical address) */
 	__u32 mmio_len;			/* Length of Memory Mapped I/O  */
-	__u32 accel;			/* Type of acceleration available */
+	__u32 accel;			/* Indicate to driver which	*/
+					/*  specific chip/card we have	*/
 	__u16 reserved[3];		/* Reserved for future compatibility */
 };
 
@@ -154,7 +155,7 @@
 #define FB_ACTIVATE_ALL	       64	/* change all VCs on this fb	*/
 #define FB_ACTIVATE_FORCE     128	/* force apply even when no change*/
 
-#define FB_ACCELF_TEXT		1	/* text mode acceleration */
+#define FB_ACCELF_TEXT		1	/* (OBSOLETE) see fb_info.flags and vc_mode */
 
 #define FB_SYNC_HOR_HIGH_ACT	1	/* horizontal sync high active	*/
 #define FB_SYNC_VERT_HIGH_ACT	2	/* vertical sync high active	*/
@@ -200,7 +201,7 @@
 	__u32 height;			/* height of picture in mm    */
 	__u32 width;			/* width of picture in mm     */
 
-	__u32 accel_flags;		/* acceleration flags (hints)	*/
+	__u32 accel_flags;		/* (OBSOLETE) see fb_info.flags */
 
 	/* Timing: All values in pixclocks, except pixclock (of course) */
 	__u32 pixclock;			/* pixel clock in ps (pico seconds) */
@@ -375,7 +376,7 @@
 	__u16 set;		/* what to set */
 	__u16 enable;		/* cursor on/off */
 	__u16 rop;		/* bitop operation */
-	char *mask;		/* cursor mask bits */
+	const char *mask;	/* cursor mask bits */
 	struct fbcurpos hot;	/* cursor hot spot */
 	struct fb_image	image;	/* Cursor image */
 };
@@ -458,8 +459,8 @@
 	/* For framebuffers with strange non linear layouts or that do not
 	 * work with normal memory mapped access
 	 */
-	ssize_t (*fb_read)(struct file *file, char *buf, size_t count, loff_t *ppos);
-	ssize_t (*fb_write)(struct file *file, const char *buf, size_t count, loff_t *ppos);
+	ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
+	ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
 
 	/* checks var and eventually tweaks it to something supported,
 	 * DO NOT MODIFY PAR */
@@ -502,10 +503,37 @@
 	int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
 };
 
+/* FBINFO_* = fb_info.flags bit flags */
+#define FBINFO_MODULE		0x0001	/* Low-level driver is a module */
+#define FBINFO_HWACCEL_DISABLED	0x0002
+	/* When FBINFO_HWACCEL_DISABLED is set:
+	 *  Hardware acceleration is turned off.  Software implementations
+	 *  of required functions (copyarea(), fillrect(), and imageblit())
+	 *  takes over; acceleration engine should be in a quiescent state */
+
+/* hints */
+#define FBINFO_PARTIAL_PAN_OK	0x0040 /* otw use pan only for double-buffering */
+#define FBINFO_READS_FAST	0x0080 /* soft-copy faster than rendering */
+
+/* hardware supported ops */
+/*  semantics: when a bit is set, it indicates that the operation is
+ *   accelerated by hardware.
+ *  required functions will still work even if the bit is not set.
+ *  optional functions may not even exist if the flag bit is not set.
+ */
+#define FBINFO_HWACCEL_NONE		0x0000
+#define FBINFO_HWACCEL_COPYAREA		0x0100 /* required */
+#define FBINFO_HWACCEL_FILLRECT		0x0200 /* required */
+#define FBINFO_HWACCEL_IMAGEBLIT	0x0400 /* required */
+#define FBINFO_HWACCEL_ROTATE		0x0800 /* optional */
+#define FBINFO_HWACCEL_XPAN		0x1000 /* optional */
+#define FBINFO_HWACCEL_YPAN		0x2000 /* optional */
+#define FBINFO_HWACCEL_YWRAP		0x4000 /* optional */
+
+
 struct fb_info {
 	int node;
 	int flags;
-#define FBINFO_FLAG_MODULE	1	/* Low-level driver is a module */
 	struct fb_var_screeninfo var;	/* Current var */
 	struct fb_fix_screeninfo fix;	/* Current fix */
 	struct fb_monspecs monspecs;	/* Current Monitor specs */
@@ -527,10 +555,22 @@
 };
 
 #ifdef MODULE
-#define FBINFO_FLAG_DEFAULT	FBINFO_FLAG_MODULE
+#define FBINFO_DEFAULT	FBINFO_MODULE
 #else
-#define FBINFO_FLAG_DEFAULT	0
+#define FBINFO_DEFAULT	0
 #endif
+
+// This will go away
+#define FBINFO_FLAG_MODULE	FBINFO_MODULE
+#define FBINFO_FLAG_DEFAULT	FBINFO_DEFAULT
+
+/* This will go away
+ * fbset currently hacks in FB_ACCELF_TEXT into var.accel_flags
+ * when it wants to turn the acceleration engine on.  This is
+ * really a separate operation, and should be modified via sysfs.
+ *  But for now, we leave it broken with the following define
+ */
+#define STUPID_ACCELF_TEXT_SHIT
 
 // This will go away
 #if defined(__sparc__)
diff -Nru a/include/linux/filter.h b/include/linux/filter.h
--- a/include/linux/filter.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/filter.h	2004-06-23 19:04:28 -07:00
@@ -5,6 +5,8 @@
 #ifndef __LINUX_FILTER_H__
 #define __LINUX_FILTER_H__
 
+#include <linux/compiler.h>
+
 /*
  * Current version of the filter code architecture.
  */
@@ -27,7 +29,7 @@
 struct sock_fprog	/* Required for SO_ATTACH_FILTER. */
 {
 	unsigned short		len;	/* Number of filter blocks */
-	struct sock_filter	*filter;
+	struct sock_filter __user *filter;
 };
 
 #ifdef __KERNEL__
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/fs.h	2004-06-23 19:04:26 -07:00
@@ -214,15 +214,17 @@
 #include <linux/list.h>
 #include <linux/radix-tree.h>
 #include <linux/audit.h>
+#include <linux/init.h>
 #include <asm/semaphore.h>
 #include <asm/byteorder.h>
 
 /* Used to be a macro which just called the function, now just a function */
 extern void update_atime (struct inode *);
 
-extern void inode_init(unsigned long);
-extern void mnt_init(unsigned long);
-extern void files_init(unsigned long);
+extern void __init inode_init(unsigned long);
+extern void __init inode_init_early(void);
+extern void __init mnt_init(unsigned long);
+extern void __init files_init(unsigned long);
 
 struct buffer_head;
 typedef int (get_block_t)(struct inode *inode, sector_t iblock,
@@ -977,7 +979,8 @@
 
 static inline void file_accessed(struct file *file)
 {
-	touch_atime(file->f_vfsmnt, file->f_dentry);
+	if (!(file->f_flags & O_NOATIME))
+		touch_atime(file->f_vfsmnt, file->f_dentry);
 }
 
 int sync_inode(struct inode *inode, struct writeback_control *wbc);
@@ -1199,7 +1202,8 @@
 extern char * getname(const char __user *);
 
 /* fs/dcache.c */
-extern void vfs_caches_init(unsigned long);
+extern void __init vfs_caches_init_early(void);
+extern void __init vfs_caches_init(unsigned long);
 
 #define __getname()	kmem_cache_alloc(names_cachep, SLAB_KERNEL)
 #define __putname(name) kmem_cache_free(names_cachep, (void *)(name))
diff -Nru a/include/linux/fsfilter.h b/include/linux/fsfilter.h
--- a/include/linux/fsfilter.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,134 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#ifndef __FILTER_H_
-#define __FILTER_H_ 1
-
-#ifdef __KERNEL__
-
-/* cachetype.c */
-
-/* 
- * it is important that things like inode, super and file operations
- * for intermezzo are not defined statically.  If methods are NULL
- * the VFS takes special action based on that.  Given that different
- * cache types have NULL ops at different slots, we must install opeation 
- * talbes for InterMezzo with NULL's in the same spot
- */
-
-struct filter_ops { 
-        struct super_operations filter_sops;
-
-        struct inode_operations filter_dir_iops;
-        struct inode_operations filter_file_iops;
-        struct inode_operations filter_sym_iops;
-
-        struct file_operations filter_dir_fops;
-        struct file_operations filter_file_fops;
-        struct file_operations filter_sym_fops;
-
-        struct dentry_operations filter_dentry_ops;
-};
-
-struct cache_ops {
-        /* operations on the file store */
-        struct super_operations *cache_sops;
-
-        struct inode_operations *cache_dir_iops;
-        struct inode_operations *cache_file_iops;
-        struct inode_operations *cache_sym_iops;
-
-        struct file_operations *cache_dir_fops;
-        struct file_operations *cache_file_fops;
-        struct file_operations *cache_sym_fops;
-
-        struct dentry_operations *cache_dentry_ops;
-};
-
-
-#define FILTER_DID_SUPER_OPS 0x1
-#define FILTER_DID_INODE_OPS 0x2
-#define FILTER_DID_FILE_OPS 0x4
-#define FILTER_DID_DENTRY_OPS 0x8
-#define FILTER_DID_DEV_OPS 0x10
-#define FILTER_DID_SYMLINK_OPS 0x20
-#define FILTER_DID_DIR_OPS 0x40
-
-struct filter_fs {
-        int o_flags;
-        struct filter_ops o_fops;
-        struct cache_ops  o_caops;
-        struct journal_ops *o_trops;
-        struct snapshot_ops *o_snops;
-};
-
-#define FILTER_FS_TYPES 6
-#define FILTER_FS_EXT2 0
-#define FILTER_FS_EXT3 1
-#define FILTER_FS_REISERFS 2
-#define FILTER_FS_XFS 3
-#define FILTER_FS_OBDFS 4
-#define FILTER_FS_TMPFS 5
-extern struct filter_fs filter_oppar[FILTER_FS_TYPES];
-
-struct filter_fs *filter_get_filter_fs(const char *cache_type);
-void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type);
-struct super_operations *filter_c2usops(struct filter_fs *cache);
-struct inode_operations *filter_c2ufiops(struct filter_fs *cache);
-struct inode_operations *filter_c2udiops(struct filter_fs *cache);
-struct inode_operations *filter_c2usiops(struct filter_fs *cache);
-struct file_operations *filter_c2uffops(struct filter_fs *cache);
-struct file_operations *filter_c2udfops(struct filter_fs *cache);
-struct file_operations *filter_c2usfops(struct filter_fs *cache);
-struct super_operations *filter_c2csops(struct filter_fs *cache);
-struct inode_operations *filter_c2cfiops(struct filter_fs *cache);
-struct inode_operations *filter_c2cdiops(struct filter_fs *cache);
-struct inode_operations *filter_c2csiops(struct filter_fs *cache);
-struct file_operations *filter_c2cffops(struct filter_fs *cache);
-struct file_operations *filter_c2cdfops(struct filter_fs *cache);
-struct file_operations *filter_c2csfops(struct filter_fs *cache);
-struct dentry_operations *filter_c2cdops(struct filter_fs *cache);
-struct dentry_operations *filter_c2udops(struct filter_fs *cache);
-
-void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_ops, struct super_operations *filter_sops);
-void filter_setup_dir_ops(struct filter_fs *cache, struct inode *cache_inode, struct inode_operations *filter_iops, struct file_operations *ffops);
-void filter_setup_file_ops(struct filter_fs *cache, struct inode *cache_inode, struct inode_operations *filter_iops, struct file_operations *filter_op);
-void filter_setup_symlink_ops(struct filter_fs *cache, struct inode *cache_inode, struct inode_operations *filter_iops, struct file_operations *filter_op);
-void filter_setup_dentry_ops(struct filter_fs *cache, struct dentry_operations *cache_dop,  struct dentry_operations *filter_dop);
-
-
-#define PRESTO_DEBUG
-#ifdef PRESTO_DEBUG
-/* debugging masks */
-#define D_SUPER     1  
-#define D_INODE     2   /* print entry and exit into procedure */
-#define D_FILE      4
-#define D_CACHE     8   /* cache debugging */
-#define D_MALLOC    16  /* print malloc, de-alloc information */
-#define D_JOURNAL   32
-#define D_UPCALL    64  /* up and downcall debugging */
-#define D_PSDEV    128
-#define D_PIOCTL   256
-#define D_SPECIAL  512
-#define D_TIMING  1024
-#define D_DOWNCALL 2048
-
-#define FDEBUG(mask, format, a...)                                      \
-        do {                                                            \
-                if (filter_debug & mask) {                              \
-                        printk("(%s,l. %d): ", __FUNCTION__, __LINE__); \
-                        printk(format, ##a); }                          \
-        } while (0)
-
-#define FENTRY                                                          \
-        if(filter_print_entry)                                          \
-                printk("Process %d entered %s\n", current->pid, __FUNCTION__)
-
-#define FEXIT                                                           \
-        if(filter_print_entry)                                          \
-                printk("Process %d leaving %s at %d\n", current->pid,   \
-                       __FUNCTION__,__LINE__)
-#endif
-#endif
-#endif
diff -Nru a/include/linux/hpet.h b/include/linux/hpet.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/hpet.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,133 @@
+#ifndef	__HPET__
+#define	__HPET__ 1
+
+/*
+ * Offsets into HPET Registers
+ */
+
+struct hpet {
+	u64 hpet_cap;		/* capabilities */
+	u64 res0;		/* reserved */
+	u64 hpet_config;	/* configuration */
+	u64 res1;		/* reserved */
+	u64 hpet_isr;		/* interrupt status reg */
+	u64 res2[25];		/* reserved */
+	union {			/* main counter */
+		u64 _hpet_mc64;
+		u32 _hpet_mc32;
+		unsigned long _hpet_mc;
+	} _u0;
+	u64 res3;		/* reserved */
+	struct hpet_timer {
+		u64 hpet_config;	/* configuration/cap */
+		union {		/* timer compare register */
+			u64 _hpet_hc64;
+			u32 _hpet_hc32;
+			unsigned long _hpet_compare;
+		} _u1;
+		u64 hpet_fsb[2];	/* FSB route */
+	} hpet_timers[1];
+};
+
+#define	hpet_mc		_u0._hpet_mc
+#define	hpet_compare	_u1._hpet_compare
+
+#define	HPET_MAX_TIMERS	(32)
+
+/*
+ * HPET general capabilities register
+ */
+
+#define	HPET_COUNTER_CLK_PERIOD_MASK	(0xffffffff00000000ULL)
+#define	HPET_COUNTER_CLK_PERIOD_SHIFT	(32UL)
+#define	HPET_VENDOR_ID_MASK		(0x00000000ffff0000ULL)
+#define	HPET_VENDOR_ID_SHIFT		(16ULL)
+#define	HPET_LEG_RT_CAP_MASK		(0x8000)
+#define	HPET_COUNTER_SIZE_MASK		(0x2000)
+#define	HPET_NUM_TIM_CAP_MASK		(0x1f00)
+#define	HPET_NUM_TIM_CAP_SHIFT		(8ULL)
+
+/*
+ * HPET general configuration register
+ */
+
+#define	HPET_LEG_RT_CNF_MASK		(2UL)
+#define	HPET_ENABLE_CNF_MASK		(1UL)
+
+/*
+ * HPET interrupt status register
+ */
+
+#define	HPET_ISR_CLEAR(HPET, TIMER)				\
+		(HPET)->hpet_isr |= (1UL << TIMER)
+
+/*
+ * Timer configuration register
+ */
+
+#define	Tn_INT_ROUTE_CAP_MASK		(0xffffffff00000000ULL)
+#define	Tn_INI_ROUTE_CAP_SHIFT		(32UL)
+#define	Tn_FSB_INT_DELCAP_MASK		(0x8000UL)
+#define	Tn_FSB_INT_DELCAP_SHIFT		(15)
+#define	Tn_FSB_EN_CNF_MASK		(0x4000UL)
+#define	Tn_FSB_EN_CNF_SHIFT		(14)
+#define	Tn_INT_ROUTE_CNF_MASK		(0x3e00UL)
+#define	Tn_INT_ROUTE_CNF_SHIFT		(9)
+#define	Tn_32MODE_CNF_MASK		(0x0100UL)
+#define	Tn_VAL_SET_CNF_MASK		(0x0040UL)
+#define	Tn_SIZE_CAP_MASK		(0x0020UL)
+#define	Tn_PER_INT_CAP_MASK		(0x0010UL)
+#define	Tn_TYPE_CNF_MASK		(0x0008UL)
+#define	Tn_INT_ENB_CNF_MASK		(0x0004UL)
+#define	Tn_INT_TYPE_CNF_MASK		(0x0002UL)
+
+/*
+ * Timer FSB Interrupt Route Register
+ */
+
+#define	Tn_FSB_INT_ADDR_MASK		(0xffffffff00000000ULL)
+#define	Tn_FSB_INT_ADDR_SHIFT		(32UL)
+#define	Tn_FSB_INT_VAL_MASK		(0x00000000ffffffffULL)
+
+struct hpet_info {
+	unsigned long hi_ireqfreq;	/* Hz */
+	unsigned long hi_flags;	/* information */
+	unsigned short hi_hpet;
+	unsigned short hi_timer;
+};
+
+#define	HPET_INFO_PERIODIC	0x0001	/* timer is periodic */
+
+#define	HPET_IE_ON	_IO('h', 0x01)	/* interrupt on */
+#define	HPET_IE_OFF	_IO('h', 0x02)	/* interrupt off */
+#define	HPET_INFO	_IOR('h', 0x03, struct hpet_info)
+#define	HPET_EPI	_IO('h', 0x04)	/* enable periodic */
+#define	HPET_DPI	_IO('h', 0x05)	/* disable periodic */
+#define	HPET_IRQFREQ	_IOW('h', 0x6, unsigned long)	/* IRQFREQ usec */
+
+/*
+ * exported interfaces
+ */
+
+struct hpet_task {
+	void (*ht_func) (void *);
+	void *ht_data;
+	void *ht_opaque;
+};
+
+struct hpet_data {
+	unsigned long hd_address;
+	unsigned short hd_nirqs;
+	unsigned short hd_flags;
+	unsigned int hd_state;	/* timer allocated */
+	unsigned int hd_irq[HPET_MAX_TIMERS];
+};
+
+#define	HPET_DATA_PLATFORM	0x0001	/* platform call to hpet_alloc */
+
+int hpet_alloc(struct hpet_data *);
+int hpet_register(struct hpet_task *, int);
+int hpet_unregister(struct hpet_task *);
+int hpet_control(struct hpet_task *, unsigned int, unsigned long);
+
+#endif				/* !__HPET__ */
diff -Nru a/include/linux/i2c-id.h b/include/linux/i2c-id.h
--- a/include/linux/i2c-id.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/i2c-id.h	2004-06-23 19:04:25 -07:00
@@ -101,6 +101,14 @@
 #define I2C_DRIVERID_UDA1342	53	/* UDA1342 audio codec		*/
 #define I2C_DRIVERID_ADV7170	54	/* video encoder		*/
 #define I2C_DRIVERID_RADEON	55	/* I2C bus on Radeon boards	*/
+#define I2C_DRIVERID_MAX1617	56	/* temp sensor			*/
+#define I2C_DRIVERID_SAA7191	57	/* video encoder		*/
+#define I2C_DRIVERID_INDYCAM	58	/* SGI IndyCam			*/
+#define I2C_DRIVERID_BT832	59	/* CMOS camera video processor	*/
+#define I2C_DRIVERID_TDA9887	60	/* TDA988x IF-PLL demodulator	*/
+#define I2C_DRIVERID_OVCAMCHIP	61	/* OmniVision CMOS image sens.	*/
+#define I2C_DRIVERID_TDA7313	62	/* TDA7313 audio processor	*/
+#define I2C_DRIVERID_MAX6900	63	/* MAX6900 real-time clock	*/
 
 
 #define I2C_DRIVERID_EXP0	0xF0	/* experimental use id's	*/
@@ -264,6 +272,10 @@
 #define I2C_HW_SMBUS_SCX200	0x0b
 #define I2C_HW_SMBUS_NFORCE2	0x0c
 #define I2C_HW_SMBUS_W9968CF	0x0d
+#define I2C_HW_SMBUS_OV511	0x0e	/* OV511(+) USB 1.1 webcam ICs	*/
+#define I2C_HW_SMBUS_OV518	0x0f	/* OV518(+) USB 1.1 webcam ICs	*/
+#define I2C_HW_SMBUS_OV519	0x10	/* OV519 USB 1.1 webcam IC	*/
+#define I2C_HW_SMBUS_OVFX2	0x11	/* Cypress/OmniVision FX2 webcam */
 
 /* --- ISA pseudo-adapter						*/
 #define I2C_HW_ISA 0x00
diff -Nru a/include/linux/i2o.h b/include/linux/i2o.h
--- a/include/linux/i2o.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/i2o.h	2004-06-23 19:04:26 -07:00
@@ -99,6 +99,7 @@
 	int		irq;
 	int		short_req:1;	/* Use small block sizes        */
 	int		dpt:1;		/* Don't quiesce                */
+	int		raptor:1;	/* split bar                    */
 	int		promise:1;	/* Promise controller		*/
 #ifdef CONFIG_MTRR
 	int		mtrr_reg0;
@@ -109,9 +110,9 @@
 	atomic_t users;
 	struct i2o_device *devices;		/* I2O device chain */
 	struct i2o_controller *next;		/* Controller chain */
-	unsigned long post_port;		/* Inbout port address */
-	unsigned long reply_port;		/* Outbound port address */
-	unsigned long irq_mask;			/* Interrupt register address */
+	void *post_port;			/* Inbout port address */
+	void *reply_port;			/* Outbound port address */
+	void *irq_mask;				/* Interrupt register address */
 
 	/* Dynamic LCT related data */
 	struct semaphore lct_sem;
@@ -128,8 +129,11 @@
 	dma_addr_t hrt_phys;
 	u32 hrt_len;
 
-	unsigned long mem_offset;		/* MFA offset */
-	unsigned long mem_phys;			/* MFA physical */
+	void *base_virt;			/* base virtual address */
+	unsigned long base_phys;		/* base physical address */
+
+	void *msg_virt;				/* messages virtual address */
+	unsigned long msg_phys;			/* messages physical address */
 
 	int battery:1;				/* Has a battery backup */
 	int io_alloc:1;				/* An I/O resource was allocated */
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/ide.h	2004-06-23 19:04:26 -07:00
@@ -255,7 +255,7 @@
 		ide_pdc4030,	ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
 		ide_pmac,	ide_etrax100,	ide_acorn,
-		ide_pc9800,	ide_forced
+		ide_forced
 } hwif_chipset_t;
 
 /*
diff -Nru a/include/linux/idr.h b/include/linux/idr.h
--- a/include/linux/idr.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/idr.h	2004-06-23 19:04:25 -07:00
@@ -1,5 +1,5 @@
 /*
- * include/linux/id.h
+ * include/linux/idr.h
  * 
  * 2002-10-18  written by Jim Houston jim.houston@ccur.com
  *	Copyright (C) 2002 by Concurrent Computer Corporation
@@ -11,14 +11,20 @@
 #include <linux/types.h>
 #include <asm/bitops.h>
 
-#define RESERVED_ID_BITS 8
-
 #if BITS_PER_LONG == 32
 # define IDR_BITS 5
 # define IDR_FULL 0xfffffffful
+/* We can only use two of the bits in the top level because there is
+   only one possible bit in the top level (5 bits * 7 levels = 35
+   bits, but you only use 31 bits in the id). */
+# define TOP_LEVEL_FULL (IDR_FULL >> 30)
 #elif BITS_PER_LONG == 64
 # define IDR_BITS 6
 # define IDR_FULL 0xfffffffffffffffful
+/* We can only use two of the bits in the top level because there is
+   only one possible bit in the top level (6 bits * 6 levels = 36
+   bits, but you only use 31 bits in the id). */
+# define TOP_LEVEL_FULL (IDR_FULL >> 62)
 #else
 # error "BITS_PER_LONG is not 32 or 64"
 #endif
@@ -26,11 +32,8 @@
 #define IDR_SIZE (1 << IDR_BITS)
 #define IDR_MASK ((1 << IDR_BITS)-1)
 
-/* Define the size of the id's */
-#define BITS_PER_INT (sizeof(int)*8)
-
-#define MAX_ID_SHIFT (BITS_PER_INT - RESERVED_ID_BITS)
-#define MAX_ID_BIT (1 << MAX_ID_SHIFT)
+#define MAX_ID_SHIFT (sizeof(int)*8 - 1)
+#define MAX_ID_BIT (1U << MAX_ID_SHIFT)
 #define MAX_ID_MASK (MAX_ID_BIT - 1)
 
 /* Leave the possibility of an incomplete final layer */
@@ -40,25 +43,23 @@
 #define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL
 
 struct idr_layer {
-	unsigned long		 bitmap;	/* A zero bit means "space here" */
+	unsigned long		 bitmap; /* A zero bit means "space here" */
 	struct idr_layer	*ary[1<<IDR_BITS];
-	int			 count;		/* When zero, we can release it */
+	int			 count;	 /* When zero, we can release it */
 };
 
 struct idr {
 	struct idr_layer *top;
 	struct idr_layer *id_free;
-	long		  count;
 	int		  layers;
 	int		  id_free_cnt;
 	spinlock_t	  lock;
 };
 
-#define IDR_INIT(name)	\
+#define IDR_INIT(name)						\
 {								\
 	.top		= NULL,					\
 	.id_free	= NULL,					\
-	.count		= 0,					\
 	.layers 	= 0,					\
 	.id_free_cnt	= 0,					\
 	.lock		= SPIN_LOCK_UNLOCKED,			\
@@ -71,9 +72,9 @@
 
 void *idr_find(struct idr *idp, int id);
 int idr_pre_get(struct idr *idp, unsigned gfp_mask);
-int idr_get_new(struct idr *idp, void *ptr);
+int idr_get_new(struct idr *idp, void *ptr, int *id);
+int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
 void idr_remove(struct idr *idp, int id);
 void idr_init(struct idr *idp);
 
 extern kmem_cache_t *idr_layer_cache;
-
diff -Nru a/include/linux/if.h b/include/linux/if.h
--- a/include/linux/if.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/if.h	2004-06-23 19:04:26 -07:00
@@ -108,15 +108,15 @@
 	unsigned int size;	/* Size of the data allocated by the caller */
 	union {
 		/* {atm/eth/dsl}_settings anyone ? */
-		raw_hdlc_proto		*raw_hdlc;
-		cisco_proto		*cisco;
-		fr_proto		*fr;
-		fr_proto_pvc		*fr_pvc;
-		fr_proto_pvc_info	*fr_pvc_info;
+		raw_hdlc_proto		__user *raw_hdlc;
+		cisco_proto		__user *cisco;
+		fr_proto		__user *fr;
+		fr_proto_pvc		__user *fr_pvc;
+		fr_proto_pvc_info	__user *fr_pvc_info;
 
 		/* interface settings */
-		sync_serial_settings	*sync;
-		te1_settings		*te1;
+		sync_serial_settings	__user *sync;
+		te1_settings		__user *te1;
 	} ifs_ifsu;
 };
 
diff -Nru a/include/linux/in_systm.h b/include/linux/in_systm.h
--- a/include/linux/in_systm.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,32 +0,0 @@
-/*
- * INET		An implementation of the TCP/IP protocol suite for the LINUX
- *		operating system.  INET is implemented using the  BSD Socket
- *		interface as the means of communication with the user level.
- *
- *		Miscellaneous internetwork definitions for kernel.
- *
- * Version:	@(#)in_systm.h  1.0.0   12/17/93
- *
- * Authors:	Original taken from Berkeley BSD UNIX 4.3-RENO.
- *		Fred N. van Kempen, <waltje@uwalt.nl.mugnet.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.
- */
-#ifndef _LINUX_IN_SYSTM_H
-#define _LINUX_IN_SYSTM_H
-
-/*
- * Network types.
- * The n_ types are network-order variants of their natural
- * equivalents.  The Linux kernel NET-2 code does not use
- * them (yet), but it might in the future.  This is mostly
- * there for compatibility with BSD user-level programs.
- */
-typedef u_short	n_short;	/* short as received from the net	*/
-typedef u_long	n_long;		/* long as received from the net	*/
-typedef u_long	n_time;		/* ms since 00:00 GMT, byte rev		*/
-
-#endif /* _LINUX_IN_SYSTM_H */
diff -Nru a/include/linux/ipmi.h b/include/linux/ipmi.h
--- a/include/linux/ipmi.h	2004-06-23 19:04:29 -07:00
+++ b/include/linux/ipmi.h	2004-06-23 19:04:29 -07:00
@@ -373,6 +373,16 @@
 			     int                  priority);
 
 /*
+ * Do polling on the IPMI interface the user is attached to.  This
+ * causes the IPMI code to do an immediate check for information from
+ * the driver and handle anything that is immediately pending.  This
+ * will not block in anyway.  This is useful if you need to implement
+ * polling from the user like you need to send periodic watchdog pings
+ * from a crash dump, or something like that.
+ */
+void ipmi_poll_interface(ipmi_user_t user);
+
+/*
  * When commands come in to the SMS, the user can register to receive
  * them.  Only one user can be listening on a specific netfn/cmd pair
  * at a time, you will get an EBUSY error if the command is already
@@ -488,7 +498,7 @@
 /* Messages sent to the interface are this format. */
 struct ipmi_req
 {
-	unsigned char *addr; /* Address to send the message to. */
+	unsigned char __user *addr; /* Address to send the message to. */
 	unsigned int  addr_len;
 
 	long    msgid; /* The sequence number for the message.  This
@@ -539,7 +549,7 @@
 	int     recv_type; /* Is this a command, response or an
 			      asyncronous event. */
 
-	unsigned char *addr;    /* Address the message was from is put
+	unsigned char __user *addr;    /* Address the message was from is put
 				   here.  The caller must supply the
 				   memory. */
 	unsigned int  addr_len; /* The size of the address buffer.
diff -Nru a/include/linux/ipmi_msgdefs.h b/include/linux/ipmi_msgdefs.h
--- a/include/linux/ipmi_msgdefs.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/ipmi_msgdefs.h	2004-06-23 19:04:28 -07:00
@@ -71,6 +71,7 @@
 
 #define IPMI_CC_NO_ERROR		0x00
 #define IPMI_NODE_BUSY_ERR		0xc0
+#define IPMI_INVALID_COMMAND_ERR	0xc1
 #define IPMI_ERR_MSG_TRUNCATED		0xc6
 #define IPMI_LOST_ARBITRATION_ERR	0x81
 #define IPMI_ERR_UNSPECIFIED		0xff
diff -Nru a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
--- a/include/linux/ipmi_smi.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/ipmi_smi.h	2004-06-23 19:04:27 -07:00
@@ -100,6 +100,10 @@
 	   out and that none are pending, and any new requests are run
 	   to completion immediately. */
 	void (*set_run_to_completion)(void *send_info, int run_to_completion);
+
+	/* 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);
 };
 
 /* Add a low-level interface to the IPMI driver. */
diff -Nru a/include/linux/isdn_lzscomp.h b/include/linux/isdn_lzscomp.h
--- a/include/linux/isdn_lzscomp.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,28 +0,0 @@
-/* $Id: isdn_lzscomp.h,v 1.1.10.1 2001/09/23 22:25:05 kai Exp $
- *
- * Header for isdn_lzscomp.c
- * Concentrated here to not mess up half a dozen kernel headers with code
- * snippets
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#define CI_LZS_COMPRESS		17
-#define CILEN_LZS_COMPRESS	5
-
-#define LZS_CMODE_NONE		0
-#define LZS_CMODE_LCB		1
-#define LZS_CMODE_CRC		2
-#define LZS_CMODE_SEQNO		3	/* MUST be implemented (default) */
-#define LZS_CMODE_EXT		4	/* Seems to be what Win0.95 uses */
-
-#define LZS_COMP_MAX_HISTS	1	/* Don't waste peers ressources */
-#define LZS_COMP_DEF_HISTS	1	/* Most likely to negotiate */
-#define LZS_DECOMP_MAX_HISTS	32	/* More is really nonsense */
-#define LZS_DECOMP_DEF_HISTS	8	/* If we get it, this may be optimal */
-
-#define LZS_HIST_BYTE1(word)   	(word>>8)	/* Just for better reading */
-#define LZS_HIST_BYTE2(word)	(word&0xff)	/* of this big endian stuff */
-#define LZS_HIST_WORD(b1,b2)	((b1<<8)|b2)	/* (network byte order rulez) */
diff -Nru a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h
--- a/include/linux/isdn_ppp.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/isdn_ppp.h	2004-06-23 19:04:26 -07:00
@@ -233,8 +233,9 @@
   struct slcompress *slcomp;
 #endif
 #ifdef CONFIG_IPPP_FILTER
-  struct sock_fprog pass_filter;	/* filter for packets to pass */
-  struct sock_fprog active_filter;	/* filter for pkts to reset idle */
+  struct sock_filter *pass_filter;	/* filter for packets to pass */
+  struct sock_filter *active_filter;	/* filter for pkts to reset idle */
+  unsigned pass_len, active_len;
 #endif
   unsigned long debug;
   struct isdn_ppp_compressor *compressor,*decompressor;
diff -Nru a/include/linux/iso_fs.h b/include/linux/iso_fs.h
--- a/include/linux/iso_fs.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/iso_fs.h	2004-06-23 19:04:27 -07:00
@@ -231,9 +231,69 @@
 extern struct buffer_head *isofs_bread(struct inode *, sector_t);
 extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
 
+extern struct inode *isofs_iget(struct super_block *sb,
+                                unsigned long block,
+                                unsigned long offset);
+
+/* Because the inode number is no longer relevant to finding the
+ * underlying meta-data for an inode, we are free to choose a more
+ * convenient 32-bit number as the inode number.  The inode numbering
+ * scheme was recommended by Sergey Vlasov and Eric Lammerts. */
+static inline unsigned long isofs_get_ino(unsigned long block,
+					  unsigned long offset,
+					  unsigned long bufbits)
+{
+	return (block << (bufbits - 5)) | (offset >> 5);
+}
+
+/* Every directory can have many redundant directory entries scattered
+ * throughout the directory tree.  First there is the directory entry
+ * with the name of the directory stored in the parent directory.
+ * Then, there is the "." directory entry stored in the directory
+ * itself.  Finally, there are possibly many ".." directory entries
+ * stored in all the subdirectories.
+ *
+ * In order for the NFS get_parent() method to work and for the
+ * general consistency of the dcache, we need to make sure the
+ * "i_iget5_block" and "i_iget5_offset" all point to exactly one of
+ * the many redundant entries for each directory.  We normalize the
+ * block and offset by always making them point to the "."  directory.
+ *
+ * Notice that we do not use the entry for the directory with the name
+ * that is located in the parent directory.  Even though choosing this
+ * first directory is more natural, it is much easier to find the "."
+ * entry in the NFS get_parent() method because it is implicitly
+ * encoded in the "extent + ext_attr_length" fields of _all_ the
+ * redundant entries for the directory.  Thus, it can always be
+ * reached regardless of which directory entry you have in hand.
+ *
+ * This works because the "." entry is simply the first directory
+ * record when you start reading the file that holds all the directory
+ * records, and this file starts at "extent + ext_attr_length" blocks.
+ * Because the "." entry is always the first entry listed in the
+ * directories file, the normalized "offset" value is always 0.
+ *
+ * You should pass the directory entry in "de".  On return, "block"
+ * and "offset" will hold normalized values.  Only directories are
+ * affected making it safe to call even for non-directory file
+ * types. */
+static void inline
+isofs_normalize_block_and_offset(struct iso_directory_record* de,
+				 unsigned long *block,
+				 unsigned long *offset)
+{
+	/* Only directories are normalized. */
+	if (de->flags[0] & 2) {
+		*offset = 0;
+		*block = (unsigned long)isonum_733(de->extent)
+			+ (unsigned long)isonum_711(de->ext_attr_length);
+	}
+}
+
 extern struct inode_operations isofs_dir_inode_operations;
 extern struct file_operations isofs_dir_operations;
 extern struct address_space_operations isofs_symlink_aops;
+extern struct export_operations isofs_export_ops;
 
 /* The following macros are used to check for memory leaks. */
 #ifdef LEAK_CHECK
diff -Nru a/include/linux/iso_fs_i.h b/include/linux/iso_fs_i.h
--- a/include/linux/iso_fs_i.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/iso_fs_i.h	2004-06-23 19:04:26 -07:00
@@ -13,10 +13,13 @@
  * iso fs inode data in memory
  */
 struct iso_inode_info {
+	unsigned long i_iget5_block;
+	unsigned long i_iget5_offset;
 	unsigned int i_first_extent;
 	unsigned char i_file_format;
 	unsigned char i_format_parm[3];
-	unsigned long i_next_section_ino;
+	unsigned long i_next_section_block;
+	unsigned long i_next_section_offset;
 	off_t i_section_size;
 	struct inode vfs_inode;
 };
diff -Nru a/include/linux/ixjuser.h b/include/linux/ixjuser.h
--- a/include/linux/ixjuser.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/ixjuser.h	2004-06-23 19:04:25 -07:00
@@ -350,7 +350,7 @@
 typedef struct {
 	int elements_used;
 	IXJ_CADENCE_TERM termination;
-	IXJ_CADENCE_ELEMENT *ce;
+	IXJ_CADENCE_ELEMENT __user *ce;
 } IXJ_CADENCE;
 
 #define IXJCTL_TONE_CADENCE		_IOW ('q', 0xCA, IXJ_CADENCE *)
diff -Nru a/include/linux/jbd.h b/include/linux/jbd.h
--- a/include/linux/jbd.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/jbd.h	2004-06-23 19:04:28 -07:00
@@ -1006,6 +1006,7 @@
 int log_start_commit(journal_t *journal, tid_t tid);
 int __log_start_commit(journal_t *journal, tid_t tid);
 int journal_start_commit(journal_t *journal, tid_t *tid);
+int journal_force_commit_nested(journal_t *journal);
 int log_wait_commit(journal_t *journal, tid_t tid);
 int log_do_checkpoint(journal_t *journal);
 
diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/kernel.h	2004-06-23 19:04:25 -07:00
@@ -92,6 +92,15 @@
 
 unsigned long int_sqrt(unsigned long);
 
+static inline int __attribute_pure__ long_log2(unsigned long x)
+{
+	int r = 0;
+	for (x >>= 1; x > 0; x >>= 1)
+		r++;
+	return r;
+}
+
+
 extern int printk_ratelimit(void);
 extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
 
diff -Nru a/include/linux/libata.h b/include/linux/libata.h
--- a/include/linux/libata.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/libata.h	2004-06-23 19:04:25 -07:00
@@ -91,6 +91,7 @@
 	ATA_DFLAG_MASTER	= (1 << 2), /* is device 0? */
 	ATA_DFLAG_WCACHE	= (1 << 3), /* has write cache we can
 					     * (hopefully) flush? */
+	ATA_DFLAG_LOCK_SECTORS	= (1 << 4), /* don't adjust max_sectors */
 
 	ATA_DEV_UNKNOWN		= 0,	/* unknown device */
 	ATA_DEV_ATA		= 1,	/* ATA device */
@@ -133,24 +134,10 @@
 	BUS_IDENTIFY		= 8,
 	BUS_PACKET		= 9,
 
-	/* thread states */
-	THR_UNKNOWN		= 0,
-	THR_PORT_RESET		= (THR_UNKNOWN + 1),
-	THR_AWAIT_DEATH		= (THR_PORT_RESET + 1),
-	THR_PROBE_FAILED	= (THR_AWAIT_DEATH + 1),
-	THR_IDLE		= (THR_PROBE_FAILED + 1),
-	THR_PROBE_SUCCESS	= (THR_IDLE + 1),
-	THR_PROBE_START		= (THR_PROBE_SUCCESS + 1),
-
 	/* SATA port states */
 	PORT_UNKNOWN		= 0,
 	PORT_ENABLED		= 1,
 	PORT_DISABLED		= 2,
-
-	/* ata_qc_cb_t flags - note uses above ATA_QCFLAG_xxx namespace,
-	 * but not numberspace
-	 */
-	ATA_QCFLAG_TIMEOUT	= (1 << 0),
 };
 
 enum pio_task_states {
@@ -294,18 +281,12 @@
 	struct ata_host_stats	stats;
 	struct ata_host_set	*host_set;
 
-	struct semaphore	probe_sem;
-
-	unsigned int		thr_state;
-
 	struct work_struct	packet_task;
 
 	struct work_struct	pio_task;
 	unsigned int		pio_task_state;
 	unsigned long		pio_task_timeout;
 
-	struct work_struct	probe_task;
-
 	void			*private_data;
 };
 
@@ -330,7 +311,7 @@
 
 	void (*bmdma_setup) (struct ata_queued_cmd *qc);
 	void (*bmdma_start) (struct ata_queued_cmd *qc);
-	void (*fill_sg) (struct ata_queued_cmd *qc);
+	void (*qc_prep) (struct ata_queued_cmd *qc);
 	void (*eng_timeout) (struct ata_port *ap);
 
 	irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
@@ -390,7 +371,7 @@
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
-extern void ata_fill_sg(struct ata_queued_cmd *qc);
+extern void ata_qc_prep(struct ata_queued_cmd *qc);
 extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
 			      unsigned int ofs, unsigned int len);
 extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
@@ -554,6 +535,46 @@
 static inline unsigned int sata_dev_present(struct ata_port *ap)
 {
 	return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
+}
+
+static inline void ata_bmdma_stop(struct ata_port *ap)
+{
+	if (ap->flags & ATA_FLAG_MMIO) {
+		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+
+		/* clear start/stop bit */
+		writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
+		      mmio + ATA_DMA_CMD);
+	} else {
+		/* clear start/stop bit */
+		outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
+		    ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	}
+
+	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+	ata_altstatus(ap);	      /* dummy read */
+}
+
+static inline void ata_bmdma_ack_irq(struct ata_port *ap)
+{
+	if (ap->flags & ATA_FLAG_MMIO) {
+		void *mmio = ((void *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
+		writeb(readb(mmio), mmio);
+	} else {
+		unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
+		outb(inb(addr), addr);
+	}
+}
+
+static inline u8 ata_bmdma_status(struct ata_port *ap)
+{
+	u8 host_stat;
+	if (ap->flags & ATA_FLAG_MMIO) {
+		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		host_stat = readb(mmio + ATA_DMA_STATUS);
+	} else
+		host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	return host_stat;
 }
 
 #endif /* __LINUX_LIBATA_H__ */
diff -Nru a/include/linux/mca.h b/include/linux/mca.h
--- a/include/linux/mca.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/mca.h	2004-06-23 19:04:26 -07:00
@@ -12,7 +12,9 @@
 #include <linux/device.h>
 
 /* get the platform specific defines */
+#ifdef CONFIG_MCA
 #include <asm/mca.h>
+#endif
 
 /* The detection of MCA bus is done in the real mode (using BIOS).
  * The information is exported to the protected code, where this
diff -Nru a/include/linux/mempolicy.h b/include/linux/mempolicy.h
--- a/include/linux/mempolicy.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/mempolicy.h	2004-06-23 19:04:25 -07:00
@@ -153,6 +153,9 @@
 struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp,
 					    unsigned long idx);
 
+extern void numa_default_policy(void);
+extern void numa_policy_init(void);
+
 #else
 
 struct mempolicy {};
@@ -214,6 +217,14 @@
 
 #define vma_policy(vma) NULL
 #define vma_set_policy(vma, pol) do {} while(0)
+
+static inline void numa_policy_init(void)
+{
+}
+
+static inline void numa_default_policy(void)
+{
+}
 
 #endif /* CONFIG_NUMA */
 #endif /* __KERNEL__ */
diff -Nru a/include/linux/miscdevice.h b/include/linux/miscdevice.h
--- a/include/linux/miscdevice.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/miscdevice.h	2004-06-23 19:04:27 -07:00
@@ -33,6 +33,7 @@
 #define SGI_STREAMS_KEYBOARD 150
 /* drivers/sgi/char/usema.c */
 #define SGI_USEMACLONE	     151
+#define	HPET_MINOR	     152
 
 #define TUN_MINOR	     200
 
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/mmzone.h	2004-06-23 19:04:27 -07:00
@@ -20,6 +20,18 @@
 #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
 #endif
 
+/*
+ * system hash table size limits
+ * - on large memory machines, we may want to allocate a bigger hash than that
+ *   permitted by MAX_ORDER, so we allocate with the bootmem allocator, and are
+ *   limited to this size
+ */
+#if MAX_ORDER > 14
+#define MAX_SYS_HASH_TABLE_ORDER MAX_ORDER
+#else
+#define MAX_SYS_HASH_TABLE_ORDER 14
+#endif
+
 struct free_area {
 	struct list_head	free_list;
 	unsigned long		*map;
diff -Nru a/include/linux/module.h b/include/linux/module.h
--- a/include/linux/module.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/module.h	2004-06-23 19:04:28 -07:00
@@ -225,6 +225,22 @@
 	struct module_attribute attr[0];
 };
 
+/* Similar stuff for section attributes. */
+#define MODULE_SECT_NAME_LEN 32
+struct module_sect_attr
+{
+	struct attribute attr;
+	char name[MODULE_SECT_NAME_LEN];
+	unsigned long address;
+};
+
+struct module_sections
+{
+	struct kobject kobj;
+	struct module_sect_attr attrs[0];
+};
+
+
 struct module
 {
 	enum module_state state;
@@ -298,6 +314,9 @@
 	Elf_Sym *symtab;
 	unsigned long num_symtab;
 	char *strtab;
+
+	/* Section attributes */
+	struct module_sections *sect_attrs;
 #endif
 
 	/* Per-cpu data. */
diff -Nru a/include/linux/mpp.h b/include/linux/mpp.h
--- a/include/linux/mpp.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,18 +0,0 @@
-#ifndef _LINUX_MPP_H
-#define _LINUX_MPP_H
-
-/*
- * Definitions related to Massively Parallel Processing support.
- */
-
-/* All mpp implementations must supply these functions */
-
-extern void mpp_init(void);
-extern void mpp_hw_init(void);
-extern void mpp_procfs_init(void);
-
-extern int mpp_num_cells(void);
-extern int mpp_cid(void);
-extern int get_mppinfo(char *buffer);
-
-#endif
diff -Nru a/include/linux/mqueue.h b/include/linux/mqueue.h
--- a/include/linux/mqueue.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/mqueue.h	2004-06-23 19:04:27 -07:00
@@ -21,6 +21,8 @@
 #include <linux/types.h>
 
 #define MQ_PRIO_MAX 	32768
+/* per-uid limit of kernel memory used by mqueue, in bytes */
+#define MQ_BYTES_MAX	819200
 
 struct mq_attr {
 	long	mq_flags;	/* message queue flags			*/
diff -Nru a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
--- a/include/linux/ncp_fs.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/ncp_fs.h	2004-06-23 19:04:26 -07:00
@@ -24,7 +24,7 @@
 struct ncp_ioctl_request {
 	unsigned int function;
 	unsigned int size;
-	char *data;
+	char __user *data;
 };
 
 struct ncp_fs_info {
@@ -88,13 +88,13 @@
 #define NCP_AUTH_NDS	0x32
 	int		auth_type;
 	size_t		object_name_len;
-	void*		object_name;	/* an userspace data, in most cases user name */
+	void __user *	object_name;	/* an userspace data, in most cases user name */
 };
 
 struct ncp_privatedata_ioctl
 {
 	size_t		len;
-	void*		data;		/* ~1000 for NDS */
+	void __user *	data;		/* ~1000 for NDS */
 };
 
 /* NLS charsets by ioctl */
diff -Nru a/include/linux/netbeui.h b/include/linux/netbeui.h
--- a/include/linux/netbeui.h	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,16 +0,0 @@
-#ifndef _LINUX_NETBEUI_H
-#define _LINUX_NETBEUI_H
-
-#include <linux/if.h>
-
-#define NB_NAME_LEN	20	/* Set this properly from the full docs when
-				   I get them */
-				   
-struct sockaddr_netbeui
-{
-	sa_family	snb_family;
-	char		snb_name[NB_NAME_LEN];
-	char		snb_devhint[IFNAMSIZ];
-};
-
-#endif
diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/netdevice.h	2004-06-23 19:04:28 -07:00
@@ -366,6 +366,8 @@
 	struct Qdisc		*qdisc_ingress;
 	unsigned long		tx_queue_len;	/* Max frames per queue allowed */
 
+	/* ingress path synchronizer */
+	spinlock_t		ingress_lock;
 	/* hard_start_xmit synchronizer */
 	spinlock_t		xmit_lock;
 	/* cpu id of processor entered to hard_start_xmit or -1,
@@ -405,6 +407,7 @@
 #define NETIF_F_HW_VLAN_FILTER	512	/* Receive filtering on VLAN */
 #define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
 #define NETIF_F_TSO		2048	/* Can offload TCP/IP segmentation */
+#define NETIF_F_LLTX		4096	/* LockLess TX */
 
 	/* Called after device is detached from network. */
 	void			(*uninit)(struct net_device *dev);
diff -Nru a/include/linux/netfilter.h b/include/linux/netfilter.h
--- a/include/linux/netfilter.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/netfilter.h	2004-06-23 19:04:27 -07:00
@@ -10,6 +10,7 @@
 #include <linux/wait.h>
 #include <linux/list.h>
 #endif
+#include <linux/compiler.h>
 
 /* Responses from hook functions. */
 #define NF_DROP 0
diff -Nru a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
--- a/include/linux/netfilter_arp/arp_tables.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/netfilter_arp/arp_tables.h	2004-06-23 19:04:26 -07:00
@@ -16,7 +16,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #endif
-
+#include <linux/compiler.h>
 #include <linux/netfilter_arp.h>
 
 #define ARPT_FUNCTION_MAXNAMELEN 30
diff -Nru a/include/linux/netfilter_ddp.h b/include/linux/netfilter_ddp.h
--- a/include/linux/netfilter_ddp.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,14 +0,0 @@
-#ifndef __LINUX_DDP_NETFILTER_H
-#define __LINUX_DDP_NETFILTER_H
-
-/* DDP-specific defines for netfilter.  Complete me sometime.
- * (C)1998 Rusty Russell -- This code is GPL.
- */
-
-#include <linux/netfilter.h>
-
-/* Appletalk hooks */
-#define NF_DDP_INPUT	0
-#define NF_DDP_FORWARD	1
-#define NF_DDP_OUTPUT	2
-#endif /*__LINUX_DDP_NETFILTER_H*/
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
--- a/include/linux/netfilter_ipv4/ip_conntrack.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h	2004-06-23 19:04:28 -07:00
@@ -103,7 +103,7 @@
 #include <linux/types.h>
 #include <linux/skbuff.h>
 
-#ifdef CONFIG_NF_DEBUG
+#ifdef CONFIG_NETFILTER_DEBUG
 #define IP_NF_ASSERT(x)							\
 do {									\
 	if (!(x))							\
diff -Nru a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
--- a/include/linux/netfilter_ipv4/ip_tables.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/netfilter_ipv4/ip_tables.h	2004-06-23 19:04:27 -07:00
@@ -22,6 +22,7 @@
 #include <linux/ip.h>
 #include <linux/skbuff.h>
 #endif
+#include <linux/compiler.h>
 #include <linux/netfilter_ipv4.h>
 
 #define IPT_FUNCTION_MAXNAMELEN 30
@@ -336,8 +337,8 @@
 /*
  *	Main firewall chains definitions and global var's definitions.
  */
-static DECLARE_MUTEX(ipt_mutex);
 #ifdef __KERNEL__
+static DECLARE_MUTEX(ipt_mutex);
 
 #include <linux/init.h>
 extern void ipt_init(void) __init;
diff -Nru a/include/linux/netfilter_ipv4/ipt_addrtype.h b/include/linux/netfilter_ipv4/ipt_addrtype.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/netfilter_ipv4/ipt_addrtype.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,11 @@
+#ifndef _IPT_ADDRTYPE_H
+#define _IPT_ADDRTYPE_H
+
+struct ipt_addrtype_info {
+	u_int16_t	source;		/* source-type mask */
+	u_int16_t	dest;		/* dest-type mask */
+	u_int32_t	invert_source;
+	u_int32_t	invert_dest;
+};
+
+#endif
diff -Nru a/include/linux/netfilter_ipv4/ipt_realm.h b/include/linux/netfilter_ipv4/ipt_realm.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/netfilter_ipv4/ipt_realm.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,10 @@
+#ifndef _IPT_REALM_H
+#define _IPT_REALM_H
+
+struct ipt_realm_info {
+	u_int32_t id;
+	u_int32_t mask;
+	u_int8_t invert;
+};
+
+#endif /* _IPT_REALM_H */
diff -Nru a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
--- a/include/linux/netfilter_ipv6/ip6_tables.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/netfilter_ipv6/ip6_tables.h	2004-06-23 19:04:28 -07:00
@@ -22,6 +22,7 @@
 #include <linux/ipv6.h>
 #include <linux/skbuff.h>
 #endif
+#include <linux/compiler.h>
 #include <linux/netfilter_ipv6.h>
 
 #define IP6T_FUNCTION_MAXNAMELEN 30
@@ -106,7 +107,9 @@
 	u_int64_t pcnt, bcnt;			/* Packet and byte counters */
 };
 
+#ifdef __KERNEL__
 static DECLARE_MUTEX(ip6t_mutex);
+#endif
 
 /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
 #define IP6T_F_PROTO		0x01	/* Set if rule cares about upper 
diff -Nru a/include/linux/netfilter_ipx.h b/include/linux/netfilter_ipx.h
--- a/include/linux/netfilter_ipx.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,14 +0,0 @@
-#ifndef __LINUX_IPX_NETFILTER_H
-#define __LINUX_IPX_NETFILTER_H
-
-/* IPX-specific defines for netfilter.  Complete me sometime.
- * (C)1998 Rusty Russell -- This code is GPL.
- */
-
-#include <linux/netfilter.h>
-
-/* IPX Hooks */
-#define NF_IPX_INPUT	0
-#define NF_IPX_FORWARD	1
-#define NF_IPX_OUTPUT	2
-#endif /*__LINUX_IPX_NETFILTER_H*/
diff -Nru a/include/linux/netfilter_x25.h b/include/linux/netfilter_x25.h
--- a/include/linux/netfilter_x25.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,15 +0,0 @@
-#ifndef __LINUX_X25_NETFILTER_H
-#define __LINUX_X25_NETFILTER_H
-
-/* X25-specific defines for netfilter.  Complete me sometime.
- * (C)1998 Rusty Russell -- This code is GPL.
- */
-
-#include <linux/netfilter.h>
-
-/* Hooks */
-#define NF_X25_INPUT	0
-#define NF_X25_FORWARD	1
-#define NF_X25_OUTPUT	2
-
-#endif /*__LINUX_X25_NETFILTER_H*/
diff -Nru a/include/linux/nfs4_mount.h b/include/linux/nfs4_mount.h
--- a/include/linux/nfs4_mount.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/nfs4_mount.h	2004-06-23 19:04:27 -07:00
@@ -20,7 +20,7 @@
 
 struct nfs_string {
 	unsigned int len;
-	const char* data;
+	const char __user * data;
 };
 
 struct nfs4_mount_data {
@@ -45,14 +45,14 @@
 	struct nfs_string hostname;		/* 1 */
 	/* Server IP address */
 	unsigned int host_addrlen;		/* 1 */
-	struct sockaddr* host_addr;		/* 1 */
+	struct sockaddr __user * host_addr;	/* 1 */
 
 	/* Transport protocol to use */
 	int proto;				/* 1 */
 
 	/* Pseudo-flavours to use for authentication. See RFC2623 */
 	int auth_flavourlen;			/* 1 */
-	int *auth_flavours;			/* 1 */
+	int __user *auth_flavours;		/* 1 */
 };
 
 /* bits in the flags field */
diff -Nru a/include/linux/page-flags.h b/include/linux/page-flags.h
--- a/include/linux/page-flags.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/page-flags.h	2004-06-23 19:04:27 -07:00
@@ -194,16 +194,10 @@
 #define ClearPageReferenced(page)	clear_bit(PG_referenced, &(page)->flags)
 #define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags)
 
-#ifndef arch_set_page_uptodate
-#define arch_set_page_uptodate(page) do { } while (0)
-#endif
-
 #define PageUptodate(page)	test_bit(PG_uptodate, &(page)->flags)
-#define SetPageUptodate(page) \
-	do {								\
-		arch_set_page_uptodate(page);				\
-		set_bit(PG_uptodate, &(page)->flags);			\
-	} while (0)
+#ifndef SetPageUptodate
+#define SetPageUptodate(page)	set_bit(PG_uptodate, &(page)->flags)
+#endif
 #define ClearPageUptodate(page)	clear_bit(PG_uptodate, &(page)->flags)
 
 #define PageDirty(page)		test_bit(PG_dirty, &(page)->flags)
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/pci_ids.h	2004-06-23 19:04:26 -07:00
@@ -1771,6 +1771,8 @@
 
 #define PCI_VENDOR_ID_3WARE		0x13C1
 #define PCI_DEVICE_ID_3WARE_1000	0x1000
+#define PCI_DEVICE_ID_3WARE_7000	0x1001
+#define PCI_DEVICE_ID_3WARE_9000	0x1002
 
 #define PCI_VENDOR_ID_IOMEGA		0x13ca
 #define PCI_DEVICE_ID_IOMEGA_BUZ	0x4231
diff -Nru a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
--- a/include/linux/pkt_cls.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/pkt_cls.h	2004-06-23 19:04:25 -07:00
@@ -1,14 +1,139 @@
 #ifndef __LINUX_PKT_CLS_H
 #define __LINUX_PKT_CLS_H
 
+/* I think i could have done better macros ; for now this is stolen from
+ * some arch/mips code - jhs
+*/
+#define _TC_MAKE32(x) ((x))
+
+#define _TC_MAKEMASK1(n) (_TC_MAKE32(1) << _TC_MAKE32(n))
+#define _TC_MAKEMASK(v,n) (_TC_MAKE32((_TC_MAKE32(1)<<(v))-1) << _TC_MAKE32(n))
+#define _TC_MAKEVALUE(v,n) (_TC_MAKE32(v) << _TC_MAKE32(n))
+#define _TC_GETVALUE(v,n,m) ((_TC_MAKE32(v) & _TC_MAKE32(m)) >> _TC_MAKE32(n))
+
+/* verdict bit breakdown 
+ *
+bit 0: when set -> this packet has been munged already
+
+bit 1: when set -> It is ok to munge this packet
+
+bit 2,3,4,5: Reclassify counter - sort of reverse TTL - if exceeded
+assume loop
+
+bit 6,7: Where this packet was last seen 
+0: Above the transmit example at the socket level
+1: on the Ingress
+2: on the Egress
+
+bit 8: when set --> Request not to classify on ingress. 
+
+bits 9,10,11: redirect counter -  redirect TTL. Loop avoidance
+
+ *
+ * */
+
+#define TC_MUNGED          _TC_MAKEMASK1(0)
+#define SET_TC_MUNGED(v)   ( TC_MUNGED | (v & ~TC_MUNGED))
+#define CLR_TC_MUNGED(v)   ( v & ~TC_MUNGED)
+
+#define TC_OK2MUNGE        _TC_MAKEMASK1(1)
+#define SET_TC_OK2MUNGE(v)   ( TC_OK2MUNGE | (v & ~TC_OK2MUNGE))
+#define CLR_TC_OK2MUNGE(v)   ( v & ~TC_OK2MUNGE)
+
+#define S_TC_VERD          _TC_MAKE32(2)
+#define M_TC_VERD          _TC_MAKEMASK(4,S_TC_VERD)
+#define G_TC_VERD(x)       _TC_GETVALUE(x,S_TC_VERD,M_TC_VERD)
+#define V_TC_VERD(x)       _TC_MAKEVALUE(x,S_TC_VERD)
+#define SET_TC_VERD(v,n)   ((V_TC_VERD(n)) | (v & ~M_TC_VERD))
+
+#define S_TC_FROM          _TC_MAKE32(6)
+#define M_TC_FROM          _TC_MAKEMASK(2,S_TC_FROM)
+#define G_TC_FROM(x)       _TC_GETVALUE(x,S_TC_FROM,M_TC_FROM)
+#define V_TC_FROM(x)       _TC_MAKEVALUE(x,S_TC_FROM)
+#define SET_TC_FROM(v,n)   ((V_TC_FROM(n)) | (v & ~M_TC_FROM))
+#define AT_STACK	0x0
+#define AT_INGRESS	0x1
+#define AT_EGRESS	0x2
+
+#define TC_NCLS          _TC_MAKEMASK1(8)
+#define SET_TC_NCLS(v)   ( TC_NCLS | (v & ~TC_NCLS))
+#define CLR_TC_NCLS(v)   ( v & ~TC_NCLS)
+
+#define S_TC_RTTL          _TC_MAKE32(9)
+#define M_TC_RTTL          _TC_MAKEMASK(3,S_TC_RTTL)
+#define G_TC_RTTL(x)       _TC_GETVALUE(x,S_TC_RTTL,M_TC_RTTL)
+#define V_TC_RTTL(x)       _TC_MAKEVALUE(x,S_TC_RTTL)
+#define SET_TC_RTTL(v,n)   ((V_TC_RTTL(n)) | (v & ~M_TC_RTTL))
+
+#define S_TC_AT          _TC_MAKE32(12)
+#define M_TC_AT          _TC_MAKEMASK(2,S_TC_AT)
+#define G_TC_AT(x)       _TC_GETVALUE(x,S_TC_AT,M_TC_AT)
+#define V_TC_AT(x)       _TC_MAKEVALUE(x,S_TC_AT)
+#define SET_TC_AT(v,n)   ((V_TC_AT(n)) | (v & ~M_TC_AT))
+
+/* Action attributes */
+enum
+{
+	TCA_ACT_UNSPEC,
+	TCA_ACT_KIND,
+	TCA_ACT_OPTIONS,
+	TCA_ACT_INDEX,
+	__TCA_ACT_MAX
+};
+
+#define TCA_ACT_MAX __TCA_ACT_MAX
+#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
+#define TCA_ACT_MAX_PRIO 32
+#define TCA_ACT_BIND	1
+#define TCA_ACT_NOBIND	0
+#define TCA_ACT_UNBIND	1
+#define TCA_ACT_NOUNBIND	0
+#define TCA_ACT_REPLACE		1
+#define TCA_ACT_NOREPLACE	0
+#define MAX_REC_LOOP 4
+#define MAX_RED_LOOP 4
+
+#define TC_ACT_UNSPEC	(-1)
+#define TC_ACT_OK		0
+#define TC_ACT_RECLASSIFY	1
+#define TC_ACT_SHOT		2
+#define TC_ACT_PIPE		3
+#define TC_ACT_STOLEN		4
+#define TC_ACT_QUEUED		5
+#define TC_ACT_REPEAT		6
+#define TC_ACT_JUMP		0x10000000
+
+/* Action type identifiers*/
+enum
+{
+	TCA_ID_UNSPEC=0,
+	TCA_ID_POLICE=1,
+	/* other actions go here */
+	__TCA_ID_MAX=255
+};
+
+#define TCA_ID_MAX __TCA_ID_MAX
+
 struct tc_police
 {
 	__u32			index;
+#ifdef CONFIG_NET_CLS_ACT
+	int 			refcnt;
+	int 			bindcnt;
+#endif
+/* Turned off because it requires new tc
+ * to work (for now maintain ABI)
+ *
+#ifdef CONFIG_NET_CLS_ACT
+	__u32			capab;
+#endif
+*/
 	int			action;
-#define TC_POLICE_UNSPEC	(-1)
-#define TC_POLICE_OK		0
-#define TC_POLICE_RECLASSIFY	1
-#define TC_POLICE_SHOT		2
+#define TC_POLICE_UNSPEC	TC_ACT_UNSPEC
+#define TC_POLICE_OK		TC_ACT_OK
+#define TC_POLICE_RECLASSIFY	TC_ACT_RECLASSIFY
+#define TC_POLICE_SHOT		TC_ACT_SHOT
+#define TC_POLICE_PIPE		TC_ACT_PIPE
 
 	__u32			limit;
 	__u32			burst;
@@ -17,6 +142,26 @@
 	struct tc_ratespec	peakrate;
 };
 
+struct tcf_t
+{
+	__u32   install;
+	__u32   lastuse;
+	__u32   expires;
+};
+
+struct tc_cnt
+{
+	int                   refcnt; 
+	int                   bindcnt;
+};
+
+#define tc_gen \
+	__u32                 index; \
+	__u32                 capab; \
+	int                   action; \
+	int                   refcnt; \
+	int                   bindcnt
+
 enum
 {
 	TCA_POLICE_UNSPEC,
@@ -25,8 +170,8 @@
 	TCA_POLICE_PEAKRATE,
 	TCA_POLICE_AVRATE,
 	TCA_POLICE_RESULT,
-#define TCA_POLICE_RESULT TCA_POLICE_RESULT
 	__TCA_POLICE_MAX
+#define TCA_POLICE_RESULT TCA_POLICE_RESULT
 };
 
 #define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1)
@@ -50,6 +195,12 @@
 	TCA_U32_DIVISOR,
 	TCA_U32_SEL,
 	TCA_U32_POLICE,
+#ifdef CONFIG_NET_CLS_ACT
+	TCA_U32_ACT,   
+#endif
+#ifdef CONFIG_NET_CLS_IND
+	TCA_U32_INDEV,
+#endif
 	__TCA_U32_MAX
 };
 
@@ -61,6 +212,9 @@
 	__u32		val;
 	int		off;
 	int		offmask;
+#ifdef CONFIG_CLS_U32_PERF
+	unsigned long	kcnt;
+#endif
 };
 
 struct tc_u32_sel
@@ -68,6 +222,9 @@
 	unsigned char		flags;
 	unsigned char		offshift;
 	unsigned char		nkeys;
+#ifdef fix_u32_bug
+	unsigned char		fshift;  /* fold shift */
+#endif
 
 	__u16			offmask;
 	__u16			off;
@@ -75,7 +232,10 @@
 
 	short			hoff;
 	__u32			hmask;
-
+#ifdef CONFIG_CLS_U32_PERF
+	unsigned long		rcnt;
+	unsigned long		rhit;
+#endif
 	struct tc_u32_key	keys[0];
 };
 
@@ -102,7 +262,7 @@
 	__TCA_RSVP_MAX
 };
 
-#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1)
+#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 )
 
 struct tc_rsvp_gpi
 {
@@ -143,6 +303,12 @@
 	TCA_FW_UNSPEC,
 	TCA_FW_CLASSID,
 	TCA_FW_POLICE,
+#ifdef CONFIG_NET_CLS_IND
+	TCA_FW_INDEV,
+#endif
+#ifdef CONFIG_NET_CLS_ACT
+	TCA_FW_ACT,
+#endif
 	__TCA_FW_MAX
 };
 
@@ -162,6 +328,6 @@
 	__TCA_TCINDEX_MAX
 };
 
-#define TCA_TCINDEX_MAX        (__TCA_TCINDEX_MAX - 1)
+#define TCA_TCINDEX_MAX     (__TCA_TCINDEX_MAX - 1)
 
 #endif
diff -Nru a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
--- a/include/linux/pkt_sched.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/pkt_sched.h	2004-06-23 19:04:28 -07:00
@@ -37,6 +37,13 @@
 	__u32	bps;			/* Current flow byte rate */
 	__u32	pps;			/* Current flow packet rate */
 	__u32	qlen;
+#ifdef CONFIG_NET_CLS_ACT
+/* eventually remove the define here; adding this(useful) 
+field at least fixes the 8 byte layout problems we 
+have with MIPS and PPC because we have a u64
+*/
+	__u32	reqs;			/* number of requeues happened */
+#endif
 	__u32	backlog;
 #ifdef __KERNEL__
 	spinlock_t *lock;
@@ -437,5 +444,6 @@
 {
 	__u32	latency;
 	__u32   limit;
-};	
+	__u32	loss;
+};
 #endif
diff -Nru a/include/linux/prctl.h b/include/linux/prctl.h
--- a/include/linux/prctl.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/prctl.h	2004-06-23 19:04:27 -07:00
@@ -29,6 +29,12 @@
 /* Get/set floating-point exception mode (if meaningful) */
 #define PR_GET_FPEXC	11
 #define PR_SET_FPEXC	12
+# define PR_FP_EXC_SW_ENABLE	0x80	/* Use FPEXC for FP exception enables */
+# define PR_FP_EXC_DIV		0x010000	/* floating point divide by zero */
+# define PR_FP_EXC_OVF		0x020000	/* floating point overflow */
+# define PR_FP_EXC_UND		0x040000	/* floating point underflow */
+# define PR_FP_EXC_RES		0x080000	/* floating point inexact result */
+# define PR_FP_EXC_INV		0x100000	/* floating point invalid operation */
 # define PR_FP_EXC_DISABLED	0	/* FP exceptions disabled */
 # define PR_FP_EXC_NONRECOV	1	/* async non-recoverable exc. mode */
 # define PR_FP_EXC_ASYNC	2	/* async recoverable exception mode */
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
--- a/include/linux/reiserfs_fs.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/reiserfs_fs.h	2004-06-23 19:04:28 -07:00
@@ -1238,8 +1238,12 @@
 gods only know how we are going to SMP the code that uses them.
 znodes are the way! */
 
+#define PATH_READA	0x1 /* do read ahead */
+#define PATH_READA_BACK 0x2 /* read backwards */
+
 struct  path {
   int                   path_length;                      	/* Length of the array above.   */
+  int			reada;
   struct  path_element  path_elements[EXTENDED_MAX_HEIGHT];	/* Array of the path elements.  */
   int			pos_in_item;
 };
@@ -1247,7 +1251,7 @@
 #define pos_in_item(path) ((path)->pos_in_item)
 
 #define INITIALIZE_PATH(var) \
-struct path var = {ILLEGAL_PATH_ELEMENT_OFFSET, }
+struct path var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,}
 
 /* Get path element by path and path position. */
 #define PATH_OFFSET_PELEMENT(p_s_path,n_offset)  ((p_s_path)->path_elements +(n_offset))
@@ -1748,6 +1752,14 @@
 int reiserfs_add_ordered_list(struct inode *inode, struct buffer_head *bh);
 int journal_mark_dirty(struct reiserfs_transaction_handle *, struct super_block *, struct buffer_head *bh) ;
 
+static inline int
+reiserfs_file_data_log(struct inode *inode) {
+    if (reiserfs_data_log(inode->i_sb) ||
+       (REISERFS_I(inode)->i_flags & i_data_log))
+        return 1 ;
+    return 0 ;
+}
+
 static inline int reiserfs_transaction_running(struct super_block *s) {
     struct reiserfs_transaction_handle *th = current->journal_info ;
     if (th && th->t_super == s)
@@ -2149,6 +2161,15 @@
 typedef struct __reiserfs_blocknr_hint reiserfs_blocknr_hint_t;
 
 int reiserfs_parse_alloc_options (struct super_block *, char *);
+void reiserfs_init_alloc_options (struct super_block *s);
+
+/*
+ * given a directory, this will tell you what packing locality
+ * to use for a new object underneat it.  The locality is returned
+ * in disk byte order (le).
+ */
+u32 reiserfs_choose_packing(struct inode *dir);
+
 int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value);
 void reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *, b_blocknr_t, int for_unformatted);
 int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *, b_blocknr_t * , int, int);
diff -Nru a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
--- a/include/linux/reiserfs_fs_i.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/reiserfs_fs_i.h	2004-06-23 19:04:28 -07:00
@@ -25,6 +25,7 @@
     i_link_saved_truncate_mask =  0x0020,
     i_priv_object              =  0x0080,
     i_has_xattr_dir            =  0x0100,
+    i_data_log	               =  0x0200,
 } reiserfs_inode_flags;
 
 
diff -Nru a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
--- a/include/linux/rtnetlink.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/rtnetlink.h	2004-06-23 19:04:28 -07:00
@@ -44,6 +44,10 @@
 #define	RTM_DELTFILTER	(RTM_BASE+29)
 #define	RTM_GETTFILTER	(RTM_BASE+30)
 
+#define RTM_NEWACTION   (RTM_BASE+32)
+#define RTM_DELACTION   (RTM_BASE+33)
+#define RTM_GETACTION   (RTM_BASE+34)
+
 #define RTM_NEWPREFIX	(RTM_BASE+36)
 #define RTM_GETPREFIX	(RTM_BASE+38)
 
@@ -639,6 +643,7 @@
 	TCA_STATS,
 	TCA_XSTATS,
 	TCA_RATE,
+	TCA_FCNT,
 	__TCA_MAX
 };
 
@@ -672,6 +677,18 @@
 #define RTMGRP_DECnet_ROUTE     0x4000
 
 #define RTMGRP_IPV6_PREFIX	0x20000
+
+/* TC action piece */
+struct tcamsg
+{
+	unsigned char	tca_family;
+	unsigned char	tca__pad1;
+	unsigned short	tca__pad2;
+};
+#define TA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg))))
+#define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg))
+#define TCA_ACT_TAB 1 /* attr type must be >=1 */	
+#define TCAA_MAX 1
 
 /* End of information exported to user level */
 
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/sched.h	2004-06-23 19:04:25 -07:00
@@ -168,8 +168,6 @@
 extern void cpu_init (void);
 extern void trap_init(void);
 extern void update_process_times(int user);
-extern void update_one_process(struct task_struct *p, unsigned long user,
-			       unsigned long system, int cpu);
 extern void scheduler_tick(int user_tick, int system);
 extern unsigned long cache_decay_ticks;
 
@@ -314,6 +312,9 @@
 	atomic_t __count;	/* reference count */
 	atomic_t processes;	/* How many processes does this user have? */
 	atomic_t files;		/* How many open files does this user have? */
+	atomic_t sigpending;	/* How many pending signals does this user have? */
+	/* protected by mq_lock	*/
+	unsigned long mq_bytes;	/* How many bytes can be allocated to mqueue? */
 
 	/* Hash table maintenance information */
 	struct list_head uidhash_list;
@@ -361,6 +362,12 @@
 	gid_t *blocks[0];
 };
 
+/*
+ * get_group_info() must be called with the owning task locked (via task_lock())
+ * when task != current.  The reason being that the vast majority of callers are
+ * looking at current->group_info, which can not be changed except by the
+ * current task.  Changing current->group_info requires the task lock, too.
+ */
 #define get_group_info(group_info) do { \
 	atomic_inc(&(group_info)->usage); \
 } while (0)
@@ -681,9 +688,9 @@
 
 extern void sched_idle_next(void);
 extern void set_user_nice(task_t *p, long nice);
-extern int task_prio(task_t *p);
-extern int task_nice(task_t *p);
-extern int task_curr(task_t *p);
+extern int task_prio(const task_t *p);
+extern int task_nice(const task_t *p);
+extern int task_curr(const task_t *p);
 extern int idle_cpu(int cpu);
 
 void yield(void);
@@ -719,6 +726,11 @@
 
 /* per-UID process charging. */
 extern struct user_struct * alloc_uid(uid_t);
+static inline struct user_struct *get_uid(struct user_struct *u)
+{
+	atomic_inc(&u->__count);
+	return u;
+}
 extern void free_uid(struct user_struct *);
 extern void switch_uid(struct user_struct *);
 
@@ -905,7 +917,7 @@
 #define while_each_thread(g, t) \
 	while ((t = next_thread(t)) != g)
 
-extern task_t * FASTCALL(next_thread(task_t *p));
+extern task_t * FASTCALL(next_thread(const task_t *p));
 
 #define thread_group_leader(p)	(p->pid == p->tgid)
 
@@ -922,7 +934,9 @@
 extern void unhash_process(struct task_struct *p);
 
 /*
- * Protects ->fs, ->files, ->mm, ->ptrace and synchronises with wait4().
+ * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info and synchronises with
+ * wait4().
+ *
  * Nests both inside and outside of read_lock(&tasklist_lock).
  * It must not be nested with write_lock_irq(&tasklist_lock),
  * neither inside nor outside.
@@ -1044,7 +1058,7 @@
  */
 #ifdef CONFIG_SMP
 
-static inline unsigned int task_cpu(struct task_struct *p)
+static inline unsigned int task_cpu(const struct task_struct *p)
 {
 	return p->thread_info->cpu;
 }
@@ -1056,7 +1070,7 @@
 
 #else
 
-static inline unsigned int task_cpu(struct task_struct *p)
+static inline unsigned int task_cpu(const struct task_struct *p)
 {
 	return 0;
 }
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	2004-06-23 19:04:28 -07:00
+++ b/include/linux/security.h	2004-06-23 19:04:28 -07:00
@@ -53,7 +53,7 @@
 extern int cap_syslog (int type);
 extern int cap_vm_enough_memory (long pages);
 
-static inline int cap_netlink_send (struct sk_buff *skb)
+static inline int cap_netlink_send (struct sock *sk, struct sk_buff *skb)
 {
 	NETLINK_CB (skb).eff_cap = current->cap_effective;
 	return 0;
@@ -639,9 +639,12 @@
  *	Save security information for a netlink message so that permission
  *	checking can be performed when the message is processed.  The security
  *	information can be saved using the eff_cap field of the
- *      netlink_skb_parms structure.
+ *      netlink_skb_parms structure.  Also may be used to provide fine
+ *	grained control over message transmission.
+ *	@sk associated sock of task sending the message.,
  *	@skb contains the sk_buff structure for the netlink message.
- *	Return 0 if the information was successfully saved.
+ *	Return 0 if the information was successfully saved and message
+ *	is allowed to be transmitted.
  * @netlink_recv:
  *	Check permission before processing the received netlink message in
  *	@skb.
@@ -1181,7 +1184,7 @@
 	int (*sem_semop) (struct sem_array * sma, 
 			  struct sembuf * sops, unsigned nsops, int alter);
 
-	int (*netlink_send) (struct sk_buff * skb);
+	int (*netlink_send) (struct sock * sk, struct sk_buff * skb);
 	int (*netlink_recv) (struct sk_buff * skb);
 
 	/* allow module stacking */
@@ -1873,9 +1876,9 @@
 	return security_ops->setprocattr(p, name, value, size);
 }
 
-static inline int security_netlink_send(struct sk_buff * skb)
+static inline int security_netlink_send(struct sock *sk, struct sk_buff * skb)
 {
-	return security_ops->netlink_send(skb);
+	return security_ops->netlink_send(sk, skb);
 }
 
 static inline int security_netlink_recv(struct sk_buff * skb)
@@ -2501,9 +2504,9 @@
  * (rather than hooking into the capability module) to reduce overhead
  * in the networking code.
  */
-static inline int security_netlink_send (struct sk_buff *skb)
+static inline int security_netlink_send (struct sock *sk, struct sk_buff *skb)
 {
-	return cap_netlink_send (skb);
+	return cap_netlink_send (sk, skb);
 }
 
 static inline int security_netlink_recv (struct sk_buff *skb)
diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h
--- a/include/linux/serial_core.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/serial_core.h	2004-06-23 19:04:25 -07:00
@@ -59,14 +59,6 @@
 /* NEC v850.  */
 #define PORT_V850E_UART	40
 
-/* NEC PC-9800 */
-#define PORT_8251_PC98	41
-#define PORT_19K_PC98	42
-#define PORT_FIFO_PC98	43
-#define PORT_VFAST_PC98	44
-#define PORT_PC9861	45
-#define PORT_PC9801_101	46
-
 /* DZ */
 #define PORT_DZ		47
 
@@ -87,6 +79,9 @@
 
 /* SGI IP22 aka Indy / Challenge S / Indigo 2 */
 #define PORT_IP22ZILOG	56
+
+/* Sharp LH7a40x -- an ARM9 SoC series */
+#define PORT_LH7A40X	57
 
 #ifdef __KERNEL__
 
diff -Nru a/include/linux/serio.h b/include/linux/serio.h
--- a/include/linux/serio.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/serio.h	2004-06-23 19:04:27 -07:00
@@ -105,7 +105,6 @@
 #define SERIO_8042	0x01000000UL
 #define SERIO_RS232	0x02000000UL
 #define SERIO_HIL_MLC	0x03000000UL
-#define SERIO_PC9800	0x04000000UL
 #define SERIO_PS_PSTHRU	0x05000000UL
 #define SERIO_8042_XL	0x06000000UL
 
diff -Nru a/include/linux/signal.h b/include/linux/signal.h
--- a/include/linux/signal.h	2004-06-23 19:04:25 -07:00
+++ b/include/linux/signal.h	2004-06-23 19:04:25 -07:00
@@ -7,6 +7,9 @@
 #include <asm/siginfo.h>
 
 #ifdef __KERNEL__
+
+#define MAX_SIGPENDING	1024
+
 /*
  * Real Time signals may be queued.
  */
@@ -16,6 +19,7 @@
 	spinlock_t *lock;
 	int flags;
 	siginfo_t info;
+	struct user_struct *user;
 };
 
 /* flags values. */
diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/skbuff.h	2004-06-23 19:04:27 -07:00
@@ -27,6 +27,7 @@
 #include <linux/highmem.h>
 #include <linux/poll.h>
 #include <linux/net.h>
+#include <net/checksum.h>
 
 #define HAVE_ALLOC_SKB		/* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB	/* Ditto 8)		   */
@@ -155,6 +156,7 @@
  *	@sk: Socket we are owned by
  *	@stamp: Time we arrived
  *	@dev: Device we arrived on/are leaving by
+ *	@input_dev: Device we arrived on
  *      @real_dev: The real device we are using
  *	@h: Transport layer header
  *	@nh: Network layer header
@@ -197,6 +199,7 @@
 	struct sock		*sk;
 	struct timeval		stamp;
 	struct net_device	*dev;
+	struct net_device	*input_dev;
 	struct net_device	*real_dev;
 
 	union {
@@ -262,9 +265,15 @@
 	} private;
 #endif
 #ifdef CONFIG_NET_SCHED
-       __u32			tc_index;               /* traffic control index */
+       __u32			tc_index;        /* traffic control index */
+#ifdef CONFIG_NET_CLS_ACT
+	__u32           tc_verd;               /* traffic control verdict */
+	__u32           tc_classid;            /* traffic control classid */
+ #endif
+
 #endif
 
+
 	/* These elements must be at the end, see alloc_skb() for details.  */
 	unsigned int		truesize;
 	atomic_t		users;
@@ -816,6 +825,30 @@
 	skb->tail += len;
 }
 
+/*
+ * CPUs often take a performance hit when accessing unaligned memory
+ * locations. The actual performance hit varies, it can be small if the
+ * hardware handles it or large if we have to take an exception and fix it
+ * in software.
+ *
+ * Since an ethernet header is 14 bytes network drivers often end up with
+ * the IP header at an unaligned offset. The IP header can be aligned by
+ * shifting the start of the packet by 2 bytes. Drivers should do this
+ * with:
+ *
+ * skb_reserve(NET_IP_ALIGN);
+ *
+ * The downside to this alignment of the IP header is that the DMA is now
+ * unaligned. On some architectures the cost of an unaligned DMA is high
+ * and this cost outweighs the gains made by aligning the IP header.
+ * 
+ * Since this trade off varies between architectures, we allow NET_IP_ALIGN
+ * to be overridden.
+ */
+#ifndef NET_IP_ALIGN
+#define NET_IP_ALIGN	2
+#endif
+
 extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
 
 static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
@@ -971,6 +1004,39 @@
 	return skb_pad(skb, len-size);
 }
 
+static inline int skb_add_data(struct sk_buff *skb,
+			       char __user *from, int copy)
+{
+	const int off = skb->len;
+
+	if (skb->ip_summed == CHECKSUM_NONE) {
+		int err = 0;
+		unsigned int csum = csum_and_copy_from_user(from,
+							    skb_put(skb, copy),
+							    copy, 0, &err);
+		if (!err) {
+			skb->csum = csum_block_add(skb->csum, csum, off);
+			return 0;
+		}
+	} else if (!copy_from_user(skb_put(skb, copy), from, copy))
+		return 0;
+
+	__skb_trim(skb, off);
+	return -EFAULT;
+}
+
+static inline int skb_can_coalesce(struct sk_buff *skb, int i,
+				   struct page *page, int off)
+{
+	if (i) {
+		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
+
+		return page == frag->page &&
+		       off == frag->page_offset + frag->size;
+	}
+	return 0;
+}
+
 /**
  *	skb_linearize - convert paged skb to linear one
  *	@skb: buffer to linarize
@@ -1034,6 +1100,8 @@
 					      int offset, u8 *to, int len,
 					      unsigned int csum);
 extern void	       skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
+extern void	       skb_split(struct sk_buff *skb,
+				 struct sk_buff *skb1, const u32 len);
 
 extern void skb_init(void);
 extern void skb_add_mtu(int mtu);
@@ -1049,6 +1117,14 @@
 	if (nfct)
 		atomic_inc(&nfct->master->use);
 }
+static inline void nf_reset(struct sk_buff *skb)
+{
+	nf_conntrack_put(skb->nfct);
+	skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug = 0;
+#endif
+}
 
 #ifdef CONFIG_BRIDGE_NETFILTER
 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
@@ -1061,9 +1137,10 @@
 	if (nf_bridge)
 		atomic_inc(&nf_bridge->use);
 }
-#endif
-
-#endif
+#endif /* CONFIG_BRIDGE_NETFILTER */
+#else /* CONFIG_NETFILTER */
+static inline void nf_reset(struct sk_buff *skb) {}
+#endif /* CONFIG_NETFILTER */
 
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
diff -Nru a/include/linux/syscalls.h b/include/linux/syscalls.h
--- a/include/linux/syscalls.h	2004-06-23 19:04:29 -07:00
+++ b/include/linux/syscalls.h	2004-06-23 19:04:29 -07:00
@@ -382,7 +382,7 @@
 asmlinkage long sys_rmdir(const char __user *pathname);
 asmlinkage long sys_lookup_dcookie(u64 cookie64, char __user *buf, size_t len);
 asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special,
-				qid_t id, caddr_t addr);
+				qid_t id, void __user *addr);
 asmlinkage long sys_getdents(unsigned int fd,
 				struct linux_dirent __user *dirent,
 				unsigned int count);
diff -Nru a/include/linux/sysfs.h b/include/linux/sysfs.h
--- a/include/linux/sysfs.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/sysfs.h	2004-06-23 19:04:26 -07:00
@@ -24,6 +24,27 @@
 };
 
 
+
+/**
+ * Use these macros to make defining attributes easier. See include/linux/device.h
+ * for examples..
+ */
+
+#define __ATTR(_name,_mode,_show,_store) { \
+	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
+	.show	= _show,					\
+	.store	= _store,					\
+}
+
+#define __ATTR_RO(_name) { \
+	.attr	= { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE },	\
+	.show	= _name##_show,	\
+}
+
+#define __ATTR_NULL { .attr = { .name = NULL } }
+
+#define attr_name(_attr) (_attr).attr.name
+
 struct bin_attribute {
 	struct attribute	attr;
 	size_t			size;
diff -Nru a/include/linux/tcp.h b/include/linux/tcp.h
--- a/include/linux/tcp.h	2004-06-23 19:04:26 -07:00
+++ b/include/linux/tcp.h	2004-06-23 19:04:26 -07:00
@@ -262,8 +262,8 @@
 	__u32	frto_highmark;	/* snd_nxt when RTO occurred */
 
 	__u8	unused_pad;
-	__u8	queue_shrunk;	/* Write queue has been shrunk recently.*/
 	__u8	defer_accept;	/* User waits for some data after accept() */
+	/* one byte hole, try to pack */
 
 /* RTT measurement */
 	__u8	backoff;	/* backoff				*/
@@ -297,7 +297,6 @@
 	struct sk_buff_head	out_of_order_queue; /* Out of order segments go here */
 
 	struct tcp_func		*af_specific;	/* Operations which are AF_INET{4,6} specific	*/
-	struct sk_buff		*send_head;	/* Front of stuff to transmit			*/
 
  	__u32	rcv_wnd;	/* Current receiver window		*/
 	__u32	rcv_wup;	/* rcv_nxt on last window update sent	*/
@@ -370,8 +369,6 @@
 	/* FIFO of established children */
 	struct open_request	*accept_queue;
 	struct open_request	*accept_queue_tail;
-
-	int			write_pending;	/* A write to socket waits to start. */
 
 	unsigned int		keepalive_time;	  /* time before keep alive takes place */
 	unsigned int		keepalive_intvl;  /* time interval between keep alive probes */
diff -Nru a/include/linux/videodev2.h b/include/linux/videodev2.h
--- a/include/linux/videodev2.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/videodev2.h	2004-06-23 19:04:27 -07:00
@@ -207,6 +207,9 @@
 #define V4L2_PIX_FMT_YYUV    v4l2_fourcc('Y','Y','U','V') /* 16  YUV 4:2:2     */
 #define V4L2_PIX_FMT_HI240   v4l2_fourcc('H','I','2','4') /*  8  8-bit color   */
 
+/* see http://www.siliconimaging.com/RGB%20Bayer.htm */
+#define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B','A','8','1') /*  8  BGBG.. GRGR.. */
+
 /* compressed formats */
 #define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M','J','P','G') /* Motion-JPEG   */
 #define V4L2_PIX_FMT_JPEG     v4l2_fourcc('J','P','E','G') /* JFIF JPEG     */
@@ -383,8 +386,8 @@
 		unsigned long   userptr;
 	} m;
 	__u32			length;
-
-	__u32			reserved[2];
+	__u32			input;
+	__u32			reserved;
 };
 
 /*  Flags for 'flags' field */
@@ -395,6 +398,7 @@
 #define V4L2_BUF_FLAG_PFRAME	0x0010	/* Image is a P-frame */
 #define V4L2_BUF_FLAG_BFRAME	0x0020	/* Image is a B-frame */
 #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
+#define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
 
 /*
  *	O V E R L A Y   P R E V I E W
@@ -526,12 +530,13 @@
 				 V4L2_STD_PAL_I)
 #define V4L2_STD_NTSC           (V4L2_STD_NTSC_M	|\
 				 V4L2_STD_NTSC_M_JP)
+#define V4L2_STD_SECAM_DK      	(V4L2_STD_SECAM_D	|\
+				 V4L2_STD_SECAM_K	|\
+				 V4L2_STD_SECAM_K1)
 #define V4L2_STD_SECAM		(V4L2_STD_SECAM_B	|\
-				 V4L2_STD_SECAM_D	|\
 				 V4L2_STD_SECAM_G	|\
 				 V4L2_STD_SECAM_H	|\
-				 V4L2_STD_SECAM_K	|\
-				 V4L2_STD_SECAM_K1	|\
+				 V4L2_STD_SECAM_DK	|\
 				 V4L2_STD_SECAM_L)
 
 #define V4L2_STD_525_60		(V4L2_STD_PAL_M		|\
@@ -541,6 +546,8 @@
 				 V4L2_STD_PAL_N		|\
 				 V4L2_STD_PAL_Nc	|\
 				 V4L2_STD_SECAM)
+#define V4L2_STD_ATSC           (V4L2_STD_ATSC_8_VSB    |\
+		                 V4L2_STD_ATSC_16_VSB)
 
 #define V4L2_STD_UNKNOWN        0
 #define V4L2_STD_ALL            (V4L2_STD_525_60	|\
diff -Nru a/include/linux/wait.h b/include/linux/wait.h
--- a/include/linux/wait.h	2004-06-23 19:04:27 -07:00
+++ b/include/linux/wait.h	2004-06-23 19:04:27 -07:00
@@ -200,7 +200,36 @@
 		__wait_event_interruptible_timeout(wq, condition, __ret); \
 	__ret;								\
 })
-	
+
+#define __wait_event_interruptible_exclusive(wq, condition, ret)	\
+do {									\
+	wait_queue_t __wait;						\
+	init_waitqueue_entry(&__wait, current);				\
+									\
+	add_wait_queue_exclusive(&wq, &__wait);				\
+	for (;;) {							\
+		set_current_state(TASK_INTERRUPTIBLE);			\
+		if (condition)						\
+			break;						\
+		if (!signal_pending(current)) {				\
+			schedule();					\
+			continue;					\
+		}							\
+		ret = -ERESTARTSYS;					\
+		break;							\
+	}								\
+	current->state = TASK_RUNNING;					\
+	remove_wait_queue(&wq, &__wait);				\
+} while (0)
+
+#define wait_event_interruptible_exclusive(wq, condition)		\
+({									\
+	int __ret = 0;							\
+	if (!(condition))						\
+		__wait_event_interruptible_exclusive(wq, condition, __ret);\
+	__ret;								\
+})
+
 /*
  * Must be called with the spinlock in the wait_queue_head_t held.
  */
diff -Nru a/include/media/ir-common.h b/include/media/ir-common.h
--- a/include/media/ir-common.h	2004-06-23 19:04:28 -07:00
+++ b/include/media/ir-common.h	2004-06-23 19:04:28 -07:00
@@ -27,7 +27,7 @@
 #define IR_TYPE_OTHER  99
 
 #define IR_KEYTAB_TYPE	u32
-#define IR_KEYTAB_SIZE	64  // enougth for rc5, probably need more some day ...
+#define IR_KEYTAB_SIZE	128  // enougth for rc5, probably need more some day ...
 
 #define IR_KEYCODE(tab,code)	(((unsigned)code < IR_KEYTAB_SIZE) \
 				 ? tab[code] : KEY_RESERVED)
diff -Nru a/include/media/ovcamchip.h b/include/media/ovcamchip.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/media/ovcamchip.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,104 @@
+/* OmniVision* camera chip driver API
+ *
+ * Copyright (c) 1999-2004 Mark McClelland
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ *
+ * * OmniVision is a trademark of OmniVision Technologies, Inc. This driver
+ * is not sponsored or developed by them.
+ */
+
+#ifndef __LINUX_OVCAMCHIP_H
+#define __LINUX_OVCAMCHIP_H
+
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+
+/* Remove these once they are officially defined */
+#ifndef I2C_DRIVERID_OVCAMCHIP
+	#define I2C_DRIVERID_OVCAMCHIP	0xf00f
+#endif
+#ifndef I2C_HW_SMBUS_OV511
+	#define I2C_HW_SMBUS_OV511	0xfe
+#endif
+#ifndef I2C_HW_SMBUS_OV518
+	#define I2C_HW_SMBUS_OV518	0xff
+#endif
+#ifndef I2C_HW_SMBUS_OVFX2
+	#define I2C_HW_SMBUS_OVFX2	0xfd
+#endif
+
+/* --------------------------------- */
+/*           ENUMERATIONS            */
+/* --------------------------------- */
+
+/* Controls */
+enum {
+	OVCAMCHIP_CID_CONT,		/* Contrast */
+	OVCAMCHIP_CID_BRIGHT,		/* Brightness */
+	OVCAMCHIP_CID_SAT,		/* Saturation */
+	OVCAMCHIP_CID_HUE,		/* Hue */
+	OVCAMCHIP_CID_EXP,		/* Exposure */
+	OVCAMCHIP_CID_FREQ,		/* Light frequency */
+	OVCAMCHIP_CID_BANDFILT,		/* Banding filter */
+	OVCAMCHIP_CID_AUTOBRIGHT,	/* Auto brightness */
+	OVCAMCHIP_CID_AUTOEXP,		/* Auto exposure */
+	OVCAMCHIP_CID_BACKLIGHT,	/* Back light compensation */
+	OVCAMCHIP_CID_MIRROR,		/* Mirror horizontally */
+};
+
+/* Chip types */
+#define NUM_CC_TYPES	9
+enum {
+	CC_UNKNOWN,
+	CC_OV76BE,
+	CC_OV7610,
+	CC_OV7620,
+	CC_OV7620AE,
+	CC_OV6620,
+	CC_OV6630,
+	CC_OV6630AE,
+	CC_OV6630AF,
+};
+
+/* --------------------------------- */
+/*           I2C ADDRESSES           */
+/* --------------------------------- */
+
+#define OV7xx0_SID   (0x42 >> 1)
+#define OV6xx0_SID   (0xC0 >> 1)
+
+/* --------------------------------- */
+/*                API                */
+/* --------------------------------- */
+
+struct ovcamchip_control {
+	__u32 id;
+	__s32 value;
+};
+
+struct ovcamchip_window {
+	int x;
+	int y;
+	int width;
+	int height;
+	int format;
+	int quarter;		/* Scale width and height down 2x */
+
+	/* This stuff will be removed eventually */
+	int clockdiv;		/* Clock divisor setting */
+};
+
+/* Commands */
+#define OVCAMCHIP_CMD_Q_SUBTYPE     _IOR  (0x88, 0x00, int)
+#define OVCAMCHIP_CMD_INITIALIZE    _IOW  (0x88, 0x01, int)
+/* You must call OVCAMCHIP_CMD_INITIALIZE before any of commands below! */
+#define OVCAMCHIP_CMD_S_CTRL        _IOW  (0x88, 0x02, struct ovcamchip_control)
+#define OVCAMCHIP_CMD_G_CTRL        _IOWR (0x88, 0x03, struct ovcamchip_control)
+#define OVCAMCHIP_CMD_S_MODE        _IOW  (0x88, 0x04, struct ovcamchip_window)
+#define OVCAMCHIP_MAX_CMD           _IO   (0x88, 0x3f)
+
+#endif
diff -Nru a/include/media/video-buf.h b/include/media/video-buf.h
--- a/include/media/video-buf.h	2004-06-23 19:04:27 -07:00
+++ b/include/media/video-buf.h	2004-06-23 19:04:27 -07:00
@@ -18,6 +18,8 @@
 
 #include <linux/videodev.h>
 
+#define UNSET (-1U)
+
 /* --------------------------------------------------------------------- */
 
 /*
@@ -34,8 +36,6 @@
  */
 struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages,
 					 int offset);
-int videobuf_lock(struct page **pages, int nr_pages);
-int videobuf_unlock(struct page **pages, int nr_pages);
 
 /* --------------------------------------------------------------------- */
 
@@ -59,6 +59,8 @@
  */
 
 struct videobuf_dmabuf {
+	u32                 magic;
+
 	/* for userland buffer */
 	int                 offset;
 	struct page         **pages;
@@ -76,6 +78,7 @@
 	int                 direction;
 };
 
+void videobuf_dma_init(struct videobuf_dmabuf *dma);
 int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
 			   unsigned long data, unsigned long size);
 int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
@@ -134,12 +137,14 @@
 
 struct videobuf_buffer {
 	unsigned int            i;
+	u32                     magic;
 
 	/* info about the buffer */
 	unsigned int            width;
 	unsigned int            height;
 	unsigned int            bytesperline; /* use only if != 0 */
 	unsigned long           size;
+	unsigned int            input;
 	enum v4l2_field         field;
 	enum videobuf_state     state;
 	struct videobuf_dmabuf  dma;
@@ -174,9 +179,10 @@
 	struct pci_dev             *pci;
 
 	enum v4l2_buf_type         type;
+	unsigned int               inputs; /* for V4L2_BUF_FLAG_INPUT */
 	unsigned int               msize;
 	enum v4l2_field            field;
-	enum v4l2_field            last; /* for field=V4L2_FIELD_ALTERNATE */
+	enum v4l2_field            last;   /* for field=V4L2_FIELD_ALTERNATE */
 	struct videobuf_buffer     *bufs[VIDEO_MAX_FRAME];
 	struct videobuf_queue_ops  *ops;
 
diff -Nru a/include/net/checksum.h b/include/net/checksum.h
--- a/include/net/checksum.h	2004-06-23 19:04:26 -07:00
+++ b/include/net/checksum.h	2004-06-23 19:04:26 -07:00
@@ -16,82 +16,14 @@
  *		2 of the License, or (at your option) any later version.
  */
 
-/*
- *	Fixes:
- *
- *	Ralf Baechle			:	generic ipv6 checksum
- *	<ralf@waldorf-gmbh.de>
- */
-
 #ifndef _CHECKSUM_H
 #define _CHECKSUM_H
 
+#include <linux/errno.h>
 #include <asm/types.h>
 #include <asm/byteorder.h>
-#include <net/ip.h>
-#include <linux/in6.h>
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
-
-#ifndef _HAVE_ARCH_IPV6_CSUM
-
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
-						     struct in6_addr *daddr,
-						     __u16 len,
-						     unsigned short proto,
-						     unsigned int csum) 
-{
-
-	int carry;
-	__u32 ulen;
-	__u32 uproto;
-
-	csum += saddr->s6_addr32[0];
-	carry = (csum < saddr->s6_addr32[0]);
-	csum += carry;
-
-	csum += saddr->s6_addr32[1];
-	carry = (csum < saddr->s6_addr32[1]);
-	csum += carry;
-
-	csum += saddr->s6_addr32[2];
-	carry = (csum < saddr->s6_addr32[2]);
-	csum += carry;
-
-	csum += saddr->s6_addr32[3];
-	carry = (csum < saddr->s6_addr32[3]);
-	csum += carry;
-
-	csum += daddr->s6_addr32[0];
-	carry = (csum < daddr->s6_addr32[0]);
-	csum += carry;
-
-	csum += daddr->s6_addr32[1];
-	carry = (csum < daddr->s6_addr32[1]);
-	csum += carry;
-
-	csum += daddr->s6_addr32[2];
-	carry = (csum < daddr->s6_addr32[2]);
-	csum += carry;
-
-	csum += daddr->s6_addr32[3];
-	carry = (csum < daddr->s6_addr32[3]);
-	csum += carry;
-
-	ulen = htonl((__u32) len);
-	csum += ulen;
-	carry = (csum < ulen);
-	csum += carry;
-
-	uproto = htonl(proto);
-	csum += uproto;
-	carry = (csum < uproto);
-	csum += carry;
-
-	return csum_fold(csum);
-}
-
-#endif
 
 #ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
 static inline
diff -Nru a/include/net/esp.h b/include/net/esp.h
--- a/include/net/esp.h	2004-06-23 19:04:27 -07:00
+++ b/include/net/esp.h	2004-06-23 19:04:27 -07:00
@@ -2,9 +2,14 @@
 #define _NET_ESP_H
 
 #include <net/xfrm.h>
+#include <asm/scatterlist.h>
+
+#define ESP_NUM_FAST_SG		4
 
 struct esp_data
 {
+	struct scatterlist		sgbuf[ESP_NUM_FAST_SG];
+
 	/* Confidentiality */
 	struct {
 		u8			*key;		/* Key */
diff -Nru a/include/net/ip.h b/include/net/ip.h
--- a/include/net/ip.h	2004-06-23 19:04:27 -07:00
+++ b/include/net/ip.h	2004-06-23 19:04:27 -07:00
@@ -37,7 +37,7 @@
 #include <net/snmp.h>
 #endif
 
-#include <net/sock.h>	/* struct sock */
+struct sock;
 
 struct inet_skb_parm
 {
diff -Nru a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/net/ip6_checksum.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,94 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Checksumming functions for IPv6
+ *
+ * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
+ *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *		Borrows very liberally from tcp.c and ip.c, see those
+ *		files for more names.
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+
+/*
+ *	Fixes:
+ *
+ *	Ralf Baechle			:	generic ipv6 checksum
+ *	<ralf@waldorf-gmbh.de>
+ */
+
+#ifndef _CHECKSUM_IPV6_H
+#define _CHECKSUM_IPV6_H
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <net/ip.h>
+#include <asm/checksum.h>
+#include <linux/in6.h>
+
+#ifndef _HAVE_ARCH_IPV6_CSUM
+
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+						     struct in6_addr *daddr,
+						     __u16 len,
+						     unsigned short proto,
+						     unsigned int csum) 
+{
+
+	int carry;
+	__u32 ulen;
+	__u32 uproto;
+
+	csum += saddr->s6_addr32[0];
+	carry = (csum < saddr->s6_addr32[0]);
+	csum += carry;
+
+	csum += saddr->s6_addr32[1];
+	carry = (csum < saddr->s6_addr32[1]);
+	csum += carry;
+
+	csum += saddr->s6_addr32[2];
+	carry = (csum < saddr->s6_addr32[2]);
+	csum += carry;
+
+	csum += saddr->s6_addr32[3];
+	carry = (csum < saddr->s6_addr32[3]);
+	csum += carry;
+
+	csum += daddr->s6_addr32[0];
+	carry = (csum < daddr->s6_addr32[0]);
+	csum += carry;
+
+	csum += daddr->s6_addr32[1];
+	carry = (csum < daddr->s6_addr32[1]);
+	csum += carry;
+
+	csum += daddr->s6_addr32[2];
+	carry = (csum < daddr->s6_addr32[2]);
+	csum += carry;
+
+	csum += daddr->s6_addr32[3];
+	carry = (csum < daddr->s6_addr32[3]);
+	csum += carry;
+
+	ulen = htonl((__u32) len);
+	csum += ulen;
+	carry = (csum < ulen);
+	csum += carry;
+
+	uproto = htonl(proto);
+	csum += uproto;
+	carry = (csum < uproto);
+	csum += carry;
+
+	return csum_fold(csum);
+}
+
+#endif
+#endif
diff -Nru a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h
--- a/include/net/irda/irda_device.h	2004-06-23 19:04:29 -07:00
+++ b/include/net/irda/irda_device.h	2004-06-23 19:04:29 -07:00
@@ -39,11 +39,13 @@
 #ifndef IRDA_DEVICE_H
 #define IRDA_DEVICE_H
 
+#include <linux/config.h>
 #include <linux/tty.h>
 #include <linux/netdevice.h>
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>		/* struct sk_buff */
 #include <linux/irda.h>
+#include <linux/types.h>
 
 #include <net/pkt_sched.h>
 #include <net/irda/irda.h>
@@ -236,7 +238,7 @@
 int irda_device_dongle_cleanup(dongle_t *dongle);
 
 #ifdef CONFIG_ISA
-void irda_setup_dma(int channel, char *buffer, int count, int mode);
+void irda_setup_dma(int channel, dma_addr_t buffer, int count, int mode);
 #endif
 
 void irda_task_delete(struct irda_task *task);
diff -Nru a/include/net/pkt_act.h b/include/net/pkt_act.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/net/pkt_act.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,286 @@
+#ifndef __NET_PKT_ACT_H
+#define __NET_PKT_ACT_H
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+
+#define tca_st(val) (struct tcf_##val *)
+#define PRIV(a,name) ( tca_st(name) (a)->priv)
+
+#if 0 /* control */
+#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define DPRINTK(format,args...)
+#endif
+
+#if 0 /* data */
+#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define D2PRINTK(format,args...)
+#endif
+
+static __inline__ unsigned
+tcf_hash(u32 index)
+{
+	return index & MY_TAB_MASK;
+}
+
+/* probably move this from being inline
+ * and put into act_generic
+*/
+static inline void
+tcf_hash_destroy(struct tcf_st *p)
+{
+	unsigned h = tcf_hash(p->index);
+	struct tcf_st **p1p;
+
+	for (p1p = &tcf_ht[h]; *p1p; p1p = &(*p1p)->next) {
+		if (*p1p == p) {
+			write_lock_bh(&tcf_t_lock);
+			*p1p = p->next;
+			write_unlock_bh(&tcf_t_lock);
+#ifdef CONFIG_NET_ESTIMATOR
+			qdisc_kill_estimator(&p->stats);
+#endif
+			kfree(p);
+			return;
+		}
+	}
+	BUG_TRAP(0);
+}
+
+static inline int
+tcf_hash_release(struct tcf_st *p, int bind )
+{
+	int ret = 0;
+	if (p) {
+		if (bind) {
+			p->bindcnt--;
+		}
+		p->refcnt--;
+	       	if(p->bindcnt <=0 && p->refcnt <= 0) {
+			tcf_hash_destroy(p);
+			ret = 1;
+		}
+	}
+	return ret;
+}
+
+static __inline__ int
+tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
+		struct tc_action *a)
+{
+	struct tcf_st *p;
+	int err =0, index =  -1,i= 0, s_i = 0, n_i = 0;
+	struct rtattr *r ;
+
+	read_lock(&tcf_t_lock);
+
+	s_i = cb->args[0];
+
+	for (i = 0; i < MY_TAB_SIZE; i++) {
+		p = tcf_ht[tcf_hash(i)];
+
+		for (; p; p = p->next) {
+			index++;
+			if (index < s_i)
+				continue;
+			a->priv = p;
+			a->order = n_i;
+			r = (struct rtattr*) skb->tail;
+			RTA_PUT(skb, a->order, 0, NULL);
+			err = tcf_action_dump_1(skb, a, 0, 0);
+			if (0 > err) {
+				index--;
+				skb_trim(skb, (u8*)r - skb->data);
+				goto done;
+			}
+			r->rta_len = skb->tail - (u8*)r;
+			n_i++;
+			if (n_i >= TCA_ACT_MAX_PRIO) {
+				goto done;
+			}
+		}
+	}
+done:
+	read_unlock(&tcf_t_lock);
+	if (n_i)
+		cb->args[0] += n_i;
+	return n_i;
+
+rtattr_failure:
+	skb_trim(skb, (u8*)r - skb->data);
+	goto done;
+}
+
+static __inline__ int
+tcf_del_walker(struct sk_buff *skb, struct tc_action *a)
+{
+	struct tcf_st *p, *s_p;
+	struct rtattr *r ;
+	int i= 0, n_i = 0;
+
+	r = (struct rtattr*) skb->tail;
+	RTA_PUT(skb, a->order, 0, NULL);
+	RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
+	for (i = 0; i < MY_TAB_SIZE; i++) {
+		p = tcf_ht[tcf_hash(i)];
+
+		while (p != NULL) {
+			s_p = p->next;
+			if (ACT_P_DELETED == tcf_hash_release(p, 0)) {
+				 module_put(a->ops->owner);
+			}
+			n_i++;
+			p = s_p;
+		}
+	}
+	RTA_PUT(skb, TCA_FCNT, 4, &n_i);
+	r->rta_len = skb->tail - (u8*)r;
+
+	return n_i;
+rtattr_failure:
+	skb_trim(skb, (u8*)r - skb->data);
+	return -EINVAL;
+}
+
+static __inline__ int
+tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, int type,
+		struct tc_action *a)
+{
+		if (type == RTM_DELACTION) {
+			return tcf_del_walker(skb,a);
+		} else if (type == RTM_GETACTION) {
+			return tcf_dump_walker(skb,cb,a);
+		} else {
+			printk("tcf_generic_walker: unknown action %d\n",type);
+			return -EINVAL;
+		}
+}
+
+static __inline__ struct tcf_st *
+tcf_hash_lookup(u32 index)
+{
+	struct tcf_st *p;
+
+	read_lock(&tcf_t_lock);
+	for (p = tcf_ht[tcf_hash(index)]; p; p = p->next) {
+		if (p->index == index)
+			break;
+	}
+	read_unlock(&tcf_t_lock);
+	return p;
+}
+
+static __inline__ u32
+tcf_hash_new_index(void)
+{
+	do {
+		if (++idx_gen == 0)
+			idx_gen = 1;
+	} while (tcf_hash_lookup(idx_gen));
+
+	return idx_gen;
+}
+
+
+static inline int
+tcf_hash_search(struct tc_action *a, u32 index)
+{
+	struct tcf_st *p = tcf_hash_lookup(index);
+
+	if (p != NULL) {
+		a->priv = p;
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+#ifdef CONFIG_NET_ACT_INIT
+static inline struct tcf_st *
+tcf_hash_check(struct tc_st *parm, struct tc_action *a, int ovr, int bind)
+{
+	struct tcf_st *p = NULL;
+	if (parm->index && (p = tcf_hash_lookup(parm->index)) != NULL) {
+		spin_lock(&p->lock);
+		if (bind) {
+			p->bindcnt++;
+			p->refcnt++;
+		}
+		spin_unlock(&p->lock);
+		a->priv = (void *) p;
+	}
+	return p;
+}
+
+static inline struct tcf_st *
+tcf_hash_create(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind)
+{
+	unsigned h;
+	struct tcf_st *p = NULL;
+
+	p = kmalloc(size, GFP_KERNEL);
+	if (p == NULL)
+		return p;
+
+	memset(p, 0, size);
+	p->refcnt = 1;
+
+	if (bind) {
+		p->bindcnt = 1;
+	}
+
+	spin_lock_init(&p->lock);
+	p->stats.lock = &p->lock;
+	p->index = parm->index ? : tcf_hash_new_index();
+	p->tm.install = jiffies;
+	p->tm.lastuse = jiffies;
+#ifdef CONFIG_NET_ESTIMATOR
+	if (est) {
+		qdisc_new_estimator(&p->stats, est);
+	}
+#endif
+	h = tcf_hash(p->index);
+	write_lock_bh(&tcf_t_lock);
+	p->next = tcf_ht[h];
+	tcf_ht[h] = p;
+	write_unlock_bh(&tcf_t_lock);
+
+	a->priv = (void *) p;
+	return p;
+}
+
+static inline struct tcf_st *
+tcf_hash_init(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind)
+{
+	struct tcf_st *p;
+	p = tcf_hash_check (parm,a,ovr,bind);
+	if (NULL == p) {
+		return tcf_hash_create(parm, est, a, size, ovr, bind);
+	}
+}
+
+#endif
+
+#endif
diff -Nru a/include/net/pkt_cls.h b/include/net/pkt_cls.h
--- a/include/net/pkt_cls.h	2004-06-23 19:04:28 -07:00
+++ b/include/net/pkt_cls.h	2004-06-23 19:04:28 -07:00
@@ -71,12 +71,38 @@
 {
 	int err = 0;
 	u32 protocol = skb->protocol;
+#ifdef CONFIG_NET_CLS_ACT
+	struct tcf_proto *otp = tp;
+reclassify:
+#endif
+	protocol = skb->protocol;
 
 	for ( ; tp; tp = tp->next) {
 		if ((tp->protocol == protocol ||
-		     tp->protocol == __constant_htons(ETH_P_ALL)) &&
-		    (err = tp->classify(skb, tp, res)) >= 0)
+			tp->protocol == __constant_htons(ETH_P_ALL)) &&
+			(err = tp->classify(skb, tp, res)) >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+			if ( TC_ACT_RECLASSIFY == err) {
+				__u32 verd = (__u32) G_TC_VERD(skb->tc_verd);
+				tp = otp;
+
+				if (MAX_REC_LOOP < verd++) {
+					printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n",tp->prio&0xffff, ntohs(tp->protocol));
+					return TC_ACT_SHOT;
+				}
+				skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd);
+				goto reclassify;
+			} else {
+				if (skb->tc_verd) 
+					skb->tc_verd = SET_TC_VERD(skb->tc_verd,0);
+				return err;
+			}
+#else
+
 			return err;
+#endif
+            }
+
 	}
 	return -1;
 }
@@ -90,6 +116,8 @@
 
 extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
 extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
+extern int ing_filter(struct sk_buff *skb);
+
 
 
 
diff -Nru a/include/net/pkt_sched.h b/include/net/pkt_sched.h
--- a/include/net/pkt_sched.h	2004-06-23 19:04:25 -07:00
+++ b/include/net/pkt_sched.h	2004-06-23 19:04:25 -07:00
@@ -11,12 +11,16 @@
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/pkt_sched.h>
+#include <linux/rcupdate.h>
 #include <net/pkt_cls.h>
+#include <linux/module.h>
+#include <linux/rtnetlink.h>
 
 #ifdef CONFIG_X86_TSC
 #include <asm/msr.h>
 #endif
 
+
 struct rtattr;
 struct Qdisc;
 
@@ -92,6 +96,7 @@
 	struct net_device	*dev;
 
 	struct tc_stats		stats;
+	struct rcu_head 	q_rcu;
 	int			(*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
 
 	/* This field is deprecated, but it is still used by CBQ
@@ -390,14 +395,15 @@
 {
 	struct tcf_police *next;
 	int		refcnt;
+#ifdef CONFIG_NET_CLS_ACT
+	int		bindcnt;
+#endif
 	u32		index;
-
 	int		action;
 	int		result;
 	u32		ewma_rate;
 	u32		burst;
 	u32		mtu;
-
 	u32		toks;
 	u32		ptoks;
 	psched_time_t	t_c;
@@ -408,16 +414,89 @@
 	struct tc_stats	stats;
 };
 
+#ifdef CONFIG_NET_CLS_ACT
+
+#define ACT_P_CREATED 1
+#define ACT_P_DELETED 1
+#define tca_gen(name) \
+struct tcf_##name *next; \
+	u32 index; \
+	int refcnt; \
+	int bindcnt; \
+	u32 capab; \
+	int action; \
+	struct tcf_t tm; \
+	struct tc_stats stats; \
+	spinlock_t lock
+
+
+struct tc_action
+{
+	void *priv;
+	struct tc_action_ops *ops;
+	__u32   type;   /* for backward compat(TCA_OLD_COMPAT) */
+	__u32   order; 
+	struct tc_action *next;
+};
+
+#define TCA_CAP_NONE 0
+struct tc_action_ops
+{
+	struct tc_action_ops *next;
+	char    kind[IFNAMSIZ];
+	__u32   type; /* TBD to match kind */
+	__u32 	capab;  /* capabilities includes 4 bit version */
+	struct module		*owner;
+	int     (*act)(struct sk_buff **, struct tc_action *);
+	int     (*get_stats)(struct sk_buff *, struct tc_action *);
+	int     (*dump)(struct sk_buff *, struct tc_action *,int , int);
+	int     (*cleanup)(struct tc_action *, int bind);
+	int     (*lookup)(struct tc_action *, u32 );
+	int     (*init)(struct rtattr *,struct rtattr *,struct tc_action *, int , int );
+	int     (*walk)(struct sk_buff *, struct netlink_callback *, int , struct tc_action *);
+};
+
+extern int tcf_register_action(struct tc_action_ops *a);
+extern int tcf_unregister_action(struct tc_action_ops *a);
+extern void tcf_action_destroy(struct tc_action *a, int bind);
+extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a);
+extern int tcf_action_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
+extern int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
+extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
+extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
+extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
+extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *);
+extern int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,struct tc_action *,int , int );
+extern int tcf_act_police_dump(struct sk_buff *, struct tc_action *, int, int);
+extern int tcf_act_police(struct sk_buff **skb, struct tc_action *a);
+#endif
+
+extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
 extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st);
 extern void tcf_police_destroy(struct tcf_police *p);
 extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
 extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
-extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
 
-static inline void tcf_police_release(struct tcf_police *p)
+static inline int tcf_police_release(struct tcf_police *p, int bind)
 {
+	int ret = 0;
+#ifdef CONFIG_NET_CLS_ACT
+	if (p) {
+		if (bind) {
+			 p->bindcnt--;
+		}
+		p->refcnt--;
+		if (p->refcnt <= 0 && !p->bindcnt) {
+			tcf_police_destroy(p);
+			ret = 1;
+		}
+	}
+#else
 	if (p && --p->refcnt == 0)
 		tcf_police_destroy(p);
+
+#endif
+	return ret;
 }
 
 extern struct Qdisc noop_qdisc;
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	2004-06-23 19:04:28 -07:00
+++ b/include/net/sock.h	2004-06-23 19:04:28 -07:00
@@ -53,6 +53,7 @@
 
 #include <asm/atomic.h>
 #include <net/dst.h>
+#include <net/checksum.h>
 
 /*
  * This structure really needs to be cleaned up.
@@ -166,6 +167,9 @@
   *	@sk_socket - Identd and reporting IO signals
   *	@sk_user_data - RPC layer private data
   *	@sk_owner - module that owns this socket
+  *	@sk_send_head - front of stuff to transmit
+  *	@sk_write_pending - a write to stream socket waits to start
+  *	@sk_queue_shrunk - write queue has been shrunk recently
   *	@sk_state_change - callback to indicate change in the state of the sock
   *	@sk_data_ready - callback to indicate there is data to be processed
   *	@sk_write_space - callback to indicate there is bf sending space available
@@ -245,8 +249,12 @@
 	struct timeval		sk_stamp;
 	struct socket		*sk_socket;
 	void			*sk_user_data;
+	struct sk_buff		*sk_send_head;
 	struct module		*sk_owner;
+	int			sk_write_pending;
 	void			*sk_security;
+	__u8			sk_queue_shrunk;
+	/* three bytes hole, try to pack */
 	void			(*sk_state_change)(struct sock *sk);
 	void			(*sk_data_ready)(struct sock *sk, int bytes);
 	void			(*sk_write_space)(struct sock *sk);
@@ -413,6 +421,44 @@
 	return sk->sk_ack_backlog > sk->sk_max_ack_backlog;
 }
 
+/*
+ * Compute minimal free write space needed to queue new packets.
+ */
+static inline int sk_stream_min_wspace(struct sock *sk)
+{
+	return sk->sk_wmem_queued / 2;
+}
+
+static inline int sk_stream_wspace(struct sock *sk)
+{
+	return sk->sk_sndbuf - sk->sk_wmem_queued;
+}
+
+extern void sk_stream_write_space(struct sock *sk);
+
+static inline int sk_stream_memory_free(struct sock *sk)
+{
+	return sk->sk_wmem_queued < sk->sk_sndbuf;
+}
+
+extern void sk_stream_rfree(struct sk_buff *skb);
+
+static inline void sk_stream_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+	skb->sk = sk;
+	skb->destructor = sk_stream_rfree;
+	atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+	sk->sk_forward_alloc -= skb->truesize;
+}
+
+static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb)
+{
+	sk->sk_queue_shrunk   = 1;
+	sk->sk_wmem_queued   -= skb->truesize;
+	sk->sk_forward_alloc += skb->truesize;
+	__kfree_skb(skb);
+}
+
 /* The per-socket spinlock must be held here. */
 #define sk_add_backlog(__sk, __skb)				\
 do {	if (!(__sk)->sk_backlog.tail) {				\
@@ -437,6 +483,11 @@
 	rc;							\
 })
 
+extern int sk_stream_wait_connect(struct sock *sk, long *timeo_p);
+extern int sk_stream_wait_memory(struct sock *sk, long *timeo_p);
+extern void sk_stream_wait_close(struct sock *sk, long timeo_p);
+extern int sk_stream_error(struct sock *sk, int flags, int err);
+
 extern int sk_wait_data(struct sock *sk, long *timeo);
 
 /* IP protocol blocks we attach to sockets.
@@ -902,6 +953,34 @@
 	return dst;
 }
 
+static inline void sk_charge_skb(struct sock *sk, struct sk_buff *skb)
+{
+	sk->sk_wmem_queued   += skb->truesize;
+	sk->sk_forward_alloc -= skb->truesize;
+}
+
+static inline int skb_copy_to_page(struct sock *sk, char __user *from,
+				   struct sk_buff *skb, struct page *page,
+				   int off, int copy)
+{
+	if (skb->ip_summed == CHECKSUM_NONE) {
+		int err = 0;
+		unsigned int csum = csum_and_copy_from_user(from,
+						     page_address(page) + off,
+							    copy, 0, &err);
+		if (err)
+			return err;
+		skb->csum = csum_block_add(skb->csum, csum, skb->len);
+	} else if (copy_from_user(page_address(page) + off, from, copy))
+		return -EFAULT;
+
+	skb->len	     += copy;
+	skb->data_len	     += copy;
+	skb->truesize	     += copy;
+	sk->sk_wmem_queued   += copy;
+	sk->sk_forward_alloc -= copy;
+	return 0;
+}
 
 /*
  * 	Queue a received datagram if it will fit. Stream and sequenced
@@ -1017,6 +1096,20 @@
 
 #define SOCK_MIN_SNDBUF 2048
 #define SOCK_MIN_RCVBUF 256
+
+static inline void sk_stream_moderate_sndbuf(struct sock *sk)
+{
+	if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) {
+		sk->sk_sndbuf = min(sk->sk_sndbuf, sk->sk_wmem_queued / 2);
+		sk->sk_sndbuf = max(sk->sk_sndbuf, SOCK_MIN_SNDBUF);
+	}
+}
+
+#define sk_stream_for_retrans_queue(skb, sk)				\
+		for (skb = (sk)->sk_write_queue.next;			\
+		     (skb != (sk)->sk_send_head) &&			\
+		     (skb != (struct sk_buff *)&(sk)->sk_write_queue);	\
+		     skb = skb->next)
 
 /*
  *	Default write policy as shown to user space via poll/select/SIGIO
diff -Nru a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h	2004-06-23 19:04:25 -07:00
+++ b/include/net/tcp.h	2004-06-23 19:04:25 -07:00
@@ -33,6 +33,7 @@
 #include <net/checksum.h>
 #include <net/sock.h>
 #include <net/snmp.h>
+#include <net/ip.h>
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/ipv6.h>
 #endif
@@ -870,7 +871,6 @@
 					  long timeout);
 extern struct sock *		tcp_accept(struct sock *sk, int flags, int *err);
 extern unsigned int		tcp_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
-extern void			tcp_write_space(struct sock *sk); 
 
 extern int			tcp_getsockopt(struct sock *sk, int level, 
 					       int optname,
@@ -1186,30 +1186,8 @@
 
 #define TCP_SKB_CB(__skb)	((struct tcp_skb_cb *)&((__skb)->cb[0]))
 
-#define for_retrans_queue(skb, sk, tp) \
-		for (skb = (sk)->sk_write_queue.next;			\
-		     (skb != (tp)->send_head) &&			\
-		     (skb != (struct sk_buff *)&(sk)->sk_write_queue);	\
-		     skb=skb->next)
-
-
 #include <net/tcp_ecn.h>
 
-
-/*
- *	Compute minimal free write space needed to queue new packets. 
- */
-static inline int tcp_min_write_space(struct sock *sk)
-{
-	return sk->sk_wmem_queued / 2;
-}
- 
-static inline int tcp_wspace(struct sock *sk)
-{
-	return sk->sk_sndbuf - sk->sk_wmem_queued;
-}
-
-
 /* This determines how many packets are "in the network" to the best
  * of our knowledge.  In many cases it is conservative, but where
  * detailed information is available from the receiver (via SACK
@@ -1415,7 +1393,7 @@
 		  tcp_minshall_check(tp))));
 }
 
-/* This checks if the data bearing packet SKB (usually tp->send_head)
+/* This checks if the data bearing packet SKB (usually sk->sk_send_head)
  * should be put on the wire right now.
  */
 static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb,
@@ -1472,7 +1450,7 @@
 						 unsigned cur_mss,
 						 int nonagle)
 {
-	struct sk_buff *skb = tp->send_head;
+	struct sk_buff *skb = sk->sk_send_head;
 
 	if (skb) {
 		if (!tcp_skb_is_last(sk, skb))
@@ -1492,7 +1470,7 @@
 
 static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_opt *tp)
 {
-	struct sk_buff *skb = tp->send_head;
+	struct sk_buff *skb = sk->sk_send_head;
 
 	return (skb &&
 		tcp_snd_test(tp, skb, tcp_current_mss(sk, 1),
@@ -1891,20 +1869,6 @@
 
 #define TCP_MEM_QUANTUM	((int)PAGE_SIZE)
 
-static inline void tcp_free_skb(struct sock *sk, struct sk_buff *skb)
-{
-	tcp_sk(sk)->queue_shrunk = 1;
-	sk->sk_wmem_queued -= skb->truesize;
-	sk->sk_forward_alloc += skb->truesize;
-	__kfree_skb(skb);
-}
-
-static inline void tcp_charge_skb(struct sock *sk, struct sk_buff *skb)
-{
-	sk->sk_wmem_queued += skb->truesize;
-	sk->sk_forward_alloc -= skb->truesize;
-}
-
 extern void __tcp_mem_reclaim(struct sock *sk);
 extern int tcp_mem_schedule(struct sock *sk, int size, int kind);
 
@@ -1922,14 +1886,6 @@
 	}
 }
 
-static inline void tcp_moderate_sndbuf(struct sock *sk)
-{
-	if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) {
-		sk->sk_sndbuf = min(sk->sk_sndbuf, sk->sk_wmem_queued / 2);
-		sk->sk_sndbuf = max(sk->sk_sndbuf, SOCK_MIN_SNDBUF);
-	}
-}
-
 static inline struct sk_buff *tcp_alloc_pskb(struct sock *sk, int size, int mem, int gfp)
 {
 	struct sk_buff *skb = alloc_skb(size+MAX_TCP_HEADER, gfp);
@@ -1944,7 +1900,7 @@
 		__kfree_skb(skb);
 	} else {
 		tcp_enter_memory_pressure();
-		tcp_moderate_sndbuf(sk);
+		sk_stream_moderate_sndbuf(sk);
 	}
 	return NULL;
 }
@@ -1963,7 +1919,7 @@
 			return page;
 	}
 	tcp_enter_memory_pressure();
-	tcp_moderate_sndbuf(sk);
+	sk_stream_moderate_sndbuf(sk);
 	return NULL;
 }
 
@@ -1972,20 +1928,10 @@
 	struct sk_buff *skb;
 
 	while ((skb = __skb_dequeue(&sk->sk_write_queue)) != NULL)
-		tcp_free_skb(sk, skb);
+		sk_stream_free_skb(sk, skb);
 	tcp_mem_reclaim(sk);
 }
 
-extern void tcp_rfree(struct sk_buff *skb);
-
-static inline void tcp_set_owner_r(struct sk_buff *skb, struct sock *sk)
-{
-	skb->sk = sk;
-	skb->destructor = tcp_rfree;
-	atomic_add(skb->truesize, &sk->sk_rmem_alloc);
-	sk->sk_forward_alloc -= skb->truesize;
-}
-
 extern void tcp_listen_wlock(void);
 
 /* - We may sleep inside this lock.
@@ -2070,8 +2016,8 @@
 	 * unsent new data, and the advertised window should allow
 	 * sending it.
 	 */
-	return (sysctl_tcp_frto && tp->send_head &&
-		!after(TCP_SKB_CB(tp->send_head)->end_seq,
+	return (sysctl_tcp_frto && sk->sk_send_head &&
+		!after(TCP_SKB_CB(sk->sk_send_head)->end_seq,
 		       tp->snd_una + tp->snd_wnd));
 }
 
diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h	2004-06-23 19:04:28 -07:00
+++ b/include/net/xfrm.h	2004-06-23 19:04:28 -07:00
@@ -497,10 +497,6 @@
 	return 0;
 }
 
-/* placeholder until xfrm6_tunnel.c is written */
-static inline int xfrm6_tunnel_check_size(struct sk_buff *skb)
-{ return 0; }
-
 /* A struct encoding bundle of transformations to apply to some set of flow.
  *
  * dst->child points to the next element of bundle.
@@ -783,6 +779,12 @@
 	void (*err_handler)(struct sk_buff *skb, void *info);
 };
 
+struct xfrm6_tunnel {
+	int (*handler)(struct sk_buff **pskb, unsigned int *nhoffp);
+	void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
+			    int type, int code, int offset, __u32 info);
+};
+
 extern void xfrm_init(void);
 extern void xfrm4_init(void);
 extern void xfrm4_fini(void);
@@ -793,6 +795,8 @@
 extern void xfrm4_state_fini(void);
 extern void xfrm6_state_init(void);
 extern void xfrm6_state_fini(void);
+extern void xfrm6_tunnel_init(void);
+extern void xfrm6_tunnel_fini(void);
 
 extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
 extern struct xfrm_state *xfrm_state_alloc(void);
@@ -812,12 +816,18 @@
 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_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
-extern int xfrm_check_output(struct xfrm_state *x, struct sk_buff *skb, unsigned short family);
+extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm4_rcv(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_check_size(struct sk_buff *skb);
 extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
+extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
+extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
+extern int xfrm6_tunnel_check_size(struct sk_buff *skb);
+extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
+extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
+extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
 
 #ifdef CONFIG_XFRM
 extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
diff -Nru a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/scsi/scsi_dbg.h	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,18 @@
+#ifndef _SCSI_SCSI_DBG_H
+#define _SCSI_SCSI_DBG_H
+
+struct scsi_cmnd;
+struct scsi_request;
+
+extern void scsi_print_command(struct scsi_cmnd *);
+extern void __scsi_print_command(unsigned char *);
+extern void scsi_print_sense(const char *, struct scsi_cmnd *);
+extern void scsi_print_req_sense(const char *, struct scsi_request *);
+extern void scsi_print_driverbyte(int);
+extern void scsi_print_hostbyte(int);
+extern void scsi_print_status(unsigned char);
+extern int scsi_print_msg(const unsigned char *);
+extern const char *scsi_sense_key_string(unsigned char);
+extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
+
+#endif /* _SCSI_SCSI_DBG_H */
diff -Nru a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
--- a/include/scsi/scsi_eh.h	2004-06-23 19:04:28 -07:00
+++ b/include/scsi/scsi_eh.h	2004-06-23 19:04:28 -07:00
@@ -1,6 +1,10 @@
 #ifndef _SCSI_SCSI_EH_H
 #define _SCSI_SCSI_EH_H
 
+struct scsi_cmnd;
+struct scsi_device;
+struct Scsi_Host;
+
 extern void scsi_add_timer(struct scsi_cmnd *, int,
 			   void (*)(struct scsi_cmnd *));
 extern int scsi_delete_timer(struct scsi_cmnd *);
diff -Nru a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
--- a/include/scsi/scsi_host.h	2004-06-23 19:04:25 -07:00
+++ b/include/scsi/scsi_host.h	2004-06-23 19:04:25 -07:00
@@ -151,7 +151,7 @@
 	 * here then you will get a call to slave_configure(), then the
 	 * device will be used for however long it is kept around, then when
 	 * the device is removed from the system (or * possibly at reboot
-	 * time), you will then get a call to slave_detach().  This is
+	 * time), you will then get a call to slave_destroy().  This is
 	 * assuming you implement slave_configure and slave_destroy.
 	 * However, if you allocate memory and hang it off the device struct,
 	 * then you must implement the slave_destroy() routine at a minimum
@@ -185,7 +185,7 @@
 	 *     specific setup basis...
 	 * 6.  Return 0 on success, non-0 on error.  The device will be marked
 	 *     as offline on error so that no access will occur.  If you return
-	 *     non-0, your slave_detach routine will never get called for this
+	 *     non-0, your slave_destroy routine will never get called for this
 	 *     device, so don't leave any loose memory hanging around, clean
 	 *     up after yourself before returning non-0
 	 *
@@ -312,6 +312,11 @@
 	 * True for emulated SCSI host adapters (e.g. ATAPI)
 	 */
 	unsigned emulated:1;
+
+	/*
+	 * True if the low-level driver performs its own reset-settle delays.
+	 */
+	unsigned skip_settle_delay:1;
 
 	/*
 	 * Countdown for host blocking with no commands outstanding
diff -Nru a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
--- a/include/scsi/scsi_ioctl.h	2004-06-23 19:04:25 -07:00
+++ b/include/scsi/scsi_ioctl.h	2004-06-23 19:04:25 -07:00
@@ -41,7 +41,6 @@
 } Scsi_FCTargAddress;
 
 extern int scsi_ioctl(struct scsi_device *, int, void __user *);
-extern int kernel_scsi_ioctl(struct scsi_device *, int , void *);
 extern int scsi_ioctl_send_command(struct scsi_device *,
 				   struct scsi_ioctl_command __user *);
 
diff -Nru a/include/video/sisfb.h b/include/video/sisfb.h
--- a/include/video/sisfb.h	2004-06-23 19:04:26 -07:00
+++ b/include/video/sisfb.h	2004-06-23 19:04:26 -07:00
@@ -38,7 +38,8 @@
 #define TV_AVIDEO               0x00000100
 #define TV_SVIDEO               0x00000200
 #define TV_SCART                0x00000400
-#define VB_CONEXANT		0x00000800
+#define VB_CONEXANT		0x00000800	/* 661 series only */
+#define VB_TRUMPION		VB_CONEXANT	/* 300 series only */
 #define TV_PALM                 0x00001000
 #define TV_PALN                 0x00002000
 #define TV_NTSCJ		0x00001000
@@ -86,204 +87,112 @@
 #define VB_DISPMODE_DUAL	VB_DUALVIEW_MODE
 #define VB_DISPLAY_MODE       	(SINGLE_MODE | MIRROR_MODE | DUALVIEW_MODE)
 
-/* *Never* change the order of the following enum */
-typedef enum _SIS_CHIP_TYPE {
-	SIS_VGALegacy = 0,	/* chip_id in sisfb_info */
-	SIS_300,
-	SIS_630,
-	SIS_540,
-	SIS_730,
-	SIS_315H,
-	SIS_315,
-	SIS_315PRO,
-	SIS_550,
-	SIS_650,
-	SIS_740,
-	SIS_330,
-	SIS_661,
-	SIS_741,
-	SIS_660,
-	SIS_760,
-	MAX_SIS_CHIP
-} SIS_CHIP_TYPE;
-
-/* Addtional IOCTLs for communication sisfb <> X driver                */
-/* If changing this, vgatypes.h must also be changed (for X driver)    */
-
-/* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO	  	_IOR('n',0xF8,__u32)
-/* ioctrl to get current vertical retrace status */
-#define SISFB_GET_VBRSTATUS  	_IOR('n',0xF9,__u32)
-/* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
-#define SISFB_GET_AUTOMAXIMIZE 	_IOR('n',0xFA,__u32)
-#define SISFB_SET_AUTOMAXIMIZE 	_IOW('n',0xFA,__u32)
-
-/* TW: Structure argument for SISFB_GET_INFO ioctl  */
+/* Structure argument for SISFB_GET_INFO ioctl  */
 typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
 
 struct _SISFB_INFO {
-	unsigned long sisfb_id;         /* for identifying sisfb */
+	__u32   sisfb_id;         	/* for identifying sisfb */
 #ifndef SISFB_ID
 #define SISFB_ID	  0x53495346    /* Identify myself with 'SISF' */
 #endif
- 	int    chip_id;			/* PCI ID of detected chip */
-	int    memory;			/* video memory in KB which sisfb manages */
-	int    heapstart;               /* heap start (= sisfb "mem" argument) in KB */
-	unsigned char fbvidmode;	/* current sisfb mode */
+ 	__u32   chip_id;		/* PCI-ID of detected chip */
+	__u32   memory;			/* video memory in KB which sisfb manages */
+	__u32   heapstart;            	/* heap start (= sisfb "mem" argument) in KB */
+	__u8    fbvidmode;		/* current sisfb mode */
 
-	unsigned char sisfb_version;
-	unsigned char sisfb_revision;
-	unsigned char sisfb_patchlevel;
+	__u8    sisfb_version;
+	__u8    sisfb_revision;
+	__u8 	sisfb_patchlevel;
 
-	unsigned char sisfb_caps;	/* Sisfb capabilities */
+	__u8 	sisfb_caps;		/* sisfb capabilities */
 
-	int    sisfb_tqlen;		/* turbo queue length (in KB) */
+	__u32	sisfb_tqlen;		/* turbo queue length (in KB) */
 
-	unsigned int sisfb_pcibus;      /* The card's PCI ID */
-	unsigned int sisfb_pcislot;
-	unsigned int sisfb_pcifunc;
+	__u32 	sisfb_pcibus;      	/* The card's PCI ID */
+	__u32 	sisfb_pcislot;
+	__u32 	sisfb_pcifunc;
 
-	unsigned char sisfb_lcdpdc;	/* PanelDelayCompensation */
+	__u8 	sisfb_lcdpdc;		/* PanelDelayCompensation */
 
-	unsigned char sisfb_lcda;	/* Detected status of LCDA for low res/text modes */
+	__u8 	sisfb_lcda;		/* Detected status of LCDA for low res/text modes */
 
-	unsigned long sisfb_vbflags;
-	unsigned long sisfb_currentvbflags;
+	__u32 	sisfb_vbflags;
+	__u32 	sisfb_currentvbflags;
 
-	int sisfb_scalelcd;
-	unsigned long sisfb_specialtiming;
+	__u32 	sisfb_scalelcd;
+	__u32 	sisfb_specialtiming;
 
-	unsigned char sisfb_haveemi;
-	unsigned char sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-	unsigned char sisfb_haveemilcd;
+	__u8 	sisfb_haveemi;
+	__u8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+	__u8 	sisfb_haveemilcd;
 
-	char reserved[213]; 		/* for future use */
-};
+	__u8 	sisfb_lcdpdca;		/* PanelDelayCompensation for LCD-via-CRT1 */
 
-/* For fb memory manager */
-struct sis_memreq {
-	unsigned long offset;
-	unsigned long size;
-};
+	__u16	sisfb_tvxpos, sisfb_tvypos;  /* Warning: Values + 32 ! */
 
-/* More or less deprecated stuff follows: */
-typedef enum _TVTYPE {
-	TVMODE_NTSC = 0,
-	TVMODE_PAL,
-	TVMODE_HIVISION,
-	TVMODE_TOTAL
-} SIS_TV_TYPE;
-
-typedef enum _TVPLUGTYPE {
-	TVPLUG_Legacy = 0,
-	TVPLUG_COMPOSITE,
-	TVPLUG_SVIDEO,
-	TVPLUG_SCART,
-	TVPLUG_TOTAL
-} SIS_TV_PLUG;
-
-struct mode_info {
-	int    bpp;
-	int    xres;
-	int    yres;
-	int    v_xres;		/* deprecated - use var instead */
-	int    v_yres;		/* deprecated - use var instead */
-	int    org_x;		/* deprecated - use var instead */
-	int    org_y;		/* deprecated - use var instead */
-	unsigned int  vrate;
+	__u8 	reserved[208]; 		/* for future use */
 };
 
-struct ap_data {
-	struct mode_info minfo;
-	unsigned long iobase;
-	unsigned int  mem_size;
-	unsigned long disp_state;  /* deprecated */
-	SIS_CHIP_TYPE chip;
-	unsigned char hasVB;
-	SIS_TV_TYPE TV_type;	   /* deprecated */
-	SIS_TV_PLUG TV_plug;	   /* deprecated */
-	unsigned long version;
-	unsigned long vbflags;	   /* replaces deprecated entries above */
-	unsigned long currentvbflags;
-	char reserved[248];
+/* Addtional IOCTLs for communication sisfb <> X driver                */
+/* If changing this, vgatypes.h must also be changed (for X driver)    */
+
+/* ioctl for identifying and giving some info (esp. memory heap start) */
+#define SISFB_GET_INFO_SIZE  	_IOR(0xF3,0x00,__u32)
+#define SISFB_GET_INFO	  	_IOR(0xF3,0x01,struct _SISFB_INFO)
+
+/* ioctrl to get current vertical retrace status */
+#define SISFB_GET_VBRSTATUS  	_IOR(0xF3,0x02,__u32)
+
+/* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
+#define SISFB_GET_AUTOMAXIMIZE 	_IOR(0xF3,0x03,__u32)
+#define SISFB_SET_AUTOMAXIMIZE 	_IOW(0xF3,0x03,__u32)
+
+/* ioctls to relocate TV output (x=D[31:16], y=D[15:0], + 32)*/
+#define SISFB_GET_TVPOSOFFSET   _IOR(0xF3,0x04,__u32)
+#define SISFB_SET_TVPOSOFFSET   _IOW(0xF3,0x04,__u32)
+
+/* ioctl for locking sisfb (no register access during lock) */
+/* As of now, only used to avoid register access during
+ * the ioctls listed above.
+ */
+#define SISFB_SET_LOCK  	_IOW(0xF3,0x06,__u32)
+
+/* more to come soon */
+
+/* ioctls 0xF3 up to 0x3F reserved for sisfb */
+
+/****************************************************************/
+/* The following are deprecated and should not be used anymore: */
+/****************************************************************/
+/* ioctl for identifying and giving some info (esp. memory heap start) */
+#define SISFB_GET_INFO_OLD  	   _IOR('n',0xF8,__u32)
+/* ioctrl to get current vertical retrace status */
+#define SISFB_GET_VBRSTATUS_OLD	   _IOR('n',0xF9,__u32)
+/* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
+#define SISFB_GET_AUTOMAXIMIZE_OLD _IOR('n',0xFA,__u32)
+#define SISFB_SET_AUTOMAXIMIZE_OLD _IOW('n',0xFA,__u32)
+/****************************************************************/
+/*               End of deprecated ioctl numbers                */
+/****************************************************************/
+
+/* For fb memory manager (FBIO_ALLOC, FBIO_FREE) */
+struct sis_memreq {
+	__u32 	offset;
+	__u32 	size;
 };
 
 /**********************************************/
 /*                  PRIVATE                   */
+/*         (for IN-KERNEL usage only)         */
 /**********************************************/
 
 #ifdef __KERNEL__
-#include <linux/spinlock.h>
-
-typedef enum _VGA_ENGINE {
-	UNKNOWN_VGA = 0,
-	SIS_300_VGA,
-	SIS_315_VGA,
-} VGA_ENGINE;
-
-struct video_info {
-	int           chip_id;
-	unsigned int  video_size;
-	unsigned long video_base;
-	char  *       video_vbase;
-	unsigned long mmio_base;
-	char  *       mmio_vbase;
-	unsigned long vga_base;
-	unsigned long mtrr;
-	unsigned long heapstart;
-
-	int    video_bpp;
-	int    video_cmap_len;
-	int    video_width;
-	int    video_height;
-	int    video_vwidth;			/* DEPRECATED - use var instead */
-	int    video_vheight;			/* DEPRECATED - use var instead */
-	int    org_x;				/* DEPRECATED - use var instead */
-	int    org_y;				/* DEPRECATED - use var instead */
-	int    video_linelength;
-	unsigned int refresh_rate;
-
-	unsigned long disp_state;		/* DEPRECATED */
-	unsigned char hasVB;			/* DEPRECATED */
-	unsigned char TV_type;			/* DEPRECATED */
-	unsigned char TV_plug;			/* DEPRECATED */
-
-	SIS_CHIP_TYPE chip;
-	unsigned char revision_id;
-
-        unsigned short DstColor;		/* For 2d acceleration */
-	unsigned long  SiS310_AccelDepth;
-	unsigned long  CommandReg;
-
-	spinlock_t     lockaccel;		/* Do not use outside of kernel! */
-
-        unsigned int   pcibus;
-	unsigned int   pcislot;
-	unsigned int   pcifunc;
-
-	int 	       accel;
-
-	unsigned short subsysvendor;
-	unsigned short subsysdevice;
-
-	unsigned long  vbflags;			/* Replacing deprecated stuff from above */
-	unsigned long  currentvbflags;
-
-	int    current_bpp;
-	int    current_width;
-	int    current_height;
-	int    current_htotal;
-	int    current_vtotal;
-	__u32  current_pixclock;
-	int    current_refresh_rate;
-
-	char reserved[200];
-};
-
-extern struct video_info ivideo;
+#define	UNKNOWN_VGA  0
+#define	SIS_300_VGA  1
+#define	SIS_315_VGA  2
 
 extern void sis_malloc(struct sis_memreq *req);
-extern void sis_free(unsigned long base);
-extern void sis_dispinfo(struct ap_data *rec);
+extern void sis_free(u32 base);
 #endif
+
 #endif
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/init/Kconfig	2004-06-23 19:04:28 -07:00
@@ -121,6 +121,18 @@
 	  up to the user level program to do useful things with this
 	  information.  This is generally a good idea, so say Y.
 
+config BSD_PROCESS_ACCT_V3
+	bool "BSD Process Accounting version 3 file format"
+	depends on BSD_PROCESS_ACCT
+	default n
+	help
+	  If you say Y here, the process accounting information is written
+	  in a new file format that also logs the process IDs of each
+	  process and it's parent. Note that this file format is incompatible
+	  with previous v0/v1/v2 file formats, so you will need updated tools
+	  for processing it. A preliminary version of these tools is available
+	  at <http://http://www.de.kernel.org/pub/linux/utils/acct/>.
+
 config SYSCTL
 	bool "Sysctl support"
 	---help---
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	2004-06-23 19:04:25 -07:00
+++ b/init/main.c	2004-06-23 19:04:25 -07:00
@@ -43,6 +43,7 @@
 #include <linux/efi.h>
 #include <linux/unistd.h>
 #include <linux/rmap.h>
+#include <linux/mempolicy.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -268,6 +269,8 @@
 				panic_later = "Too many boot env vars at `%s'";
 				panic_param = param;
 			}
+			if (!strncmp(param, envp_init[i], val - param))
+				break;
 		}
 		envp_init[i] = param;
 	} else {
@@ -385,6 +388,7 @@
 static void noinline rest_init(void)
 {
 	kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
+	numa_default_policy();
 	unlock_kernel();
  	cpu_idle();
 } 
@@ -454,8 +458,10 @@
 		initrd_start = 0;
 	}
 #endif
+	vfs_caches_init_early();
 	mem_init();
 	kmem_cache_init();
+	numa_policy_init();
 	if (late_time_init)
 		late_time_init();
 	calibrate_delay();
@@ -645,6 +651,7 @@
 	free_initmem();
 	unlock_kernel();
 	system_state = SYSTEM_RUNNING;
+	numa_default_policy();
 
 	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
 		printk("Warning: unable to open an initial console.\n");
diff -Nru a/ipc/mqueue.c b/ipc/mqueue.c
--- a/ipc/mqueue.c	2004-06-23 19:04:27 -07:00
+++ b/ipc/mqueue.c	2004-06-23 19:04:27 -07:00
@@ -43,10 +43,10 @@
 #define CTL_MSGSIZEMAX 	4
 
 /* default values */
-#define DFLT_QUEUESMAX	64	/* max number of message queues */
-#define DFLT_MSGMAX 	40	/* max number of messages in each queue */
+#define DFLT_QUEUESMAX	256	/* max number of message queues */
+#define DFLT_MSGMAX 	10	/* max number of messages in each queue */
 #define HARD_MSGMAX 	(131072/sizeof(void*))
-#define DFLT_MSGSIZEMAX 16384	/* max message size */
+#define DFLT_MSGSIZEMAX 8192	/* max message size */
 
 #define NOTIFY_COOKIE_LEN	32
 
@@ -67,6 +67,7 @@
 
 	struct sigevent notify;
 	pid_t notify_owner;
+ 	struct user_struct *user;	/* user who created, for accouting */
 	struct sock *notify_sock;
 	struct sk_buff *notify_cookie;
 
@@ -114,6 +115,9 @@
 
 		if (S_ISREG(mode)) {
 			struct mqueue_inode_info *info;
+			struct task_struct *p = current;
+			struct user_struct *u = p->user;
+			unsigned long mq_bytes, mq_msg_tblsz;
 
 			inode->i_fop = &mqueue_file_operations;
 			inode->i_size = FILENT_SIZE;
@@ -123,8 +127,10 @@
 			init_waitqueue_head(&info->wait_q);
 			INIT_LIST_HEAD(&info->e_wait_q[0].list);
 			INIT_LIST_HEAD(&info->e_wait_q[1].list);
+			info->messages = NULL;
 			info->notify_owner = 0;
 			info->qsize = 0;
+			info->user = NULL;	/* set when all is ok */
 			memset(&info->attr, 0, sizeof(info->attr));
 			info->attr.mq_maxmsg = DFLT_MSGMAX;
 			info->attr.mq_msgsize = DFLT_MSGSIZEMAX;
@@ -132,12 +138,29 @@
 				info->attr.mq_maxmsg = attr->mq_maxmsg;
 				info->attr.mq_msgsize = attr->mq_msgsize;
 			}
-			info->messages = kmalloc(info->attr.mq_maxmsg * sizeof(struct msg_msg *), GFP_KERNEL);
+			mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
+			mq_bytes = (mq_msg_tblsz +
+				(info->attr.mq_maxmsg * info->attr.mq_msgsize));
+
+			spin_lock(&mq_lock);
+			if (u->mq_bytes + mq_bytes < u->mq_bytes ||
+		 	    u->mq_bytes + mq_bytes >
+			    p->rlim[RLIMIT_MSGQUEUE].rlim_cur) {
+				spin_unlock(&mq_lock);
+				goto out_inode;
+			}
+			u->mq_bytes += mq_bytes;
+			spin_unlock(&mq_lock);
+
+			info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
 			if (!info->messages) {
-				make_bad_inode(inode);
-				iput(inode);
-				inode = NULL;
+				spin_lock(&mq_lock);
+				u->mq_bytes -= mq_bytes;
+				spin_unlock(&mq_lock);
+				goto out_inode;
 			}
+			/* all is ok */
+			info->user = get_uid(u);
 		} else if (S_ISDIR(mode)) {
 			inode->i_nlink++;
 			/* Some things misbehave if size == 0 on a directory */
@@ -147,6 +170,10 @@
 		}
 	}
 	return inode;
+out_inode:
+	make_bad_inode(inode);
+	iput(inode);
+	return NULL;
 }
 
 static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
@@ -205,6 +232,8 @@
 static void mqueue_delete_inode(struct inode *inode)
 {
 	struct mqueue_inode_info *info;
+	struct user_struct *user;
+	unsigned long mq_bytes;
 	int i;
 
 	if (S_ISDIR(inode->i_mode)) {
@@ -220,10 +249,15 @@
 
 	clear_inode(inode);
 
-	if (info->messages) {
+	mq_bytes = (info->attr.mq_maxmsg * sizeof(struct msg_msg *) +
+		   (info->attr.mq_maxmsg * info->attr.mq_msgsize));
+	user = info->user;
+	if (user) {
 		spin_lock(&mq_lock);
+		user->mq_bytes -= mq_bytes;
 		queues_count--;
 		spin_unlock(&mq_lock);
+		free_uid(user);
 	}
 }
 
@@ -534,6 +568,28 @@
 	info->notify_owner = 0;
 }
 
+static int mq_attr_ok(struct mq_attr *attr)
+{
+	if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0)
+		return 0;
+	if (capable(CAP_SYS_RESOURCE)) {
+		if (attr->mq_maxmsg > HARD_MSGMAX)
+			return 0;
+	} else {
+		if (attr->mq_maxmsg > msg_max ||
+				attr->mq_msgsize > msgsize_max)
+			return 0;
+	}
+	/* check for overflow */
+	if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
+		return 0;
+	if ((unsigned long)(attr->mq_maxmsg * attr->mq_msgsize) +
+	    (attr->mq_maxmsg * sizeof (struct msg_msg *)) <
+	    (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize))
+		return 0;
+	return 1;
+}
+
 /*
  * Invoked when creating a new queue via sys_mq_open
  */
@@ -547,17 +603,8 @@
 	if (u_attr != NULL) {
 		if (copy_from_user(&attr, u_attr, sizeof(attr)))
 			return ERR_PTR(-EFAULT);
-
-		if (attr.mq_maxmsg <= 0 || attr.mq_msgsize <= 0)
+		if (!mq_attr_ok(&attr))
 			return ERR_PTR(-EINVAL);
-		if (capable(CAP_SYS_RESOURCE)) {
-			if (attr.mq_maxmsg > HARD_MSGMAX)
-				return ERR_PTR(-EINVAL);
-		} else {
-			if (attr.mq_maxmsg > msg_max ||
-					attr.mq_msgsize > msgsize_max)
-				return ERR_PTR(-EINVAL);
-		}
 		/* store for use during create */
 		dentry->d_fsdata = &attr;
 	}
diff -Nru a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile	2004-06-23 19:04:25 -07:00
+++ b/kernel/Makefile	2004-06-23 19:04:25 -07:00
@@ -48,7 +48,7 @@
       cmd_ikconfig = $(CONFIG_SHELL) $< .config $(srctree)/Makefile > $@
 
 targets += ikconfig.h
-$(obj)/ikconfig.h: scripts/mkconfigs .config Makefile FORCE
+$(obj)/ikconfig.h: scripts/mkconfigs .config $(srctree)/Makefile FORCE
 	$(call if_changed,ikconfig)
 
 # config_data.h contains the same information as ikconfig.h but gzipped.
diff -Nru a/kernel/acct.c b/kernel/acct.c
--- a/kernel/acct.c	2004-06-23 19:04:27 -07:00
+++ b/kernel/acct.c	2004-06-23 19:04:27 -07:00
@@ -302,6 +302,69 @@
 	return exp;
 }
 
+#if ACCT_VERSION==1 || ACCT_VERSION==2
+/*
+ * encode an u64 into a comp2_t (24 bits)
+ *
+ * Format: 5 bit base 2 exponent, 20 bits mantissa.
+ * The leading bit of the mantissa is not stored, but implied for
+ * non-zero exponents.
+ * Largest encodable value is 50 bits.
+ */
+
+#define MANTSIZE2       20                      /* 20 bit mantissa. */
+#define EXPSIZE2        5                       /* 5 bit base 2 exponent. */
+#define MAXFRACT2       ((1ul << MANTSIZE2) - 1) /* Maximum fractional value. */
+#define MAXEXP2         ((1 <<EXPSIZE2) - 1)    /* Maximum exponent. */
+
+static comp2_t encode_comp2_t(u64 value)
+{
+        int exp, rnd;
+
+        exp = (value > (MAXFRACT2>>1));
+        rnd = 0;
+        while (value > MAXFRACT2) {
+                rnd = value & 1;
+                value >>= 1;
+                exp++;
+        }
+
+        /*
+         * If we need to round up, do it (and handle overflow correctly).
+         */
+        if (rnd && (++value > MAXFRACT2)) {
+                value >>= 1;
+                exp++;
+        }
+
+        if (exp > MAXEXP2) {
+                /* Overflow. Return largest representable number instead. */
+                return (1ul << (MANTSIZE2+EXPSIZE2-1)) - 1;
+        } else {
+                return (value & (MAXFRACT2>>1)) | (exp << (MANTSIZE2-1));
+        }
+}
+#endif
+
+#if ACCT_VERSION==3
+/*
+ * encode an u64 into a 32 bit IEEE float
+ */
+static u32 encode_float(u64 value)
+{
+	unsigned exp = 190;
+	unsigned u;
+
+	if (value==0) return 0;
+	while ((s64)value > 0){
+		value <<= 1;
+		exp--;
+	}
+	u = (u32)(value >> 40) & 0x7fffffu;
+	return u | (exp << 23);
+}
+#endif
+
 /*
  *  Write an accounting entry for an exiting process
  *
@@ -316,7 +379,7 @@
  */
 static void do_acct_process(long exitcode, struct file *file)
 {
-	struct acct ac;
+	acct_t ac;
 	mm_segment_t fs;
 	unsigned long vsize;
 	unsigned long flim;
@@ -333,27 +396,53 @@
 	 * Fill the accounting struct with the needed info as recorded
 	 * by the different kernel functions.
 	 */
-	memset((caddr_t)&ac, 0, sizeof(struct acct));
+	memset((caddr_t)&ac, 0, sizeof(acct_t));
 
+	ac.ac_version = ACCT_VERSION;
 	strlcpy(ac.ac_comm, current->comm, sizeof(ac.ac_comm));
 
-	elapsed = jiffies_64_to_clock_t(get_jiffies_64() - current->start_time);
+	elapsed = jiffies_64_to_AHZ(get_jiffies_64() - current->start_time);
+#if ACCT_VERSION==3
+	ac.ac_etime = encode_float(elapsed);
+#else
 	ac.ac_etime = encode_comp_t(elapsed < (unsigned long) -1l ?
 	                       (unsigned long) elapsed : (unsigned long) -1l);
-	do_div(elapsed, USER_HZ);
+#endif
+#if ACCT_VERSION==1 || ACCT_VERSION==2
+	{
+		/* new enlarged etime field */
+		comp2_t etime = encode_comp2_t(elapsed);
+		ac.ac_etime_hi = etime >> 16;
+		ac.ac_etime_lo = (u16) etime;
+	}
+#endif
+	do_div(elapsed, AHZ);
 	ac.ac_btime = xtime.tv_sec - elapsed;
-	ac.ac_utime = encode_comp_t(jiffies_to_clock_t(current->utime));
-	ac.ac_stime = encode_comp_t(jiffies_to_clock_t(current->stime));
+	ac.ac_utime = encode_comp_t(jiffies_to_AHZ(current->utime));
+	ac.ac_stime = encode_comp_t(jiffies_to_AHZ(current->stime));
 	/* we really need to bite the bullet and change layout */
 	ac.ac_uid = current->uid;
 	ac.ac_gid = current->gid;
+#if ACCT_VERSION==2
+	ac.ac_ahz = AHZ;
+#endif
+#if ACCT_VERSION==1 || ACCT_VERSION==2
+	/* backward-compatible 16 bit fields */
+	ac.ac_uid16 = current->uid;
+	ac.ac_gid16 = current->gid;
+#endif
+#if ACCT_VERSION==3
+	ac.ac_pid = current->pid;
+	ac.ac_ppid = current->parent->pid;
+#endif
 
 	read_lock(&tasklist_lock);	/* pin current->signal */
 	ac.ac_tty = current->signal->tty ?
 		old_encode_dev(tty_devnum(current->signal->tty)) : 0;
 	read_unlock(&tasklist_lock);
 
-	ac.ac_flag = 0;
+	/* ABYTESEX is always set to allow byte order detection */
+	ac.ac_flag = ABYTESEX;
 	if (current->flags & PF_FORKNOEXEC)
 		ac.ac_flag |= AFORK;
 	if (current->flags & PF_SUPERPRIV)
@@ -395,7 +484,7 @@
 	flim = current->rlim[RLIMIT_FSIZE].rlim_cur;
 	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
 	file->f_op->write(file, (char *)&ac,
-			       sizeof(struct acct), &file->f_pos);
+			       sizeof(acct_t), &file->f_pos);
 	current->rlim[RLIMIT_FSIZE].rlim_cur = flim;
 	set_fs(fs);
 }
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	2004-06-23 19:04:28 -07:00
+++ b/kernel/exit.c	2004-06-23 19:04:28 -07:00
@@ -834,10 +834,10 @@
 	do_exit((error_code&0xff)<<8);
 }
 
-task_t fastcall *next_thread(task_t *p)
+task_t fastcall *next_thread(const task_t *p)
 {
-	struct pid_link *link = p->pids + PIDTYPE_TGID;
-	struct list_head *tmp, *head = &link->pidptr->task_list;
+	const struct pid_link *link = p->pids + PIDTYPE_TGID;
+	const struct list_head *tmp, *head = &link->pidptr->task_list;
 
 #ifdef CONFIG_SMP
 	if (!p->sighand)
diff -Nru a/kernel/kallsyms.c b/kernel/kallsyms.c
--- a/kernel/kallsyms.c	2004-06-23 19:04:28 -07:00
+++ b/kernel/kallsyms.c	2004-06-23 19:04:28 -07:00
@@ -320,5 +320,4 @@
 }
 __initcall(kallsyms_init);
 
-EXPORT_SYMBOL(kallsyms_lookup);
 EXPORT_SYMBOL(__print_symbol);
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	2004-06-23 19:04:28 -07:00
+++ b/kernel/module.c	2004-06-23 19:04:28 -07:00
@@ -36,7 +36,6 @@
 #include <linux/stop_machine.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
-#include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 
 #if 0
@@ -717,7 +716,7 @@
 }
 
 asmlinkage long
-sys_delete_module(const char *name_user, unsigned int flags)
+sys_delete_module(const char __user *name_user, unsigned int flags)
 {
 	return -ENOSYS;
 }
@@ -981,6 +980,104 @@
 	return ret;
 }
 
+
+/*
+ * /sys/module/foo/sections stuff
+ * J. Corbet <corbet@lwn.net>
+ */
+#ifdef CONFIG_KALLSYMS
+static void module_sect_attrs_release(struct kobject *kobj)
+{
+	kfree(container_of(kobj, struct module_sections, kobj));
+}
+
+static ssize_t module_sect_show(struct kobject *kobj, struct attribute *attr,
+		char *buf)
+{
+	struct module_sect_attr *sattr =
+		container_of(attr, struct module_sect_attr, attr);
+	return sprintf(buf, "0x%lx\n", sattr->address);
+}
+
+static struct sysfs_ops module_sect_ops = {
+	.show = module_sect_show,
+};
+
+static struct kobj_type module_sect_ktype = {
+	.sysfs_ops = &module_sect_ops,
+	.release =   module_sect_attrs_release,
+};
+
+static void add_sect_attrs(struct module *mod, unsigned int nsect,
+		char *secstrings, Elf_Shdr *sechdrs)
+{
+	unsigned int nloaded = 0, i;
+	struct module_sect_attr *sattr;
+	
+	if (!mod->mkobj)
+		return;
+	
+	/* Count loaded sections and allocate structures */
+	for (i = 0; i < nsect; i++)
+		if (sechdrs[i].sh_flags & SHF_ALLOC)
+			nloaded++;
+	mod->sect_attrs = kmalloc(sizeof(struct module_sections) +
+			nloaded*sizeof(mod->sect_attrs->attrs[0]), GFP_KERNEL);
+	if (! mod->sect_attrs)
+		return;
+
+	/* sections entry setup */
+	memset(mod->sect_attrs, 0, sizeof(struct module_sections));
+	if (kobject_set_name(&mod->sect_attrs->kobj, "sections"))
+		goto out;
+	mod->sect_attrs->kobj.parent = &mod->mkobj->kobj;
+	mod->sect_attrs->kobj.ktype = &module_sect_ktype;
+	if (kobject_register(&mod->sect_attrs->kobj))
+		goto out;
+
+	/* And the section attributes. */
+	sattr = &mod->sect_attrs->attrs[0];
+	for (i = 0; i < nsect; i++) {
+		if (! (sechdrs[i].sh_flags & SHF_ALLOC))
+			continue;
+		sattr->address = sechdrs[i].sh_addr;
+		strlcpy(sattr->name, secstrings + sechdrs[i].sh_name,
+				MODULE_SECT_NAME_LEN);
+		sattr->attr.name = sattr->name;
+		sattr->attr.owner = mod;
+		sattr->attr.mode = S_IRUGO;
+		(void) sysfs_create_file(&mod->sect_attrs->kobj, &sattr->attr);
+		sattr++;
+	}
+	return;
+  out:
+	kfree(mod->sect_attrs);
+	mod->sect_attrs = NULL;
+}
+
+static void remove_sect_attrs(struct module *mod)
+{
+	if (mod->sect_attrs) {
+		kobject_unregister(&mod->sect_attrs->kobj);
+		mod->sect_attrs = NULL;
+	}
+}
+
+
+#else
+static inline void add_sect_attrs(struct module *mod, unsigned int nsect,
+		char *sectstrings, Elf_Shdr *sechdrs)
+{
+}
+
+static inline void remove_sect_attrs(struct module *mod)
+{
+}
+#endif /* CONFIG_KALLSYMS */
+
+
+
+
 #define to_module_attr(n) container_of(n, struct module_attribute, attr);
 
 static ssize_t module_attr_show(struct kobject *kobj,
@@ -1099,6 +1196,7 @@
 	list_del(&mod->list);
 	spin_unlock_irq(&modlist_lock);
 
+	remove_sect_attrs(mod);
 	mod_kobject_remove(mod);
 
 	/* Arch-specific cleanup. */
@@ -1712,6 +1810,7 @@
 			      / sizeof(struct kernel_param));
 	if (err < 0)
 		goto arch_cleanup;
+	add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
 
 	/* Get rid of temporary copy */
 	vfree(hdr);
diff -Nru a/kernel/posix-timers.c b/kernel/posix-timers.c
--- a/kernel/posix-timers.c	2004-06-23 19:04:27 -07:00
+++ b/kernel/posix-timers.c	2004-06-23 19:04:27 -07:00
@@ -397,7 +397,6 @@
 	if (!tmr)
 		return tmr;
 	memset(tmr, 0, sizeof (struct k_itimer));
-	tmr->it_id = (timer_t)-1;
 	if (unlikely(!(tmr->sigq = sigqueue_alloc()))) {
 		kmem_cache_free(posix_timers_cache, tmr);
 		tmr = 0;
@@ -405,9 +404,11 @@
 	return tmr;
 }
 
-static void release_posix_timer(struct k_itimer *tmr)
+#define IT_ID_SET	1
+#define IT_ID_NOT_SET	0
+static void release_posix_timer(struct k_itimer *tmr, int it_id_set)
 {
-	if (tmr->it_id != -1) {
+	if (it_id_set) {
 		unsigned long flags;
 		spin_lock_irqsave(&idr_lock, flags);
 		idr_remove(&posix_timers_id, tmr->it_id);
@@ -429,10 +430,11 @@
 {
 	int error = 0;
 	struct k_itimer *new_timer = NULL;
-	timer_t new_timer_id;
+	int new_timer_id;
 	struct task_struct *process = 0;
 	unsigned long flags;
 	sigevent_t event;
+	int it_id_set = IT_ID_NOT_SET;
 
 	if ((unsigned) which_clock >= MAX_CLOCKS ||
 				!posix_clocks[which_clock].res)
@@ -443,19 +445,38 @@
 		return -EAGAIN;
 
 	spin_lock_init(&new_timer->it_lock);
-	do {
-		if (unlikely(!idr_pre_get(&posix_timers_id, GFP_KERNEL))) {
-			error = -EAGAIN;
-			new_timer->it_id = (timer_t)-1;
-			goto out;
-		}
-		spin_lock_irq(&idr_lock);
-		new_timer_id = (timer_t) idr_get_new(&posix_timers_id,
-							(void *) new_timer);
-		spin_unlock_irq(&idr_lock);
-	} while (unlikely(new_timer_id == -1));
+ retry:
+	if (unlikely(!idr_pre_get(&posix_timers_id, GFP_KERNEL))) {
+		error = -EAGAIN;
+		goto out;
+	}
+	spin_lock_irq(&idr_lock);
+	error = idr_get_new(&posix_timers_id,
+			    (void *) new_timer,
+			    &new_timer_id);
+	spin_unlock_irq(&idr_lock);
+	if (error == -EAGAIN)
+		goto retry;
+	else if (error) {
+		/*
+		 * Wierd looking, but we return EAGAIN if the IDR is
+		 * full (proper POSIX return value for this)
+		 */
+		error = -EAGAIN;
+		goto out;
+	}
+
+	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;
+	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);
 
-	new_timer->it_id = new_timer_id;
 	/*
 	 * return the timer_id now.  The next step is hard to
 	 * back out if there is an error.
@@ -470,6 +491,10 @@
 			error = -EFAULT;
 			goto out;
 		}
+		new_timer->it_sigev_notify = event.sigev_notify;
+		new_timer->it_sigev_signo = event.sigev_signo;
+		new_timer->it_sigev_value = event.sigev_value;
+
 		read_lock(&tasklist_lock);
 		if ((process = good_sigevent(&event))) {
 			/*
@@ -489,6 +514,7 @@
 			 */
 			spin_lock_irqsave(&process->sighand->siglock, flags);
 			if (!(process->flags & PF_EXITING)) {
+				new_timer->it_process = process;
 				list_add(&new_timer->list,
 					 &process->signal->posix_timers);
 				spin_unlock_irqrestore(&process->sighand->siglock, flags);
@@ -503,35 +529,27 @@
 			error = -EINVAL;
 			goto out;
 		}
-		new_timer->it_sigev_notify = event.sigev_notify;
-		new_timer->it_sigev_signo = event.sigev_signo;
-		new_timer->it_sigev_value = event.sigev_value;
 	} else {
 		new_timer->it_sigev_notify = SIGEV_SIGNAL;
 		new_timer->it_sigev_signo = SIGALRM;
 		new_timer->it_sigev_value.sival_int = new_timer->it_id;
 		process = current->group_leader;
 		spin_lock_irqsave(&process->sighand->siglock, flags);
+		new_timer->it_process = process;
 		list_add(&new_timer->list, &process->signal->posix_timers);
 		spin_unlock_irqrestore(&process->sighand->siglock, flags);
 	}
 
-	new_timer->it_clock = which_clock;
-	new_timer->it_incr = 0;
-	new_timer->it_overrun = -1;
-	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);
-
-	/*
-	 * Once we set the process, it can be found so do it last...
+ 	/*
+	 * In the case of the timer belonging to another task, after
+	 * the task is unlocked, the timer is owned by the other task
+	 * and may cease to exist at any time.  Don't use or modify
+	 * new_timer after the unlock call.
 	 */
-	new_timer->it_process = process;
+
 out:
 	if (error)
-		release_posix_timer(new_timer);
+		release_posix_timer(new_timer, it_id_set);
 
 	return error;
 }
@@ -952,7 +970,7 @@
 	timer->it_process = NULL;
 	}
 	unlock_timer(timer, flags);
-	release_posix_timer(timer);
+	release_posix_timer(timer, IT_ID_SET);
 	return 0;
 }
 /*
@@ -989,7 +1007,7 @@
 		timer->it_process = NULL;
 	}
 	unlock_timer(timer, flags);
-	release_posix_timer(timer);
+	release_posix_timer(timer, IT_ID_SET);
 }
 
 /*
diff -Nru a/kernel/power/pmdisk.c b/kernel/power/pmdisk.c
--- a/kernel/power/pmdisk.c	2004-06-23 19:04:27 -07:00
+++ b/kernel/power/pmdisk.c	2004-06-23 19:04:27 -07:00
@@ -732,19 +732,6 @@
 
 /* More restore stuff */
 
-/* FIXME: Why not memcpy(to, from, 1<<pagedir_order*PAGE_SIZE)? */
-static void __init copy_pagedir(suspend_pagedir_t *to, suspend_pagedir_t *from)
-{
-	int i;
-	char *topointer=(char *)to, *frompointer=(char *)from;
-
-	for(i=0; i < 1 << pagedir_order; i++) {
-		copy_page(topointer, frompointer);
-		topointer += PAGE_SIZE;
-		frompointer += PAGE_SIZE;
-	}
-}
-
 #define does_collide(addr) does_collide_order(pm_pagedir_nosave, addr, 0)
 
 /*
@@ -792,9 +779,10 @@
 	 * We have to avoid recursion (not to overflow kernel stack),
 	 * and that's why code looks pretty cryptic 
 	 */
-	suspend_pagedir_t *new_pagedir, *old_pagedir = pm_pagedir_nosave;
+	suspend_pagedir_t *old_pagedir = pm_pagedir_nosave;
 	void **eaten_memory = NULL;
 	void **c = eaten_memory, *m, *f;
+	int err;
 
 	pr_debug("pmdisk: Relocating pagedir\n");
 
@@ -803,32 +791,31 @@
 		return 0;
 	}
 
+	err = -ENOMEM;
 	while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order))) {
-		memset(m, 0, PAGE_SIZE);
-		if (!does_collide_order(old_pagedir, (unsigned long)m, pagedir_order))
+		if (!does_collide_order(old_pagedir, (unsigned long)m,
+					pagedir_order)) {
+			pm_pagedir_nosave =
+				memcpy(m, old_pagedir,
+				       PAGE_SIZE << pagedir_order);
+			err = 0;
 			break;
+		}
 		eaten_memory = m;
 		printk( "." ); 
 		*eaten_memory = c;
 		c = eaten_memory;
 	}
 
-	if (!m)
-		return -ENOMEM;
-
-	pm_pagedir_nosave = new_pagedir = m;
-	copy_pagedir(new_pagedir, old_pagedir);
-
 	c = eaten_memory;
 	while(c) {
 		printk(":");
-		f = *c;
+		f = c;
 		c = *c;
-		if (f)
-			free_pages((unsigned long)f, pagedir_order);
+		free_pages((unsigned long)f, pagedir_order);
 	}
 	printk("|\n");
-	return 0;
+	return err;
 }
 
 
diff -Nru a/kernel/power/swsusp.c b/kernel/power/swsusp.c
--- a/kernel/power/swsusp.c	2004-06-23 19:04:26 -07:00
+++ b/kernel/power/swsusp.c	2004-06-23 19:04:26 -07:00
@@ -503,6 +503,9 @@
 		if (!pbe)
 			continue;
 		pbe->orig_address = (long) page_address(page);
+		/* Copy page is dangerous: it likes to mess with
+		   preempt count on specific cpus. Wrong preempt count is then copied,
+		   oops. */
 		copy_page((void *)pbe->address, (void *)pbe->orig_address);
 		pbe++;
 	}
@@ -860,19 +863,6 @@
 
 /* More restore stuff */
 
-/* FIXME: Why not memcpy(to, from, 1<<pagedir_order*PAGE_SIZE)? */
-static void copy_pagedir(suspend_pagedir_t *to, suspend_pagedir_t *from)
-{
-	int i;
-	char *topointer=(char *)to, *frompointer=(char *)from;
-
-	for(i=0; i < 1 << pagedir_order; i++) {
-		copy_page(topointer, frompointer);
-		topointer += PAGE_SIZE;
-		frompointer += PAGE_SIZE;
-	}
-}
-
 #define does_collide(addr) does_collide_order(pagedir_nosave, addr, 0)
 
 /*
@@ -920,11 +910,12 @@
 	 * We have to avoid recursion (not to overflow kernel stack),
 	 * and that's why code looks pretty cryptic 
 	 */
-	suspend_pagedir_t *new_pagedir, *old_pagedir = pagedir_nosave;
+	suspend_pagedir_t *old_pagedir = pagedir_nosave;
 	void **eaten_memory = NULL;
 	void **c = eaten_memory, *m, *f;
+	int ret = 0;
 
-	printk("Relocating pagedir");
+	printk("Relocating pagedir ");
 
 	if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) {
 		printk("not necessary\n");
@@ -932,7 +923,6 @@
 	}
 
 	while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order))) {
-		memset(m, 0, PAGE_SIZE);
 		if (!does_collide_order(old_pagedir, (unsigned long)m, pagedir_order))
 			break;
 		eaten_memory = m;
@@ -941,22 +931,23 @@
 		c = eaten_memory;
 	}
 
-	if (!m)
-		return -ENOMEM;
-
-	pagedir_nosave = new_pagedir = m;
-	copy_pagedir(new_pagedir, old_pagedir);
+	if (!m) {
+		printk("out of memory\n");
+		ret = -ENOMEM;
+	} else {
+		pagedir_nosave =
+			memcpy(m, old_pagedir, PAGE_SIZE << pagedir_order);
+	}
 
 	c = eaten_memory;
-	while(c) {
+	while (c) {
 		printk(":");
-		f = *c;
+		f = c;
 		c = *c;
-		if (f)
-			free_pages((unsigned long)f, pagedir_order);
+		free_pages((unsigned long)f, pagedir_order);
 	}
 	printk("|\n");
-	return 0;
+	return ret;
 }
 
 /*
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	2004-06-23 19:04:28 -07:00
+++ b/kernel/sched.c	2004-06-23 19:04:28 -07:00
@@ -546,7 +546,7 @@
  * task_curr - is this task currently executing on a CPU?
  * @p: the task in question.
  */
-inline int task_curr(task_t *p)
+inline int task_curr(const task_t *p)
 {
 	return cpu_curr(task_cpu(p)) == p;
 }
@@ -2658,7 +2658,7 @@
  * RT tasks are offset by -200. Normal tasks are centered
  * around 0, value goes from -16 to +15.
  */
-int task_prio(task_t *p)
+int task_prio(const task_t *p)
 {
 	return p->prio - MAX_RT_PRIO;
 }
@@ -2667,7 +2667,7 @@
  * task_nice - return the nice value of a given task.
  * @p: the task in question.
  */
-int task_nice(task_t *p)
+int task_nice(const task_t *p)
 {
 	return TASK_NICE(p);
 }
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	2004-06-23 19:04:26 -07:00
+++ b/kernel/signal.c	2004-06-23 19:04:26 -07:00
@@ -32,9 +32,6 @@
 
 static kmem_cache_t *sigqueue_cachep;
 
-atomic_t nr_queued_signals;
-int max_queued_signals = 1024;
-
 /*
  * In POSIX a signal is sent either to a specific thread (Linux task)
  * or to the process as a whole (Linux thread group).  How the signal
@@ -265,17 +262,19 @@
 	return sig;
 }
 
-struct sigqueue *__sigqueue_alloc(void)
+static struct sigqueue *__sigqueue_alloc(void)
 {
 	struct sigqueue *q = 0;
 
-	if (atomic_read(&nr_queued_signals) < max_queued_signals)
+	if (atomic_read(&current->user->sigpending) <
+			current->rlim[RLIMIT_SIGPENDING].rlim_cur)
 		q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
 	if (q) {
-		atomic_inc(&nr_queued_signals);
 		INIT_LIST_HEAD(&q->list);
 		q->flags = 0;
 		q->lock = 0;
+		q->user = get_uid(current->user);
+		atomic_inc(&q->user->sigpending);
 	}
 	return(q);
 }
@@ -284,8 +283,9 @@
 {
 	if (q->flags & SIGQUEUE_PREALLOC)
 		return;
+	atomic_dec(&q->user->sigpending);
+	free_uid(q->user);
 	kmem_cache_free(sigqueue_cachep, q);
-	atomic_dec(&nr_queued_signals);
 }
 
 static void flush_sigqueue(struct sigpending *queue)
@@ -699,7 +699,8 @@
 	}
 }
 
-static int send_signal(int sig, struct siginfo *info, struct sigpending *signals)
+static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
+			struct sigpending *signals)
 {
 	struct sigqueue * q = NULL;
 	int ret = 0;
@@ -719,12 +720,14 @@
 	   make sure at least one signal gets delivered and don't
 	   pass on the info struct.  */
 
-	if (atomic_read(&nr_queued_signals) < max_queued_signals)
+	if (atomic_read(&t->user->sigpending) <
+			t->rlim[RLIMIT_SIGPENDING].rlim_cur)
 		q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
 
 	if (q) {
-		atomic_inc(&nr_queued_signals);
 		q->flags = 0;
+		q->user = get_uid(t->user);
+		atomic_inc(&q->user->sigpending);
 		list_add_tail(&q->list, &signals->list);
 		switch ((unsigned long) info) {
 		case 0:
@@ -798,7 +801,7 @@
 	if (LEGACY_QUEUE(&t->pending, sig))
 		goto out;
 
-	ret = send_signal(sig, info, &t->pending);
+	ret = send_signal(sig, info, t, &t->pending);
 	if (!ret && !sigismember(&t->blocked, sig))
 		signal_wake_up(t, sig == SIGKILL);
 out:
@@ -999,7 +1002,7 @@
 	 * We always use the shared queue for process-wide signals,
 	 * to avoid several races.
 	 */
-	ret = send_signal(sig, info, &p->signal->shared_pending);
+	ret = send_signal(sig, info, p, &p->signal->shared_pending);
 	if (unlikely(ret))
 		return ret;
 
@@ -1071,23 +1074,19 @@
 	struct task_struct *p;
 	struct list_head *l;
 	struct pid *pid;
-	int retval;
-	int found;
+	int retval, success;
 
 	if (pgrp <= 0)
 		return -EINVAL;
 
-	found = 0;
-	retval = 0;
+	success = 0;
+	retval = -ESRCH;
 	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
-		int err;
-
-		found = 1;
-		err = group_send_sig_info(sig, info, p);
-		if (!retval)
-			retval = err;
+		int err = group_send_sig_info(sig, info, p);
+		success |= !err;
+		retval = err;
 	}
-	return found ? retval : -ESRCH;
+	return success ? 0 : retval;
 }
 
 int
@@ -1196,6 +1195,13 @@
 {
 	int ret;
 	unsigned long flags;
+
+	/*
+	 * Make sure legacy kernel users don't send in bad values
+	 * (normal paths check this in check_kill_permission).
+	 */
+	if (sig < 0 || sig > _NSIG)
+		return -EINVAL;
 
 	/*
 	 * We need the tasklist lock even for the specific
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	2004-06-23 19:04:25 -07:00
+++ b/kernel/sysctl.c	2004-06-23 19:04:25 -07:00
@@ -53,8 +53,6 @@
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern int max_threads;
-extern atomic_t nr_queued_signals;
-extern int max_queued_signals;
 extern int sysrq_enabled;
 extern int core_uses_pid;
 extern char core_pattern[];
@@ -429,22 +427,6 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
-	{
-		.ctl_name	= KERN_RTSIGNR,
-		.procname	= "rtsig-nr",
-		.data		= &nr_queued_signals,
-		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= KERN_RTSIGMAX,
-		.procname	= "rtsig-max",
-		.data		= &max_queued_signals,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
 #ifdef CONFIG_SYSVIPC
 	{
 		.ctl_name	= KERN_SHMMAX,
diff -Nru a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c	2004-06-23 19:04:28 -07:00
+++ b/kernel/timer.c	2004-06-23 19:04:28 -07:00
@@ -829,7 +829,7 @@
 	}
 }
 
-void update_one_process(struct task_struct *p, unsigned long user,
+static void update_one_process(struct task_struct *p, unsigned long user,
 			unsigned long system, int cpu)
 {
 	do_process_times(p, user, system);
diff -Nru a/kernel/uid16.c b/kernel/uid16.c
--- a/kernel/uid16.c	2004-06-23 19:04:27 -07:00
+++ b/kernel/uid16.c	2004-06-23 19:04:27 -07:00
@@ -39,7 +39,7 @@
 
 asmlinkage long sys_setgid16(old_gid_t gid)
 {
-	return sys_setgid((gid_t)gid);
+	return sys_setgid(low2highgid(gid));
 }
 
 asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
@@ -49,7 +49,7 @@
 
 asmlinkage long sys_setuid16(old_uid_t uid)
 {
-	return sys_setuid((uid_t)uid);
+	return sys_setuid(low2highuid(uid));
 }
 
 asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid)
@@ -88,12 +88,12 @@
 
 asmlinkage long sys_setfsuid16(old_uid_t uid)
 {
-	return sys_setfsuid((uid_t)uid);
+	return sys_setfsuid(low2highuid(uid));
 }
 
 asmlinkage long sys_setfsgid16(old_gid_t gid)
 {
-	return sys_setfsgid((gid_t)gid);
+	return sys_setfsgid(low2highgid(gid));
 }
 
 static int groups16_to_user(old_gid_t __user *grouplist,
@@ -103,7 +103,7 @@
 	old_gid_t group;
 
 	for (i = 0; i < group_info->ngroups; i++) {
-		group = (old_gid_t)GROUP_AT(group_info, i);
+		group = high2lowgid(GROUP_AT(group_info, i));
 		if (put_user(group, grouplist+i))
 			return -EFAULT;
 	}
@@ -120,7 +120,7 @@
 	for (i = 0; i < group_info->ngroups; i++) {
 		if (get_user(group, grouplist+i))
 			return  -EFAULT;
-		GROUP_AT(group_info, i) = (gid_t)group;
+		GROUP_AT(group_info, i) = low2highgid(group);
 	}
 
 	return 0;
diff -Nru a/kernel/user.c b/kernel/user.c
--- a/kernel/user.c	2004-06-23 19:04:26 -07:00
+++ b/kernel/user.c	2004-06-23 19:04:26 -07:00
@@ -30,7 +30,9 @@
 struct user_struct root_user = {
 	.__count	= ATOMIC_INIT(1),
 	.processes	= ATOMIC_INIT(1),
-	.files		= ATOMIC_INIT(0)
+	.files		= ATOMIC_INIT(0),
+	.sigpending	= ATOMIC_INIT(0),
+	.mq_bytes	= 0
 };
 
 /*
@@ -108,6 +110,9 @@
 		atomic_set(&new->__count, 1);
 		atomic_set(&new->processes, 0);
 		atomic_set(&new->files, 0);
+		atomic_set(&new->sigpending, 0);
+
+		new->mq_bytes = 0;
 
 		/*
 		 * Before adding this, check whether we raced
diff -Nru a/lib/idr.c b/lib/idr.c
--- a/lib/idr.c	2004-06-23 19:04:29 -07:00
+++ b/lib/idr.c	2004-06-23 19:04:29 -07:00
@@ -27,15 +27,6 @@
  * so you don't need to be too concerned about locking and conflicts
  * with the slab allocator.
 
- * A word on reuse.  We reuse empty id slots as soon as we can, always
- * using the lowest one available.  But we also merge a counter in the
- * high bits of the id.  The counter is RESERVED_ID_BITS (8 at this time)
- * long.  This means that if you allocate and release the same id in a 
- * loop we will reuse an id after about 256 times around the loop.  The
- * word about is used here as we will NOT return a valid id of -1 so if
- * you loop on the largest possible id (and that is 24 bits, wow!) we
- * will kick the counter to avoid -1.  (Paranoid?  You bet!)
- *
  * What you need to do is, since we don't keep the counter as part of
  * id / ptr pair, to keep a copy of it in the pointed to structure
  * (or else where) so that when you ask for a ptr you can varify that
@@ -70,14 +61,21 @@
  *   sleep, so must not be called with any spinlocks held.  If the system is
  *   REALLY out of memory this function returns 0, other wise 1.
 
- * int idr_get_new(struct idr *idp, void *ptr);
+ * int idr_get_new(struct idr *idp, void *ptr, int *id);
  
  *   This is the allocate id function.  It should be called with any
  *   required locks.  In fact, in the SMP case, you MUST lock prior to
- *   calling this function to avoid possible out of memory problems.  If
- *   memory is required, it will return a -1, in which case you should
- *   unlock and go back to the idr_pre_get() call.  ptr is the pointer
- *   you want associated with the id.  In other words:
+ *   calling this function to avoid possible out of memory problems.
+ *   If memory is required, it will return -EAGAIN, you should unlock
+ *   and go back to the idr_pre_get() call.  If the idr is full, it
+ *   will return a -ENOSPC.  ptr is the pointer you want associated
+ *   with the id.  The value is returned in the "id" field.  idr_get_new()
+ *   returns a value in the range 0 ... 0x7fffffff
+
+ * int idr_get_new_above(struct idr *idp, void *ptr, int start_id, int *id);
+
+ *   Like idr_get_new(), but the returned id is guaranteed to be at or
+ *   above start_id.
 
  * void *idr_find(struct idr *idp, int id);
  
@@ -92,6 +90,10 @@
  *   removes the given id, freeing that slot and any memory that may
  *   now be unused.  See idr_find() for locking restrictions.
 
+ * int idr_full(struct idr *idp);
+
+ *   Returns true if the idr is full and false if not.
+
  */
 
 
@@ -115,7 +117,7 @@
 
 	spin_lock(&idp->lock);
 	if (!(p = idp->id_free))
-		BUG();
+		return NULL;
 	idp->id_free = p->ary[0];
 	idp->id_free_cnt--;
 	p->ary[0] = 0;
@@ -181,8 +183,8 @@
 			sh = IDR_BITS*l;
 			id = ((id >> sh) ^ n ^ m) << sh;
 		}
-		if (id >= MAX_ID_BIT)
-			return -1;
+		if ((id >= MAX_ID_BIT) || (id < 0))
+			return -3;
 		if (l == 0)
 			break;
 		/*
@@ -220,7 +222,7 @@
 	return(id);
 }
 
-int idr_get_new_above(struct idr *idp, void *ptr, int starting_id)
+static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
 {
 	struct idr_layer *p, *new;
 	int layers, v, id;
@@ -238,7 +240,7 @@
 	 * Add a new layer to the top of the tree if the requested
 	 * id is larger than the currently allocated space.
 	 */
-	while (id >= (1 << (layers*IDR_BITS))) {
+	while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
 		layers++;
 		if (!p->count)
 			continue;
@@ -266,23 +268,47 @@
 	v = sub_alloc(idp, ptr, &id);
 	if (v == -2)
 		goto build_up;
-	if ( likely(v >= 0 )) {
-		idp->count++;
-		v += (idp->count << MAX_ID_SHIFT);
-		if ( unlikely( v == -1 ))
-		     v += (1L << MAX_ID_SHIFT);
-	}
 	return(v);
 }
+
+int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
+{
+	int rv;
+	rv = idr_get_new_above_int(idp, ptr, starting_id);
+	/*
+	 * This is a cheap hack until the IDR code can be fixed to
+	 * return proper error values.
+	 */
+	if (rv < 0) {
+		if (rv == -1)
+			return -EAGAIN;
+		else /* Will be -3 */
+			return -ENOSPC;
+	}
+	*id = rv;
+	return 0;
+}
 EXPORT_SYMBOL(idr_get_new_above);
 
-int idr_get_new(struct idr *idp, void *ptr)
+int idr_get_new(struct idr *idp, void *ptr, int *id)
 {
-	return idr_get_new_above(idp, ptr, 0);
+	int rv;
+	rv = idr_get_new_above_int(idp, ptr, 0);
+	/*
+	 * This is a cheap hack until the IDR code can be fixed to
+	 * return proper error values.
+	 */
+	if (rv < 0) {
+		if (rv == -1)
+			return -EAGAIN;
+		else /* Will be -3 */
+			return -ENOSPC;
+	}
+	*id = rv;
+	return 0;
 }
 EXPORT_SYMBOL(idr_get_new);
 
-
 static void sub_remove(struct idr *idp, int shift, int id)
 {
 	struct idr_layer *p = idp->top;
@@ -311,10 +337,14 @@
 			idp->layers = 0;
 	}
 }
+
 void idr_remove(struct idr *idp, int id)
 {
 	struct idr_layer *p;
 
+	/* Mask off upper bits we don't use for the search. */
+	id &= MAX_ID_MASK;
+
 	sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);
 	if ( idp->top && idp->top->count == 1 && 
 	     (idp->layers > 1) &&
@@ -350,6 +380,9 @@
 	if ( unlikely( (id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS)))
 	     return NULL;
 #endif
+	/* Mask off upper bits we don't use for the search. */
+	id &= MAX_ID_MASK;
+
 	while (n > 0 && p) {
 		n -= IDR_BITS;
 		p = p->ary[(id >> n) & IDR_MASK];
diff -Nru a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
--- a/lib/rwsem-spinlock.c	2004-06-23 19:04:25 -07:00
+++ b/lib/rwsem-spinlock.c	2004-06-23 19:04:25 -07:00
@@ -1,5 +1,5 @@
-/* rwsem-spinlock.c: R/W semaphores: contention handling functions for generic spinlock
- *                                   implementation
+/* rwsem-spinlock.c: R/W semaphores: contention handling functions for
+ * generic spinlock implementation
  *
  * Copyright (c) 2001   David Howells (dhowells@redhat.com).
  * - Derived partially from idea by Andrea Arcangeli <andrea@suse.de>
@@ -10,9 +10,9 @@
 #include <linux/module.h>
 
 struct rwsem_waiter {
-	struct list_head	list;
-	struct task_struct	*task;
-	unsigned int		flags;
+	struct list_head list;
+	struct task_struct *task;
+	unsigned int flags;
 #define RWSEM_WAITING_FOR_READ	0x00000001
 #define RWSEM_WAITING_FOR_WRITE	0x00000002
 };
@@ -22,7 +22,8 @@
 {
 	if (sem->debug)
 		printk("[%d] %s({%d,%d})\n",
-		       current->pid,str,sem->activity,list_empty(&sem->wait_list)?0:1);
+		       current->pid, str, sem->activity,
+		       list_empty(&sem->wait_list) ? 0 : 1);
 }
 #endif
 
@@ -40,7 +41,7 @@
 }
 
 /*
- * handle the lock being released whilst there are processes blocked on it that can now run
+ * handle the lock release when processes blocked on it that can now run
  * - if we come here, then:
  *   - the 'active count' _reached_ zero
  *   - the 'waiting count' is non-zero
@@ -48,15 +49,16 @@
  * - woken process blocks are discarded from the list after having task zeroed
  * - writers are only woken if wakewrite is non-zero
  */
-static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
+static inline struct rw_semaphore *
+__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
 {
 	struct rwsem_waiter *waiter;
 	struct task_struct *tsk;
 	int woken;
 
-	rwsemtrace(sem,"Entering __rwsem_do_wake");
+	rwsemtrace(sem, "Entering __rwsem_do_wake");
 
-	waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
+	waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
 
 	if (!wakewrite) {
 		if (waiter->flags & RWSEM_WAITING_FOR_WRITE)
@@ -64,14 +66,16 @@
 		goto dont_wake_writers;
 	}
 
-	/* if we are allowed to wake writers try to grant a single write lock if there's a
-	 * writer at the front of the queue
-	 * - we leave the 'waiting count' incremented to signify potential contention
+	/* if we are allowed to wake writers try to grant a single write lock
+	 * if there's a writer at the front of the queue
+	 * - we leave the 'waiting count' incremented to signify potential
+	 *   contention
 	 */
 	if (waiter->flags & RWSEM_WAITING_FOR_WRITE) {
 		sem->activity = -1;
 		list_del(&waiter->list);
 		tsk = waiter->task;
+		/* Don't touch waiter after ->task has been NULLed */
 		mb();
 		waiter->task = NULL;
 		wake_up_process(tsk);
@@ -79,10 +83,10 @@
 		goto out;
 	}
 
-	/* grant an infinite number of read locks to the readers at the front of the queue */
+	/* grant an infinite number of read locks to the front of the queue */
  dont_wake_writers:
 	woken = 0;
-	while (waiter->flags&RWSEM_WAITING_FOR_READ) {
+	while (waiter->flags & RWSEM_WAITING_FOR_READ) {
 		struct list_head *next = waiter->list.next;
 
 		list_del(&waiter->list);
@@ -94,27 +98,28 @@
 		woken++;
 		if (list_empty(&sem->wait_list))
 			break;
-		waiter = list_entry(next,struct rwsem_waiter,list);
+		waiter = list_entry(next, struct rwsem_waiter, list);
 	}
 
 	sem->activity += woken;
 
  out:
-	rwsemtrace(sem,"Leaving __rwsem_do_wake");
+	rwsemtrace(sem, "Leaving __rwsem_do_wake");
 	return sem;
 }
 
 /*
  * wake a single writer
  */
-static inline struct rw_semaphore *__rwsem_wake_one_writer(struct rw_semaphore *sem)
+static inline struct rw_semaphore *
+__rwsem_wake_one_writer(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter *waiter;
 	struct task_struct *tsk;
 
 	sem->activity = -1;
 
-	waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
+	waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
 	list_del(&waiter->list);
 
 	tsk = waiter->task;
@@ -128,16 +133,16 @@
 /*
  * get a read lock on the semaphore
  */
-void fastcall __down_read(struct rw_semaphore *sem)
+void fastcall __sched __down_read(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 	struct task_struct *tsk;
 
-	rwsemtrace(sem,"Entering __down_read");
+	rwsemtrace(sem, "Entering __down_read");
 
 	spin_lock(&sem->wait_lock);
 
-	if (sem->activity>=0 && list_empty(&sem->wait_list)) {
+	if (sem->activity >= 0 && list_empty(&sem->wait_list)) {
 		/* granted */
 		sem->activity++;
 		spin_unlock(&sem->wait_lock);
@@ -145,14 +150,14 @@
 	}
 
 	tsk = current;
-	set_task_state(tsk,TASK_UNINTERRUPTIBLE);
+	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 
 	/* set up my own style of waitqueue */
 	waiter.task = tsk;
 	waiter.flags = RWSEM_WAITING_FOR_READ;
 	get_task_struct(tsk);
 
-	list_add_tail(&waiter.list,&sem->wait_list);
+	list_add_tail(&waiter.list, &sem->wait_list);
 
 	/* we don't need to touch the semaphore struct anymore */
 	spin_unlock(&sem->wait_lock);
@@ -168,7 +173,7 @@
 	tsk->state = TASK_RUNNING;
 
  out:
-	rwsemtrace(sem,"Leaving __down_read");
+	rwsemtrace(sem, "Leaving __down_read");
 }
 
 /*
@@ -177,11 +182,11 @@
 int fastcall __down_read_trylock(struct rw_semaphore *sem)
 {
 	int ret = 0;
-	rwsemtrace(sem,"Entering __down_read_trylock");
+	rwsemtrace(sem, "Entering __down_read_trylock");
 
 	spin_lock(&sem->wait_lock);
 
-	if (sem->activity>=0 && list_empty(&sem->wait_list)) {
+	if (sem->activity >= 0 && list_empty(&sem->wait_list)) {
 		/* granted */
 		sem->activity++;
 		ret = 1;
@@ -189,24 +194,24 @@
 
 	spin_unlock(&sem->wait_lock);
 
-	rwsemtrace(sem,"Leaving __down_read_trylock");
+	rwsemtrace(sem, "Leaving __down_read_trylock");
 	return ret;
 }
 
 /*
  * get a write lock on the semaphore
- * - note that we increment the waiting count anyway to indicate an exclusive lock
+ * - we increment the waiting count anyway to indicate an exclusive lock
  */
-void fastcall __down_write(struct rw_semaphore *sem)
+void fastcall __sched __down_write(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 	struct task_struct *tsk;
 
-	rwsemtrace(sem,"Entering __down_write");
+	rwsemtrace(sem, "Entering __down_write");
 
 	spin_lock(&sem->wait_lock);
 
-	if (sem->activity==0 && list_empty(&sem->wait_list)) {
+	if (sem->activity == 0 && list_empty(&sem->wait_list)) {
 		/* granted */
 		sem->activity = -1;
 		spin_unlock(&sem->wait_lock);
@@ -214,14 +219,14 @@
 	}
 
 	tsk = current;
-	set_task_state(tsk,TASK_UNINTERRUPTIBLE);
+	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 
 	/* set up my own style of waitqueue */
 	waiter.task = tsk;
 	waiter.flags = RWSEM_WAITING_FOR_WRITE;
 	get_task_struct(tsk);
 
-	list_add_tail(&waiter.list,&sem->wait_list);
+	list_add_tail(&waiter.list, &sem->wait_list);
 
 	/* we don't need to touch the semaphore struct anymore */
 	spin_unlock(&sem->wait_lock);
@@ -237,7 +242,7 @@
 	tsk->state = TASK_RUNNING;
 
  out:
-	rwsemtrace(sem,"Leaving __down_write");
+	rwsemtrace(sem, "Leaving __down_write");
 }
 
 /*
@@ -246,11 +251,11 @@
 int fastcall __down_write_trylock(struct rw_semaphore *sem)
 {
 	int ret = 0;
-	rwsemtrace(sem,"Entering __down_write_trylock");
+	rwsemtrace(sem, "Entering __down_write_trylock");
 
 	spin_lock(&sem->wait_lock);
 
-	if (sem->activity==0 && list_empty(&sem->wait_list)) {
+	if (sem->activity == 0 && list_empty(&sem->wait_list)) {
 		/* granted */
 		sem->activity = -1;
 		ret = 1;
@@ -258,7 +263,7 @@
 
 	spin_unlock(&sem->wait_lock);
 
-	rwsemtrace(sem,"Leaving __down_write_trylock");
+	rwsemtrace(sem, "Leaving __down_write_trylock");
 	return ret;
 }
 
@@ -267,16 +272,16 @@
  */
 void fastcall __up_read(struct rw_semaphore *sem)
 {
-	rwsemtrace(sem,"Entering __up_read");
+	rwsemtrace(sem, "Entering __up_read");
 
 	spin_lock(&sem->wait_lock);
 
-	if (--sem->activity==0 && !list_empty(&sem->wait_list))
+	if (--sem->activity == 0 && !list_empty(&sem->wait_list))
 		sem = __rwsem_wake_one_writer(sem);
 
 	spin_unlock(&sem->wait_lock);
 
-	rwsemtrace(sem,"Leaving __up_read");
+	rwsemtrace(sem, "Leaving __up_read");
 }
 
 /*
@@ -284,7 +289,7 @@
  */
 void fastcall __up_write(struct rw_semaphore *sem)
 {
-	rwsemtrace(sem,"Entering __up_write");
+	rwsemtrace(sem, "Entering __up_write");
 
 	spin_lock(&sem->wait_lock);
 
@@ -294,7 +299,7 @@
 
 	spin_unlock(&sem->wait_lock);
 
-	rwsemtrace(sem,"Leaving __up_write");
+	rwsemtrace(sem, "Leaving __up_write");
 }
 
 /*
@@ -303,17 +308,17 @@
  */
 void fastcall __downgrade_write(struct rw_semaphore *sem)
 {
-	rwsemtrace(sem,"Entering __downgrade_write");
+	rwsemtrace(sem, "Entering __downgrade_write");
 
 	spin_lock(&sem->wait_lock);
 
 	sem->activity = 1;
 	if (!list_empty(&sem->wait_list))
-		sem = __rwsem_do_wake(sem,0);
+		sem = __rwsem_do_wake(sem, 0);
 
 	spin_unlock(&sem->wait_lock);
 
-	rwsemtrace(sem,"Leaving __downgrade_write");
+	rwsemtrace(sem, "Leaving __downgrade_write");
 }
 
 EXPORT_SYMBOL(init_rwsem);
diff -Nru a/lib/rwsem.c b/lib/rwsem.c
--- a/lib/rwsem.c	2004-06-23 19:04:25 -07:00
+++ b/lib/rwsem.c	2004-06-23 19:04:25 -07:00
@@ -9,9 +9,9 @@
 #include <linux/module.h>
 
 struct rwsem_waiter {
-	struct list_head	list;
-	struct task_struct	*task;
-	unsigned int		flags;
+	struct list_head list;
+	struct task_struct *task;
+	unsigned int flags;
 #define RWSEM_WAITING_FOR_READ	0x00000001
 #define RWSEM_WAITING_FOR_WRITE	0x00000002
 };
@@ -20,31 +20,32 @@
 #undef rwsemtrace
 void rwsemtrace(struct rw_semaphore *sem, const char *str)
 {
-	printk("sem=%p\n",sem);
-	printk("(sem)=%08lx\n",sem->count);
+	printk("sem=%p\n", sem);
+	printk("(sem)=%08lx\n", sem->count);
 	if (sem->debug)
-		printk("[%d] %s({%08lx})\n",current->pid,str,sem->count);
+		printk("[%d] %s({%08lx})\n", current->pid, str, sem->count);
 }
 #endif
 
 /*
- * handle the lock being released whilst there are processes blocked on it that can now run
+ * handle the lock release when processes blocked on it that can now run
  * - if we come here from up_xxxx(), then:
- *   - the 'active part' of the count (&0x0000ffff) had reached zero (but may have changed)
- *   - the 'waiting part' of the count (&0xffff0000) is negative (and will still be so)
+ *   - the 'active part' of count (&0x0000ffff) reached 0 (but may have changed)
+ *   - the 'waiting part' of count (&0xffff0000) is -ve (and will still be so)
  *   - there must be someone on the queue
  * - the spinlock must be held by the caller
  * - woken process blocks are discarded from the list after having task zeroed
  * - writers are only woken if downgrading is false
  */
-static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int downgrading)
+static inline struct rw_semaphore *
+__rwsem_do_wake(struct rw_semaphore *sem, int downgrading)
 {
 	struct rwsem_waiter *waiter;
 	struct task_struct *tsk;
 	struct list_head *next;
 	signed long oldcount, woken, loop;
 
-	rwsemtrace(sem,"Entering __rwsem_do_wake");
+	rwsemtrace(sem, "Entering __rwsem_do_wake");
 
 	if (downgrading)
 		goto dont_wake_writers;
@@ -53,19 +54,24 @@
 	 * if we can transition the active part of the count from 0 -> 1
 	 */
  try_again:
-	oldcount = rwsem_atomic_update(RWSEM_ACTIVE_BIAS,sem) - RWSEM_ACTIVE_BIAS;
+	oldcount = rwsem_atomic_update(RWSEM_ACTIVE_BIAS, sem)
+						- RWSEM_ACTIVE_BIAS;
 	if (oldcount & RWSEM_ACTIVE_MASK)
 		goto undo;
 
-	waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
+	waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
 
-	/* try to grant a single write lock if there's a writer at the front of the queue
-	 * - note we leave the 'active part' of the count incremented by 1 and the waiting part
-	 *   incremented by 0x00010000
+	/* try to grant a single write lock if there's a writer at the front
+	 * of the queue - note we leave the 'active part' of the count
+	 * incremented by 1 and the waiting part incremented by 0x00010000
 	 */
 	if (!(waiter->flags & RWSEM_WAITING_FOR_WRITE))
 		goto readers_only;
 
+	/* We must be careful not to touch 'waiter' after we set ->task = NULL.
+	 * It is an allocated on the waiter's stack and may become invalid at
+	 * any time after that point (due to a wakeup from another source).
+	 */
 	list_del(&waiter->list);
 	tsk = waiter->task;
 	mb();
@@ -76,7 +82,7 @@
 
 	/* don't want to wake any writers */
  dont_wake_writers:
-	waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
+	waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
 	if (waiter->flags & RWSEM_WAITING_FOR_WRITE)
 		goto out;
 
@@ -90,23 +96,25 @@
 	do {
 		woken++;
 
-		if (waiter->list.next==&sem->wait_list)
+		if (waiter->list.next == &sem->wait_list)
 			break;
 
-		waiter = list_entry(waiter->list.next,struct rwsem_waiter,list);
+		waiter = list_entry(waiter->list.next,
+					struct rwsem_waiter, list);
 
 	} while (waiter->flags & RWSEM_WAITING_FOR_READ);
 
 	loop = woken;
 	woken *= RWSEM_ACTIVE_BIAS - RWSEM_WAITING_BIAS;
 	if (!downgrading)
-		woken -= RWSEM_ACTIVE_BIAS; /* we'd already done one increment
-					     * earlier */
-	rwsem_atomic_add(woken,sem);
+		/* we'd already done one increment earlier */
+		woken -= RWSEM_ACTIVE_BIAS;
+
+	rwsem_atomic_add(woken, sem);
 
 	next = sem->wait_list.next;
-	for (; loop>0; loop--) {
-		waiter = list_entry(next,struct rwsem_waiter,list);
+	for (; loop > 0; loop--) {
+		waiter = list_entry(next, struct rwsem_waiter, list);
 		next = waiter->list.next;
 		tsk = waiter->task;
 		mb();
@@ -119,12 +127,12 @@
 	next->prev = &sem->wait_list;
 
  out:
-	rwsemtrace(sem,"Leaving __rwsem_do_wake");
+	rwsemtrace(sem, "Leaving __rwsem_do_wake");
 	return sem;
 
 	/* undo the change to count, but check for a transition 1->0 */
  undo:
-	if (rwsem_atomic_update(-RWSEM_ACTIVE_BIAS,sem)!=0)
+	if (rwsem_atomic_update(-RWSEM_ACTIVE_BIAS, sem) != 0)
 		goto out;
 	goto try_again;
 }
@@ -132,28 +140,26 @@
 /*
  * wait for a lock to be granted
  */
-static inline struct rw_semaphore *rwsem_down_failed_common(struct rw_semaphore *sem,
-								 struct rwsem_waiter *waiter,
-								 signed long adjustment)
+static inline struct rw_semaphore *
+rwsem_down_failed_common(struct rw_semaphore *sem,
+			struct rwsem_waiter *waiter, signed long adjustment)
 {
 	struct task_struct *tsk = current;
 	signed long count;
 
-	set_task_state(tsk,TASK_UNINTERRUPTIBLE);
+	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 
 	/* set up my own style of waitqueue */
 	spin_lock(&sem->wait_lock);
 	waiter->task = tsk;
 	get_task_struct(tsk);
 
-	list_add_tail(&waiter->list,&sem->wait_list);
+	list_add_tail(&waiter->list, &sem->wait_list);
 
-	/* note that we're now waiting on the lock, but no longer actively read-locking */
-	count = rwsem_atomic_update(adjustment,sem);
+	/* we're now waiting on the lock, but no longer actively read-locking */
+	count = rwsem_atomic_update(adjustment, sem);
 
-	/* if there are no longer active locks, wake the front queued process(es) up
-	 * - it might even be this process, since the waker takes a more active part
-	 */
+	/* if there are no active locks, wake the front queued process(es) up */
 	if (!(count & RWSEM_ACTIVE_MASK))
 		sem = __rwsem_do_wake(sem, 0);
 
@@ -175,42 +181,45 @@
 /*
  * wait for the read lock to be granted
  */
-struct rw_semaphore fastcall __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
+struct rw_semaphore fastcall __sched *
+rwsem_down_read_failed(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 
-	rwsemtrace(sem,"Entering rwsem_down_read_failed");
+	rwsemtrace(sem, "Entering rwsem_down_read_failed");
 
 	waiter.flags = RWSEM_WAITING_FOR_READ;
-	rwsem_down_failed_common(sem,&waiter,RWSEM_WAITING_BIAS-RWSEM_ACTIVE_BIAS);
+	rwsem_down_failed_common(sem, &waiter,
+				RWSEM_WAITING_BIAS - RWSEM_ACTIVE_BIAS);
 
-	rwsemtrace(sem,"Leaving rwsem_down_read_failed");
+	rwsemtrace(sem, "Leaving rwsem_down_read_failed");
 	return sem;
 }
 
 /*
  * wait for the write lock to be granted
  */
-struct rw_semaphore fastcall __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
+struct rw_semaphore fastcall __sched *
+rwsem_down_write_failed(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 
-	rwsemtrace(sem,"Entering rwsem_down_write_failed");
+	rwsemtrace(sem, "Entering rwsem_down_write_failed");
 
 	waiter.flags = RWSEM_WAITING_FOR_WRITE;
-	rwsem_down_failed_common(sem,&waiter,-RWSEM_ACTIVE_BIAS);
+	rwsem_down_failed_common(sem, &waiter, -RWSEM_ACTIVE_BIAS);
 
-	rwsemtrace(sem,"Leaving rwsem_down_write_failed");
+	rwsemtrace(sem, "Leaving rwsem_down_write_failed");
 	return sem;
 }
 
 /*
  * handle waking up a waiter on the semaphore
- * - up_read/up_write has decremented the active part of the count if we come here
+ * - up_read/up_write has decremented the active part of count if we come here
  */
 struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem)
 {
-	rwsemtrace(sem,"Entering rwsem_wake");
+	rwsemtrace(sem, "Entering rwsem_wake");
 
 	spin_lock(&sem->wait_lock);
 
@@ -220,19 +229,19 @@
 
 	spin_unlock(&sem->wait_lock);
 
-	rwsemtrace(sem,"Leaving rwsem_wake");
+	rwsemtrace(sem, "Leaving rwsem_wake");
 
 	return sem;
 }
 
 /*
  * downgrade a write lock into a read lock
- * - caller incremented waiting part of count, and discovered it to be still negative
+ * - caller incremented waiting part of count and discovered it still negative
  * - just wake up any readers at the front of the queue
  */
 struct rw_semaphore fastcall *rwsem_downgrade_wake(struct rw_semaphore *sem)
 {
-	rwsemtrace(sem,"Entering rwsem_downgrade_wake");
+	rwsemtrace(sem, "Entering rwsem_downgrade_wake");
 
 	spin_lock(&sem->wait_lock);
 
@@ -242,7 +251,7 @@
 
 	spin_unlock(&sem->wait_lock);
 
-	rwsemtrace(sem,"Leaving rwsem_downgrade_wake");
+	rwsemtrace(sem, "Leaving rwsem_downgrade_wake");
 	return sem;
 }
 
diff -Nru a/lib/string.c b/lib/string.c
--- a/lib/string.c	2004-06-23 19:04:28 -07:00
+++ b/lib/string.c	2004-06-23 19:04:28 -07:00
@@ -162,7 +162,7 @@
 	if (count) {
 		while (*dest)
 			dest++;
-		while ((*dest++ = *src++)) {
+		while ((*dest++ = *src++) != 0) {
 			if (--count == 0) {
 				*dest = '\0';
 				break;
diff -Nru a/lib/vsprintf.c b/lib/vsprintf.c
--- a/lib/vsprintf.c	2004-06-23 19:04:28 -07:00
+++ b/lib/vsprintf.c	2004-06-23 19:04:28 -07:00
@@ -40,11 +40,14 @@
 		if (*cp == '0') {
 			base = 8;
 			cp++;
-			if ((*cp == 'x') && isxdigit(cp[1])) {
+			if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
 				cp++;
 				base = 16;
 			}
 		}
+	} else if (base == 16) {
+		if (cp[0] == '0' && toupper(cp[1]) == 'X')
+			cp += 2;
 	}
 	while (isxdigit(*cp) &&
 	       (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
@@ -88,11 +91,14 @@
 		if (*cp == '0') {
 			base = 8;
 			cp++;
-			if ((*cp == 'x') && isxdigit(cp[1])) {
+			if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
 				cp++;
 				base = 16;
 			}
 		}
+	} else if (base == 16) {
+		if (cp[0] == '0' && toupper(cp[1]) == 'X')
+			cp += 2;
 	}
 	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
 	    ? toupper(*cp) : *cp)-'A'+10) < base) {
diff -Nru a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c
--- a/lib/zlib_deflate/deflate.c	2004-06-23 19:04:25 -07:00
+++ b/lib/zlib_deflate/deflate.c	2004-06-23 19:04:25 -07:00
@@ -1262,7 +1262,7 @@
     return flush == Z_FINISH ? finish_done : block_done;
 }
 
-extern int zlib_deflate_workspacesize(void)
+int zlib_deflate_workspacesize(void)
 {
     return sizeof(deflate_workspace);
 }
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	2004-06-23 19:04:26 -07:00
+++ b/mm/filemap.c	2004-06-23 19:04:26 -07:00
@@ -650,7 +650,8 @@
 			     read_actor_t actor)
 {
 	struct inode *inode = mapping->host;
-	unsigned long index, offset;
+	unsigned long index, end_index, offset;
+	loff_t isize;
 	struct page *cached_page;
 	int error;
 	struct file_ra_state ra = *_ra;
@@ -659,26 +660,18 @@
 	index = *ppos >> PAGE_CACHE_SHIFT;
 	offset = *ppos & ~PAGE_CACHE_MASK;
 
+	isize = i_size_read(inode);
+	end_index = isize >> PAGE_CACHE_SHIFT;
+	if (index > end_index)
+		goto out;
+
 	for (;;) {
 		struct page *page;
-		unsigned long end_index, nr, ret;
-		loff_t isize = i_size_read(inode);
-
-		end_index = isize >> PAGE_CACHE_SHIFT;
-			
-		if (index > end_index)
-			break;
-		nr = PAGE_CACHE_SIZE;
-		if (index == end_index) {
-			nr = isize & ~PAGE_CACHE_MASK;
-			if (nr <= offset)
-				break;
-		}
+		unsigned long nr, ret;
 
 		cond_resched();
 		page_cache_readahead(mapping, &ra, filp, index);
 
-		nr = nr - offset;
 find_page:
 		page = find_get_page(mapping, index);
 		if (unlikely(page == NULL)) {
@@ -688,6 +681,17 @@
 		if (!PageUptodate(page))
 			goto page_not_up_to_date;
 page_ok:
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index == end_index) {
+			nr = isize & ~PAGE_CACHE_MASK;
+			if (nr <= offset) {
+				page_cache_release(page);
+				goto out;
+			}
+		}
+		nr = nr - offset;
+
 		/* If users can be writing to this page using arbitrary
 		 * virtual addresses, take care about potential aliasing
 		 * before reading the page on the kernel side.
@@ -719,7 +723,7 @@
 		page_cache_release(page);
 		if (ret == nr && desc->count)
 			continue;
-		break;
+		goto out;
 
 page_not_up_to_date:
 		/* Get exclusive access to the page ... */
@@ -739,22 +743,41 @@
 		}
 
 readpage:
-		/* ... and start the actual read. The read will unlock the page. */
+		/* Start the actual read. The read will unlock the page. */
 		error = mapping->a_ops->readpage(filp, page);
 
-		if (!error) {
-			if (PageUptodate(page))
-				goto page_ok;
+		if (unlikely(error))
+			goto readpage_error;
+
+		if (!PageUptodate(page)) {
 			wait_on_page_locked(page);
-			if (PageUptodate(page))
-				goto page_ok;
-			error = -EIO;
+			if (!PageUptodate(page)) {
+				error = -EIO;
+				goto readpage_error;
+			}
 		}
 
+		/*
+		 * i_size must be checked after we have done ->readpage.
+		 *
+		 * Checking i_size after the readpage allows us to calculate
+		 * the correct value for "nr", which means the zero-filled
+		 * part of the page is not copied back to userspace (unless
+		 * another truncate extends the file - this is desired though).
+		 */
+		isize = i_size_read(inode);
+		end_index = isize >> PAGE_CACHE_SHIFT;
+		if (index > end_index) {
+			page_cache_release(page);
+			goto out;
+		}
+		goto page_ok;
+
+readpage_error:
 		/* UHHUH! A synchronous read error occurred. Report it */
 		desc->error = error;
 		page_cache_release(page);
-		break;
+		goto out;
 
 no_cached_page:
 		/*
@@ -765,7 +788,7 @@
 			cached_page = page_cache_alloc_cold(mapping);
 			if (!cached_page) {
 				desc->error = -ENOMEM;
-				break;
+				goto out;
 			}
 		}
 		error = add_to_page_cache_lru(cached_page, mapping,
@@ -774,13 +797,14 @@
 			if (error == -EEXIST)
 				goto find_page;
 			desc->error = error;
-			break;
+			goto out;
 		}
 		page = cached_page;
 		cached_page = NULL;
 		goto readpage;
 	}
 
+out:
 	*_ra = ra;
 
 	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
@@ -1891,7 +1915,7 @@
 		count -= written;
 	}
 
-	buf = iov->iov_base;
+	buf = iov->iov_base + written;	/* handle partial DIO write */
 	do {
 		unsigned long index;
 		unsigned long offset;
diff -Nru a/mm/fremap.c b/mm/fremap.c
--- a/mm/fremap.c	2004-06-23 19:04:25 -07:00
+++ b/mm/fremap.c	2004-06-23 19:04:25 -07:00
@@ -161,6 +161,7 @@
 	unsigned long end = start + size;
 	struct vm_area_struct *vma;
 	int err = -EINVAL;
+	int has_write_lock = 0;
 
 	if (__prot)
 		return err;
@@ -181,7 +182,8 @@
 #endif
 
 	/* We need down_write() to change vma->vm_flags. */
-	down_write(&mm->mmap_sem);
+	down_read(&mm->mmap_sem);
+ retry:
 	vma = find_vma(mm, start);
 
 	/*
@@ -200,6 +202,12 @@
 		/* Must set VM_NONLINEAR before any pages are populated. */
 		if (pgoff != linear_page_index(vma, start) &&
 		    !(vma->vm_flags & VM_NONLINEAR)) {
+			if (!has_write_lock) {
+				up_read(&mm->mmap_sem);
+				down_write(&mm->mmap_sem);
+				has_write_lock = 1;
+				goto retry;
+			}
 			mapping = vma->vm_file->f_mapping;
 			spin_lock(&mapping->i_mmap_lock);
 			flush_dcache_mmap_lock(mapping);
@@ -212,8 +220,6 @@
 			spin_unlock(&mapping->i_mmap_lock);
 		}
 
-		/* ->populate can take a long time, so downgrade the lock. */
-		downgrade_write(&mm->mmap_sem);
 		err = vma->vm_ops->populate(vma, start, size,
 					    vma->vm_page_prot,
 					    pgoff, flags & MAP_NONBLOCK);
@@ -223,10 +229,11 @@
 		 * it after ->populate completes, and that would prevent
 		 * downgrading the lock.  (Locks can't be upgraded).
 		 */
+	}
+	if (likely(!has_write_lock))
 		up_read(&mm->mmap_sem);
-	} else {
+	else
 		up_write(&mm->mmap_sem);
-	}
 
 	return err;
 }
diff -Nru a/mm/highmem.c b/mm/highmem.c
--- a/mm/highmem.c	2004-06-23 19:04:27 -07:00
+++ b/mm/highmem.c	2004-06-23 19:04:27 -07:00
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/hash.h>
 #include <linux/highmem.h>
-#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 
 static mempool_t *page_pool, *isa_page_pool;
diff -Nru a/mm/mempolicy.c b/mm/mempolicy.c
--- a/mm/mempolicy.c	2004-06-23 19:04:29 -07:00
+++ b/mm/mempolicy.c	2004-06-23 19:04:29 -07:00
@@ -26,7 +26,7 @@
  *                process policy.
  * default        Allocate on the local node first, or when on a VMA
  *                use the process policy. This is what Linux always did
- *				   in a NUMA aware kernel and still does by, ahem, default.
+ *		  in a NUMA aware kernel and still does by, ahem, default.
  *
  * The process policy is applied for most non interrupt memory allocations
  * in that process' context. Interrupts ignore the policies and always
@@ -135,6 +135,10 @@
 	unsigned long endmask;
 
 	--maxnode;
+	bitmap_zero(nodes, MAX_NUMNODES);
+	if (maxnode == 0 || !nmask)
+		return 0;
+
 	nlongs = BITS_TO_LONGS(maxnode);
 	if ((maxnode % BITS_PER_LONG) == 0)
 		endmask = ~0UL;
@@ -143,7 +147,7 @@
 
 	/* When the user specified more nodes than supported just check
 	   if the non supported part is all zero. */
-	if (nmask && nlongs > BITS_TO_LONGS(MAX_NUMNODES)) {
+	if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) {
 		for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) {
 			unsigned long t;
 			if (get_user(t,  nmask + k))
@@ -158,8 +162,7 @@
 		endmask = ~0UL;
 	}
 
-	bitmap_zero(nodes, MAX_NUMNODES);
-	if (nmask && copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long)))
+	if (copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long)))
 		return -EFAULT;
 	nodes[nlongs-1] &= endmask;
 	return mpol_check_policy(mode, nodes);
@@ -622,14 +625,14 @@
 
 /* Allocate a page in interleaved policy.
    Own path because it needs to do special accounting. */
-static struct page *alloc_page_interleave(unsigned gfp, unsigned nid)
+static struct page *alloc_page_interleave(unsigned gfp, unsigned order, unsigned nid)
 {
 	struct zonelist *zl;
 	struct page *page;
 
 	BUG_ON(!test_bit(nid, node_online_map));
 	zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK);
-	page = __alloc_pages(gfp, 0, zl);
+	page = __alloc_pages(gfp, order, zl);
 	if (page && page_zone(page) == zl->zones[0]) {
 		zl->zones[0]->pageset[get_cpu()].interleave_hit++;
 		put_cpu();
@@ -677,7 +680,7 @@
 			/* fall back to process interleaving */
 			nid = interleave_nodes(pol);
 		}
-		return alloc_page_interleave(gfp, nid);
+		return alloc_page_interleave(gfp, 0, nid);
 	}
 	return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol));
 }
@@ -686,7 +689,7 @@
  * 	alloc_pages_current - Allocate pages.
  *
  *	@gfp:
- *			%GFP_USER   user allocation,
+ *		%GFP_USER   user allocation,
  *      	%GFP_KERNEL kernel allocation,
  *      	%GFP_HIGHMEM highmem allocation,
  *      	%GFP_FS     don't call back into a file system.
@@ -703,8 +706,8 @@
 
 	if (!pol || in_interrupt())
 		pol = &default_policy;
-	if (pol->policy == MPOL_INTERLEAVE && order == 0)
-		return alloc_page_interleave(gfp, interleave_nodes(pol));
+	if (pol->policy == MPOL_INTERLEAVE)
+		return alloc_page_interleave(gfp, order, interleave_nodes(pol));
 	return __alloc_pages(gfp, order, zonelist_policy(gfp, pol));
 }
 EXPORT_SYMBOL(alloc_pages_current);
@@ -1002,7 +1005,8 @@
 	up(&p->sem);
 }
 
-static __init int numa_policy_init(void)
+/* assumes fs == KERNEL_DS */
+void __init numa_policy_init(void)
 {
 	policy_cache = kmem_cache_create("numa_policy",
 					 sizeof(struct mempolicy),
@@ -1011,6 +1015,17 @@
 	sn_cache = kmem_cache_create("shared_policy_node",
 				     sizeof(struct sp_node),
 				     0, SLAB_PANIC, NULL, NULL);
-	return 0;
+
+	/* Set interleaving policy for system init. This way not all
+	   the data structures allocated at system boot end up in node zero. */
+
+	if (sys_set_mempolicy(MPOL_INTERLEAVE, node_online_map, MAX_NUMNODES) < 0)
+		printk("numa_policy_init: interleaving failed\n");
+}
+
+/* Reset policy of current process to default.
+ * Assumes fs == KERNEL_DS */
+void numa_default_policy(void)
+{
+	sys_set_mempolicy(MPOL_DEFAULT, NULL, 0);
 }
-module_init(numa_policy_init);
diff -Nru a/mm/mempool.c b/mm/mempool.c
--- a/mm/mempool.c	2004-06-23 19:04:27 -07:00
+++ b/mm/mempool.c	2004-06-23 19:04:27 -07:00
@@ -89,11 +89,6 @@
 }
 EXPORT_SYMBOL(mempool_create);
 
-/*
- * mempool_resize is disabled for now, because it has no callers.  Feel free
- * to turn it back on if needed.
- */
-#if 0
 /**
  * mempool_resize - resize an existing memory pool
  * @pool:       pointer to the memory pool which was allocated via
@@ -163,7 +158,6 @@
 	return 0;
 }
 EXPORT_SYMBOL(mempool_resize);
-#endif
 
 /**
  * mempool_destroy - deallocate a memory pool
diff -Nru a/mm/mincore.c b/mm/mincore.c
--- a/mm/mincore.c	2004-06-23 19:04:29 -07:00
+++ b/mm/mincore.c	2004-06-23 19:04:29 -07:00
@@ -14,7 +14,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/pgalloc.h>
 
 /*
  * Later we can get more picky about what "in core" means precisely.
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	2004-06-23 19:04:27 -07:00
+++ b/mm/mmap.c	2004-06-23 19:04:27 -07:00
@@ -25,7 +25,6 @@
 #include <linux/rmap.h>
 
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/tlb.h>
 
@@ -363,6 +362,7 @@
 {
 	struct mm_struct *mm = vma->vm_mm;
 	struct vm_area_struct *next = vma->vm_next;
+	struct vm_area_struct *importer = NULL;
 	struct address_space *mapping = NULL;
 	struct prio_tree_root *root = NULL;
 	struct file *file = vma->vm_file;
@@ -386,6 +386,7 @@
 			 */
 			adjust_next = (end - next->vm_start) >> PAGE_SHIFT;
 			anon_vma = next->anon_vma;
+			importer = vma;
 		} else if (end < vma->vm_end) {
 			/*
 			 * vma shrinks, and !insert tells it's not
@@ -394,6 +395,7 @@
 			 */
 			adjust_next = - ((vma->vm_end - end) >> PAGE_SHIFT);
 			anon_vma = next->anon_vma;
+			importer = next;
 		}
 	}
 
@@ -419,8 +421,18 @@
 	 */
 	if (vma->anon_vma)
 		anon_vma = vma->anon_vma;
-	if (anon_vma)
+	if (anon_vma) {
 		spin_lock(&anon_vma->lock);
+		/*
+		 * Easily overlooked: when mprotect shifts the boundary,
+		 * make sure the expanding vma has anon_vma set if the
+		 * shrinking vma had, to cover any anon pages imported.
+		 */
+		if (importer && !importer->anon_vma) {
+			importer->anon_vma = anon_vma;
+			__anon_vma_link(importer);
+		}
+	}
 
 	if (root) {
 		flush_dcache_mmap_lock(mapping);
diff -Nru a/mm/mprotect.c b/mm/mprotect.c
--- a/mm/mprotect.c	2004-06-23 19:04:29 -07:00
+++ b/mm/mprotect.c	2004-06-23 19:04:29 -07:00
@@ -19,7 +19,6 @@
 #include <linux/mempolicy.h>
 
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
diff -Nru a/mm/mremap.c b/mm/mremap.c
--- a/mm/mremap.c	2004-06-23 19:04:27 -07:00
+++ b/mm/mremap.c	2004-06-23 19:04:27 -07:00
@@ -18,7 +18,6 @@
 #include <linux/security.h>
 
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
diff -Nru a/mm/msync.c b/mm/msync.c
--- a/mm/msync.c	2004-06-23 19:04:26 -07:00
+++ b/mm/msync.c	2004-06-23 19:04:26 -07:00
@@ -14,7 +14,6 @@
 #include <linux/hugetlb.h>
 
 #include <asm/pgtable.h>
-#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 
 /*
diff -Nru a/mm/nommu.c b/mm/nommu.c
--- a/mm/nommu.c	2004-06-23 19:04:28 -07:00
+++ b/mm/nommu.c	2004-06-23 19:04:28 -07:00
@@ -20,7 +20,6 @@
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 
-#include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
--- a/mm/page_alloc.c	2004-06-23 19:04:25 -07:00
+++ b/mm/page_alloc.c	2004-06-23 19:04:25 -07:00
@@ -55,6 +55,9 @@
 static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
 int min_free_kbytes = 1024;
 
+static unsigned long __initdata nr_kernel_pages;
+static unsigned long __initdata nr_all_pages;
+
 /*
  * Temporary debugging check for pages not lying within a given zone.
  */
@@ -732,53 +735,12 @@
 
 EXPORT_SYMBOL(__alloc_pages);
 
-#ifdef CONFIG_NUMA
-/* Early boot: Everything is done by one cpu, but the data structures will be
- * used by all cpus - spread them on all nodes.
- */
-static __init unsigned long get_boot_pages(unsigned int gfp_mask, unsigned int order)
-{
-static int nodenr;
-	int i = nodenr;
-	struct page *page;
-
-	for (;;) {
-		if (i > nodenr + numnodes)
-			return 0;
-		if (node_present_pages(i%numnodes)) {
-			struct zone **z;
-			/* The node contains memory. Check that there is
-			 * memory in the intended zonelist.
-			 */
-			z = NODE_DATA(i%numnodes)->node_zonelists[gfp_mask & GFP_ZONEMASK].zones;
-			while (*z) {
-				if ( (*z)->free_pages > (1UL<<order))
-					goto found_node;
-				z++;
-			}
-		}
-		i++;
-	}
-found_node:
-	nodenr = i+1;
-	page = alloc_pages_node(i%numnodes, gfp_mask, order);
-	if (!page)
-		return 0;
-	return (unsigned long) page_address(page);
-}
-#endif
-
 /*
  * Common helper functions.
  */
 fastcall unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)
 {
 	struct page * page;
-
-#ifdef CONFIG_NUMA
-	if (unlikely(system_state == SYSTEM_BOOTING))
-		return get_boot_pages(gfp_mask, order);
-#endif
 	page = alloc_pages(gfp_mask, order);
 	if (!page)
 		return 0;
@@ -1471,6 +1433,10 @@
 		if (zholes_size)
 			realsize -= zholes_size[j];
 
+		if (j == ZONE_DMA || j == ZONE_NORMAL)
+			nr_kernel_pages += realsize;
+		nr_all_pages += realsize;
+
 		zone->spanned_pages = size;
 		zone->present_pages = realsize;
 		zone->name = zone_names[j];
@@ -2010,4 +1976,70 @@
 	proc_dointvec_minmax(table, write, file, buffer, length);
 	setup_per_zone_protection();
 	return 0;
+}
+
+/*
+ * allocate a large system hash table from bootmem
+ * - it is assumed that the hash table must contain an exact power-of-2
+ *   quantity of entries
+ */
+void *__init alloc_large_system_hash(const char *tablename,
+				     unsigned long bucketsize,
+				     unsigned long numentries,
+				     int scale,
+				     int consider_highmem,
+				     unsigned int *_hash_shift,
+				     unsigned int *_hash_mask)
+{
+	unsigned long mem, max, log2qty, size;
+	void *table;
+
+	/* round applicable memory size up to nearest megabyte */
+	mem = consider_highmem ? nr_all_pages : nr_kernel_pages;
+	mem += (1UL << (20 - PAGE_SHIFT)) - 1;
+	mem >>= 20 - PAGE_SHIFT;
+	mem <<= 20 - PAGE_SHIFT;
+
+	/* limit to 1 bucket per 2^scale bytes of low memory (rounded up to
+	 * nearest power of 2 in size) */
+	if (scale > PAGE_SHIFT)
+		mem >>= (scale - PAGE_SHIFT);
+	else
+		mem <<= (PAGE_SHIFT - scale);
+
+	mem = 1UL << (long_log2(mem) + 1);
+
+	/* limit allocation size */
+	max = (1UL << (PAGE_SHIFT + MAX_SYS_HASH_TABLE_ORDER)) / bucketsize;
+	if (max > mem)
+		max = mem;
+
+	/* allow the kernel cmdline to have a say */
+	if (!numentries || numentries > max)
+		numentries = max;
+
+	log2qty = long_log2(numentries);
+
+	do {
+		size = bucketsize << log2qty;
+
+		table = (void *) alloc_bootmem(size);
+
+	} while (!table && size > PAGE_SIZE);
+
+	if (!table)
+		panic("Failed to allocate %s hash table\n", tablename);
+
+	printk("%s hash table entries: %d (order: %d, %lu bytes)\n",
+	       tablename,
+	       (1U << log2qty),
+	       long_log2(size) - PAGE_SHIFT,
+	       size);
+
+	if (_hash_shift)
+		*_hash_shift = log2qty;
+	if (_hash_mask)
+		*_hash_mask = (1 << log2qty) - 1;
+
+	return table;
 }
diff -Nru a/mm/rmap.c b/mm/rmap.c
--- a/mm/rmap.c	2004-06-23 19:04:28 -07:00
+++ b/mm/rmap.c	2004-06-23 19:04:28 -07:00
@@ -226,7 +226,7 @@
 	if (page_to_pfn(page) != pte_pfn(*pte))
 		goto out_unmap;
 
-	if (ptep_test_and_clear_young(pte))
+	if (ptep_clear_flush_young(vma, address, pte))
 		referenced++;
 
 	(*mapcount)--;
@@ -465,7 +465,7 @@
 	 * skipped over this mm) then we should reactivate it.
 	 */
 	if ((vma->vm_flags & (VM_LOCKED|VM_RESERVED)) ||
-			ptep_test_and_clear_young(pte)) {
+			ptep_clear_flush_young(vma, address, pte)) {
 		ret = SWAP_FAIL;
 		goto out_unmap;
 	}
@@ -592,7 +592,7 @@
 		if (PageReserved(page))
 			continue;
 
-		if (ptep_test_and_clear_young(pte))
+		if (ptep_clear_flush_young(vma, address, pte))
 			continue;
 
 		/* Nuke the page table entry. */
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	2004-06-23 19:04:25 -07:00
+++ b/mm/swapfile.c	2004-06-23 19:04:25 -07:00
@@ -467,6 +467,13 @@
 		if (unlikely(pte_same(*pte, swp_pte))) {
 			unuse_pte(vma, offset + address, pte, entry, page);
 			pte_unmap(pte);
+
+			/*
+			 * Move the page to the active list so it is not
+			 * immediately swapped out again after swapon.
+			 */
+			activate_page(page);
+
 			/* add 1 since address may be 0 */
 			return 1 + offset + address;
 		}
@@ -645,7 +652,7 @@
 	 * open() method called) - so swap entries may be invisible
 	 * to swapoff for a while, then reappear - but that is rare.
 	 */
-	while ((i = find_next_to_unuse(si, i))) {
+	while ((i = find_next_to_unuse(si, i)) != 0) {
 		if (signal_pending(current)) {
 			retval = -EINTR;
 			break;
diff -Nru a/mm/truncate.c b/mm/truncate.c
--- a/mm/truncate.c	2004-06-23 19:04:28 -07:00
+++ b/mm/truncate.c	2004-06-23 19:04:28 -07:00
@@ -243,6 +243,10 @@
  * where the page is seen to be mapped into process pagetables.  In that case,
  * the page is marked clean but is left attached to its address_space.
  *
+ * The page is also marked not uptodate so that a subsequent pagefault will
+ * perform I/O to bringthe page's contents back into sync with its backing
+ * store.
+ *
  * FIXME: invalidate_inode_pages2() is probably trivially livelockable.
  */
 void invalidate_inode_pages2(struct address_space *mapping)
@@ -260,10 +264,12 @@
 			if (page->mapping == mapping) {	/* truncate race? */
 				wait_on_page_writeback(page);
 				next = page->index + 1;
-				if (page_mapped(page))
+				if (page_mapped(page)) {
 					clear_page_dirty(page);
-				else
+					ClearPageUptodate(page);
+				} else {
 					invalidate_complete_page(mapping, page);
+				}
 			}
 			unlock_page(page);
 		}
diff -Nru a/mm/vmalloc.c b/mm/vmalloc.c
--- a/mm/vmalloc.c	2004-06-23 19:04:27 -07:00
+++ b/mm/vmalloc.c	2004-06-23 19:04:27 -07:00
@@ -17,7 +17,6 @@
 #include <linux/vmalloc.h>
 
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 
 
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	2004-06-23 19:04:25 -07:00
+++ b/mm/vmscan.c	2004-06-23 19:04:25 -07:00
@@ -33,7 +33,6 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 
-#include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
 
diff -Nru a/net/bridge/br.c b/net/bridge/br.c
--- a/net/bridge/br.c	2004-06-23 19:04:25 -07:00
+++ b/net/bridge/br.c	2004-06-23 19:04:25 -07:00
@@ -33,8 +33,6 @@
 {
 	br_fdb_init();
 
-	br_sysfs_init();
-
 #ifdef CONFIG_BRIDGE_NETFILTER
 	if (br_netfilter_init())
 		return 1;
@@ -69,7 +67,6 @@
 #endif
 
 	br_handle_frame_hook = NULL;
-	br_sysfs_fini();
 	br_fdb_fini();
 }
 
diff -Nru a/net/bridge/br_if.c b/net/bridge/br_if.c
--- a/net/bridge/br_if.c	2004-06-23 19:04:29 -07:00
+++ b/net/bridge/br_if.c	2004-06-23 19:04:29 -07:00
@@ -41,7 +41,7 @@
 	int err;
 
 	strncpy(ifr.ifr_name, dev->name, IFNAMSIZ);
-	ifr.ifr_data = (void *) &ecmd;
+	ifr.ifr_data = (void __user *) &ecmd;
 
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h	2004-06-23 19:04:26 -07:00
+++ b/net/bridge/br_private.h	2004-06-23 19:04:26 -07:00
@@ -217,9 +217,6 @@
 extern void br_sysfs_freeif(struct net_bridge_port *p);
 
 /* br_sysfs_br.c */
-extern struct subsystem bridge_subsys;
-extern void br_sysfs_init(void);
-extern void br_sysfs_fini(void);
 extern int br_sysfs_addbr(struct net_device *dev);
 extern void br_sysfs_delbr(struct net_device *dev);
 
@@ -228,8 +225,6 @@
 #define br_sysfs_addif(p)	(0)
 #define br_sysfs_removeif(p)	do { } while(0)
 #define br_sysfs_freeif(p)	kfree(p)
-#define br_sysfs_init()		do { } while(0)
-#define br_sysfs_fini()		do { } while(0)
 #define br_sysfs_addbr(dev)	(0)
 #define br_sysfs_delbr(dev)	do { } while(0)
 #endif /* CONFIG_SYSFS */
diff -Nru a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
--- a/net/bridge/br_sysfs_br.c	2004-06-23 19:04:26 -07:00
+++ b/net/bridge/br_sysfs_br.c	2004-06-23 19:04:26 -07:00
@@ -300,25 +300,6 @@
 	.read = brforward_read,
 };
 
-
-/*
- * This is a dummy kset so bridge objects don't cause
- * hotplug events 
- */
-struct subsystem bridge_subsys = { 
-	.kset = { .hotplug_ops = NULL },
-};
-
-void br_sysfs_init(void)
-{
-	subsystem_register(&bridge_subsys);
-}
-
-void br_sysfs_fini(void)
-{
-	subsystem_unregister(&bridge_subsys);
-}
-
 /*
  * Add entries in sysfs onto the existing network class device
  * for the bridge.
@@ -353,7 +334,7 @@
 	
 	kobject_set_name(&br->ifobj, SYSFS_BRIDGE_PORT_SUBDIR);
 	br->ifobj.ktype = NULL;
-	br->ifobj.kset = &bridge_subsys.kset;
+	br->ifobj.kset = NULL;
 	br->ifobj.parent = brobj;
 
 	err = kobject_register(&br->ifobj);
diff -Nru a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
--- a/net/bridge/br_sysfs_if.c	2004-06-23 19:04:28 -07:00
+++ b/net/bridge/br_sysfs_if.c	2004-06-23 19:04:28 -07:00
@@ -227,7 +227,7 @@
 	kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
 	p->kobj.ktype = &brport_ktype;
 	p->kobj.parent = &(p->dev->class_dev.kobj);
-	p->kobj.kset = &bridge_subsys.kset;
+	p->kobj.kset = NULL;
 
 	err = kobject_add(&p->kobj);
 	if(err)
diff -Nru a/net/core/Makefile b/net/core/Makefile
--- a/net/core/Makefile	2004-06-23 19:04:28 -07:00
+++ b/net/core/Makefile	2004-06-23 19:04:28 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the Linux networking core.
 #
 
-obj-y := sock.o skbuff.o iovec.o datagram.o scm.o
+obj-y := sock.o skbuff.o iovec.o datagram.o stream.o scm.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	2004-06-23 19:04:27 -07:00
+++ b/net/core/dev.c	2004-06-23 19:04:27 -07:00
@@ -107,6 +107,7 @@
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/netpoll.h>
+#include <linux/rcupdate.h>
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>		/* Note : will define WIRELESS_EXT */
 #include <net/iw_handler.h>
@@ -1305,6 +1306,20 @@
 	return 0;
 }
 
+#define HARD_TX_LOCK_BH(dev, cpu) {			\
+	if ((dev->features & NETIF_F_LLTX) == 0) {	\
+		spin_lock_bh(&dev->xmit_lock);		\
+		dev->xmit_lock_owner = cpu;		\
+	}						\
+}
+
+#define HARD_TX_UNLOCK_BH(dev) {			\
+	if ((dev->features & NETIF_F_LLTX) == 0) {	\
+		dev->xmit_lock_owner = -1;		\
+		spin_unlock_bh(&dev->xmit_lock);	\
+	}						\
+}
+
 /**
  *	dev_queue_xmit - transmit a buffer
  *	@skb: buffer to transmit
@@ -1348,18 +1363,38 @@
 	      	if (skb_checksum_help(&skb, 0))
 	      		goto out_kfree_skb;
 
-	/* Grab device queue */
-	spin_lock_bh(&dev->queue_lock);
+	rcu_read_lock();
+	/* Updates of qdisc are serialized by queue_lock. 
+	 * The struct Qdisc which is pointed to by qdisc is now a 
+	 * rcu structure - it may be accessed without acquiring 
+	 * a lock (but the structure may be stale.) The freeing of the
+	 * qdisc will be deferred until it's known that there are no 
+	 * more references to it.
+	 * 
+	 * If the qdisc has an enqueue function, we still need to 
+	 * hold the queue_lock before calling it, since queue_lock
+	 * also serializes access to the device queue.
+	 */
+
 	q = dev->qdisc;
+	smp_read_barrier_depends();
+#ifdef CONFIG_NET_CLS_ACT
+	skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
+#endif
 	if (q->enqueue) {
+		/* Grab device queue */
+		spin_lock_bh(&dev->queue_lock);
+
 		rc = q->enqueue(skb, q);
 
 		qdisc_run(dev);
 
 		spin_unlock_bh(&dev->queue_lock);
+		rcu_read_unlock();
 		rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
 		goto out;
 	}
+	rcu_read_unlock();
 
 	/* The device has no queue. Common case for software devices:
 	   loopback, all the sorts of tunnels...
@@ -1374,18 +1409,12 @@
 	   Either shot noqueue qdisc, it is even simpler 8)
 	 */
 	if (dev->flags & IFF_UP) {
-		int cpu = smp_processor_id();
+		int cpu = get_cpu();
 
 		if (dev->xmit_lock_owner != cpu) {
-			/*
-			 * The spin_lock effectivly does a preempt lock, but 
-			 * we are about to drop that...
-			 */
-			preempt_disable();
-			spin_unlock(&dev->queue_lock);
-			spin_lock(&dev->xmit_lock);
-			dev->xmit_lock_owner = cpu;
-			preempt_enable();
+
+			HARD_TX_LOCK_BH(dev, cpu);
+			put_cpu();
 
 			if (!netif_queue_stopped(dev)) {
 				if (netdev_nit)
@@ -1393,18 +1422,17 @@
 
 				rc = 0;
 				if (!dev->hard_start_xmit(skb, dev)) {
-					dev->xmit_lock_owner = -1;
-					spin_unlock_bh(&dev->xmit_lock);
+					HARD_TX_UNLOCK_BH(dev);
 					goto out;
 				}
 			}
-			dev->xmit_lock_owner = -1;
-			spin_unlock_bh(&dev->xmit_lock);
+			HARD_TX_UNLOCK_BH(dev);
 			if (net_ratelimit())
 				printk(KERN_CRIT "Virtual device %s asks to "
 				       "queue packet!\n", dev->name);
 			goto out_enetdown;
 		} else {
+			put_cpu();
 			/* Recursion is detected! It is possible,
 			 * unfortunately */
 			if (net_ratelimit())
@@ -1412,7 +1440,6 @@
 				       "%s, fix it urgently!\n", dev->name);
 		}
 	}
-	spin_unlock_bh(&dev->queue_lock);
 out_enetdown:
 	rc = -ENETDOWN;
 out_kfree_skb:
@@ -1731,6 +1758,48 @@
 	return 0;
 }
 
+
+#ifdef CONFIG_NET_CLS_ACT
+/* TODO: Maybe we should just force sch_ingress to be compiled in
+ * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
+ * a compare and 2 stores extra right now if we dont have it on
+ * but have CONFIG_NET_CLS_ACT
+ * NOTE: This doesnt stop any functionality; if you dont have 
+ * the ingress scheduler, you just cant add policies on ingress.
+ *
+ */
+int ing_filter(struct sk_buff *skb) 
+{
+	struct Qdisc *q;
+	struct net_device *dev = skb->dev;
+	int result = TC_ACT_OK;
+	
+	if (dev->qdisc_ingress) {
+		__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
+		if (MAX_RED_LOOP < ttl++) {
+			printk("Redir loop detected Dropping packet (%s->%s)\n",
+				skb->input_dev?skb->input_dev->name:"??",skb->dev->name);
+			return TC_ACT_SHOT;
+		}
+
+		skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl);
+
+		skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
+		if (NULL == skb->input_dev) {
+			skb->input_dev = skb->dev;
+			printk("ing_filter:  fixed  %s out %s\n",skb->input_dev->name,skb->dev->name);
+		}
+		spin_lock(&dev->ingress_lock);
+		if ((q = dev->qdisc_ingress) != NULL)
+			result = q->enqueue(skb, q);
+		spin_unlock(&dev->ingress_lock);
+
+	}
+
+	return result;
+}
+#endif
+
 int netif_receive_skb(struct sk_buff *skb)
 {
 	struct packet_type *ptype, *pt_prev;
@@ -1762,6 +1831,13 @@
 	skb->mac_len = skb->nh.raw - skb->mac.raw;
 
 	pt_prev = NULL;
+#ifdef CONFIG_NET_CLS_ACT
+	if (skb->tc_verd & TC_NCLS) {
+		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
+		goto ncls;
+	}
+ #endif
+
 	rcu_read_lock();
 	list_for_each_entry_rcu(ptype, &ptype_all, list) {
 		if (!ptype->dev || ptype->dev == skb->dev) {
@@ -1771,6 +1847,26 @@
 		}
 	}
 
+#ifdef CONFIG_NET_CLS_ACT
+	if (pt_prev) {
+		atomic_inc(&skb->users);
+		ret = pt_prev->func(skb, skb->dev, pt_prev);
+		pt_prev = NULL; /* noone else should process this after*/
+	} else {
+		skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
+	}
+
+	ret = ing_filter(skb);
+
+	if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) {
+		kfree_skb(skb);
+		goto out;
+	}
+
+	skb->tc_verd = 0;
+ncls:
+#endif
+
 	handle_diverter(skb);
 
 	if (__handle_bridge(skb, &pt_prev, &ret))
@@ -2824,6 +2920,10 @@
 	spin_lock_init(&dev->queue_lock);
 	spin_lock_init(&dev->xmit_lock);
 	dev->xmit_lock_owner = -1;
+#ifdef CONFIG_NET_CLS_ACT
+	spin_lock_init(&dev->ingress_lock);
+#endif
+
 #ifdef CONFIG_NET_FASTROUTE
 	dev->fastpath_lock = RW_LOCK_UNLOCKED;
 #endif
@@ -3177,6 +3277,8 @@
 	/* Finish processing unregister after unlock */
 	net_set_todo(dev);
 
+	synchronize_net();
+
 	dev_put(dev);
 	return 0;
 }
@@ -3357,5 +3459,10 @@
 EXPORT_SYMBOL(netdev_fastroute);
 EXPORT_SYMBOL(netdev_fastroute_obstacles);
 #endif
+
+#ifdef CONFIG_NET_CLS_ACT
+EXPORT_SYMBOL(ing_filter);
+#endif
+
 
 EXPORT_PER_CPU_SYMBOL(softnet_data);
diff -Nru a/net/core/dst.c b/net/core/dst.c
--- a/net/core/dst.c	2004-06-23 19:04:27 -07:00
+++ b/net/core/dst.c	2004-06-23 19:04:27 -07:00
@@ -210,6 +210,41 @@
 	return NULL;
 }
 
+/* Dirty hack. We did it in 2.2 (in __dst_free),
+ * we have _very_ good reasons not to repeat
+ * this mistake in 2.3, but we have no choice
+ * now. _It_ _is_ _explicit_ _deliberate_
+ * _race_ _condition_.
+ *
+ * Commented and originally written by Alexey.
+ */
+static void dst_ifdown(struct dst_entry *dst, int unregister)
+{
+	struct net_device *dev = dst->dev;
+
+	if (!unregister) {
+		dst->input = dst_discard_in;
+		dst->output = dst_discard_out;
+	}
+
+	do {
+		if (unregister) {
+			dst->dev = &loopback_dev;
+			dev_hold(&loopback_dev);
+			dev_put(dev);
+			if (dst->neighbour && dst->neighbour->dev == dev) {
+				dst->neighbour->dev = &loopback_dev;
+				dev_put(dev);
+				dev_hold(&loopback_dev);
+			}
+		}
+
+		if (dst->ops->ifdown)
+			dst->ops->ifdown(dst, unregister);
+	} while ((dst = dst->child) && dst->flags & DST_NOHASH &&
+		 dst->dev == dev);
+}
+
 static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
 	struct net_device *dev = ptr;
@@ -220,31 +255,8 @@
 	case NETDEV_DOWN:
 		spin_lock_bh(&dst_lock);
 		for (dst = dst_garbage_list; dst; dst = dst->next) {
-			if (dst->dev == dev) {
-				/* Dirty hack. We did it in 2.2 (in __dst_free),
-				   we have _very_ good reasons not to repeat
-				   this mistake in 2.3, but we have no choice
-				   now. _It_ _is_ _explicit_ _deliberate_
-				   _race_ _condition_.
-				 */
-				if (event!=NETDEV_DOWN &&
-				    dst->output == dst_discard_out) {
-					dst->dev = &loopback_dev;
-					dev_hold(&loopback_dev);
-					dev_put(dev);
-					dst->output = dst_discard_out;
-					if (dst->neighbour && dst->neighbour->dev == dev) {
-						dst->neighbour->dev = &loopback_dev;
-						dev_put(dev);
-						dev_hold(&loopback_dev);
-					}
-				} else {
-					dst->input = dst_discard_in;
-					dst->output = dst_discard_out;
-				}
-				if (dst->ops->ifdown)
-					dst->ops->ifdown(dst, event != NETDEV_DOWN);
-			}
+			if (dst->dev == dev)
+				dst_ifdown(dst, event != NETDEV_DOWN);
 		}
 		spin_unlock_bh(&dst_lock);
 		break;
diff -Nru a/net/core/net-sysfs.c b/net/core/net-sysfs.c
--- a/net/core/net-sysfs.c	2004-06-23 19:04:28 -07:00
+++ b/net/core/net-sysfs.c	2004-06-23 19:04:28 -07:00
@@ -414,7 +414,7 @@
 	if ((ret = class_device_register(class_dev)))
 		goto out;
 
-	for (i = 0; (attr = net_class_attributes[i]); i++) {
+	for (i = 0; (attr = net_class_attributes[i]) != NULL; i++) {
 		if ((ret = class_device_create_file(class_dev, attr)))
 		    goto out_unreg;
 	}
diff -Nru a/net/core/rtnetlink.c b/net/core/rtnetlink.c
--- a/net/core/rtnetlink.c	2004-06-23 19:04:29 -07:00
+++ b/net/core/rtnetlink.c	2004-06-23 19:04:29 -07:00
@@ -93,7 +93,8 @@
 	NLMSG_LENGTH(sizeof(struct rtmsg)),
 	NLMSG_LENGTH(sizeof(struct tcmsg)),
 	NLMSG_LENGTH(sizeof(struct tcmsg)),
-	NLMSG_LENGTH(sizeof(struct tcmsg))
+	NLMSG_LENGTH(sizeof(struct tcmsg)),
+	NLMSG_LENGTH(sizeof(struct tcamsg))
 };
 
 static const int rta_max[(RTM_MAX+1-RTM_BASE)/4] =
@@ -105,7 +106,8 @@
 	RTA_MAX,
 	TCA_MAX,
 	TCA_MAX,
-	TCA_MAX
+	TCA_MAX,
+	TCAA_MAX
 };
 
 void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c	2004-06-23 19:04:28 -07:00
+++ b/net/core/skbuff.c	2004-06-23 19:04:28 -07:00
@@ -49,6 +49,9 @@
 #include <linux/inet.h>
 #include <linux/slab.h>
 #include <linux/netdevice.h>
+#ifdef CONFIG_NET_CLS_ACT
+#include <net/pkt_sched.h>
+#endif
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/cache.h>
@@ -241,6 +244,15 @@
 	nf_bridge_put(skb->nf_bridge);
 #endif
 #endif
+/* XXX: IS this still necessary? - JHS */
+#ifdef CONFIG_NET_SCHED
+	skb->tc_index = 0;
+#ifdef CONFIG_NET_CLS_ACT
+	skb->tc_verd = 0;
+	skb->tc_classid = 0;
+#endif
+#endif
+
 	kfree_skbmem(skb);
 }
 
@@ -312,6 +324,14 @@
 #endif
 #ifdef CONFIG_NET_SCHED
 	C(tc_index);
+#ifdef CONFIG_NET_CLS_ACT
+	n->tc_verd = SET_TC_VERD(skb->tc_verd,0);
+	n->tc_verd = CLR_TC_OK2MUNGE(skb->tc_verd);
+	n->tc_verd = CLR_TC_MUNGED(skb->tc_verd);
+	C(input_dev);
+	C(tc_classid);
+#endif
+
 #endif
 	C(truesize);
 	atomic_set(&n->users, 1);
@@ -366,6 +386,9 @@
 #endif
 #endif
 #ifdef CONFIG_NET_SCHED
+#ifdef CONFIG_NET_CLS_ACT
+	new->tc_verd = old->tc_verd;
+#endif
 	new->tc_index	= old->tc_index;
 #endif
 	atomic_set(&new->users, 1);
@@ -1263,6 +1286,81 @@
 }
 #endif
 
+static void inline skb_split_inside_header(struct sk_buff *skb,
+					   struct sk_buff* skb1,
+					   const u32 len, const int pos)
+{
+	int i;
+
+	memcpy(skb_put(skb1, pos - len), skb->data + len, pos - len);
+
+	/* And move data appendix as is. */
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+		skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i];
+
+	skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags;
+	skb_shinfo(skb)->nr_frags  = 0;
+	skb1->data_len		   = skb->data_len;
+	skb1->len		   += skb1->data_len;
+	skb->data_len		   = 0;
+	skb->len		   = len;
+	skb->tail		   = skb->data + len;
+}
+
+static void inline skb_split_no_header(struct sk_buff *skb,
+				       struct sk_buff* skb1,
+				       const u32 len, int pos)
+{
+	int i, k = 0;
+	const int nfrags = skb_shinfo(skb)->nr_frags;
+
+	skb_shinfo(skb)->nr_frags = 0;
+	skb1->len		  = skb1->data_len = skb->len - len;
+	skb->len		  = len;
+	skb->data_len		  = len - pos;
+
+	for (i = 0; i < nfrags; i++) {
+		int size = skb_shinfo(skb)->frags[i].size;
+
+		if (pos + size > len) {
+			skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i];
+
+			if (pos < len) {
+				/* Split frag.
+				 * We have to variants in this case:
+				 * 1. Move all the frag to the second
+				 *    part, if it is possible. F.e.
+				 *    this approach is mandatory for TUX,
+				 *    where splitting is expensive.
+				 * 2. Split is accurately. We make this.
+				 */
+				get_page(skb_shinfo(skb)->frags[i].page);
+				skb_shinfo(skb1)->frags[0].page_offset += len - pos;
+				skb_shinfo(skb1)->frags[0].size -= len - pos;
+				skb_shinfo(skb)->frags[i].size	= len - pos;
+				skb_shinfo(skb)->nr_frags++;
+			}
+			k++;
+		} else
+			skb_shinfo(skb)->nr_frags++;
+		pos += size;
+	}
+	skb_shinfo(skb1)->nr_frags = k;
+}
+
+/**
+ * skb_split - Split fragmented skb to two parts at length len.
+ */
+void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
+{
+	int pos = skb_headlen(skb);
+
+	if (len < pos)	/* Split line is inside header. */
+		skb_split_inside_header(skb, skb1, len, pos);
+	else		/* Second chunk has no header, nothing to copy. */
+		skb_split_no_header(skb, skb1, len, pos);
+}
+
 void __init skb_init(void)
 {
 	skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
@@ -1300,3 +1398,4 @@
 EXPORT_SYMBOL(skb_queue_tail);
 EXPORT_SYMBOL(skb_unlink);
 EXPORT_SYMBOL(skb_append);
+EXPORT_SYMBOL(skb_split);
diff -Nru a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c	2004-06-23 19:04:28 -07:00
+++ b/net/core/sock.c	2004-06-23 19:04:28 -07:00
@@ -1147,6 +1147,8 @@
 	skb_queue_head_init(&sk->sk_write_queue);
 	skb_queue_head_init(&sk->sk_error_queue);
 
+	sk->sk_send_head	=	NULL;
+
 	init_timer(&sk->sk_timer);
 	
 	sk->sk_allocation	=	GFP_KERNEL;
@@ -1176,6 +1178,7 @@
 	sk->sk_peercred.pid 	=	0;
 	sk->sk_peercred.uid	=	-1;
 	sk->sk_peercred.gid	=	-1;
+	sk->sk_write_pending	=	0;
 	sk->sk_rcvlowat		=	1;
 	sk->sk_rcvtimeo		=	MAX_SCHEDULE_TIMEOUT;
 	sk->sk_sndtimeo		=	MAX_SCHEDULE_TIMEOUT;
diff -Nru a/net/core/stream.c b/net/core/stream.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/core/stream.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,190 @@
+/*
+ *     SUCS NET3:
+ *
+ *     Generic stream handling routines. These are generic for most
+ *     protocols. Even IP. Tonight 8-).
+ *     This is used because TCP, LLC (others too) layer all have mostly
+ *     identical sendmsg() and recvmsg() code.
+ *     So we (will) share it here.
+ *
+ *     Authors:        Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *                     (from old tcp.c code)
+ *                     Alan Cox <alan@redhat.com> (Borrowed comments 8-))
+ */
+
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/signal.h>
+#include <linux/tcp.h>
+#include <linux/wait.h>
+#include <net/sock.h>
+
+/**
+ * sk_stream_write_space - stream socket write_space callback.
+ * sk - socket
+ *
+ * FIXME: write proper description
+ */
+void sk_stream_write_space(struct sock *sk)
+{
+	struct socket *sock = sk->sk_socket;
+
+	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) {
+		clear_bit(SOCK_NOSPACE, &sock->flags);
+
+		if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+			wake_up_interruptible(sk->sk_sleep);
+		if (sock->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN))
+			sock_wake_async(sock, 2, POLL_OUT);
+	}
+}
+
+EXPORT_SYMBOL(sk_stream_write_space);
+
+/**
+ * sk_stream_wait_connect - Wait for a socket to get into the connected state
+ * @sk - sock to wait on
+ * @timeo_p - for how long to wait
+ *
+ * Must be called with the socket locked.
+ */
+int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
+{
+	struct task_struct *tsk = current;
+	DEFINE_WAIT(wait);
+
+	while (1) {
+		if (sk->sk_err)
+			return sock_error(sk);
+		if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV))
+			return -EPIPE;
+		if (!*timeo_p)
+			return -EAGAIN;
+		if (signal_pending(tsk))
+			return sock_intr_errno(*timeo_p);
+
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+		sk->sk_write_pending++;
+		if (sk_wait_event(sk, timeo_p,
+				  !((1 << sk->sk_state) & 
+				    ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))))
+			break;
+		finish_wait(sk->sk_sleep, &wait);
+		sk->sk_write_pending--;
+	}
+	return 0;
+}
+
+EXPORT_SYMBOL(sk_stream_wait_connect);
+
+/**
+ * sk_stream_closing - Return 1 if we still have things to send in our buffers.
+ * @sk - socket to verify
+ */
+static inline int sk_stream_closing(struct sock *sk)
+{
+	return (1 << sk->sk_state) &
+	       (TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK);
+}
+
+void sk_stream_wait_close(struct sock *sk, long timeout)
+{
+	if (timeout) {
+		DEFINE_WAIT(wait);
+
+		do {
+			prepare_to_wait(sk->sk_sleep, &wait,
+					TASK_INTERRUPTIBLE);
+			if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk)))
+				break;
+		} while (!signal_pending(current) && timeout);
+
+		finish_wait(sk->sk_sleep, &wait);
+	}
+}
+
+EXPORT_SYMBOL(sk_stream_wait_close);
+
+/**
+ * sk_stream_wait_memory - Wait for more memory for a socket
+ * @sk - socket to wait for memory
+ * @timeo_p - for how long
+ */
+int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
+{
+	int err = 0;
+	long vm_wait = 0;
+	long current_timeo = *timeo_p;
+	DEFINE_WAIT(wait);
+
+	if (sk_stream_memory_free(sk))
+		current_timeo = vm_wait = (net_random() % (HZ / 5)) + 2;
+
+	while (1) {
+		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
+
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+
+		if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
+			goto do_error;
+		if (!*timeo_p)
+			goto do_nonblock;
+		if (signal_pending(current))
+			goto do_interrupted;
+		clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
+		if (sk_stream_memory_free(sk) && !vm_wait)
+			break;
+
+		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+		sk->sk_write_pending++;
+		sk_wait_event(sk, &current_timeo, sk_stream_memory_free(sk) &&
+						  vm_wait);
+		sk->sk_write_pending--;
+
+		if (vm_wait) {
+			vm_wait -= current_timeo;
+			current_timeo = *timeo_p;
+			if (current_timeo != MAX_SCHEDULE_TIMEOUT &&
+			    (current_timeo -= vm_wait) < 0)
+				current_timeo = 0;
+			vm_wait = 0;
+		}
+		*timeo_p = current_timeo;
+	}
+out:
+	finish_wait(sk->sk_sleep, &wait);
+	return err;
+
+do_error:
+	err = -EPIPE;
+	goto out;
+do_nonblock:
+	err = -EAGAIN;
+	goto out;
+do_interrupted:
+	err = sock_intr_errno(*timeo_p);
+	goto out;
+}
+
+EXPORT_SYMBOL(sk_stream_wait_memory);
+
+void sk_stream_rfree(struct sk_buff *skb)
+{
+	struct sock *sk = skb->sk;
+
+	atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
+	sk->sk_forward_alloc += skb->truesize;
+}
+
+EXPORT_SYMBOL(sk_stream_rfree);
+
+int sk_stream_error(struct sock *sk, int flags, int err)
+{
+	if (err == -EPIPE)
+		err = sock_error(sk) ? : -EPIPE;
+	if (err == -EPIPE && !(flags & MSG_NOSIGNAL))
+		send_sig(SIGPIPE, current, 0);
+	return err;
+}
+
+EXPORT_SYMBOL(sk_stream_error);
diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c
--- a/net/econet/af_econet.c	2004-06-23 19:04:27 -07:00
+++ b/net/econet/af_econet.c	2004-06-23 19:04:27 -07:00
@@ -201,6 +201,7 @@
 	return 0;
 }
 
+#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
 /*
  *	Queue a transmit result for the user to be told about.
  */
@@ -227,6 +228,7 @@
 	if (sock_queue_rcv_skb(sk, skb) < 0)
 		kfree_skb(skb);
 }
+#endif
 
 #ifdef CONFIG_ECONET_NATIVE
 /*
@@ -255,10 +257,9 @@
 	struct ec_addr addr;
 	int err;
 	unsigned char port, cb;
+#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
 	struct sk_buff *skb;
 	struct ec_cb *eb;
-#ifdef CONFIG_ECONET_NATIVE
-	unsigned short proto = 0;
 #endif
 #ifdef CONFIG_ECONET_AUNUDP
 	struct msghdr udpmsg;
@@ -316,6 +317,8 @@
 	{
 		/* Real hardware Econet.  We're not worthy etc. */
 #ifdef CONFIG_ECONET_NATIVE
+		unsigned short proto = 0;
+
 		dev_hold(dev);
 		
 		skb = sock_alloc_send_skb(sk, len+LL_RESERVED_SPACE(dev), 
@@ -718,6 +721,7 @@
 #include <linux/smp_lock.h>
 SOCKOPS_WRAP(econet, PF_ECONET);
 
+#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
 /*
  *	Find the listening socket, if any, for the given data.
  */
@@ -761,9 +765,9 @@
 
 	return sock_queue_rcv_skb(sk, skb);
 }
+#endif
 
 #ifdef CONFIG_ECONET_AUNUDP
-
 /*
  *	Send an AUN protocol response. 
  */
diff -Nru a/net/ethernet/eth.c b/net/ethernet/eth.c
--- a/net/ethernet/eth.c	2004-06-23 19:04:27 -07:00
+++ b/net/ethernet/eth.c	2004-06-23 19:04:27 -07:00
@@ -164,6 +164,9 @@
 	skb->mac.raw=skb->data;
 	skb_pull(skb,ETH_HLEN);
 	eth= skb->mac.ethernet;
+#ifdef CONFIG_NET_CLS_ACT
+	skb->input_dev = dev;
+#endif
 	
 	if(*eth->h_dest&1)
 	{
diff -Nru a/net/ipv4/ah4.c b/net/ipv4/ah4.c
--- a/net/ipv4/ah4.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/ah4.c	2004-06-23 19:04:28 -07:00
@@ -74,12 +74,15 @@
 	}
 
 	spin_lock_bh(&x->lock);
-	err = xfrm_check_output(x, *pskb, AF_INET);
+	err = xfrm_state_check(x, *pskb);
 	if (err)
 		goto error;
 
 	iph = (*pskb)->nh.iph;
 	if (x->props.mode) {
+		err = xfrm4_tunnel_check_size(*pskb);
+		if (err)
+			goto error;
 		top_iph = (struct iphdr*)skb_push(*pskb, x->props.header_len);
 		top_iph->ihl = 5;
 		top_iph->version = 4;
diff -Nru a/net/ipv4/esp4.c b/net/ipv4/esp4.c
--- a/net/ipv4/esp4.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv4/esp4.c	2004-06-23 19:04:27 -07:00
@@ -11,8 +11,6 @@
 #include <net/icmp.h>
 #include <net/udp.h>
 
-#define MAX_SG_ONSTACK 4
-
 /* decapsulation data for use when post-processing */
 struct esp_decap_data {
 	xfrm_address_t	saddr;
@@ -49,19 +47,24 @@
 	}
 
 	spin_lock_bh(&x->lock);
-	err = xfrm_check_output(x, *pskb, AF_INET);
+	err = xfrm_state_check(x, *pskb);
 	if (err)
 		goto error;
-	err = -ENOMEM;
 
-	/* Strip IP header in transport mode. Save it. */
-	if (!x->props.mode) {
+	if (x->props.mode) {
+		err = xfrm4_tunnel_check_size(*pskb);
+		if (err)
+			goto error;
+	} else {
+		/* Strip IP header in transport mode. Save it. */
 		iph = (*pskb)->nh.iph;
 		memcpy(&tmp_iph, iph, iph->ihl*4);
 		__skb_pull(*pskb, iph->ihl*4);
 	}
 	/* Now skb is pure payload to encrypt */
 
+	err = -ENOMEM;
+
 	/* Round to block size */
 	clen = (*pskb)->len;
 
@@ -180,17 +183,16 @@
 		crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
 
 	do {
-		struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
-		struct scatterlist *sg = sgbuf;
+		struct scatterlist *sg = &esp->sgbuf[0];
 
-		if (unlikely(nfrags > MAX_SG_ONSTACK)) {
+		if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
 			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
 			if (!sg)
 				goto error;
 		}
 		skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen);
 		crypto_cipher_encrypt(tfm, sg, sg, clen);
-		if (unlikely(sg != sgbuf))
+		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
 	} while (0);
 
@@ -278,19 +280,18 @@
 
         {
 		u8 nexthdr[2];
-		struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
-		struct scatterlist *sg = sgbuf;
+		struct scatterlist *sg = &esp->sgbuf[0];
 		u8 workbuf[60];
 		int padlen;
 
-		if (unlikely(nfrags > MAX_SG_ONSTACK)) {
+		if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
 			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
 			if (!sg)
 				goto out;
 		}
 		skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen);
 		crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
-		if (unlikely(sg != sgbuf))
+		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
 
 		if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
diff -Nru a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
--- a/net/ipv4/ip_gre.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/ip_gre.c	2004-06-23 19:04:28 -07:00
@@ -643,13 +643,7 @@
 		skb->dev = tunnel->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
-#ifdef CONFIG_NETFILTER
-		nf_conntrack_put(skb->nfct);
-		skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#endif
-#endif
+		nf_reset(skb);
 		ipgre_ecn_decapsulate(iph, skb);
 		netif_rx(skb);
 		read_unlock(&ipgre_lock);
@@ -877,13 +871,7 @@
 		}
 	}
 
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
-#endif
+	nf_reset(skb);
 
 	IPTUNNEL_XMIT();
 	tunnel->recursion--;
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
--- a/net/ipv4/ip_input.c	2004-06-23 19:04:25 -07:00
+++ b/net/ipv4/ip_input.c	2004-06-23 19:04:25 -07:00
@@ -202,17 +202,13 @@
 
 #ifdef CONFIG_NETFILTER_DEBUG
 	nf_debug_ip_local_deliver(skb);
-	skb->nf_debug = 0;
 #endif /*CONFIG_NETFILTER_DEBUG*/
 
 	__skb_pull(skb, ihl);
 
-#ifdef CONFIG_NETFILTER
 	/* Free reference early: we don't need it any more, and it may
            hold ip_conntrack module loaded indefinitely. */
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#endif /*CONFIG_NETFILTER*/
+	nf_reset(skb);
 
         /* Point into the IP datagram, just past the header. */
         skb->h.raw = skb->data;
diff -Nru a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
--- a/net/ipv4/ip_output.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/ip_output.c	2004-06-23 19:04:29 -07:00
@@ -702,17 +702,6 @@
 	return 0;
 }
 
-static inline int
-skb_can_coalesce(struct sk_buff *skb, int i, struct page *page, int off)
-{
-	if (i) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
-		return page == frag->page &&
-			off == frag->page_offset+frag->size;
-	}
-	return 0;
-}
-
 static inline unsigned int
 csum_page(struct page *page, int offset, int copy)
 {
diff -Nru a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
--- a/net/ipv4/ip_sockglue.c	2004-06-23 19:04:26 -07:00
+++ b/net/ipv4/ip_sockglue.c	2004-06-23 19:04:26 -07:00
@@ -759,6 +759,7 @@
 				err = ip_mc_join_group(sk, &mreq);
 				if (err)
 					break;
+				greqs.gsr_interface = mreq.imr_ifindex;
 				omode = MCAST_INCLUDE;
 				add = 1;
 			} else /* MCAST_LEAVE_SOURCE_GROUP */ {
diff -Nru a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
--- a/net/ipv4/ipcomp.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/ipcomp.c	2004-06-23 19:04:28 -07:00
@@ -164,12 +164,16 @@
 	}
 
 	spin_lock_bh(&x->lock);
-	err = xfrm_check_output(x, *pskb, AF_INET);
+	err = xfrm_state_check(x, *pskb);
 	if (err)
 		goto error;
 
-	/* Don't bother compressing */
-	if (!x->props.mode) {
+	if (x->props.mode) {
+		err = xfrm4_tunnel_check_size(*pskb);
+		if (err)
+			goto error;
+	} else {
+		/* Don't bother compressing */
 		iph = (*pskb)->nh.iph;
 		hdr_len = iph->ihl * 4;
 	}
diff -Nru a/net/ipv4/ipip.c b/net/ipv4/ipip.c
--- a/net/ipv4/ipip.c	2004-06-23 19:04:29 -07:00
+++ b/net/ipv4/ipip.c	2004-06-23 19:04:29 -07:00
@@ -497,13 +497,7 @@
 		skb->dev = tunnel->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
-#ifdef CONFIG_NETFILTER
-		nf_conntrack_put(skb->nfct);
-		skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#endif
-#endif
+		nf_reset(skb);
 		ipip_ecn_decapsulate(iph, skb);
 		netif_rx(skb);
 		read_unlock(&ipip_lock);
@@ -648,13 +642,7 @@
 	if ((iph->ttl = tiph->ttl) == 0)
 		iph->ttl	=	old_iph->ttl;
 
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
-#endif
+	nf_reset(skb);
 
 	IPTUNNEL_XMIT();
 	tunnel->recursion--;
diff -Nru a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
--- a/net/ipv4/ipmr.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv4/ipmr.c	2004-06-23 19:04:27 -07:00
@@ -1105,10 +1105,7 @@
 	skb->h.ipiph = skb->nh.iph;
 	skb->nh.iph = iph;
 	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#endif
+	nf_reset(skb);
 }
 
 static inline int ipmr_forward_finish(struct sk_buff *skb)
@@ -1461,10 +1458,7 @@
 	skb->dst = NULL;
 	((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
 	((struct net_device_stats*)reg_dev->priv)->rx_packets++;
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#endif
+	nf_reset(skb);
 	netif_rx(skb);
 	dev_put(reg_dev);
 	return 0;
@@ -1520,10 +1514,7 @@
 	((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
 	((struct net_device_stats*)reg_dev->priv)->rx_packets++;
 	skb->dst = NULL;
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#endif
+	nf_reset(skb);
 	netif_rx(skb);
 	dev_put(reg_dev);
 	return 0;
diff -Nru a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
--- a/net/ipv4/netfilter/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/netfilter/Kconfig	2004-06-23 19:04:28 -07:00
@@ -603,5 +603,29 @@
 	  <file:Documentation/modules.txt>.  If unsure, say `N'.
 	  help
 
+config IP_NF_MATCH_ADDRTYPE
+	tristate  'address type match support'
+	depends on IP_NF_IPTABLES
+	help
+	  This option allows you to match what routing thinks of an address,
+	  eg. UNICAST, LOCAL, BROADCAST, ...
+	
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
+config IP_NF_MATCH_REALM
+	tristate  'realm match support'
+	depends on IP_NF_IPTABLES
+	select NET_CLS_ROUTE
+	help
+	  This option adds a `realm' match, which allows you to use the realm
+	  key from the routing subsytem inside iptables.
+	
+	  This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option 
+	  in tc world.
+	
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
 endmenu
 
diff -Nru a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
--- a/net/ipv4/netfilter/Makefile	2004-06-23 19:04:26 -07:00
+++ b/net/ipv4/netfilter/Makefile	2004-06-23 19:04:26 -07:00
@@ -64,6 +64,8 @@
 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
+obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
 
 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
 
diff -Nru a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c	2004-06-23 19:04:27 -07:00
@@ -107,7 +107,7 @@
 		exp->mask.dst.u.tcp.port = 0xFFFF;
 
 		exp_amanda_info = &exp->help.exp_amanda_info;
-		exp_amanda_info->offset = data - amanda_buffer;
+		exp_amanda_info->offset = tmp - amanda_buffer;
 		exp_amanda_info->port   = port;
 		exp_amanda_info->len    = len;
 
diff -Nru a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
--- a/net/ipv4/netfilter/ip_conntrack_core.c	2004-06-23 19:04:24 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_core.c	2004-06-23 19:04:24 -07:00
@@ -28,6 +28,7 @@
 #include <linux/proc_fs.h>
 #include <linux/vmalloc.h>
 #include <net/checksum.h>
+#include <net/ip.h>
 #include <linux/stddef.h>
 #include <linux/sysctl.h>
 #include <linux/slab.h>
@@ -173,13 +174,12 @@
 destroy_expect(struct ip_conntrack_expect *exp)
 {
 	DEBUGP("destroy_expect(%p) use=%d\n", exp, atomic_read(&exp->use));
-	IP_NF_ASSERT(atomic_read(&exp->use));
+	IP_NF_ASSERT(atomic_read(&exp->use) == 0);
 	IP_NF_ASSERT(!timer_pending(&exp->timeout));
 
 	kfree(exp);
 }
 
-
 inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
 {
 	IP_NF_ASSERT(exp);
@@ -715,7 +715,6 @@
 		DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
 			conntrack, expected);
 		/* Welcome, Mr. Bond.  We've been expecting you... */
-		IP_NF_ASSERT(master_ct(conntrack));
 		__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
 		conntrack->master = expected;
 		expected->sibling = conntrack;
@@ -948,9 +947,8 @@
 	atomic_set(&new->use, 1);
 
 	/* add to expected list for this connection */
-	list_add(&new->expected_list, &related_to->sibling_list);
+	list_add_tail(&new->expected_list, &related_to->sibling_list);
 	/* add to global list of expectations */
-
 	list_prepend(&ip_conntrack_expect_list, &new->list);
 	/* add and start timer if required */
 	if (related_to->helper->timeout) {
@@ -1004,7 +1002,6 @@
 
 	} else if (related_to->helper->max_expected && 
 		   related_to->expecting >= related_to->helper->max_expected) {
-		struct list_head *cur_item;
 		/* old == NULL */
 		if (!(related_to->helper->flags & 
 		      IP_CT_HELPER_F_REUSE_EXPECT)) {
@@ -1030,21 +1027,14 @@
 		       NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
  
 		/* choose the the oldest expectation to evict */
-		list_for_each(cur_item, &related_to->sibling_list) { 
-			struct ip_conntrack_expect *cur;
-
-			cur = list_entry(cur_item, 
-					 struct ip_conntrack_expect,
-					 expected_list);
-			if (cur->sibling == NULL) {
-				old = cur;
+		list_for_each_entry(old, &related_to->sibling_list, 
+		                                      expected_list)
+			if (old->sibling == NULL)
 				break;
-			}
-		}
 
-		/* (!old) cannot happen, since related_to->expecting is the
-		 * number of unconfirmed expects */
-		IP_NF_ASSERT(old);
+		/* We cannot fail since related_to->expecting is the number
+		 * of unconfirmed expectations */
+		IP_NF_ASSERT(old && old->sibling == NULL);
 
 		/* newnat14 does not reuse the real allocated memory
 		 * structures but rather unexpects the old and
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	2004-06-23 19:04:26 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-06-23 19:04:26 -07:00
@@ -24,6 +24,7 @@
 #include <linux/sysctl.h>
 #endif
 #include <net/checksum.h>
+#include <net/ip.h>
 
 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
@@ -502,7 +503,7 @@
 	if (ret < 0)
 		goto cleanup_nothing;
 
-	proc = proc_net_create("ip_conntrack",0,list_conntracks);
+	proc = proc_net_create("ip_conntrack", 0440, list_conntracks);
 	if (!proc) goto cleanup_init;
 	proc->owner = THIS_MODULE;
 
diff -Nru a/net/ipv4/netfilter/ip_fw_compat_redir.c b/net/ipv4/netfilter/ip_fw_compat_redir.c
--- a/net/ipv4/netfilter/ip_fw_compat_redir.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/netfilter/ip_fw_compat_redir.c	2004-06-23 19:04:28 -07:00
@@ -22,6 +22,7 @@
 #include <linux/udp.h>
 #include <linux/tcp.h>
 #include <net/checksum.h>
+#include <net/ip.h>
 #include <linux/timer.h>
 #include <linux/netdevice.h>
 #include <linux/if.h>
diff -Nru a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
--- a/net/ipv4/netfilter/ip_nat_core.c	2004-06-23 19:04:25 -07:00
+++ b/net/ipv4/netfilter/ip_nat_core.c	2004-06-23 19:04:25 -07:00
@@ -528,6 +528,7 @@
 	MUST_BE_WRITE_LOCKED(&ip_nat_lock);
 	IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
 		     || hooknum == NF_IP_POST_ROUTING
+		     || hooknum == NF_IP_LOCAL_IN
 		     || hooknum == NF_IP_LOCAL_OUT);
 	IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
 	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
@@ -816,7 +817,7 @@
 
 		/* Have to grab read lock before sibling_list traversal */
 		READ_LOCK(&ip_conntrack_lock);
-		list_for_each(cur_item, &ct->sibling_list) { 
+		list_for_each_prev(cur_item, &ct->sibling_list) { 
 			exp = list_entry(cur_item, struct ip_conntrack_expect, 
 					 expected_list);
 					 
@@ -899,10 +900,10 @@
 
 	/* Must be RELATED */
 	IP_NF_ASSERT((*pskb)->nfct
-		     - (struct ip_conntrack *)(*pskb)->nfct->master
+		     - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos
 		     == IP_CT_RELATED
 		     || (*pskb)->nfct
-		     - (struct ip_conntrack *)(*pskb)->nfct->master
+		     - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos
 		     == IP_CT_RELATED+IP_CT_IS_REPLY);
 
 	/* Redirects on non-null nats must be dropped, else they'll
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/netfilter/ip_nat_standalone.c	2004-06-23 19:04:28 -07:00
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/proc_fs.h>
+#include <net/ip.h>
 #include <net/checksum.h>
 #include <linux/spinlock.h>
 
diff -Nru a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
--- a/net/ipv4/netfilter/ip_tables.c	2004-06-23 19:04:26 -07:00
+++ b/net/ipv4/netfilter/ip_tables.c	2004-06-23 19:04:26 -07:00
@@ -1731,6 +1731,15 @@
 	return 0;
 }
 
+static inline int print_target(const struct ipt_target *t,
+                               off_t start_offset, char *buffer, int length,
+                               off_t *pos, unsigned int *count)
+{
+	if (t == &ipt_standard_target || t == &ipt_error_target)
+		return 0;
+	return print_name((char *)t, start_offset, buffer, length, pos, count);
+}
+
 static int ipt_get_tables(char *buffer, char **start, off_t offset, int length)
 {
 	off_t pos = 0;
@@ -1757,7 +1766,7 @@
 	if (down_interruptible(&ipt_mutex) != 0)
 		return 0;
 
-	LIST_FIND(&ipt_target, print_name, void *,
+	LIST_FIND(&ipt_target, print_target, struct ipt_target *,
 		  offset, buffer, length, &pos, &count);
 	
 	up(&ipt_mutex);
diff -Nru a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/ipv4/netfilter/ipt_CLASSIFY.c
--- a/net/ipv4/netfilter/ipt_CLASSIFY.c	2004-06-23 19:04:25 -07:00
+++ b/net/ipv4/netfilter/ipt_CLASSIFY.c	2004-06-23 19:04:25 -07:00
@@ -54,15 +54,17 @@
 		return 0;
 	}
 	
-	if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
-		printk(KERN_ERR "CLASSIFY: only valid in POST_ROUTING.\n");
+	if (hook_mask & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
+	                  (1 << NF_IP_POST_ROUTING))) {
+		printk(KERN_ERR "CLASSIFY: only valid in LOCAL_OUT, FORWARD "
+		                "and POST_ROUTING.\n");
 		return 0;
 	}
 
 	if (strcmp(tablename, "mangle") != 0) {
-		printk(KERN_WARNING "CLASSIFY: can only be called from "
-		                    "\"mangle\" table, not \"%s\".\n",
-		                    tablename);
+		printk(KERN_ERR "CLASSIFY: can only be called from "
+		                "\"mangle\" table, not \"%s\".\n",
+		                tablename);
 		return 0;
 	}
 
diff -Nru a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-06-23 19:04:27 -07:00
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/netfilter.h>
 #include <net/protocol.h>
+#include <net/ip.h>
 #include <net/checksum.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
diff -Nru a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
--- a/net/ipv4/netfilter/ipt_REJECT.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/netfilter/ipt_REJECT.c	2004-06-23 19:04:28 -07:00
@@ -142,12 +142,8 @@
 	nskb->dst = &rt->u.dst;
 
 	/* This packet will not be the same as the other: clear nf fields */
-	nf_conntrack_put(nskb->nfct);
-	nskb->nfct = NULL;
+	nf_reset(nskb);
 	nskb->nfcache = 0;
-#ifdef CONFIG_NETFILTER_DEBUG
-	nskb->nf_debug = 0;
-#endif
 	nskb->nfmark = 0;
 #ifdef CONFIG_BRIDGE_NETFILTER
 	nf_bridge_put(nskb->nf_bridge);
diff -Nru a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/ipv4/netfilter/ipt_addrtype.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,77 @@
+/*
+ *  iptables module to match inet_addr_type() of an ip.
+ *
+ *  Copyright (c) 2004 Patrick McHardy <kaber@trash.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
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <net/route.h>
+
+#include <linux/netfilter_ipv4/ipt_addrtype.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("iptables addrtype match");
+
+static inline int match_type(u_int32_t addr, u_int16_t mask)
+{
+	return !!(mask & (1 << inet_addr_type(addr)));
+}
+
+static int match(const struct sk_buff *skb, const struct net_device *in,
+		 const struct net_device *out, const void *matchinfo,
+		 int offset, int *hotdrop)
+{
+	const struct ipt_addrtype_info *info = matchinfo;
+	const struct iphdr *iph = skb->nh.iph;
+	int ret = 1;
+
+	if (info->source)
+		ret &= match_type(iph->saddr, info->source)^info->invert_source;
+	if (info->dest)
+		ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
+	
+	return ret;
+}
+
+static int checkentry(const char *tablename, const struct ipt_ip *ip,
+		      void *matchinfo, unsigned int matchsize,
+		      unsigned int hook_mask)
+{
+	if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
+		printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
+		       matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
+		return 0;
+	}
+
+	return 1;
+}
+
+static struct ipt_match addrtype_match = {
+	.name		= "addrtype",
+	.match		= match,
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE
+};
+
+static int __init init(void)
+{
+	return ipt_register_match(&addrtype_match);
+}
+
+static void __exit fini(void)
+{
+	ipt_unregister_match(&addrtype_match);
+}
+
+module_init(init);
+module_exit(fini);
diff -Nru a/net/ipv4/netfilter/ipt_helper.c b/net/ipv4/netfilter/ipt_helper.c
--- a/net/ipv4/netfilter/ipt_helper.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/netfilter/ipt_helper.c	2004-06-23 19:04:28 -07:00
@@ -41,17 +41,17 @@
 	struct ip_conntrack_expect *exp;
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
-	int ret = 0;
+	int ret = info->invert;
 	
 	ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
 	if (!ct) {
 		DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
-		return 0;
+		return ret;
 	}
 
 	if (!ct->master) {
 		DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
-		return 0;
+		return ret;
 	}
 
 	exp = ct->master;
@@ -71,8 +71,11 @@
 	DEBUGP("master's name = %s , info->name = %s\n", 
 		exp->expectant->helper->name, info->name);
 
-	ret = !strncmp(exp->expectant->helper->name, info->name, 
-	               strlen(exp->expectant->helper->name)) ^ info->invert;
+	if (info->name[0] == '\0')
+		ret ^= 1;
+	else
+		ret ^= !strncmp(exp->expectant->helper->name, info->name, 
+		                strlen(exp->expectant->helper->name));
 out_unlock:
 	READ_UNLOCK(&ip_conntrack_lock);
 	return ret;
@@ -92,10 +95,6 @@
 	if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
 		return 0;
 
-	/* verify that we actually should match anything */
-	if ( strlen(info->name) == 0 )
-		return 0;
-	
 	return 1;
 }
 
@@ -108,7 +107,6 @@
 
 static int __init init(void)
 {
-	need_ip_conntrack();
 	return ipt_register_match(&helper_match);
 }
 
diff -Nru a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
--- a/net/ipv4/netfilter/ipt_owner.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/netfilter/ipt_owner.c	2004-06-23 19:04:28 -07:00
@@ -184,7 +184,15 @@
 		       IPT_ALIGN(sizeof(struct ipt_owner_info)));
 		return 0;
 	}
-
+#ifdef CONFIG_SMP
+	/* files->file_lock can not be used in a BH */
+	if (((struct ipt_owner_info *)matchinfo)->match
+	    & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) {
+		printk("ipt_owner: pid, sid and command matching is broken "
+		       "on SMP.\n");
+		return 0;
+	}
+#endif
 	return 1;
 }
 
diff -Nru a/net/ipv4/netfilter/ipt_realm.c b/net/ipv4/netfilter/ipt_realm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/ipv4/netfilter/ipt_realm.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,76 @@
+/* IP tables module for matching the routing realm
+ *
+ * $Id: ipt_realm.c,v 1.3 2004/03/05 13:25:40 laforge Exp $
+ *
+ * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <net/route.h>
+
+#include <linux/netfilter_ipv4/ipt_realm.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("iptables realm match");
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      int *hotdrop)
+{
+	const struct ipt_realm_info *info = matchinfo;
+	struct dst_entry *dst = skb->dst;
+    
+	return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
+}
+
+static int check(const char *tablename,
+                 const struct ipt_ip *ip,
+                 void *matchinfo,
+                 unsigned int matchsize,
+                 unsigned int hook_mask)
+{
+	if (hook_mask
+	    & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
+	        (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) {
+		printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
+		       "LOCAL_IN or FORWARD.\n");
+		return 0;
+	}
+	if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) {
+		printk("ipt_realm: invalid matchsize.\n");
+		return 0;
+	}
+	return 1;
+}
+
+static struct ipt_match realm_match = {
+	.name		= "realm",
+	.match		= match, 
+	.checkentry	= check,
+	.me		= THIS_MODULE
+};
+
+static int __init init(void)
+{
+	return ipt_register_match(&realm_match);
+}
+
+static void __exit fini(void)
+{
+	ipt_unregister_match(&realm_match);
+}
+
+module_init(init);
+module_exit(fini);
diff -Nru a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
--- a/net/ipv4/netfilter/iptable_mangle.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/netfilter/iptable_mangle.c	2004-06-23 19:04:28 -07:00
@@ -173,7 +173,9 @@
 	if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
 	    && ((*pskb)->nh.iph->saddr != saddr
 		|| (*pskb)->nh.iph->daddr != daddr
+#ifdef CONFIG_IP_ROUTE_FWMARK
 		|| (*pskb)->nfmark != nfmark
+#endif
 		|| (*pskb)->nh.iph->tos != tos))
 		return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
 
diff -Nru a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
--- a/net/ipv4/netfilter/iptable_raw.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/netfilter/iptable_raw.c	2004-06-23 19:04:28 -07:00
@@ -32,43 +32,70 @@
 	struct ipt_replace repl;
 	struct ipt_standard entries[2];
 	struct ipt_error term;
-} initial_table __initdata
-= { { "raw", RAW_VALID_HOOKS, 3,
-      sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
-      { [NF_IP_PRE_ROUTING] 0,
-	[NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
-      { [NF_IP_PRE_ROUTING] 0,
-	[NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
-      0, NULL, { } },
-    {
-	    /* PRE_ROUTING */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* LOCAL_OUT */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } }
-    },
-    /* ERROR */
-    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-	0,
-	sizeof(struct ipt_entry),
-	sizeof(struct ipt_error),
-	0, { 0, 0 }, { } },
-      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
-	  { } },
-	"ERROR"
-      }
-    }
+} initial_table __initdata = {
+	.repl = {
+		.name = "raw", 
+		.valid_hooks = RAW_VALID_HOOKS, 
+		.num_entries = 3,
+		.size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
+		.hook_entry = { 
+			[NF_IP_PRE_ROUTING] = 0,
+			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) },
+		.underflow = { 
+			[NF_IP_PRE_ROUTING] = 0,
+			[NF_IP_LOCAL_OUT]  = sizeof(struct ipt_standard) },
+	},
+	.entries = {
+	     /* PRE_ROUTING */
+	     { 
+		     .entry = { 
+			     .target_offset = sizeof(struct ipt_entry),
+			     .next_offset = sizeof(struct ipt_standard),
+		     },
+		     .target = { 
+			  .target = { 
+				  .u = {
+					  .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
+				  },
+			  },
+			  .verdict = -NF_ACCEPT - 1,
+		     },
+	     },
+
+	     /* LOCAL_OUT */
+	     {
+		     .entry = {
+			     .target_offset = sizeof(struct ipt_entry),
+			     .next_offset = sizeof(struct ipt_standard),
+		     },
+		     .target = {
+			     .target = {
+				     .u = {
+					     .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
+				     },
+			     },
+			     .verdict = -NF_ACCEPT - 1,
+		     },
+	     },
+	},
+	/* ERROR */
+	.term = {
+		.entry = {
+			.target_offset = sizeof(struct ipt_entry),
+			.next_offset = sizeof(struct ipt_error),
+		},
+		.target = {
+			.target = {
+				.u = {
+					.user = {
+						.target_size = IPT_ALIGN(sizeof(struct ipt_error_target)), 
+						.name = IPT_ERROR_TARGET,
+					},
+				},
+			},
+			.errorname = "ERROR",
+		},
+	}
 };
 
 static struct ipt_table packet_raw = { 
diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c	2004-06-23 19:04:26 -07:00
+++ b/net/ipv4/tcp.c	2004-06-23 19:04:26 -07:00
@@ -276,7 +276,7 @@
 
 atomic_t tcp_orphan_count = ATOMIC_INIT(0);
 
-int sysctl_tcp_default_win_scale;
+int sysctl_tcp_default_win_scale = 7;
 
 int sysctl_tcp_mem[3];
 int sysctl_tcp_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
@@ -333,7 +333,7 @@
 suppress_allocation:
 
 	if (!kind) {
-		tcp_moderate_sndbuf(sk);
+		sk_stream_moderate_sndbuf(sk);
 
 		/* Fail only if socket is _under_ its sndbuf.
 		 * In this case we cannot block, so that we have to fail.
@@ -360,14 +360,6 @@
 	}
 }
 
-void tcp_rfree(struct sk_buff *skb)
-{
-	struct sock *sk = skb->sk;
-
-	atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
-	sk->sk_forward_alloc += skb->truesize;
-}
-
 /*
  * LISTEN is a special case for poll..
  */
@@ -447,7 +439,7 @@
 			mask |= POLLIN | POLLRDNORM;
 
 		if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
-			if (tcp_wspace(sk) >= tcp_min_write_space(sk)) {
+			if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
 				mask |= POLLOUT | POLLWRNORM;
 			} else {  /* send SIGIO later */
 				set_bit(SOCK_ASYNC_NOSPACE,
@@ -458,7 +450,7 @@
 				 * wspace test but before the flags are set,
 				 * IO signal will be lost.
 				 */
-				if (tcp_wspace(sk) >= tcp_min_write_space(sk))
+				if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
 					mask |= POLLOUT | POLLWRNORM;
 			}
 		}
@@ -469,24 +461,6 @@
 	return mask;
 }
 
-/*
- *	TCP socket write_space callback.
- */
-void tcp_write_space(struct sock *sk)
-{
-	struct socket *sock = sk->sk_socket;
-
-	if (tcp_wspace(sk) >= tcp_min_write_space(sk) && sock) {
-		clear_bit(SOCK_NOSPACE, &sock->flags);
-
-		if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-			wake_up_interruptible(sk->sk_sleep);
-
-		if (sock->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN))
-			sock_wake_async(sock, 2, POLL_OUT);
-	}
-}
-
 int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
@@ -654,118 +628,6 @@
 	BUG_TRAP(!sk->sk_ack_backlog);
 }
 
-/*
- *	Wait for a socket to get into the connected state
- *
- *	Note: Must be called with the socket locked.
- */
-static int wait_for_tcp_connect(struct sock *sk, int flags, long *timeo_p)
-{
-	struct tcp_opt *tp = tcp_sk(sk);
-	struct task_struct *tsk = current;
-	DEFINE_WAIT(wait);
-
-	while ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
-		if (sk->sk_err)
-			return sock_error(sk);
-		if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV))
-			return -EPIPE;
-		if (!*timeo_p)
-			return -EAGAIN;
-		if (signal_pending(tsk))
-			return sock_intr_errno(*timeo_p);
-
-		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
-		tp->write_pending++;
-
-		release_sock(sk);
-		*timeo_p = schedule_timeout(*timeo_p);
-		lock_sock(sk);
-
-		finish_wait(sk->sk_sleep, &wait);
-		tp->write_pending--;
-	}
-	return 0;
-}
-
-static inline int tcp_memory_free(struct sock *sk)
-{
-	return sk->sk_wmem_queued < sk->sk_sndbuf;
-}
-
-/*
- *	Wait for more memory for a socket
- */
-static int wait_for_tcp_memory(struct sock *sk, long *timeo)
-{
-	struct tcp_opt *tp = tcp_sk(sk);
-	int err = 0;
-	long vm_wait = 0;
-	long current_timeo = *timeo;
-	DEFINE_WAIT(wait);
-
-	if (tcp_memory_free(sk))
-		current_timeo = vm_wait = (net_random() % (HZ / 5)) + 2;
-
-	for (;;) {
-		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
-
-		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
-
-		if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
-			goto do_error;
-		if (!*timeo)
-			goto do_nonblock;
-		if (signal_pending(current))
-			goto do_interrupted;
-		clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
-		if (tcp_memory_free(sk) && !vm_wait)
-			break;
-
-		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
-		tp->write_pending++;
-		release_sock(sk);
-		if (!tcp_memory_free(sk) || vm_wait)
-			current_timeo = schedule_timeout(current_timeo);
-		lock_sock(sk);
-		tp->write_pending--;
-
-		if (vm_wait) {
-			vm_wait -= current_timeo;
-			current_timeo = *timeo;
-			if (current_timeo != MAX_SCHEDULE_TIMEOUT &&
-			    (current_timeo -= vm_wait) < 0)
-				current_timeo = 0;
-			vm_wait = 0;
-		}
-		*timeo = current_timeo;
-	}
-out:
-	finish_wait(sk->sk_sleep, &wait);
-	return err;
-
-do_error:
-	err = -EPIPE;
-	goto out;
-do_nonblock:
-	err = -EAGAIN;
-	goto out;
-do_interrupted:
-	err = sock_intr_errno(*timeo);
-	goto out;
-}
-
-static inline int can_coalesce(struct sk_buff *skb, int i, struct page *page,
-			       int off)
-{
-	if (i) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
-		return page == frag->page &&
-		       off == frag->page_offset + frag->size;
-	}
-	return 0;
-}
-
 static inline void fill_page_desc(struct sk_buff *skb, int i,
 				  struct page *page, int off, int size)
 {
@@ -796,9 +658,9 @@
 	TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
 	TCP_SKB_CB(skb)->sacked = 0;
 	__skb_queue_tail(&sk->sk_write_queue, skb);
-	tcp_charge_skb(sk, skb);
-	if (!tp->send_head)
-		tp->send_head = skb;
+	sk_charge_skb(sk, skb);
+	if (!sk->sk_send_head)
+		sk->sk_send_head = skb;
 	else if (tp->nonagle&TCP_NAGLE_PUSH)
 		tp->nonagle &= ~TCP_NAGLE_PUSH; 
 }
@@ -816,7 +678,7 @@
 static inline void tcp_push(struct sock *sk, struct tcp_opt *tp, int flags,
 			    int mss_now, int nonagle)
 {
-	if (tp->send_head) {
+	if (sk->sk_send_head) {
 		struct sk_buff *skb = sk->sk_write_queue.prev;
 		if (!(flags & MSG_MORE) || forced_push(tp))
 			tcp_mark_push(tp, skb);
@@ -826,15 +688,6 @@
 	}
 }
 
-static int tcp_error(struct sock *sk, int flags, int err)
-{
-	if (err == -EPIPE)
-		err = sock_error(sk) ? : -EPIPE;
-	if (err == -EPIPE && !(flags & MSG_NOSIGNAL))
-		send_sig(SIGPIPE, current, 0);
-	return err;
-}
-
 static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset,
 			 size_t psize, int flags)
 {
@@ -846,7 +699,7 @@
 
 	/* Wait for a connection to finish. */
 	if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
-		if ((err = wait_for_tcp_connect(sk, 0, &timeo)) != 0)
+		if ((err = sk_stream_wait_connect(sk, &timeo)) != 0)
 			goto out_err;
 
 	clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
@@ -865,9 +718,9 @@
 		int offset = poffset % PAGE_SIZE;
 		int size = min_t(size_t, psize, PAGE_SIZE - offset);
 
-		if (!tp->send_head || (copy = mss_now - skb->len) <= 0) {
+		if (!sk->sk_send_head || (copy = mss_now - skb->len) <= 0) {
 new_segment:
-			if (!tcp_memory_free(sk))
+			if (!sk_stream_memory_free(sk))
 				goto wait_for_sndbuf;
 
 			skb = tcp_alloc_pskb(sk, 0, tp->mss_cache,
@@ -883,7 +736,7 @@
 			copy = size;
 
 		i = skb_shinfo(skb)->nr_frags;
-		if (can_coalesce(skb, i, page, offset)) {
+		if (skb_can_coalesce(skb, i, page, offset)) {
 			skb_shinfo(skb)->frags[i - 1].size += copy;
 		} else if (i < MAX_SKB_FRAGS) {
 			get_page(page);
@@ -913,7 +766,7 @@
 		if (forced_push(tp)) {
 			tcp_mark_push(tp, skb);
 			__tcp_push_pending_frames(sk, tp, mss_now, TCP_NAGLE_PUSH);
-		} else if (skb == tp->send_head)
+		} else if (skb == sk->sk_send_head)
 			tcp_push_one(sk, mss_now);
 		continue;
 
@@ -923,7 +776,7 @@
 		if (copied)
 			tcp_push(sk, tp, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
 
-		if ((err = wait_for_tcp_memory(sk, &timeo)) != 0)
+		if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
 			goto do_error;
 
 		mss_now = tcp_current_mss(sk, !(flags&MSG_OOB));
@@ -938,7 +791,7 @@
 	if (copied)
 		goto out;
 out_err:
-	return tcp_error(sk, flags, err);
+	return sk_stream_error(sk, flags, err);
 }
 
 ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset,
@@ -966,53 +819,6 @@
 #define TCP_PAGE(sk)	(inet_sk(sk)->sndmsg_page)
 #define TCP_OFF(sk)	(inet_sk(sk)->sndmsg_off)
 
-static inline int tcp_copy_to_page(struct sock *sk, char __user *from,
-				   struct sk_buff *skb, struct page *page,
-				   int off, int copy)
-{
-	int err = 0;
-	unsigned int csum;
-
-	if (skb->ip_summed == CHECKSUM_NONE) {
-		csum = csum_and_copy_from_user(from, page_address(page) + off,
-				       copy, 0, &err);
-		if (err) return err;
-		skb->csum = csum_block_add(skb->csum, csum, skb->len);
-	} else {
-		if (copy_from_user(page_address(page) + off, from, copy))
-			return -EFAULT;
-	}
-
-	skb->len += copy;
-	skb->data_len += copy;
-	skb->truesize += copy;
-	sk->sk_wmem_queued += copy;
-	sk->sk_forward_alloc -= copy;
-	return 0;
-}
-
-static inline int skb_add_data(struct sk_buff *skb, char __user *from, int copy)
-{
-	int err = 0;
-	unsigned int csum;
-	int off = skb->len;
-
-	if (skb->ip_summed == CHECKSUM_NONE) {
-		csum = csum_and_copy_from_user(from, skb_put(skb, copy),
-				       copy, 0, &err);
-		if (!err) {
-			skb->csum = csum_block_add(skb->csum, csum, off);
-			return 0;
-		}
-	} else {
-		if (!copy_from_user(skb_put(skb, copy), from, copy))
-			return 0;
-	}
-
-	__skb_trim(skb, off);
-	return -EFAULT;
-}
-
 static inline int select_size(struct sock *sk, struct tcp_opt *tp)
 {
 	int tmp = tp->mss_cache_std;
@@ -1046,7 +852,7 @@
 
 	/* Wait for a connection to finish. */
 	if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
-		if ((err = wait_for_tcp_connect(sk, flags, &timeo)) != 0)
+		if ((err = sk_stream_wait_connect(sk, &timeo)) != 0)
 			goto out_err;
 
 	/* This should be in poll */
@@ -1074,14 +880,14 @@
 
 			skb = sk->sk_write_queue.prev;
 
-			if (!tp->send_head ||
+			if (!sk->sk_send_head ||
 			    (copy = mss_now - skb->len) <= 0) {
 
 new_segment:
 				/* Allocate new segment. If the interface is SG,
 				 * allocate skb fitting to single page.
 				 */
-				if (!tcp_memory_free(sk))
+				if (!sk_stream_memory_free(sk))
 					goto wait_for_sndbuf;
 
 				skb = tcp_alloc_pskb(sk, select_size(sk, tp),
@@ -1118,7 +924,7 @@
 				struct page *page = TCP_PAGE(sk);
 				int off = TCP_OFF(sk);
 
-				if (can_coalesce(skb, i, page, off) &&
+				if (skb_can_coalesce(skb, i, page, off) &&
 				    off != PAGE_SIZE) {
 					/* We can extend the last page
 					 * fragment. */
@@ -1156,7 +962,7 @@
 
 				/* Time to copy data. We are close to
 				 * the end! */
-				err = tcp_copy_to_page(sk, from, skb, page,
+				err = skb_copy_to_page(sk, from, skb, page,
 						       off, copy);
 				if (err) {
 					/* If this page was new, give it to the
@@ -1203,7 +1009,7 @@
 			if (forced_push(tp)) {
 				tcp_mark_push(tp, skb);
 				__tcp_push_pending_frames(sk, tp, mss_now, TCP_NAGLE_PUSH);
-			} else if (skb == tp->send_head)
+			} else if (skb == sk->sk_send_head)
 				tcp_push_one(sk, mss_now);
 			continue;
 
@@ -1213,7 +1019,7 @@
 			if (copied)
 				tcp_push(sk, tp, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
 
-			if ((err = wait_for_tcp_memory(sk, &timeo)) != 0)
+			if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
 				goto do_error;
 
 			mss_now = tcp_current_mss(sk, !(flags&MSG_OOB));
@@ -1229,17 +1035,17 @@
 
 do_fault:
 	if (!skb->len) {
-		if (tp->send_head == skb)
-			tp->send_head = NULL;
+		if (sk->sk_send_head == skb)
+			sk->sk_send_head = NULL;
 		__skb_unlink(skb, skb->list);
-		tcp_free_skb(sk, skb);
+		sk_stream_free_skb(sk, skb);
 	}
 
 do_error:
 	if (copied)
 		goto out;
 out_err:
-	err = tcp_error(sk, flags, err);
+	err = sk_stream_error(sk, flags, err);
 	TCP_CHECK_TIMER(sk);
 	release_sock(sk);
 	return err;
@@ -1828,17 +1634,6 @@
 	}
 }
 
-
-/*
- *	Return 1 if we still have things to send in our buffers.
- */
-
-static inline int closing(struct sock *sk)
-{
-	return (1 << sk->sk_state) &
-	       (TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK);
-}
-
 static __inline__ void tcp_kill_sk_queues(struct sock *sk)
 {
 	/* First the read buffer. */
@@ -1981,22 +1776,7 @@
 		tcp_send_fin(sk);
 	}
 
-	if (timeout) {
-		struct task_struct *tsk = current;
-		DEFINE_WAIT(wait);
-
-		do {
-			prepare_to_wait(sk->sk_sleep, &wait,
-					TASK_INTERRUPTIBLE);
-			if (!closing(sk))
-				break;
-			release_sock(sk);
-			timeout = schedule_timeout(timeout);
-			lock_sock(sk);
-		} while (!signal_pending(tsk) && timeout);
-
-		finish_wait(sk->sk_sleep, &wait);
-	}
+	sk_stream_wait_close(sk, timeout);
 
 adjudge_to_death:
 	/* It is the last release_sock in its life. It will remove backlog. */
@@ -2127,7 +1907,7 @@
 	tcp_set_ca_state(tp, TCP_CA_Open);
 	tcp_clear_retrans(tp);
 	tcp_delack_init(tp);
-	tp->send_head = NULL;
+	sk->sk_send_head = NULL;
 	tp->saw_tstamp = 0;
 	tcp_sack_reset(tp);
 	__sk_dst_reset(sk);
@@ -2635,4 +2415,3 @@
 EXPORT_SYMBOL(tcp_sockets_allocated);
 EXPORT_SYMBOL(tcp_statistics);
 EXPORT_SYMBOL(tcp_timewait_cachep);
-EXPORT_SYMBOL(tcp_write_space);
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/tcp_input.c	2004-06-23 19:04:28 -07:00
@@ -90,7 +90,7 @@
 int sysctl_tcp_westwood;
 int sysctl_tcp_vegas_cong_avoid;
 
-int sysctl_tcp_moderate_rcvbuf;
+int sysctl_tcp_moderate_rcvbuf = 1;
 
 /* Default values of the Vegas variables, in fixed-point representation
  * with V_PARAM_SHIFT bits to the right of the binary point.
@@ -99,7 +99,7 @@
 int sysctl_tcp_vegas_alpha = 1<<V_PARAM_SHIFT;
 int sysctl_tcp_vegas_beta  = 3<<V_PARAM_SHIFT;
 int sysctl_tcp_vegas_gamma = 1<<V_PARAM_SHIFT;
-int sysctl_tcp_bic;
+int sysctl_tcp_bic = 1;
 int sysctl_tcp_bic_fast_convergence = 1;
 int sysctl_tcp_bic_low_window = 14;
 
@@ -1009,7 +1009,7 @@
 		if (after(end_seq, tp->high_seq))
 			flag |= FLAG_DATA_LOST;
 
-		for_retrans_queue(skb, sk, tp) {
+		sk_stream_for_retrans_queue(skb, sk) {
 			u8 sacked = TCP_SKB_CB(skb)->sacked;
 			int in_sack;
 
@@ -1113,7 +1113,7 @@
 	if (lost_retrans && tp->ca_state == TCP_CA_Recovery) {
 		struct sk_buff *skb;
 
-		for_retrans_queue(skb, sk, tp) {
+		sk_stream_for_retrans_queue(skb, sk) {
 			if (after(TCP_SKB_CB(skb)->seq, lost_retrans))
 				break;
 			if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
@@ -1179,7 +1179,7 @@
 	tp->undo_marker = tp->snd_una;
 	tp->undo_retrans = 0;
 
-	for_retrans_queue(skb, sk, tp) {
+	sk_stream_for_retrans_queue(skb, sk) {
 		TCP_SKB_CB(skb)->sacked &= ~TCPCB_RETRANS;
 	}
 	tcp_sync_left_out(tp);
@@ -1202,7 +1202,7 @@
 	tp->lost_out = 0;
 	tp->fackets_out = 0;
 
-	for_retrans_queue(skb, sk, tp) {
+	sk_stream_for_retrans_queue(skb, sk) {
 		cnt++;
 		TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
 		if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
@@ -1275,7 +1275,7 @@
 	if (!how)
 		tp->undo_marker = tp->snd_una;
 
-	for_retrans_queue(skb, sk, tp) {
+	sk_stream_for_retrans_queue(skb, sk) {
 		cnt++;
 		if (TCP_SKB_CB(skb)->sacked&TCPCB_RETRANS)
 			tp->undo_marker = 0;
@@ -1518,7 +1518,7 @@
 
 	BUG_TRAP(cnt <= tp->packets_out);
 
-	for_retrans_queue(skb, sk, tp) {
+	sk_stream_for_retrans_queue(skb, sk) {
 		if (--cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq))
 			break;
 		if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
@@ -1550,7 +1550,7 @@
 	if (tcp_head_timedout(sk, tp)) {
 		struct sk_buff *skb;
 
-		for_retrans_queue(skb, sk, tp) {
+		sk_stream_for_retrans_queue(skb, sk) {
 			if (tcp_skb_timedout(tp, skb) &&
 			    !(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
 				TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
@@ -1719,7 +1719,7 @@
 {
 	if (tcp_may_undo(tp)) {
 		struct sk_buff *skb;
-		for_retrans_queue(skb, sk, tp) {
+		sk_stream_for_retrans_queue(skb, sk) {
 			TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
 		}
 		DBGUNDO(sk, tp, "partial loss");
@@ -2328,7 +2328,7 @@
 	int acked = 0;
 	__s32 seq_rtt = -1;
 
-	while ((skb = skb_peek(&sk->sk_write_queue)) && skb != tp->send_head) {
+	while ((skb = skb_peek(&sk->sk_write_queue)) && skb != sk->sk_send_head) {
 		struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
 		__u8 sacked = scb->sacked;
 
@@ -2376,7 +2376,7 @@
 			tp->fackets_out--;
 		tp->packets_out--;
 		__skb_unlink(skb, skb->list);
-		tcp_free_skb(sk, skb);
+		sk_stream_free_skb(sk, skb);
 	}
 
 	if (acked&FLAG_ACKED) {
@@ -2416,7 +2416,7 @@
 
 	/* Was it a usable window open? */
 
-	if (!after(TCP_SKB_CB(tp->send_head)->end_seq,
+	if (!after(TCP_SKB_CB(sk->sk_send_head)->end_seq,
 		   tp->snd_una + tp->snd_wnd)) {
 		tp->backoff = 0;
 		tcp_clear_xmit_timer(sk, TCP_TIME_PROBE0);
@@ -2857,7 +2857,7 @@
 	 * being used to time the probes, and is probably far higher than
 	 * it needs to be for normal retransmission.
 	 */
-	if (tp->send_head)
+	if (sk->sk_send_head)
 		tcp_ack_probe(sk);
 	return 1;
 
@@ -3461,7 +3461,7 @@
 				if (tcp_prune_queue(sk) < 0 || !tcp_rmem_schedule(sk, skb))
 					goto drop;
 			}
-			tcp_set_owner_r(skb, sk);
+			sk_stream_set_owner_r(skb, sk);
 			__skb_queue_tail(&sk->sk_receive_queue, skb);
 		}
 		tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
@@ -3542,7 +3542,7 @@
 	SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n",
 		   tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
 
-	tcp_set_owner_r(skb, sk);
+	sk_stream_set_owner_r(skb, sk);
 
 	if (!skb_peek(&tp->out_of_order_queue)) {
 		/* Initial out of order segment, build 1 SACK. */
@@ -3681,7 +3681,7 @@
 		memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
 		TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start;
 		__skb_insert(nskb, skb->prev, skb, skb->list);
-		tcp_set_owner_r(nskb, sk);
+		sk_stream_set_owner_r(nskb, sk);
 
 		/* Copy data, releasing collapsed skbs. */
 		while (copy > 0) {
@@ -3837,7 +3837,7 @@
 
 
 /* When incoming ACK allowed to free some skb from write_queue,
- * we remember this event in flag tp->queue_shrunk and wake up socket
+ * we remember this event in flag sk->sk_queue_shrunk and wake up socket
  * on the exit from tcp input handler.
  *
  * PROBLEM: sndbuf expansion does not work well with largesend.
@@ -3865,10 +3865,8 @@
 
 static inline void tcp_check_space(struct sock *sk)
 {
-	struct tcp_opt *tp = tcp_sk(sk);
-
-	if (tp->queue_shrunk) {
-		tp->queue_shrunk = 0;
+	if (sk->sk_queue_shrunk) {
+		sk->sk_queue_shrunk = 0;
 		if (sk->sk_socket &&
 		    test_bit(SOCK_NOSPACE, &sk->sk_socket->flags))
 			tcp_new_space(sk);
@@ -3887,8 +3885,7 @@
 
 static __inline__ void tcp_data_snd_check(struct sock *sk)
 {
-	struct tcp_opt *tp = tcp_sk(sk);
-	struct sk_buff *skb = tp->send_head;
+	struct sk_buff *skb = sk->sk_send_head;
 
 	if (skb != NULL)
 		__tcp_data_snd_check(sk, skb);
@@ -4242,7 +4239,7 @@
 				/* Bulk data transfer: receiver */
 				__skb_pull(skb,tcp_header_len);
 				__skb_queue_tail(&sk->sk_receive_queue, skb);
-				tcp_set_owner_r(skb, sk);
+				sk_stream_set_owner_r(skb, sk);
 				tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
 			}
 
@@ -4482,7 +4479,7 @@
 			sk_wake_async(sk, 0, POLL_OUT);
 		}
 
-		if (tp->write_pending || tp->defer_accept || tp->ack.pingpong) {
+		if (sk->sk_write_pending || tp->defer_accept || tp->ack.pingpong) {
 			/* Save one ACK. Data will be ready after
 			 * several ticks, if write_pending is set.
 			 *
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	2004-06-23 19:04:26 -07:00
+++ b/net/ipv4/tcp_ipv4.c	2004-06-23 19:04:26 -07:00
@@ -2081,7 +2081,7 @@
 
 	sk->sk_state = TCP_CLOSE;
 
-	sk->sk_write_space = tcp_write_space;
+	sk->sk_write_space = sk_stream_write_space;
 	sk->sk_use_write_queue = 1;
 
 	tp->af_specific = &ipv4_specific;
diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
--- a/net/ipv4/tcp_minisocks.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/tcp_minisocks.c	2004-06-23 19:04:28 -07:00
@@ -718,9 +718,10 @@
 		sock_reset_flag(newsk, SOCK_DONE);
 		newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK;
 		newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL;
+		newsk->sk_send_head = NULL;
 		newsk->sk_callback_lock = RW_LOCK_UNLOCKED;
 		skb_queue_head_init(&newsk->sk_error_queue);
-		newsk->sk_write_space = tcp_write_space;
+		newsk->sk_write_space = sk_stream_write_space;
 
 		if ((filter = newsk->sk_filter) != NULL)
 			sk_filter_charge(newsk, filter);
@@ -775,7 +776,6 @@
 		tcp_set_ca_state(newtp, TCP_CA_Open);
 		tcp_init_xmit_timers(newsk);
 		skb_queue_head_init(&newtp->out_of_order_queue);
-		newtp->send_head = NULL;
 		newtp->rcv_wup = req->rcv_isn + 1;
 		newtp->write_seq = req->snt_isn + 1;
 		newtp->pushed_seq = newtp->write_seq;
diff -Nru a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
--- a/net/ipv4/tcp_output.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv4/tcp_output.c	2004-06-23 19:04:27 -07:00
@@ -48,9 +48,9 @@
 static __inline__
 void update_send_head(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
 {
-	tp->send_head = skb->next;
-	if (tp->send_head == (struct sk_buff *)&sk->sk_write_queue)
-		tp->send_head = NULL;
+	sk->sk_send_head = skb->next;
+	if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue)
+		sk->sk_send_head = NULL;
 	tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
 	if (tp->packets_out++ == 0)
 		tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
@@ -326,11 +326,11 @@
 	/* Advance write_seq and place onto the write_queue. */
 	tp->write_seq = TCP_SKB_CB(skb)->end_seq;
 	__skb_queue_tail(&sk->sk_write_queue, skb);
-	tcp_charge_skb(sk, skb);
+	sk_charge_skb(sk, skb);
 
 	/* Queue it, remembering where we must start sending. */
-	if (tp->send_head == NULL)
-		tp->send_head = skb;
+	if (sk->sk_send_head == NULL)
+		sk->sk_send_head = skb;
 }
 
 /* Send _single_ skb sitting at the send head. This function requires
@@ -339,13 +339,13 @@
 void tcp_push_one(struct sock *sk, unsigned cur_mss)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
-	struct sk_buff *skb = tp->send_head;
+	struct sk_buff *skb = sk->sk_send_head;
 
 	if (tcp_snd_test(tp, skb, cur_mss, TCP_NAGLE_PUSH)) {
 		/* Send it out now. */
 		TCP_SKB_CB(skb)->when = tcp_time_stamp;
 		if (!tcp_transmit_skb(sk, skb_clone(skb, sk->sk_allocation))) {
-			tp->send_head = NULL;
+			sk->sk_send_head = NULL;
 			tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
 			if (tp->packets_out++ == 0)
 				tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
@@ -354,70 +354,6 @@
 	}
 }
 
-/* Split fragmented skb to two parts at length len. */
-
-static void skb_split(struct sk_buff *skb, struct sk_buff *skb1, u32 len)
-{
-	int i;
-	int pos = skb_headlen(skb);
-
-	if (len < pos) {
-		/* Split line is inside header. */
-		memcpy(skb_put(skb1, pos-len), skb->data + len, pos-len);
-
-		/* And move data appendix as is. */
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-			skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i];
-
-		skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags;
-		skb_shinfo(skb)->nr_frags = 0;
-
-		skb1->data_len = skb->data_len;
-		skb1->len += skb1->data_len;
-		skb->data_len = 0;
-		skb->len = len;
-		skb->tail = skb->data+len;
-	} else {
-		int k = 0;
-		int nfrags = skb_shinfo(skb)->nr_frags;
-
-		/* Second chunk has no header, nothing to copy. */
-
-		skb_shinfo(skb)->nr_frags = 0;
-		skb1->len = skb1->data_len = skb->len - len;
-		skb->len = len;
-		skb->data_len = len - pos;
-
-		for (i=0; i<nfrags; i++) {
-			int size = skb_shinfo(skb)->frags[i].size;
-			if (pos + size > len) {
-				skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i];
-
-				if (pos < len) {
-					/* Split frag.
-					 * We have to variants in this case:
-					 * 1. Move all the frag to the second
-					 *    part, if it is possible. F.e.
-					 *    this approach is mandatory for TUX,
-					 *    where splitting is expensive.
-					 * 2. Split is accurately. We make this.
-					 */
-					get_page(skb_shinfo(skb)->frags[i].page);
-					skb_shinfo(skb1)->frags[0].page_offset += (len-pos);
-					skb_shinfo(skb1)->frags[0].size -= (len-pos);
-					skb_shinfo(skb)->frags[i].size = len-pos;
-					skb_shinfo(skb)->nr_frags++;
-				}
-				k++;
-			} else {
-				skb_shinfo(skb)->nr_frags++;
-			}
-			pos += size;
-		}
-		skb_shinfo(skb1)->nr_frags = k;
-	}
-}
-
 /* Function to create two new TCP segments.  Shrinks the given segment
  * to the specified size and appends a new segment with the rest of the
  * packet to the list.  This won't be called frequently, I hope. 
@@ -439,7 +375,7 @@
 	buff = tcp_alloc_skb(sk, nsize, GFP_ATOMIC);
 	if (buff == NULL)
 		return -ENOMEM; /* We'll just try again later. */
-	tcp_charge_skb(sk, buff);
+	sk_charge_skb(sk, buff);
 
 	/* Correct the sequence numbers. */
 	TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
@@ -636,8 +572,10 @@
 		 */
 		mss_now = tcp_current_mss(sk, 1);
 
-		while((skb = tp->send_head) &&
-		      tcp_snd_test(tp, skb, mss_now, tcp_skb_is_last(sk, skb) ? nonagle : TCP_NAGLE_PUSH)) {
+		while ((skb = sk->sk_send_head) &&
+		       tcp_snd_test(tp, skb, mss_now,
+			       	    tcp_skb_is_last(sk, skb) ? nonagle :
+				    			       TCP_NAGLE_PUSH)) {
 			if (skb->len > mss_now) {
 				if (tcp_fragment(sk, skb, mss_now))
 					break;
@@ -657,7 +595,7 @@
 			return 0;
 		}
 
-		return !tp->packets_out && tp->send_head;
+		return !tp->packets_out && sk->sk_send_head;
 	}
 	return 0;
 }
@@ -827,7 +765,7 @@
 		 */
 		if (tp->fackets_out)
 			tp->fackets_out--;
-		tcp_free_skb(sk, next_skb);
+		sk_stream_free_skb(sk, next_skb);
 		tp->packets_out--;
 	}
 }
@@ -843,7 +781,7 @@
 	unsigned int mss = tcp_current_mss(sk, 0);
 	int lost = 0;
 
-	for_retrans_queue(skb, sk, tp) {
+	sk_stream_for_retrans_queue(skb, sk) {
 		if (skb->len > mss && 
 		    !(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
 			if (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) {
@@ -929,7 +867,7 @@
 	/* Collapse two adjacent packets if worthwhile and we can. */
 	if(!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_SYN) &&
 	   (skb->len < (cur_mss >> 1)) &&
-	   (skb->next != tp->send_head) &&
+	   (skb->next != sk->sk_send_head) &&
 	   (skb->next != (struct sk_buff *)&sk->sk_write_queue) &&
 	   (skb_shinfo(skb)->nr_frags == 0 && skb_shinfo(skb->next)->nr_frags == 0) &&
 	   (sysctl_tcp_retrans_collapse != 0))
@@ -1004,7 +942,7 @@
 
 	/* First pass: retransmit lost packets. */
 	if (packet_cnt) {
-		for_retrans_queue(skb, sk, tp) {
+		sk_stream_for_retrans_queue(skb, sk) {
 			__u8 sacked = TCP_SKB_CB(skb)->sacked;
 
 			if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
@@ -1052,7 +990,7 @@
 
 	packet_cnt = 0;
 
-	for_retrans_queue(skb, sk, tp) {
+	sk_stream_for_retrans_queue(skb, sk) {
 		if(++packet_cnt > tp->fackets_out)
 			break;
 
@@ -1089,7 +1027,7 @@
 	 */
 	mss_now = tcp_current_mss(sk, 1); 
 
-	if(tp->send_head != NULL) {
+	if (sk->sk_send_head != NULL) {
 		TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN;
 		TCP_SKB_CB(skb)->end_seq++;
 		tp->write_seq++;
@@ -1168,8 +1106,8 @@
 				return -ENOMEM;
 			__skb_unlink(skb, &sk->sk_write_queue);
 			__skb_queue_head(&sk->sk_write_queue, nskb);
-			tcp_free_skb(sk, skb);
-			tcp_charge_skb(sk, nskb);
+			sk_stream_free_skb(sk, skb);
+			sk_charge_skb(sk, nskb);
 			skb = nskb;
 		}
 
@@ -1329,7 +1267,7 @@
 	TCP_SKB_CB(buff)->when = tcp_time_stamp;
 	tp->retrans_stamp = TCP_SKB_CB(buff)->when;
 	__skb_queue_tail(&sk->sk_write_queue, buff);
-	tcp_charge_skb(sk, buff);
+	sk_charge_skb(sk, buff);
 	tp->packets_out++;
 	tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL));
 	TCP_INC_STATS(TcpActiveOpens);
@@ -1468,7 +1406,7 @@
 		struct tcp_opt *tp = tcp_sk(sk);
 		struct sk_buff *skb;
 
-		if ((skb = tp->send_head) != NULL &&
+		if ((skb = sk->sk_send_head) != NULL &&
 		    before(TCP_SKB_CB(skb)->seq, tp->snd_una+tp->snd_wnd)) {
 			int err;
 			int mss = tcp_current_mss(sk, 0);
@@ -1522,7 +1460,7 @@
 
 	err = tcp_write_wakeup(sk);
 
-	if (tp->packets_out || !tp->send_head) {
+	if (tp->packets_out || !sk->sk_send_head) {
 		/* Cancel probe timer, if it is not required. */
 		tp->probes_out = 0;
 		tp->backoff = 0;
diff -Nru a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
--- a/net/ipv4/tcp_timer.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv4/tcp_timer.c	2004-06-23 19:04:28 -07:00
@@ -269,7 +269,7 @@
 	struct tcp_opt *tp = tcp_sk(sk);
 	int max_probes;
 
-	if (tp->packets_out || !tp->send_head) {
+	if (tp->packets_out || !sk->sk_send_head) {
 		tp->probes_out = 0;
 		return;
 	}
@@ -606,7 +606,7 @@
 	elapsed = keepalive_time_when(tp);
 
 	/* It is alive without keepalive 8) */
-	if (tp->packets_out || tp->send_head)
+	if (tp->packets_out || sk->sk_send_head)
 		goto resched;
 
 	elapsed = tcp_time_stamp - tp->rcv_tstamp;
diff -Nru a/net/ipv6/Makefile b/net/ipv6/Makefile
--- a/net/ipv6/Makefile	2004-06-23 19:04:28 -07:00
+++ b/net/ipv6/Makefile	2004-06-23 19:04:28 -07:00
@@ -10,7 +10,8 @@
 		exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
 		ip6_flowlabel.o ipv6_syms.o
 
-ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o
+ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
+	xfrm6_tunnel.o
 ipv6-objs += $(ipv6-y)
 
 obj-$(CONFIG_INET6_AH) += ah6.o
diff -Nru a/net/ipv6/ah6.c b/net/ipv6/ah6.c
--- a/net/ipv6/ah6.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv6/ah6.c	2004-06-23 19:04:27 -07:00
@@ -163,11 +163,15 @@
 	}
 
 	spin_lock_bh(&x->lock);
-	err = xfrm_check_output(x, *pskb, AF_INET6);
+	err = xfrm_state_check(x, *pskb);
 	if (err)
 		goto error;
 
 	if (x->props.mode) {
+		err = xfrm6_tunnel_check_size(*pskb);
+		if (err)
+			goto error;
+
 		iph = (*pskb)->nh.ipv6h;
 		(*pskb)->nh.ipv6h = (struct ipv6hdr*)skb_push(*pskb, x->props.header_len);
 		(*pskb)->nh.ipv6h->version = 6;
diff -Nru a/net/ipv6/esp6.c b/net/ipv6/esp6.c
--- a/net/ipv6/esp6.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv6/esp6.c	2004-06-23 19:04:27 -07:00
@@ -38,8 +38,6 @@
 #include <net/ipv6.h>
 #include <linux/icmpv6.h>
 
-#define MAX_SG_ONSTACK 4
-
 int esp6_output(struct sk_buff **pskb)
 {
 	int err;
@@ -65,14 +63,16 @@
 	}
 
 	spin_lock_bh(&x->lock);
-	err = xfrm_check_output(x, *pskb, AF_INET6);
+	err = xfrm_state_check(x, *pskb);
 	if (err)
 		goto error;
-	err = -ENOMEM;
 
-	/* Strip IP header in transport mode. Save it. */
-
-	if (!x->props.mode) {
+	if (x->props.mode) {
+		err = xfrm6_tunnel_check_size(*pskb);
+		if (err)
+			goto error;
+	} else {
+		/* Strip IP header in transport mode. Save it. */
 		hdr_len = ip6_find_1stfragopt(*pskb, &prevhdr);
 		nexthdr = *prevhdr;
 		*prevhdr = IPPROTO_ESP;
@@ -86,6 +86,7 @@
 	}
 
 	/* Now skb is pure payload to encrypt */
+	err = -ENOMEM;
 
 	/* Round to block size */
 	clen = (*pskb)->len;
@@ -148,17 +149,16 @@
 		crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
 
 	do {
-		struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
-		struct scatterlist *sg = sgbuf;
+		struct scatterlist *sg = &esp->sgbuf[0];
 
-		if (unlikely(nfrags > MAX_SG_ONSTACK)) {
+		if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
 			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
 			if (!sg)
 				goto error;
 		}
 		skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen);
 		crypto_cipher_encrypt(tfm, sg, sg, clen);
-		if (unlikely(sg != sgbuf))
+		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
 	} while (0);
 
@@ -256,12 +256,11 @@
 
         {
 		u8 nexthdr[2];
-		struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
-		struct scatterlist *sg = sgbuf;
+		struct scatterlist *sg = &esp->sgbuf[0];
 		u8 padlen;
 		u8 *prevhdr;
 
-		if (unlikely(nfrags > MAX_SG_ONSTACK)) {
+		if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
 			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
 			if (!sg) {
 				ret = -ENOMEM;
@@ -270,7 +269,7 @@
 		}
 		skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen);
 		crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
-		if (unlikely(sg != sgbuf))
+		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
 
 		if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c
--- a/net/ipv6/icmp.c	2004-06-23 19:04:26 -07:00
+++ b/net/ipv6/icmp.c	2004-06-23 19:04:26 -07:00
@@ -55,7 +55,7 @@
 #include <net/sock.h>
 
 #include <net/ipv6.h>
-#include <net/checksum.h>
+#include <net/ip6_checksum.h>
 #include <net/protocol.h>
 #include <net/raw.h>
 #include <net/rawv6.h>
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c	2004-06-23 19:04:25 -07:00
+++ b/net/ipv6/ip6_output.c	2004-06-23 19:04:25 -07:00
@@ -607,13 +607,11 @@
 				frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr));
 				ip6_copy_metadata(frag, skb);
 			}
-			err = output(pskb);
-			if (err || !frag) {
-				if (unlikely(skb != *pskb))
-					skb = *pskb;
-				break;
-			}
 			
+			err = output(&skb);
+			if (err || !frag)
+				break;
+
 			skb = frag;
 			frag = skb->next;
 			skb->next = NULL;
diff -Nru a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
--- a/net/ipv6/ip6_tunnel.c	2004-06-23 19:04:25 -07:00
+++ b/net/ipv6/ip6_tunnel.c	2004-06-23 19:04:25 -07:00
@@ -123,7 +123,7 @@
  *   else %NULL
  **/
 
-struct ip6_tnl *
+static struct ip6_tnl *
 ip6ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local)
 {
 	unsigned h0 = HASH(remote);
@@ -387,8 +387,9 @@
  *   to the specifications in RFC 2473.
  **/
 
-void ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-		   int type, int code, int offset, __u32 info)
+static void 
+ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+	   int type, int code, int offset, __u32 info)
 {
 	struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data;
 	struct ip6_tnl *t;
@@ -496,7 +497,8 @@
  * Return: 0
  **/
 
-int ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int 
+ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
 {
 	struct sk_buff *skb = *pskb;
 	struct ipv6hdr *ipv6h;
@@ -510,6 +512,11 @@
 	read_lock(&ip6ip6_lock);
 
 	if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
+		if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+			kfree_skb(skb);
+			return 0;
+		}
+
 		if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
 			t->stat.rx_dropped++;
 			read_unlock(&ip6ip6_lock);
@@ -533,8 +540,7 @@
 	read_unlock(&ip6ip6_lock);
 	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
 discard:
-	kfree_skb(skb);
-	return 0;
+	return 1;
 }
 
 static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
@@ -598,7 +604,8 @@
  *   0
  **/
 
-int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
+static int 
+ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
 	struct net_device_stats *stats = &t->stat;
@@ -715,13 +722,7 @@
 	ipv6h->nexthdr = proto;
 	ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src);
 	ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
-#endif
+	nf_reset(skb);
 	pkt_len = skb->len;
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, 
 		      skb->dst->dev, dst_output);
@@ -1079,7 +1080,8 @@
  * Return: 0
  **/
 
-int ip6ip6_fb_tnl_dev_init(struct net_device *dev)
+static int 
+ip6ip6_fb_tnl_dev_init(struct net_device *dev)
 {
 	struct ip6_tnl *t = dev->priv;
 	ip6ip6_tnl_dev_init_gen(dev);
@@ -1088,10 +1090,9 @@
 	return 0;
 }
 
-static struct inet6_protocol ip6ip6_protocol = {
+static struct xfrm6_tunnel ip6ip6_handler = {
 	.handler = ip6ip6_rcv,
 	.err_handler = ip6ip6_err,
-	.flags = INET6_PROTO_FINAL
 };
 
 /**
@@ -1104,9 +1105,9 @@
 {
 	int  err;
 
-	if ((err = inet6_add_protocol(&ip6ip6_protocol, IPPROTO_IPV6)) < 0) {
-		printk(KERN_ERR "Failed to register IPv6 protocol\n");
-		return err;
+	if (xfrm6_tunnel_register(&ip6ip6_handler) < 0) {
+		printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
+		return -EAGAIN;
 	}
 	ip6ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
 					 ip6ip6_tnl_dev_setup);
@@ -1123,7 +1124,7 @@
 	}
 	return 0;
 fail:
-	inet6_del_protocol(&ip6ip6_protocol, IPPROTO_IPV6);
+	xfrm6_tunnel_deregister(&ip6ip6_handler);
 	return err;
 }
 
@@ -1133,8 +1134,10 @@
 
 static void __exit ip6_tunnel_cleanup(void)
 {
+	if (xfrm6_tunnel_deregister(&ip6ip6_handler) < 0)
+		printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
+
 	unregister_netdev(ip6ip6_fb_tnl_dev);
-	inet6_del_protocol(&ip6ip6_protocol, IPPROTO_IPV6);
 }
 
 module_init(ip6_tunnel_init);
diff -Nru a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
--- a/net/ipv6/ipcomp6.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv6/ipcomp6.c	2004-06-23 19:04:27 -07:00
@@ -140,11 +140,15 @@
 
 	spin_lock_bh(&x->lock);
 
-	err = xfrm_check_output(x, *pskb, AF_INET6);
+	err = xfrm_state_check(x, *pskb);
 	if (err)
 		goto error;
 
 	if (x->props.mode) {
+		err = xfrm6_tunnel_check_size(*pskb);
+		if (err)
+			goto error;
+
 		hdr_len = sizeof(struct ipv6hdr);
 		nexthdr = IPPROTO_IPV6;
 		iph = (*pskb)->nh.ipv6h;
@@ -258,6 +262,66 @@
 	xfrm_state_put(x);
 }
 
+static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
+{
+	struct xfrm_state *t = NULL;
+
+	t = xfrm_state_alloc();
+	if (!t)
+		goto out;
+
+	t->id.proto = IPPROTO_IPV6;
+	t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr);
+	memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr));
+	memcpy(&t->sel, &x->sel, sizeof(t->sel));
+	t->props.family = AF_INET6;
+	t->props.mode = 1;
+	memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
+
+	t->type = xfrm_get_type(IPPROTO_IPV6, t->props.family);
+	if (t->type == NULL)
+		goto error;
+
+	if (t->type->init_state(t, NULL))
+		goto error;
+
+	t->km.state = XFRM_STATE_VALID;
+	atomic_set(&t->tunnel_users, 1);
+
+out:
+	return t;
+
+error:
+	xfrm_state_put(t);
+	goto out;
+}
+
+static int ipcomp6_tunnel_attach(struct xfrm_state *x)
+{
+	int err = 0;
+	struct xfrm_state *t = NULL;
+	u32 spi;
+
+	spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&x->props.saddr);
+	if (spi)
+		t = xfrm_state_lookup((xfrm_address_t *)&x->id.daddr,
+					      spi, IPPROTO_IPV6, AF_INET6);
+	if (!t) {
+		t = ipcomp6_tunnel_create(x);
+		if (!t) {
+			err = -EINVAL;
+			goto out;
+		}
+		xfrm_state_insert(t);
+		xfrm_state_hold(t);
+	}
+	x->tunnel = t;
+	atomic_inc(&t->tunnel_users);
+
+out:
+	return err;
+}
+
 static void ipcomp6_free_data(struct ipcomp_data *ipcd)
 {
 	if (ipcd->tfm)
@@ -271,8 +335,11 @@
 	struct ipcomp_data *ipcd = x->data;
 	if (!ipcd)
 		return;
+	xfrm_state_delete_tunnel(x);
 	ipcomp6_free_data(ipcd);
 	kfree(ipcd);
+
+	xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
 }
 
 static int ipcomp6_init_state(struct xfrm_state *x, void *args)
@@ -302,6 +369,12 @@
 	ipcd->tfm = crypto_alloc_tfm(x->calg->alg_name, 0);
 	if (!ipcd->tfm)
 		goto error;
+
+	if (x->props.mode) {
+		err = ipcomp6_tunnel_attach(x);
+		if (err)
+			goto error;
+	}
 
 	calg_desc = xfrm_calg_get_byname(x->calg->alg_name);
 	BUG_ON(!calg_desc);
diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c
--- a/net/ipv6/mcast.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv6/mcast.c	2004-06-23 19:04:28 -07:00
@@ -60,7 +60,7 @@
 #include <net/addrconf.h>
 #include <net/ip6_route.h>
 
-#include <net/checksum.h>
+#include <net/ip6_checksum.h>
 
 /* Set to 3 to get tracing... */
 #define MCAST_DEBUG 2
@@ -365,7 +365,7 @@
 	err = -EADDRNOTAVAIL;
 
 	for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
-		if (pmc->ifindex != pgsr->gsr_interface)
+		if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface)
 			continue;
 		if (ipv6_addr_cmp(&pmc->addr, group) == 0)
 			break;
diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv6/ndisc.c	2004-06-23 19:04:27 -07:00
@@ -77,7 +77,7 @@
 #include <net/icmp.h>
 
 #include <net/flow.h>
-#include <net/checksum.h>
+#include <net/ip6_checksum.h>
 #include <linux/proc_fs.h>
 
 #include <linux/netfilter.h>
diff -Nru a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
--- a/net/ipv6/netfilter/ip6_tables.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv6/netfilter/ip6_tables.c	2004-06-23 19:04:28 -07:00
@@ -1845,6 +1845,15 @@
 	return 0;
 }
 
+static inline int print_target(const struct ip6t_target *t,
+                               off_t start_offset, char *buffer, int length,
+                               off_t *pos, unsigned int *count)
+{
+	if (t == &ip6t_standard_target || t == &ip6t_error_target)
+		return 0;
+	return print_name((char *)t, start_offset, buffer, length, pos, count);
+}
+
 static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length)
 {
 	off_t pos = 0;
@@ -1871,7 +1880,7 @@
 	if (down_interruptible(&ip6t_mutex) != 0)
 		return 0;
 
-	LIST_FIND(&ip6t_target, print_name, char *,
+	LIST_FIND(&ip6t_target, print_target, struct ip6t_target *,
 		  offset, buffer, length, &pos, &count);
 
 	up(&ip6t_mutex);
diff -Nru a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
--- a/net/ipv6/netfilter/ip6t_owner.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv6/netfilter/ip6t_owner.c	2004-06-23 19:04:28 -07:00
@@ -143,7 +143,14 @@
 
 	if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info)))
 		return 0;
-
+#ifdef CONFIG_SMP
+	/* files->file_lock can not be used in a BH */
+	if (((struct ip6t_owner_info *)matchinfo)->match
+	    & (IP6T_OWNER_PID|IP6T_OWNER_SID)) {
+		printk("ip6t_owner: pid and sid matching is broken on SMP.\n");
+		return 0;
+	}
+#endif
 	return 1;
 }
 
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	2004-06-23 19:04:26 -07:00
+++ b/net/ipv6/raw.c	2004-06-23 19:04:26 -07:00
@@ -35,6 +35,7 @@
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
+#include <net/ip.h>
 #include <net/sock.h>
 #include <net/snmp.h>
 
@@ -42,6 +43,7 @@
 #include <net/ndisc.h>
 #include <net/protocol.h>
 #include <net/ip6_route.h>
+#include <net/ip6_checksum.h>
 #include <net/addrconf.h>
 #include <net/transp_v6.h>
 #include <net/udp.h>
diff -Nru a/net/ipv6/sit.c b/net/ipv6/sit.c
--- a/net/ipv6/sit.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv6/sit.c	2004-06-23 19:04:28 -07:00
@@ -388,13 +388,7 @@
 		skb->dev = tunnel->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
-#ifdef CONFIG_NETFILTER
-		nf_conntrack_put(skb->nfct);
-		skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#endif
-#endif
+		nf_reset(skb);
 		ipip6_ecn_decapsulate(iph, skb);
 		netif_rx(skb);
 		read_unlock(&ipip6_lock);
@@ -580,13 +574,7 @@
 	if ((iph->ttl = tiph->ttl) == 0)
 		iph->ttl	=	iph6->hop_limit;
 
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
-#endif
+	nf_reset(skb);
 
 	IPTUNNEL_XMIT();
 	tunnel->recursion--;
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c	2004-06-23 19:04:27 -07:00
+++ b/net/ipv6/tcp_ipv6.c	2004-06-23 19:04:27 -07:00
@@ -51,6 +51,7 @@
 #include <net/transp_v6.h>
 #include <net/addrconf.h>
 #include <net/ip6_route.h>
+#include <net/ip6_checksum.h>
 #include <net/inet_ecn.h>
 #include <net/protocol.h>
 #include <net/xfrm.h>
@@ -1878,7 +1879,7 @@
 
 	tp->af_specific = &ipv6_specific;
 
-	sk->sk_write_space = tcp_write_space;
+	sk->sk_write_space = sk_stream_write_space;
 	sk->sk_use_write_queue = 1;
 
 	sk->sk_sndbuf = sysctl_tcp_wmem[1];
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c	2004-06-23 19:04:28 -07:00
+++ b/net/ipv6/udp.c	2004-06-23 19:04:28 -07:00
@@ -51,7 +51,7 @@
 #include <net/udp.h>
 #include <net/inet_common.h>
 
-#include <net/checksum.h>
+#include <net/ip6_checksum.h>
 #include <net/xfrm.h>
 
 #include <linux/proc_fs.h>
@@ -507,7 +507,7 @@
 		return -1;
 	}
 
-	if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
+	if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
 		if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
 			UDP6_INC_STATS_BH(UdpInErrors);
 			kfree_skb(skb);
diff -Nru a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
--- a/net/ipv6/xfrm6_policy.c	2004-06-23 19:04:26 -07:00
+++ b/net/ipv6/xfrm6_policy.c	2004-06-23 19:04:26 -07:00
@@ -277,10 +277,12 @@
 {
 	xfrm6_policy_init();
 	xfrm6_state_init();
+	xfrm6_tunnel_init();
 }
 
 void __exit xfrm6_fini(void)
 {
+	xfrm6_tunnel_fini();
 	//xfrm6_input_fini();
 	xfrm6_policy_fini();
 	xfrm6_state_fini();
diff -Nru a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/ipv6/xfrm6_tunnel.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,634 @@
+/*
+ * Copyright (C)2003,2004 USAGI/WIDE Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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
+ *
+ * Authors	Mitsuru KANDA  <mk@linux-ipv6.org>
+ * 		YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+ *
+ * Based on net/ipv4/xfrm4_tunnel.c
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/xfrm.h>
+#include <linux/list.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+#include <net/icmp.h>
+#include <net/ipv6.h>
+#include <linux/ipv6.h>
+#include <linux/icmpv6.h>
+
+#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG
+# define X6TDEBUG	3
+#else
+# define X6TDEBUG	1
+#endif
+
+#define X6TPRINTK(fmt, args...)		printk(fmt, ## args)
+#define X6TNOPRINTK(fmt, args...)	do { ; } while(0)
+
+#if X6TDEBUG >= 1
+# define X6TPRINTK1	X6TPRINTK
+#else
+# define X6TPRINTK1	X6TNOPRINTK
+#endif
+
+#if X6TDEBUG >= 3
+# define X6TPRINTK3	X6TPRINTK
+#else
+# define X6TPRINTK3	X6TNOPRINTK
+#endif
+
+/*
+ * xfrm_tunnel_spi things are for allocating unique id ("spi") 
+ * per xfrm_address_t.
+ */
+struct xfrm6_tunnel_spi {
+	struct hlist_node list_byaddr;
+	struct hlist_node list_byspi;
+	xfrm_address_t addr;
+	u32 spi;
+	atomic_t refcnt;
+#ifdef XFRM6_TUNNEL_SPI_MAGIC
+	u32 magic;
+#endif
+};
+
+#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG
+# define XFRM6_TUNNEL_SPI_MAGIC 0xdeadbeef
+#endif
+
+static rwlock_t xfrm6_tunnel_spi_lock = RW_LOCK_UNLOCKED;
+
+static u32 xfrm6_tunnel_spi;
+
+#define XFRM6_TUNNEL_SPI_MIN	1
+#define XFRM6_TUNNEL_SPI_MAX	0xffffffff
+
+static kmem_cache_t *xfrm6_tunnel_spi_kmem;
+
+#define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256
+#define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256
+
+static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE];
+static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE];
+
+#ifdef XFRM6_TUNNEL_SPI_MAGIC
+static int x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi,
+			     const char *name)
+{
+	if (unlikely(x6spi->magic != XFRM6_TUNNEL_SPI_MAGIC)) {
+		X6TPRINTK3(KERN_DEBUG "%s(): x6spi object "
+				      "at %p has corrupted magic %08x "
+				      "(should be %08x)\n",
+			   name, x6spi, x6spi->magic, XFRM6_TUNNEL_SPI_MAGIC);
+		return -1;
+	}
+	return 0;
+}
+#else
+static int inline x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi,
+				    const char *name)
+{
+	return 0;
+}
+#endif
+
+#define X6SPI_CHECK_MAGIC(x6spi) x6spi_check_magic((x6spi), __FUNCTION__)
+
+
+static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr)
+{
+	unsigned h;
+
+	X6TPRINTK3(KERN_DEBUG "%s(addr=%p)\n", __FUNCTION__, addr);
+
+	h = addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3];
+	h ^= h >> 16;
+	h ^= h >> 8;
+	h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1;
+
+	X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, h);
+
+	return h;
+}
+
+static unsigned inline xfrm6_tunnel_spi_hash_byspi(u32 spi)
+{
+	return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE;
+}
+
+
+static int xfrm6_tunnel_spi_init(void)
+{
+	int i;
+
+	X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+	xfrm6_tunnel_spi = 0;
+	xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi",
+						  sizeof(struct xfrm6_tunnel_spi),
+						  0, SLAB_HWCACHE_ALIGN,
+						  NULL, NULL);
+	if (!xfrm6_tunnel_spi_kmem) {
+		X6TPRINTK1(KERN_ERR
+			   "%s(): failed to allocate xfrm6_tunnel_spi_kmem\n",
+		           __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
+		INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byaddr[i]);
+	for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++)
+		INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byspi[i]);
+	return 0;
+}
+
+static void xfrm6_tunnel_spi_fini(void)
+{
+	int i;
+
+	X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+	for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) {
+		if (!hlist_empty(&xfrm6_tunnel_spi_byaddr[i]))
+			goto err;
+	}
+	for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) {
+		if (!hlist_empty(&xfrm6_tunnel_spi_byspi[i]))
+			goto err;
+	}
+	kmem_cache_destroy(xfrm6_tunnel_spi_kmem);
+	xfrm6_tunnel_spi_kmem = NULL;
+	return;
+err:
+	X6TPRINTK1(KERN_ERR "%s(): table is not empty\n", __FUNCTION__);
+	return;
+}
+
+static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
+{
+	struct xfrm6_tunnel_spi *x6spi;
+	struct hlist_node *pos;
+
+	X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+	hlist_for_each_entry(x6spi, pos,
+			     &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
+			     list_byaddr) {
+		if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
+			X6SPI_CHECK_MAGIC(x6spi);
+			X6TPRINTK3(KERN_DEBUG "%s() = %p(%u)\n", __FUNCTION__, x6spi, x6spi->spi);
+			return x6spi;
+		}
+	}
+
+	X6TPRINTK3(KERN_DEBUG "%s() = NULL(0)\n", __FUNCTION__);
+	return NULL;
+}
+
+u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
+{
+	struct xfrm6_tunnel_spi *x6spi;
+	u32 spi;
+
+	X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+	read_lock_bh(&xfrm6_tunnel_spi_lock);
+	x6spi = __xfrm6_tunnel_spi_lookup(saddr);
+	spi = x6spi ? x6spi->spi : 0;
+	read_unlock_bh(&xfrm6_tunnel_spi_lock);
+	return spi;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup);
+
+static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+{
+	u32 spi;
+	struct xfrm6_tunnel_spi *x6spi;
+	struct hlist_node *pos;
+	unsigned index;
+
+	X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+	if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN ||
+	    xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX)
+		xfrm6_tunnel_spi = XFRM6_TUNNEL_SPI_MIN;
+	else
+		xfrm6_tunnel_spi++;
+
+	for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) {
+		index = xfrm6_tunnel_spi_hash_byspi(spi);
+		hlist_for_each_entry(x6spi, pos, 
+				     &xfrm6_tunnel_spi_byspi[index], 
+				     list_byspi) {
+			if (x6spi->spi == spi)
+				goto try_next_1;
+		}
+		xfrm6_tunnel_spi = spi;
+		goto alloc_spi;
+try_next_1:;
+	}
+	for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) {
+		index = xfrm6_tunnel_spi_hash_byspi(spi);
+		hlist_for_each_entry(x6spi, pos, 
+				     &xfrm6_tunnel_spi_byspi[index], 
+				     list_byspi) {
+			if (x6spi->spi == spi)
+				goto try_next_2;
+		}
+		xfrm6_tunnel_spi = spi;
+		goto alloc_spi;
+try_next_2:;
+	}
+	spi = 0;
+	goto out;
+alloc_spi:
+	X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for "
+			      "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", 
+			      __FUNCTION__, 
+			      NIP6(*(struct in6_addr *)saddr));
+	x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC);
+	if (!x6spi) {
+		X6TPRINTK1(KERN_ERR "%s(): kmem_cache_alloc() failed\n", 
+			   __FUNCTION__);
+		goto out;
+	}
+#ifdef XFRM6_TUNNEL_SPI_MAGIC
+	x6spi->magic = XFRM6_TUNNEL_SPI_MAGIC;
+#endif
+	memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr));
+	x6spi->spi = spi;
+	atomic_set(&x6spi->refcnt, 1);
+
+	hlist_add_head(&x6spi->list_byspi, &xfrm6_tunnel_spi_byspi[index]);
+
+	index = xfrm6_tunnel_spi_hash_byaddr(saddr);
+	hlist_add_head(&x6spi->list_byaddr, &xfrm6_tunnel_spi_byaddr[index]);
+	X6SPI_CHECK_MAGIC(x6spi);
+out:
+	X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi);
+	return spi;
+}
+
+u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+{
+	struct xfrm6_tunnel_spi *x6spi;
+	u32 spi;
+
+	X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+	write_lock_bh(&xfrm6_tunnel_spi_lock);
+	x6spi = __xfrm6_tunnel_spi_lookup(saddr);
+	if (x6spi) {
+		atomic_inc(&x6spi->refcnt);
+		spi = x6spi->spi;
+	} else
+		spi = __xfrm6_tunnel_alloc_spi(saddr);
+	write_unlock_bh(&xfrm6_tunnel_spi_lock);
+
+	X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi);
+
+	return spi;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi);
+
+void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
+{
+	struct xfrm6_tunnel_spi *x6spi;
+	struct hlist_node *pos, *n;
+
+	X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+	write_lock_bh(&xfrm6_tunnel_spi_lock);
+
+	hlist_for_each_entry_safe(x6spi, pos, n, 
+				  &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
+				  list_byaddr)
+	{
+		if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
+			X6TPRINTK3(KERN_DEBUG "%s(): x6spi object "
+					      "for %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
+					      "found at %p\n",
+				   __FUNCTION__, 
+				   NIP6(*(struct in6_addr *)saddr),
+				   x6spi);
+			X6SPI_CHECK_MAGIC(x6spi);
+			if (atomic_dec_and_test(&x6spi->refcnt)) {
+				hlist_del(&x6spi->list_byaddr);
+				hlist_del(&x6spi->list_byspi);
+				kmem_cache_free(xfrm6_tunnel_spi_kmem, x6spi);
+				break;
+			}
+		}
+	}
+	write_unlock_bh(&xfrm6_tunnel_spi_lock);
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
+
+int xfrm6_tunnel_check_size(struct sk_buff *skb)
+{
+	int mtu, ret = 0;
+	struct dst_entry *dst = skb->dst;
+
+	mtu = dst_pmtu(dst) - sizeof(struct ipv6hdr);
+	if (mtu < IPV6_MIN_MTU)
+		mtu = IPV6_MIN_MTU;
+
+	if (skb->len > mtu) {
+		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
+		ret = -EMSGSIZE;
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_check_size);
+
+static int xfrm6_tunnel_output(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct dst_entry *dst = skb->dst;
+	struct xfrm_state *x = dst->xfrm;
+	struct ipv6hdr *iph, *top_iph;
+	int err;
+
+	if ((err = xfrm6_tunnel_check_size(skb)) != 0)
+		goto error_nolock;
+
+	iph = skb->nh.ipv6h;
+
+	top_iph = (struct ipv6hdr *)skb_push(skb, x->props.header_len);
+	top_iph->version = 6;
+	top_iph->priority = iph->priority;
+	top_iph->flow_lbl[0] = iph->flow_lbl[0];
+	top_iph->flow_lbl[1] = iph->flow_lbl[1];
+	top_iph->flow_lbl[2] = iph->flow_lbl[2];
+	top_iph->nexthdr = IPPROTO_IPV6; 
+	top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+	top_iph->hop_limit = iph->hop_limit;
+	memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr));
+	memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr));
+	skb->nh.raw = skb->data;
+	skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
+
+	x->curlft.bytes += skb->len;
+	x->curlft.packets++;
+
+	spin_unlock_bh(&x->lock);
+
+	if ((skb->dst = dst_pop(dst)) == NULL) { 
+		kfree_skb(skb);
+		err = -EHOSTUNREACH;
+		goto error_nolock;
+	}
+
+	return NET_XMIT_BYPASS;
+
+error_nolock:
+	kfree_skb(skb);
+	return err;
+}
+
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+{
+	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 
+		return -EINVAL;
+
+	skb->mac.raw = skb->nh.raw;
+	skb->nh.raw = skb->data;
+	dst_release(skb->dst);
+	skb->dst = NULL;
+	skb->protocol = htons(ETH_P_IPV6);
+	skb->pkt_type = PACKET_HOST;
+	netif_rx(skb);
+
+	return 0;
+}
+
+static struct xfrm6_tunnel *xfrm6_tunnel_handler;
+static DECLARE_MUTEX(xfrm6_tunnel_sem);
+
+int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+{
+	int ret;
+
+	down(&xfrm6_tunnel_sem);
+	ret = 0;
+	if (xfrm6_tunnel_handler != NULL)
+		ret = -EINVAL;
+	if (!ret)
+		xfrm6_tunnel_handler = handler;
+	up(&xfrm6_tunnel_sem);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_register);
+
+int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
+{
+	int ret;
+
+	down(&xfrm6_tunnel_sem);
+	ret = 0;
+	if (xfrm6_tunnel_handler != handler)
+		ret = -EINVAL;
+	if (!ret)
+		xfrm6_tunnel_handler = NULL;
+	up(&xfrm6_tunnel_sem);
+
+	synchronize_net();
+
+	return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_deregister);
+
+static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+{
+	struct sk_buff *skb = *pskb;
+	struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
+	struct xfrm_state *x = NULL;
+	struct ipv6hdr *iph = skb->nh.ipv6h;
+	int err = 0;
+	u32 spi;
+
+	/* device-like_ip6ip6_handler() */
+	if (handler) {
+		err = handler->handler(pskb, nhoffp);
+		if (!err)
+			goto out;
+	}
+
+	spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
+	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, 
+			spi,
+			IPPROTO_IPV6, AF_INET6);
+
+	if (!x)
+		goto drop;
+
+	spin_lock(&x->lock);
+
+	if (unlikely(x->km.state != XFRM_STATE_VALID))
+		goto drop_unlock;
+
+	err = xfrm6_tunnel_input(x, NULL, skb);
+	if (err)
+		goto drop_unlock;
+
+	x->curlft.bytes += skb->len;
+	x->curlft.packets++; 
+	spin_unlock(&x->lock); 
+	xfrm_state_put(x); 
+
+out:
+	return 0;
+
+drop_unlock:
+	spin_unlock(&x->lock);
+	xfrm_state_put(x);
+drop:
+	kfree_skb(skb);
+	return -1;
+}
+
+static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+			     int type, int code, int offset, __u32 info)
+{
+	struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
+
+	/* call here first for device-like ip6ip6 err handling */
+	if (handler) {
+		handler->err_handler(skb, opt, type, code, offset, info);
+		return;
+	}
+
+	/* xfrm6_tunnel native err handling */
+	switch (type) {
+	case ICMPV6_DEST_UNREACH: 
+		switch (code) {
+		case ICMPV6_NOROUTE: 
+		case ICMPV6_ADM_PROHIBITED:
+		case ICMPV6_NOT_NEIGHBOUR:
+		case ICMPV6_ADDR_UNREACH:
+		case ICMPV6_PORT_UNREACH:
+		default:
+			X6TPRINTK3(KERN_DEBUG
+				   "xfrm6_tunnel: Destination Unreach.\n");
+			break;
+		}
+		break;
+	case ICMPV6_PKT_TOOBIG:
+			X6TPRINTK3(KERN_DEBUG 
+				   "xfrm6_tunnel: Packet Too Big.\n");
+		break;
+	case ICMPV6_TIME_EXCEED:
+		switch (code) {
+		case ICMPV6_EXC_HOPLIMIT:
+			X6TPRINTK3(KERN_DEBUG
+				   "xfrm6_tunnel: Too small Hoplimit.\n");
+			break;
+		case ICMPV6_EXC_FRAGTIME:
+		default: 
+			break;
+		}
+		break;
+	case ICMPV6_PARAMPROB:
+		switch (code) {
+		case ICMPV6_HDR_FIELD: break;
+		case ICMPV6_UNK_NEXTHDR: break;
+		case ICMPV6_UNK_OPTION: break;
+		}
+		break;
+	default:
+		break;
+	}
+	return;
+}
+
+static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args)
+{
+	if (!x->props.mode)
+		return -EINVAL;
+
+	x->props.header_len = sizeof(struct ipv6hdr);
+
+	return 0;
+}
+
+static void xfrm6_tunnel_destroy(struct xfrm_state *x)
+{
+	xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
+}
+
+static struct xfrm_type xfrm6_tunnel_type = {
+	.description	= "IP6IP6",
+	.owner          = THIS_MODULE,
+	.proto		= IPPROTO_IPV6,
+	.init_state	= xfrm6_tunnel_init_state,
+	.destructor	= xfrm6_tunnel_destroy,
+	.input		= xfrm6_tunnel_input,
+	.output		= xfrm6_tunnel_output,
+};
+
+static struct inet6_protocol xfrm6_tunnel_protocol = {
+	.handler	= xfrm6_tunnel_rcv,
+	.err_handler	= xfrm6_tunnel_err, 
+	.flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+};
+
+void __init xfrm6_tunnel_init(void)
+{
+	X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+	if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) {
+		X6TPRINTK1(KERN_ERR
+			   "xfrm6_tunnel init: can't add xfrm type\n");
+		return;
+	}
+	if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) {
+		X6TPRINTK1(KERN_ERR
+			   "xfrm6_tunnel init(): can't add protocol\n");
+		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+		return;
+	}
+	if (xfrm6_tunnel_spi_init() < 0) {
+		X6TPRINTK1(KERN_ERR
+			   "xfrm6_tunnel init: failed to initialize spi\n");
+		inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
+		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+		return;
+	}
+}
+
+void __exit xfrm6_tunnel_fini(void)
+{
+	X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+	xfrm6_tunnel_spi_fini();
+	if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0)
+		X6TPRINTK1(KERN_ERR 
+			   "xfrm6_tunnel close: can't remove protocol\n");
+	if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0)
+		X6TPRINTK1(KERN_ERR
+			   "xfrm6_tunnel close: can't remove xfrm type\n");
+}
diff -Nru a/net/irda/irda_device.c b/net/irda/irda_device.c
--- a/net/irda/irda_device.c	2004-06-23 19:04:26 -07:00
+++ b/net/irda/irda_device.c	2004-06-23 19:04:26 -07:00
@@ -536,7 +536,7 @@
  *    Setup the DMA channel. Commonly used by ISA FIR drivers
  *
  */
-void irda_setup_dma(int channel, char *buffer, int count, int mode)
+void irda_setup_dma(int channel, dma_addr_t buffer, int count, int mode)
 {
 	unsigned long flags;
 
@@ -545,7 +545,7 @@
 	disable_dma(channel);
 	clear_dma_ff(channel);
 	set_dma_mode(channel, mode);
-	set_dma_addr(channel, isa_virt_to_bus(buffer));
+	set_dma_addr(channel, buffer);
 	set_dma_count(channel, count);
 	enable_dma(channel);
 
diff -Nru a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
--- a/net/netlink/af_netlink.c	2004-06-23 19:04:27 -07:00
+++ b/net/netlink/af_netlink.c	2004-06-23 19:04:27 -07:00
@@ -728,14 +728,14 @@
 	   to corresponding kernel module.   --ANK (980802)
 	 */
 
-	err = security_netlink_send(skb);
-	if (err) {
+	err = -EFAULT;
+	if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) {
 		kfree_skb(skb);
 		goto out;
 	}
 
-	err = -EFAULT;
-	if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) {
+	err = security_netlink_send(sk, skb);
+	if (err) {
 		kfree_skb(skb);
 		goto out;
 	}
diff -Nru a/net/sched/Kconfig b/net/sched/Kconfig
--- a/net/sched/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/net/sched/Kconfig	2004-06-23 19:04:28 -07:00
@@ -177,7 +177,7 @@
 
 config NET_SCH_INGRESS
 	tristate "Ingress Qdisc"
-	depends on NET_SCHED && NETFILTER
+	depends on NET_SCHED 
 	help
 	  If you say Y here, you will be able to police incoming bandwidth
 	  and drop packets when this bandwidth exceeds your desired rate.
@@ -242,6 +242,7 @@
 config NET_CLS_ROUTE4
 	tristate "Routing table based classifier"
 	depends on NET_CLS
+	select NET_CLS_ROUTE
 	help
 	  If you say Y here, you will be able to classify outgoing packets
 	  according to the route table entry they matched. If unsure, say Y.
@@ -251,8 +252,7 @@
 
 config NET_CLS_ROUTE
 	bool
-	depends on NET_CLS_ROUTE4
-	default y
+	default n
 
 config NET_CLS_FW
 	tristate "Firewall based classifier"
@@ -274,6 +274,24 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called cls_u32.
 
+config CLS_U32_PERF
+	bool "     U32 classifier perfomance counters"
+	depends on NET_CLS_U32
+	help
+	  gathers stats that could be used to tune u32 classifier perfomance.
+	  Requires a new iproute2
+	  You MUST NOT turn this on if you dont have an update iproute2.
+
+config NET_CLS_IND
+	bool "classify input device (slows things u32/fw) "
+	depends on NET_CLS_U32 || NET_CLS_FW
+	help
+	  This option will be killed eventually when a 
+          metadata action appears because it slows things a little
+          Available only for u32 and fw classifiers.
+	  Requires a new iproute2
+	  You MUST NOT turn this on if you dont have an update iproute2.
+
 config NET_CLS_RSVP
 	tristate "Special RSVP classifier"
 	depends on NET_CLS && NET_QOS
@@ -303,9 +321,26 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called cls_rsvp6.
 
+config NET_CLS_ACT
+	bool '  Packet ACTION ' 
+	depends on EXPERIMENTAL && NET_CLS && NET_QOS
+	---help---
+	This option requires you have a new iproute2. It enables
+	tc extensions which can be used with tc classifiers.
+	Only the u32 and fw classifiers are supported at the moment.
+	  You MUST NOT turn this on if you dont have an update iproute2.
+
+config NET_ACT_POLICE
+	tristate '      Policing Actions' 
+        depends on NET_CLS_ACT 
+        ---help---
+        If you are using a newer iproute2 select this one, otherwise use one
+	below to select a policer.
+	  You MUST NOT turn this on if you dont have an update iproute2.
+
 config NET_CLS_POLICE
 	bool "Traffic policing (needed for in/egress)"
-	depends on NET_CLS && NET_QOS
+	depends on NET_CLS && NET_QOS && NET_ACT_POLICE!=y && NET_ACT_POLICE!=m
 	help
 	  Say Y to support traffic policing (bandwidth limits).  Needed for
 	  ingress and egress rate limiting.
diff -Nru a/net/sched/Makefile b/net/sched/Makefile
--- a/net/sched/Makefile	2004-06-23 19:04:27 -07:00
+++ b/net/sched/Makefile	2004-06-23 19:04:27 -07:00
@@ -7,7 +7,9 @@
 obj-$(CONFIG_NET_SCHED)		+= sch_api.o sch_fifo.o
 obj-$(CONFIG_NET_ESTIMATOR)	+= estimator.o
 obj-$(CONFIG_NET_CLS)		+= cls_api.o
-obj-$(CONFIG_NET_CLS_POLICE)	+= police.o
+obj-$(CONFIG_NET_CLS_ACT)       += act_api.o
+obj-$(CONFIG_NET_ACT_POLICE)    += police.o
+obj-$(CONFIG_NET_CLS_POLICE)    += police.o
 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
 obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
 obj-$(CONFIG_NET_SCH_CSZ)	+= sch_csz.o
diff -Nru a/net/sched/act_api.c b/net/sched/act_api.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sched/act_api.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,1016 @@
+/*
+ * net/sched/act_api.c	Packet action 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.
+ *
+ * Author:	Jamal Hadi Salim
+ *
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/init.h>
+#include <linux/kmod.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+
+#if 1 /* control */
+#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define DPRINTK(format,args...)
+#endif
+
+static struct tc_action_ops *act_base = NULL;
+static rwlock_t act_mod_lock = RW_LOCK_UNLOCKED;
+
+int tcf_register_action(struct tc_action_ops *act)
+{
+	struct tc_action_ops *a, **ap;
+
+	write_lock(&act_mod_lock);
+	for (ap = &act_base; (a=*ap)!=NULL; ap = &a->next) {
+		if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
+			write_unlock(&act_mod_lock);
+			return -EEXIST;
+		}
+	}
+
+        act->next = NULL;
+	*ap = act;
+
+	write_unlock(&act_mod_lock);
+
+	return 0;
+}
+
+int tcf_unregister_action(struct tc_action_ops *act)
+{
+	struct tc_action_ops *a, **ap;
+	int err = -ENOENT;
+
+	write_lock(&act_mod_lock);
+	for (ap = &act_base; (a=*ap)!=NULL; ap = &a->next) 
+		if(a == act)
+			break;
+
+	if (a) {
+		*ap = a->next;
+		a->next = NULL;
+		err = 0;
+	}
+	write_unlock(&act_mod_lock);
+	return err;
+}
+
+/* lookup by name */
+struct tc_action_ops *tc_lookup_action_n(char *kind)
+{
+
+	struct tc_action_ops *a = NULL;
+
+	if (kind) {
+		read_lock(&act_mod_lock);
+		for (a = act_base; a; a = a->next) {
+			if (strcmp(kind,a->kind) == 0) {
+				if (!try_module_get(a->owner)) {
+					read_unlock(&act_mod_lock);
+					return NULL;
+				} 
+				break;
+			}
+		}
+		read_unlock(&act_mod_lock);
+	}
+
+	return a;
+}
+
+/* lookup by rtattr */
+struct tc_action_ops *tc_lookup_action(struct rtattr *kind)
+{
+
+	struct tc_action_ops *a = NULL;
+
+	if (kind) {
+		read_lock(&act_mod_lock);
+		for (a = act_base; a; a = a->next) {
+
+			if (strcmp((char*)RTA_DATA(kind),a->kind) == 0){
+				if (!try_module_get(a->owner)) {
+					read_unlock(&act_mod_lock);
+					return NULL;
+				} 
+				break;
+			}
+		}
+		read_unlock(&act_mod_lock);
+	}
+
+	return a;
+}
+
+/* lookup by id */
+struct tc_action_ops *tc_lookup_action_id(u32 type)
+{
+	struct tc_action_ops *a = NULL;
+
+	if (type) {
+		read_lock(&act_mod_lock);
+		for (a = act_base; a; a = a->next) {
+			if (a->type == type) {
+				if (!try_module_get(a->owner)) {
+					read_unlock(&act_mod_lock);
+					return NULL;
+				} 
+				break;
+			}
+		}
+		read_unlock(&act_mod_lock);
+	}
+
+	return a;
+}
+
+int tcf_action_exec(struct sk_buff *skb,struct tc_action *act)
+{
+
+	struct tc_action *a;
+	int ret = -1; 
+
+	if (skb->tc_verd & TC_NCLS) {
+		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
+		DPRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n",skb,skb->input_dev?skb->input_dev->name:"xxx",skb->dev->name);
+		return TC_ACT_OK;
+	}
+	while ((a = act) != NULL) {
+repeat:
+		if (a->ops && a->ops->act) {
+			ret = a->ops->act(&skb,a);
+				if (TC_MUNGED & skb->tc_verd) {
+					/* copied already, allow trampling */
+					skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
+					skb->tc_verd = CLR_TC_MUNGED(skb->tc_verd);
+				}
+
+			if (ret != TC_ACT_PIPE)
+				goto exec_done;
+			if (ret == TC_ACT_REPEAT)
+				goto repeat;	/* we need a ttl - JHS */
+
+		}
+		act = a->next;
+	}
+
+exec_done:
+
+	return ret;
+}
+
+void tcf_action_destroy(struct tc_action *act, int bind)
+{
+	struct tc_action *a;
+
+	for (a = act; act; a = act) {
+		if (a && a->ops && a->ops->cleanup) {
+			DPRINTK("tcf_action_destroy destroying %p next %p\n", a,a->next?a->next:NULL);
+			act = act->next;
+			if (ACT_P_DELETED == a->ops->cleanup(a, bind)) {
+				module_put(a->ops->owner);
+			}
+			
+			a->ops = NULL;  
+			kfree(a);
+		} else { /*FIXME: Remove later - catch insertion bugs*/
+			printk("tcf_action_destroy: BUG? destroying NULL ops \n");
+			if (a) {
+				act = act->next;
+				kfree(a);
+			} else {
+				printk("tcf_action_destroy: BUG? destroying NULL action! \n");
+				break;
+			}
+		}
+	}
+}
+
+int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+	int err = -EINVAL;
+
+
+	if ( (NULL == a) || (NULL == a->ops)
+	   || (NULL == a->ops->dump) )
+		return err;
+	return a->ops->dump(skb, a, bind, ref);
+
+}
+
+
+int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+	int err = -EINVAL;
+	unsigned char    *b = skb->tail;
+	struct rtattr *r;
+
+
+	if ( (NULL == a) || (NULL == a->ops)
+	   || (NULL == a->ops->dump) || (NULL == a->ops->kind))
+		return err;
+
+
+	RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
+	if (tcf_action_copy_stats(skb,a))
+		goto rtattr_failure;
+	r = (struct rtattr*) skb->tail;
+	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	if ((err = tcf_action_dump_old(skb, a, bind, ref)) > 0) {
+		r->rta_len = skb->tail - (u8*)r;
+		return err;
+	}
+
+
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+
+}
+
+int tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref)
+{
+	struct tc_action *a;
+	int err = -EINVAL;
+	unsigned char    *b = skb->tail;
+	struct rtattr *r ;
+
+	while ((a = act) != NULL) {
+		r = (struct rtattr*) skb->tail;
+		act = a->next;
+		RTA_PUT(skb, a->order, 0, NULL);
+		err = tcf_action_dump_1(skb, a, bind, ref);
+		if (0 > err) 
+			goto rtattr_failure;
+
+		r->rta_len = skb->tail - (u8*)r;
+	}
+
+	return 0;
+
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -err;
+	
+}
+
+int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *a, char *name, int ovr, int bind )
+{
+	struct tc_action_ops *a_o;
+	char act_name[4 + IFNAMSIZ + 1];
+	struct rtattr *tb[TCA_ACT_MAX+1];
+	struct rtattr *kind = NULL;
+
+	int err = -EINVAL;
+
+	if (NULL == name) {
+		if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta))<0)
+			goto err_out;
+		kind = tb[TCA_ACT_KIND-1];
+		if (NULL != kind) {
+			sprintf(act_name, "%s", (char*)RTA_DATA(kind));
+			if (RTA_PAYLOAD(kind) >= IFNAMSIZ) {
+				printk(" Action %s bad\n", (char*)RTA_DATA(kind));
+				goto err_out;
+			}
+
+		} else {
+			printk("Action bad kind\n");
+			goto err_out;
+		}
+		a_o = tc_lookup_action(kind);
+	} else {
+		sprintf(act_name, "%s", name);
+		DPRINTK("tcf_action_init_1: finding  %s\n",act_name);
+		a_o = tc_lookup_action_n(name);
+	}
+#ifdef CONFIG_KMOD
+	if (NULL == a_o) {
+		DPRINTK("tcf_action_init_1: trying to load module %s\n",act_name);
+		request_module (act_name);
+		a_o = tc_lookup_action_n(act_name);
+	}
+
+#endif
+	if (NULL == a_o) {
+		printk("failed to find %s\n",act_name);
+		goto err_out;
+	}
+
+	if (NULL == a) {
+		goto err_mod;
+	}
+
+	/* backward compatibility for policer */
+	if (NULL == name) {
+		err = a_o->init(tb[TCA_ACT_OPTIONS-1], est, a, ovr, bind);
+		if (0 > err ) {
+			err = -EINVAL;
+			goto err_mod;
+		}
+	} else {
+		err = a_o->init(rta, est, a, ovr, bind);
+		if (0 > err ) {
+			err = -EINVAL;
+			goto err_mod;
+		}
+	}
+
+	/* module count goes up only when brand new policy is created
+	   if it exists and is only bound to in a_o->init() then
+           ACT_P_CREATED is not returned (a zero is).
+        */
+	if (ACT_P_CREATED != err) {
+		module_put(a_o->owner);
+	} 
+	a->ops = a_o;
+	DPRINTK("tcf_action_init_1: successfull %s \n",act_name);
+
+	return 0;
+err_mod:
+	module_put(a_o->owner);
+err_out:
+	return err;
+}
+
+int tcf_action_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, char *name, int ovr , int bind)
+{
+	struct rtattr *tb[TCA_ACT_MAX_PRIO+1];
+	int i;
+	struct tc_action *act = a, *a_s = a;
+
+	int err = -EINVAL;
+
+	if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(rta), RTA_PAYLOAD(rta))<0)
+		return err;
+
+	for (i=0; i < TCA_ACT_MAX_PRIO ; i++) {
+		if (tb[i]) {
+			if (NULL == act) {
+				act = kmalloc(sizeof(*act),GFP_KERNEL);
+				if (NULL == act) {
+					err = -ENOMEM;
+					goto bad_ret;
+				}
+				memset(act, 0,sizeof(*act));
+			}
+			act->next = NULL;
+			if (0 > tcf_action_init_1(tb[i],est,act,name,ovr,bind)) {
+				printk("Error processing action order %d\n",i);
+				return err;
+			}
+
+			act->order = i+1;
+			if (a_s != act) {
+				a_s->next = act;
+				a_s = act;
+			}
+			act = NULL;
+		}
+
+	}
+
+	return 0;
+bad_ret:
+	tcf_action_destroy(a, bind);
+	return err;
+}
+
+int tcf_action_copy_stats (struct sk_buff *skb,struct tc_action *a)
+{
+#ifdef CONFIG_KMOD
+	/* place holder */
+#endif
+
+	if (NULL == a->ops || NULL == a->ops->get_stats)
+		return 1;
+
+	return a->ops->get_stats(skb,a);
+}
+
+
+static int
+tca_get_fill(struct sk_buff *skb,  struct tc_action *a,
+	      u32 pid, u32 seq, unsigned flags, int event, int bind, int ref)
+{
+	struct tcamsg *t;
+	struct nlmsghdr  *nlh;
+	unsigned char	 *b = skb->tail;
+	struct rtattr *x;
+
+	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*t));
+	nlh->nlmsg_flags = flags;
+	t = NLMSG_DATA(nlh);
+	t->tca_family = AF_UNSPEC;
+	
+	x = (struct rtattr*) skb->tail;
+	RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+
+	if (0 > tcf_action_dump(skb, a, bind, ref)) {
+		goto rtattr_failure;
+	}
+
+	x->rta_len = skb->tail - (u8*)x;
+	
+	nlh->nlmsg_len = skb->tail - b;
+	return skb->len;
+
+rtattr_failure:
+nlmsg_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static int act_get_notify(u32 pid, struct nlmsghdr *n,
+			   struct tc_action *a, int event)
+{
+	struct sk_buff *skb;
+
+	int err = 0;
+
+	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!skb)
+		return -ENOBUFS;
+
+	if (tca_get_fill(skb, a,  pid, n->nlmsg_seq, 0, event, 0, 0) <= 0) {
+		kfree_skb(skb);
+		return -EINVAL;
+	}
+
+	err =  netlink_unicast(rtnl,skb, pid, MSG_DONTWAIT);
+	if (err > 0)
+		err = 0;
+	return err;
+}
+
+int tcf_action_get_1(struct rtattr *rta, struct tc_action *a, struct nlmsghdr *n, u32 pid)
+{
+	struct tc_action_ops *a_o;
+	char act_name[4 + IFNAMSIZ + 1];
+	struct rtattr *tb[TCA_ACT_MAX+1];
+	struct rtattr *kind = NULL;
+	int index;
+
+	int err = -EINVAL;
+
+	if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta))<0)
+		goto err_out;
+
+
+	kind = tb[TCA_ACT_KIND-1];
+	if (NULL != kind) {
+		sprintf(act_name, "%s", (char*)RTA_DATA(kind));
+		if (RTA_PAYLOAD(kind) >= IFNAMSIZ) {
+			printk("tcf_action_get_1: action %s bad\n", (char*)RTA_DATA(kind));
+			goto err_out;
+		}
+
+	} else {
+		printk("tcf_action_get_1: action bad kind\n");
+		goto err_out;
+	}
+
+	if (tb[TCA_ACT_INDEX - 1]) {
+		index = *(int *)RTA_DATA(tb[TCA_ACT_INDEX - 1]);
+	} else {
+		printk("tcf_action_get_1: index not received\n");
+		goto err_out;
+	}
+
+	a_o = tc_lookup_action(kind);
+#ifdef CONFIG_KMOD
+	if (NULL == a_o) {
+		request_module (act_name);
+		a_o = tc_lookup_action_n(act_name);
+	}
+
+#endif
+	if (NULL == a_o) {
+		printk("failed to find %s\n",act_name);
+		goto err_out;
+	}
+
+	if (NULL == a) {
+		goto err_mod;
+	}
+
+	a->ops = a_o;
+
+	if (NULL == a_o->lookup || 0 == a_o->lookup(a, index)) {
+		a->ops = NULL;
+		err = -EINVAL;
+		goto err_mod;
+	}
+
+	module_put(a_o->owner);
+	return 0;
+err_mod:
+	module_put(a_o->owner);
+err_out:
+	return err;
+}
+
+void cleanup_a (struct tc_action *act) 
+{
+	struct tc_action *a;
+
+	for (a = act; act; a = act) {
+		if (a) {
+			act = act->next;
+			a->ops = NULL;
+			a->priv = NULL;
+			kfree(a);
+		} else {
+			printk("cleanup_a: BUG? empty action\n");
+		}
+	}
+}
+
+struct tc_action_ops *get_ao(struct rtattr *kind, struct tc_action *a)
+{
+	char act_name[4 + IFNAMSIZ + 1];
+	struct tc_action_ops *a_o = NULL;
+
+	if (NULL != kind) {
+		sprintf(act_name, "%s", (char*)RTA_DATA(kind));
+		if (RTA_PAYLOAD(kind) >= IFNAMSIZ) {
+			printk("get_ao: action %s bad\n", (char*)RTA_DATA(kind));
+			return NULL;
+		}
+
+	} else {
+		printk("get_ao: action bad kind\n");
+		return NULL;
+	}
+
+	a_o = tc_lookup_action(kind);
+#ifdef CONFIG_KMOD
+	if (NULL == a_o) {
+		DPRINTK("get_ao: trying to load module %s\n",act_name);
+		request_module (act_name);
+		a_o = tc_lookup_action_n(act_name);
+	}
+#endif
+
+	if (NULL == a_o) {
+		printk("get_ao: failed to find %s\n",act_name);
+		return NULL;
+	}
+
+	a->ops = a_o;
+	return a_o;
+}
+
+struct tc_action *create_a(int i)
+{
+	struct tc_action *act = NULL;
+
+	act = kmalloc(sizeof(*act),GFP_KERNEL);
+	if (NULL == act) { /* grrr .. */
+		printk("create_a: failed to alloc! \n");
+		return NULL;
+	}
+
+	memset(act, 0,sizeof(*act));
+
+	act->order = i;
+
+	return act;
+}
+
+int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
+{
+	struct sk_buff *skb;
+	unsigned char *b;
+	struct nlmsghdr *nlh;
+	struct tcamsg *t;
+	struct rtattr *x;
+	struct rtattr *tb[TCA_ACT_MAX+1];
+	struct rtattr *kind = NULL;
+	struct tc_action *a = create_a(0);
+	int err = -EINVAL;
+
+	if (NULL == a) {
+		printk("tca_action_flush: couldnt create tc_action\n");
+		return err;
+	}
+
+	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!skb) {
+		printk("tca_action_flush: failed skb alloc\n");
+		kfree(a);
+		return -ENOBUFS;
+	}
+
+	b = (unsigned char *)skb->tail;
+
+	if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta))<0) {
+		goto err_out;
+	}
+
+	kind = tb[TCA_ACT_KIND-1];
+	if (NULL == get_ao(kind, a)) {
+		goto err_out;
+	}
+
+	nlh = NLMSG_PUT(skb, pid,  n->nlmsg_seq, RTM_DELACTION, sizeof (*t));
+	t = NLMSG_DATA(nlh);
+	t->tca_family = AF_UNSPEC;
+
+	x = (struct rtattr *) skb->tail;
+	RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+
+	err = a->ops->walk(skb, NULL, RTM_DELACTION, a);
+	if (0 > err ) {
+		goto rtattr_failure;
+	}
+
+	x->rta_len = skb->tail - (u8 *) x;
+
+	nlh->nlmsg_len = skb->tail - b;
+	nlh->nlmsg_flags |= NLM_F_ROOT;
+	module_put(a->ops->owner);
+	kfree(a);
+	err = rtnetlink_send(skb, pid, RTMGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+	if (err > 0)
+		return 0;
+
+	return err;
+
+
+rtattr_failure:
+	module_put(a->ops->owner);
+nlmsg_failure:
+err_out:
+	kfree_skb(skb);
+	kfree(a);
+	return err;
+}
+
+int tca_action_gd(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int event )
+{
+
+	int s = 0;
+	int i, ret = 0;
+	struct tc_action *act = NULL;
+	struct rtattr *tb[TCA_ACT_MAX_PRIO+1];
+	struct tc_action *a = NULL, *a_s = NULL;
+
+	if (event != RTM_GETACTION  && event != RTM_DELACTION)
+		ret = -EINVAL;
+
+	if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(rta), RTA_PAYLOAD(rta))<0) {
+		ret = -EINVAL;
+		goto nlmsg_failure;
+	}
+
+	if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) {
+		if (NULL != tb[0]  && NULL == tb[1]) {
+			return tca_action_flush(tb[0],n,pid);
+		}
+	}
+
+	for (i=0; i < TCA_ACT_MAX_PRIO ; i++) {
+
+		if (NULL == tb[i])
+			break;
+
+		act = create_a(i+1);
+		if (NULL != a && a != act) {
+			a->next = act;
+			a = act;
+		} else {
+			a = act;
+		}
+
+		if (!s) {
+			s = 1;
+			a_s = a;
+		}
+
+		ret = tcf_action_get_1(tb[i],act,n,pid);
+		if (ret < 0) {
+			printk("tcf_action_get: failed to get! \n");
+			ret = -EINVAL;
+			goto rtattr_failure;
+		}
+
+	}
+
+
+	if (RTM_GETACTION == event) {
+		ret = act_get_notify(pid, n, a_s, event);
+	} else { /* delete */
+
+		struct sk_buff *skb;
+
+		skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+		if (!skb) {
+			ret = -ENOBUFS;
+			goto nlmsg_failure;
+		}
+
+		if (tca_get_fill(skb, a_s,  pid, n->nlmsg_seq, 0, event, 0 , 1) <= 0) {
+			kfree_skb(skb);
+			ret = -EINVAL;
+			goto nlmsg_failure;
+		}
+
+		/* now do the delete */
+		tcf_action_destroy(a_s, 0);
+
+		ret = rtnetlink_send(skb, pid, RTMGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+		if (ret > 0)
+			return 0;
+		return ret;
+	}
+rtattr_failure:
+nlmsg_failure:
+	cleanup_a(a_s);
+	return ret;
+}
+
+
+int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, unsigned flags) 
+{
+	struct tcamsg *t;
+	struct nlmsghdr  *nlh;
+	struct sk_buff *skb;
+	struct rtattr *x;
+	unsigned char *b;
+
+
+	int err = 0;
+
+	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!skb)
+		return -ENOBUFS;
+
+	b = (unsigned char *)skb->tail;
+
+	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*t));
+	nlh->nlmsg_flags = flags;
+	t = NLMSG_DATA(nlh);
+	t->tca_family = AF_UNSPEC;
+	
+	x = (struct rtattr*) skb->tail;
+	RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+
+	if (0 > tcf_action_dump(skb, a, 0, 0)) {
+		goto rtattr_failure;
+	}
+
+	x->rta_len = skb->tail - (u8*)x;
+	
+	nlh->nlmsg_len = skb->tail - b;
+	NETLINK_CB(skb).dst_groups = RTMGRP_TC;
+	
+	err = rtnetlink_send(skb, pid, RTMGRP_TC, flags&NLM_F_ECHO);
+	if (err > 0)
+		err = 0;
+
+	return err;
+
+rtattr_failure:
+nlmsg_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+	
+int tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int ovr ) 
+{
+	int ret = 0;
+	struct tc_action *act = NULL;
+	struct tc_action *a = NULL;
+	u32 seq = n->nlmsg_seq;
+
+	act = kmalloc(sizeof(*act),GFP_KERNEL);
+	if (NULL == act)
+		return -ENOMEM;
+
+	ret = tcf_action_init(rta, NULL,act,NULL,ovr,0);
+	/* NOTE: We have an all-or-none model
+	 * This means that of any of the actions fail
+	 * to update then all are undone.
+	 * */
+	if (0 > ret) {
+		tcf_action_destroy(act, 0);
+		goto done;
+	}
+
+	/* dump then free all the actions after update; inserted policy
+	 * stays intact
+	 * */
+	ret = tcf_add_notify(act, pid, seq, RTM_NEWACTION, n->nlmsg_flags); 
+	for (a = act; act; a = act) {
+		if (a) {
+			act = act->next;
+			a->ops = NULL;
+			a->priv = NULL;
+			kfree(a);
+		} else {
+			printk("tcf_action_add: BUG? empty action\n");
+		}
+	}
+done:
+
+	return ret;
+}
+
+static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+{
+	struct rtattr **tca = arg;
+	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
+
+	int ret = 0, ovr = 0;
+
+	if (NULL == tca[TCA_ACT_TAB-1]) {
+			printk("tc_ctl_action: received NO action attribs\n");
+			return -EINVAL;
+	}
+
+	/* n->nlmsg_flags&NLM_F_CREATE
+	 * */
+	switch (n->nlmsg_type) {
+	case RTM_NEWACTION:    
+		/* we are going to assume all other flags
+		 * imply create only if it doesnt exist
+		 * Note that CREATE | EXCL implies that
+		 * but since we want avoid ambiguity (eg when flags
+		 * is zero) then just set this
+		 */
+		if (n->nlmsg_flags&NLM_F_REPLACE) {
+			ovr = 1;
+		}
+		ret =  tcf_action_add(tca[TCA_ACT_TAB-1], n, pid, ovr);
+		break;
+	case RTM_DELACTION:
+		ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid,RTM_DELACTION);
+		break;
+	case RTM_GETACTION:
+		ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid,RTM_GETACTION);
+		break;
+	default:
+		printk(" Unknown cmd was detected\n");
+		break;
+	}
+
+	return ret;
+}
+
+char *
+find_dump_kind(struct nlmsghdr *n)
+{
+	struct rtattr *tb1, *tb2[TCA_ACT_MAX+1];
+	struct rtattr *tb[TCA_ACT_MAX_PRIO + 1];
+	struct rtattr *rta[TCAA_MAX + 1];
+	struct rtattr *kind = NULL;
+	int min_len = NLMSG_LENGTH(sizeof (struct tcamsg));
+
+	int attrlen = n->nlmsg_len - NLMSG_ALIGN(min_len);
+	struct rtattr *attr = (void *) n + NLMSG_ALIGN(min_len);
+
+	if (rtattr_parse(rta, TCAA_MAX, attr, attrlen) < 0)
+		return NULL;
+	tb1 = rta[TCA_ACT_TAB - 1];
+	if (NULL == tb1) {
+		return NULL;
+	}
+
+	if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(tb1), NLMSG_ALIGN(RTA_PAYLOAD(tb1))) < 0)
+		return NULL;
+	if (NULL == tb[0]) 
+		return NULL;
+
+	if (rtattr_parse(tb2, TCA_ACT_MAX, RTA_DATA(tb[0]), RTA_PAYLOAD(tb[0]))<0)
+		return NULL;
+	kind = tb2[TCA_ACT_KIND-1];
+
+	return (char *) RTA_DATA(kind);
+}
+
+static int
+tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+	struct rtattr *x;
+	struct tc_action_ops *a_o;
+	struct tc_action a;
+	int ret = 0;
+
+	struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh);
+	char *kind = find_dump_kind(cb->nlh);
+	if (NULL == kind) {
+		printk("tc_dump_action: action bad kind\n");
+		return 0;
+	}
+
+	a_o = tc_lookup_action_n(kind);
+
+#ifdef CONFIG_KMOD
+	if (NULL == a_o) {
+		DPRINTK("tc_dump_action: trying to load module %s\n", kind);
+		request_module(kind);
+		a_o = tc_lookup_action_n(kind);
+	}
+#endif
+	if (NULL == a_o) {
+		printk("failed to find %s\n", kind);
+		return 0;
+	}
+
+	memset(&a,0,sizeof(struct tc_action));
+	a.ops = a_o;
+
+	if (NULL == a_o->walk) {
+		printk("tc_dump_action: %s !capable of dumping table\n",kind);
+		goto rtattr_failure;
+	}
+
+	nlh = NLMSG_PUT(skb, NETLINK_CB(cb->skb).pid,  cb->nlh->nlmsg_seq, cb->nlh->nlmsg_type, sizeof (*t));
+	t = NLMSG_DATA(nlh);
+	t->tca_family = AF_UNSPEC;
+
+	x = (struct rtattr *) skb->tail;
+	RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+
+	ret = a_o->walk(skb, cb, RTM_GETACTION, &a);
+	if (0 > ret ) {
+		goto rtattr_failure;
+	}
+
+	if (ret > 0) {
+		x->rta_len = skb->tail - (u8 *) x;
+		ret = skb->len;
+	} else {
+		skb_trim(skb, (u8*)x - skb->data);
+	}
+
+	nlh->nlmsg_len = skb->tail - b;
+	if (NETLINK_CB(cb->skb).pid && ret) 
+		nlh->nlmsg_flags |= NLM_F_MULTI;
+	module_put(a_o->owner);
+	return skb->len;
+
+rtattr_failure:
+nlmsg_failure:
+	module_put(a_o->owner);
+	skb_trim(skb, b - skb->data);
+	return skb->len;
+}
+
+static int __init tc_action_init(void)
+{
+	struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC];
+
+	if (link_p) {
+		link_p[RTM_NEWACTION-RTM_BASE].doit = tc_ctl_action;
+		link_p[RTM_DELACTION-RTM_BASE].doit = tc_ctl_action;
+		link_p[RTM_GETACTION-RTM_BASE].doit = tc_ctl_action;
+		link_p[RTM_GETACTION-RTM_BASE].dumpit = tc_dump_action;
+	}
+
+	printk("TC classifier action (bugs to netdev@oss.sgi.com cc hadi@cyberus.ca)\n");
+	return 0;
+}
+
+subsys_initcall(tc_action_init);
+
+EXPORT_SYMBOL(tcf_register_action);
+EXPORT_SYMBOL(tcf_unregister_action);
+EXPORT_SYMBOL(tcf_action_init_1);
+EXPORT_SYMBOL(tcf_action_init);
+EXPORT_SYMBOL(tcf_action_destroy);
+EXPORT_SYMBOL(tcf_action_exec);
+EXPORT_SYMBOL(tcf_action_copy_stats);
+EXPORT_SYMBOL(tcf_action_dump);
+EXPORT_SYMBOL(tcf_action_dump_1);
+EXPORT_SYMBOL(tcf_action_dump_old);
diff -Nru a/net/sched/cls_api.c b/net/sched/cls_api.c
--- a/net/sched/cls_api.c	2004-06-23 19:04:26 -07:00
+++ b/net/sched/cls_api.c	2004-06-23 19:04:26 -07:00
@@ -11,6 +11,7 @@
  * Changes:
  *
  * Eduardo J. Blanco <ejbs@netlabs.com.uy> :990222: kmod support
+ *
  */
 
 #include <asm/uaccess.h>
@@ -36,6 +37,12 @@
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 
+#if 0 /* control */
+#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define DPRINTK(format,args...)
+#endif
+
 /* The list of all installed classifier types */
 
 static struct tcf_proto_ops *tcf_proto_base;
@@ -132,7 +139,7 @@
 	struct tcf_proto_ops *tp_ops;
 	struct Qdisc_class_ops *cops;
 	unsigned long cl = 0;
-	unsigned long fh;
+	unsigned long fh, fh_s;
 	int err;
 
 	if (prio == 0) {
@@ -238,7 +245,7 @@
 	} else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
 		goto errout;
 
-	fh = tp->ops->get(tp, t->tcm_handle);
+	fh_s = fh = tp->ops->get(tp, t->tcm_handle);
 
 	if (fh == 0) {
 		if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
@@ -247,6 +254,7 @@
 			*back = tp->next;
 			spin_unlock_bh(&dev->queue_lock);
 			write_unlock(&qdisc_tree_lock);
+			tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER);
 			tcf_destroy(tp);
 			err = 0;
 			goto errout;
@@ -264,6 +272,8 @@
 			break;
 		case RTM_DELTFILTER:
 			err = tp->ops->delete(tp, fh);
+			if (err == 0)
+				tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER);
 			goto errout;
 		case RTM_GETTFILTER:
 			err = tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER);
@@ -298,11 +308,14 @@
 	tcm->tcm_family = AF_UNSPEC;
 	tcm->tcm_ifindex = tp->q->dev->ifindex;
 	tcm->tcm_parent = tp->classid;
-	tcm->tcm_handle = 0;
 	tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
 	RTA_PUT(skb, TCA_KIND, IFNAMSIZ, tp->ops->kind);
-	if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0)
-		goto rtattr_failure;
+	tcm->tcm_handle = fh;
+	if (RTM_DELTFILTER != event) {
+		tcm->tcm_handle = 0;
+		if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0)
+			goto rtattr_failure;
+	}
 	nlh->nlmsg_len = skb->tail - b;
 	return skb->len;
 
diff -Nru a/net/sched/cls_fw.c b/net/sched/cls_fw.c
--- a/net/sched/cls_fw.c	2004-06-23 19:04:26 -07:00
+++ b/net/sched/cls_fw.c	2004-06-23 19:04:26 -07:00
@@ -11,6 +11,11 @@
  * Changes:
  * Karlis Peisenieks <karlis@mt.lv> : 990415 : fw_walk off by one
  * Karlis Peisenieks <karlis@mt.lv> : 990415 : fw_delete killed all the filter (and kernel).
+ * Alex <alex@pilotsoft.com> : 2004xxyy: Added Action extension
+ *
+ * JHS: We should remove the CONFIG_NET_CLS_IND from here
+ * eventually when the meta match extension is made available
+ *
  */
 
 #include <linux/config.h>
@@ -50,9 +55,16 @@
 	struct fw_filter	*next;
 	u32			id;
 	struct tcf_result	res;
+#ifdef CONFIG_NET_CLS_ACT
+       struct tc_action        *action;
+#ifdef CONFIG_NET_CLS_IND
+       char			indev[IFNAMSIZ];
+#endif
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 	struct tcf_police	*police;
 #endif
+#endif
 };
 
 static __inline__ int fw_hash(u32 handle)
@@ -77,10 +89,29 @@
 	for (f=head->ht[fw_hash(id)]; f; f=f->next) {
 		if (f->id == id) {
 			*res = f->res;
+#ifdef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NET_CLS_IND
+			if (0 != f->indev[0]) {
+				if  (NULL == skb->input_dev) {
+					continue;
+				} else {
+					if (0 != strcmp(f->indev, skb->input_dev->name)) {
+						continue;
+					}
+				}
+			}
+#endif
+                               if (f->action) {
+                                       int pol_res = tcf_action_exec(skb, f->action);
+                                       if (pol_res >= 0)
+                                               return pol_res;
+                               } else
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 			if (f->police)
 				return tcf_police(skb, f->police);
 #endif
+#endif
 			return 0;
 		}
 	}
@@ -136,9 +167,16 @@
 
 			if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
 				tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
+#ifdef CONFIG_NET_CLS_ACT
+       if (f->action) {
+               tcf_action_destroy(f->action,TCA_ACT_UNBIND);
+       }
+#else
 #ifdef CONFIG_NET_CLS_POLICE
-			tcf_police_release(f->police);
+			tcf_police_release(f->police,TCA_ACT_UNBIND);
+#endif
 #endif
+
 			kfree(f);
 		}
 	}
@@ -164,8 +202,14 @@
 
 			if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0)
 				tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
+#ifdef CONFIG_NET_CLS_ACT
+       if (f->action) {
+               tcf_action_destroy(f->action,TCA_ACT_UNBIND);
+       }
+#else
 #ifdef CONFIG_NET_CLS_POLICE
-			tcf_police_release(f->police);
+			tcf_police_release(f->police,TCA_ACT_UNBIND);
+#endif
 #endif
 			kfree(f);
 			return 0;
@@ -185,6 +229,11 @@
 	struct rtattr *opt = tca[TCA_OPTIONS-1];
 	struct rtattr *tb[TCA_FW_MAX];
 	int err;
+#ifdef CONFIG_NET_CLS_ACT
+       struct tc_action *act = NULL;
+       int ret;
+#endif
+
 
 	if (!opt)
 		return handle ? -EINVAL : 0;
@@ -206,6 +255,58 @@
 			if (cl)
 				tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
 		}
+#ifdef CONFIG_NET_CLS_ACT
+		if (tb[TCA_FW_POLICE-1]) {
+			act = kmalloc(sizeof(*act),GFP_KERNEL);
+			if (NULL == act)
+				return -ENOMEM;
+
+			memset(act,0,sizeof(*act));
+			ret = tcf_action_init_1(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1] ,act,"police",TCA_ACT_NOREPLACE,TCA_ACT_BIND);
+			if (0 > ret){
+				tcf_action_destroy(act,TCA_ACT_UNBIND);
+				return ret;
+			}
+			act->type = TCA_OLD_COMPAT;
+
+			sch_tree_lock(tp->q);
+			act = xchg(&f->action, act);
+			sch_tree_unlock(tp->q);
+
+			tcf_action_destroy(act,TCA_ACT_UNBIND);
+
+		}
+
+		if(tb[TCA_FW_ACT-1]) {
+			act = kmalloc(sizeof(*act),GFP_KERNEL);
+			if (NULL == act)
+				return -ENOMEM;
+			memset(act,0,sizeof(*act));
+			ret = tcf_action_init(tb[TCA_FW_ACT-1], tca[TCA_RATE-1],act,NULL, TCA_ACT_NOREPLACE,TCA_ACT_BIND);
+			if (0 > ret) {
+				tcf_action_destroy(act,TCA_ACT_UNBIND);
+				return ret;
+			}
+
+			sch_tree_lock(tp->q);
+			act = xchg(&f->action, act);
+			sch_tree_unlock(tp->q);
+
+			tcf_action_destroy(act,TCA_ACT_UNBIND);
+		}
+#ifdef CONFIG_NET_CLS_IND
+		if(tb[TCA_FW_INDEV-1]) {
+			struct rtattr *idev = tb[TCA_FW_INDEV-1];
+			if (RTA_PAYLOAD(idev) >= IFNAMSIZ) {
+				printk("cls_fw: bad indev name %s\n",(char*)RTA_DATA(idev));
+				err = -EINVAL;
+				goto errout;
+			}
+			memset(f->indev,0,IFNAMSIZ);
+			sprintf(f->indev, "%s", (char*)RTA_DATA(idev));
+		}
+#endif
+#else /* only POLICE defined */
 #ifdef CONFIG_NET_CLS_POLICE
 		if (tb[TCA_FW_POLICE-1]) {
 			struct tcf_police *police = tcf_police_locate(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1]);
@@ -214,9 +315,10 @@
 			police = xchg(&f->police, police);
 			tcf_tree_unlock(tp);
 
-			tcf_police_release(police);
+			tcf_police_release(police,TCA_ACT_UNBIND);
 		}
 #endif
+#endif
 		return 0;
 	}
 
@@ -249,10 +351,37 @@
 		cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
 	}
 
+#ifdef CONFIG_NET_CLS_ACT
+	if(tb[TCA_FW_ACT-1]) {
+		act = kmalloc(sizeof(*act),GFP_KERNEL);
+		if (NULL == act)
+			return -ENOMEM;
+		memset(act,0,sizeof(*act));
+		ret = tcf_action_init(tb[TCA_FW_ACT-1], tca[TCA_RATE-1],act,NULL,TCA_ACT_NOREPLACE,TCA_ACT_BIND);
+		if (0 > ret) {
+			tcf_action_destroy(act,TCA_ACT_UNBIND);
+			return ret;
+		}
+		f->action= act;
+	}
+#ifdef CONFIG_NET_CLS_IND
+		if(tb[TCA_FW_INDEV-1]) {
+			struct rtattr *idev = tb[TCA_FW_INDEV-1];
+			if (RTA_PAYLOAD(idev) >= IFNAMSIZ) {
+				printk("cls_fw: bad indev name %s\n",(char*)RTA_DATA(idev));
+				err = -EINVAL;
+				goto errout;
+			}
+			memset(f->indev,0,IFNAMSIZ);
+			sprintf(f->indev, "%s", (char*)RTA_DATA(idev));
+		}
+#endif
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 	if (tb[TCA_FW_POLICE-1])
 		f->police = tcf_police_locate(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1]);
 #endif
+#endif
 
 	f->next = head->ht[fw_hash(handle)];
 	tcf_tree_lock(tp);
@@ -309,9 +438,13 @@
 	t->tcm_handle = f->id;
 
        if (!f->res.classid
+#ifdef CONFIG_NET_CLS_ACT
+           && !f->action
+#else
 #ifdef CONFIG_NET_CLS_POLICE
            && !f->police
 #endif
+#endif
            )
 		return skb->len;
 
@@ -320,6 +453,36 @@
 
 	if (f->res.classid)
 		RTA_PUT(skb, TCA_FW_CLASSID, 4, &f->res.classid);
+#ifdef CONFIG_NET_CLS_ACT
+               /* again for backward compatible mode - we want
+               *  to work with both old and new modes of entering
+               *  tc data even if iproute2  was newer - jhs
+               */
+	if (f->action) {
+		struct rtattr * p_rta = (struct rtattr*)skb->tail;
+
+		if (f->action->type != TCA_OLD_COMPAT) {
+			RTA_PUT(skb, TCA_FW_ACT, 0, NULL);
+			if (tcf_action_dump(skb,f->action,0,0) < 0) {
+				goto rtattr_failure;
+			}
+		} else {
+			RTA_PUT(skb, TCA_FW_POLICE, 0, NULL);
+			if (tcf_action_dump_old(skb,f->action,0,0) < 0) {
+				goto rtattr_failure;
+			}
+		}
+
+		p_rta->rta_len = skb->tail - (u8*)p_rta;
+	}
+#ifdef CONFIG_NET_CLS_IND
+	if(strlen(f->indev)) {
+		struct rtattr * p_rta = (struct rtattr*)skb->tail;
+		RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev);
+		p_rta->rta_len = skb->tail - (u8*)p_rta;
+	}
+#endif
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 	if (f->police) {
 		struct rtattr * p_rta = (struct rtattr*)skb->tail;
@@ -332,13 +495,21 @@
 		p_rta->rta_len = skb->tail - (u8*)p_rta;
 	}
 #endif
+#endif
 
 	rta->rta_len = skb->tail - b;
+#ifdef CONFIG_NET_CLS_ACT
+       if (f->action && f->action->type == TCA_OLD_COMPAT) {
+               if (tcf_action_copy_stats(skb,f->action))
+                       goto rtattr_failure;
+       }
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 	if (f->police) {
 		if (qdisc_copy_stats(skb, &f->police->stats))
 			goto rtattr_failure;
 	}
+#endif
 #endif
 	return skb->len;
 
diff -Nru a/net/sched/cls_route.c b/net/sched/cls_route.c
--- a/net/sched/cls_route.c	2004-06-23 19:04:26 -07:00
+++ b/net/sched/cls_route.c	2004-06-23 19:04:26 -07:00
@@ -297,7 +297,7 @@
 					if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
 						tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
 #ifdef CONFIG_NET_CLS_POLICE
-					tcf_police_release(f->police);
+					tcf_police_release(f->police,TCA_ACT_UNBIND);
 #endif
 					kfree(f);
 				}
@@ -336,7 +336,7 @@
 				tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
 
 #ifdef CONFIG_NET_CLS_POLICE
-			tcf_police_release(f->police);
+			tcf_police_release(f->police,TCA_ACT_UNBIND);
 #endif
 			kfree(f);
 
@@ -398,7 +398,7 @@
 			police = xchg(&f->police, police);
 			tcf_tree_unlock(tp);
 
-			tcf_police_release(police);
+			tcf_police_release(police,TCA_ACT_UNBIND);
 		}
 #endif
 		return 0;
diff -Nru a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
--- a/net/sched/cls_rsvp.h	2004-06-23 19:04:25 -07:00
+++ b/net/sched/cls_rsvp.h	2004-06-23 19:04:25 -07:00
@@ -278,7 +278,7 @@
 					if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
 						tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
 #ifdef CONFIG_NET_CLS_POLICE
-					tcf_police_release(f->police);
+					tcf_police_release(f->police,TCA_ACT_UNBIND);
 #endif
 					kfree(f);
 				}
@@ -310,7 +310,7 @@
 				tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
 
 #ifdef CONFIG_NET_CLS_POLICE
-			tcf_police_release(f->police);
+			tcf_police_release(f->police,TCA_ACT_UNBIND);
 #endif
 
 			kfree(f);
@@ -452,7 +452,7 @@
 			police = xchg(&f->police, police);
 			tcf_tree_unlock(tp);
 
-			tcf_police_release(police);
+			tcf_police_release(police,TCA_ACT_UNBIND);
 		}
 #endif
 		return 0;
diff -Nru a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
--- a/net/sched/cls_tcindex.c	2004-06-23 19:04:26 -07:00
+++ b/net/sched/cls_tcindex.c	2004-06-23 19:04:26 -07:00
@@ -190,7 +190,7 @@
 	if (cl)
 		tp->q->ops->cl_ops->unbind_tcf(tp->q,cl);
 #ifdef CONFIG_NET_CLS_POLICE
-	tcf_police_release(r->police);
+	tcf_police_release(r->police, TCA_ACT_UNBIND);
 #endif
 	if (f)
 		kfree(f);
@@ -333,7 +333,7 @@
 		tcf_tree_lock(tp);
 		police = xchg(&r->police,police);
 		tcf_tree_unlock(tp);
-		tcf_police_release(police);
+		tcf_police_release(police,TCA_ACT_UNBIND);
 	}
 #endif
 	if (r != &new_filter_result)
diff -Nru a/net/sched/cls_u32.c b/net/sched/cls_u32.c
--- a/net/sched/cls_u32.c	2004-06-23 19:04:26 -07:00
+++ b/net/sched/cls_u32.c	2004-06-23 19:04:26 -07:00
@@ -23,6 +23,10 @@
  *	It is especially useful for link sharing combined with QoS;
  *	pure RSVP doesn't need such a general approach and can use
  *	much simpler (and faster) schemes, sort of cls_rsvp.c.
+ *
+ *	JHS: We should remove the CONFIG_NET_CLS_IND from here
+ *	eventually when the meta match extension is made available
+ *
  */
 
 #include <asm/uaccess.h>
@@ -58,9 +62,16 @@
 	struct tc_u_knode	*next;
 	u32			handle;
 	struct tc_u_hnode	*ht_up;
+#ifdef CONFIG_NET_CLS_ACT
+	struct tc_action	*action;
+#ifdef CONFIG_NET_CLS_IND
+	char                     indev[IFNAMSIZ];
+#endif
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 	struct tcf_police	*police;
 #endif
+#endif
 	struct tcf_result	res;
 	struct tc_u_hnode	*ht_down;
 	struct tc_u32_sel	sel;
@@ -90,10 +101,14 @@
 
 static __inline__ unsigned u32_hash_fold(u32 key, struct tc_u32_sel *sel)
 {
-	unsigned h = key & sel->hmask;
+#ifdef fix_u32_bug
+	unsigned h = (key & sel->hmask)>>sel->fshift;
+#else
+	unsigned h = (key & sel->hmask);
 
 	h ^= h>>16;
 	h ^= h>>8;
+#endif
 	return h;
 }
 
@@ -119,16 +134,54 @@
 	if (n) {
 		struct tc_u32_key *key = n->sel.keys;
 
+#ifdef CONFIG_CLS_U32_PERF
+		n->sel.rcnt +=1;
+#endif
 		for (i = n->sel.nkeys; i>0; i--, key++) {
+
 			if ((*(u32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) {
 				n = n->next;
 				goto next_knode;
 			}
+#ifdef CONFIG_CLS_U32_PERF
+			key->kcnt +=1;
+#endif
 		}
 		if (n->ht_down == NULL) {
 check_terminal:
 			if (n->sel.flags&TC_U32_TERMINAL) {
+
 				*res = n->res;
+#ifdef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NET_CLS_IND
+				/* yes, i know it sucks but the feature is 
+				** optional dammit! - JHS */
+				if (0 != n->indev[0]) {
+					if  (NULL == skb->input_dev) {
+						n = n->next;
+						goto next_knode;
+					} else {
+						if (0 != strcmp(n->indev, skb->input_dev->name)) {
+							n = n->next;
+							goto next_knode;
+						}
+					}
+				}
+#endif
+#ifdef CONFIG_CLS_U32_PERF
+		n->sel.rhit +=1;
+#endif
+				if (n->action) {
+					int pol_res = tcf_action_exec(skb, n->action);
+					if (skb->tc_classid > 0) {
+						res->classid = skb->tc_classid;
+						skb->tc_classid = 0;
+					}
+
+					if (pol_res >= 0)
+						return pol_res;
+				} else
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 				if (n->police) {
 					int pol_res = tcf_police(skb, n->police);
@@ -136,6 +189,7 @@
 						return pol_res;
 				} else
 #endif
+#endif
 					return 0;
 			}
 			n = n->next;
@@ -298,8 +352,14 @@
 
 	if ((cl = __cls_set_class(&n->res.class, 0)) != 0)
 		tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
+#ifdef CONFIG_NET_CLS_ACT
+	if (n->action) {
+		tcf_action_destroy(n->action, TCA_ACT_UNBIND);
+	}
+#else
 #ifdef CONFIG_NET_CLS_POLICE
-	tcf_police_release(n->police);
+	tcf_police_release(n->police, TCA_ACT_UNBIND);
+#endif
 #endif
 	if (n->ht_down)
 		n->ht_down->refcnt--;
@@ -438,6 +498,10 @@
 			 struct tc_u_knode *n, struct rtattr **tb,
 			 struct rtattr *est)
 {
+#ifdef CONFIG_NET_CLS_ACT
+	struct tc_action *act = NULL;
+	int ret;
+#endif
 	if (tb[TCA_U32_LINK-1]) {
 		u32 handle = *(u32*)RTA_DATA(tb[TCA_U32_LINK-1]);
 		struct tc_u_hnode *ht_down = NULL;
@@ -470,17 +534,73 @@
 		if (cl)
 			q->ops->cl_ops->unbind_tcf(q, cl);
 	}
+#ifdef CONFIG_NET_CLS_ACT
+	/*backward compatibility */
+	if (tb[TCA_U32_POLICE-1])
+	{
+		act = kmalloc(sizeof(*act),GFP_KERNEL);
+		if (NULL == act)
+			return -ENOMEM;
+
+		memset(act,0,sizeof(*act));
+		ret = tcf_action_init_1(tb[TCA_U32_POLICE-1], est,act,"police", TCA_ACT_NOREPLACE, TCA_ACT_BIND);
+		if (0 > ret){
+			tcf_action_destroy(act, TCA_ACT_UNBIND);
+			return ret;
+		}
+		act->type = TCA_OLD_COMPAT;
+
+		sch_tree_lock(q);
+		act = xchg(&n->action, act);
+		sch_tree_unlock(q);
+
+		tcf_action_destroy(act, TCA_ACT_UNBIND);
+
+	}
+
+	if(tb[TCA_U32_ACT-1]) {
+		act = kmalloc(sizeof(*act),GFP_KERNEL);
+		if (NULL == act)
+			return -ENOMEM;
+		memset(act,0,sizeof(*act));
+		ret = tcf_action_init(tb[TCA_U32_ACT-1], est,act,NULL,TCA_ACT_NOREPLACE, TCA_ACT_BIND);
+		if (0 > ret) {
+			tcf_action_destroy(act, TCA_ACT_UNBIND);
+			return ret;
+		}
+
+		sch_tree_lock(q);
+		act = xchg(&n->action, act);
+		sch_tree_unlock(q);
+
+		tcf_action_destroy(act, TCA_ACT_UNBIND);
+	}
+
+#ifdef CONFIG_NET_CLS_IND
+	n->indev[0] = 0;
+	if(tb[TCA_U32_INDEV-1]) {
+		struct rtattr *input_dev = tb[TCA_U32_INDEV-1];
+		if (RTA_PAYLOAD(input_dev) >= IFNAMSIZ) {
+			printk("cls_u32: bad indev name %s\n",(char*)RTA_DATA(input_dev));
+			/* should we clear state first? */
+			return  -EINVAL;
+		}
+		sprintf(n->indev, "%s", (char*)RTA_DATA(input_dev));
+	}
+#endif
+
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 	if (tb[TCA_U32_POLICE-1]) {
 		struct tcf_police *police = tcf_police_locate(tb[TCA_U32_POLICE-1], est);
-
 		sch_tree_lock(q);
 		police = xchg(&n->police, police);
 		sch_tree_unlock(q);
-
-		tcf_police_release(police);
+		tcf_police_release(police, TCA_ACT_UNBIND);
 	}
 #endif
+#endif
+
 	return 0;
 }
 
@@ -566,6 +686,14 @@
 		return -EINVAL;
 
 	s = RTA_DATA(tb[TCA_U32_SEL-1]);
+
+#ifdef CONFIG_CLS_U32_PERF
+	if (RTA_PAYLOAD(tb[TCA_U32_SEL-1]) < 
+		(s->nkeys*sizeof(struct tc_u32_key)) + sizeof(struct tc_u32_sel)) {
+			printk("Please upgrade your iproute2 tools or compile proper options in!\n");
+			return -EINVAL;
+}
+#endif
 	n = kmalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
 	if (n == NULL)
 		return -ENOBUFS;
@@ -656,26 +784,68 @@
 			RTA_PUT(skb, TCA_U32_CLASSID, 4, &n->res.classid);
 		if (n->ht_down)
 			RTA_PUT(skb, TCA_U32_LINK, 4, &n->ht_down->handle);
+#ifdef CONFIG_CLS_U32_PERF2
+		n->sel.rcnt = n->sel.rhit = 0;
+#endif
+#ifdef CONFIG_NET_CLS_ACT
+		/* again for backward compatible mode - we want
+		*  to work with both old and new modes of entering
+		*  tc data even if iproute2  was newer - jhs 
+		*/
+		if (n->action) {
+			struct rtattr * p_rta = (struct rtattr*)skb->tail;
+
+			if (n->action->type != TCA_OLD_COMPAT) {
+				RTA_PUT(skb, TCA_U32_ACT, 0, NULL);
+				if (tcf_action_dump(skb,n->action, 0, 0) < 0) {
+					goto rtattr_failure;
+				}
+			} else {
+				RTA_PUT(skb, TCA_U32_POLICE, 0, NULL);
+				if (tcf_action_dump_old(skb,n->action,0,0) < 0) {
+					goto rtattr_failure;
+				}
+			}
+
+			p_rta->rta_len = skb->tail - (u8*)p_rta;
+		}
+#ifdef CONFIG_NET_CLS_IND
+		if(strlen(n->indev)) {
+			struct rtattr * p_rta = (struct rtattr*)skb->tail;
+			RTA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev);
+			p_rta->rta_len = skb->tail - (u8*)p_rta;
+		}
+#endif
+
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 		if (n->police) {
 			struct rtattr * p_rta = (struct rtattr*)skb->tail;
-
 			RTA_PUT(skb, TCA_U32_POLICE, 0, NULL);
-
+	 
 			if (tcf_police_dump(skb, n->police) < 0)
 				goto rtattr_failure;
 
 			p_rta->rta_len = skb->tail - (u8*)p_rta;
+
 		}
 #endif
+#endif
 	}
 
 	rta->rta_len = skb->tail - b;
+#ifdef CONFIG_NET_CLS_ACT
+	if (TC_U32_KEY(n->handle) && n->action && n->action->type == TCA_OLD_COMPAT) {
+		if (tcf_action_copy_stats(skb,n->action))
+			goto rtattr_failure;
+	}
+#else
 #ifdef CONFIG_NET_CLS_POLICE
 	if (TC_U32_KEY(n->handle) && n->police) {
-		if (qdisc_copy_stats(skb, &n->police->stats))
+		if (qdisc_copy_stats(skb,&n->police->stats))
 			goto rtattr_failure;
 	}
+#endif
 #endif
 	return skb->len;
 
diff -Nru a/net/sched/police.c b/net/sched/police.c
--- a/net/sched/police.c	2004-06-23 19:04:28 -07:00
+++ b/net/sched/police.c	2004-06-23 19:04:28 -07:00
@@ -7,6 +7,7 @@
  *		2 of the License, or (at your option) any later version.
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ * 		J Hadi Salim (action changes)
  */
 
 #include <asm/uaccess.h>
@@ -26,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
+#include <linux/module.h>
 #include <linux/rtnetlink.h>
 #include <linux/init.h>
 #include <net/sock.h>
@@ -33,9 +35,13 @@
 
 #define L2T(p,L)   ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log])
 #define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log])
+#define PRIV(a) ((struct tcf_police *) (a)->priv)
 
+/* use generic hash table */
+#define MY_TAB_SIZE     16
+#define MY_TAB_MASK     15
 static u32 idx_gen;
-static struct tcf_police *tcf_police_ht[16];
+static struct tcf_police *tcf_police_ht[MY_TAB_SIZE];
 /* Policer hash table lock */
 static rwlock_t police_lock = RW_LOCK_UNLOCKED;
 
@@ -59,6 +65,68 @@
 	return p;
 }
 
+#ifdef CONFIG_NET_CLS_ACT
+static __inline__ int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, int type, struct tc_action *a)
+{
+	struct tcf_police *p;
+	int err =0, index =  -1,i= 0, s_i = 0, n_i = 0;
+	struct rtattr *r ;
+
+	read_lock(&police_lock);
+
+	s_i = cb->args[0];
+
+	for (i = 0; i < MY_TAB_SIZE; i++) {
+		p = tcf_police_ht[tcf_police_hash(i)];
+
+		for (; p; p = p->next) {
+			index++;
+			if (index < s_i)
+				continue;
+			a->priv = p;
+			a->order = index;
+			r = (struct rtattr*) skb->tail;
+			RTA_PUT(skb, a->order, 0, NULL);
+			if (type == RTM_DELACTION)
+				err = tcf_action_dump_1(skb, a, 0, 1);
+			else
+				err = tcf_action_dump_1(skb, a, 0, 0);
+			if (0 > err) {
+				index--;
+				skb_trim(skb, (u8*)r - skb->data);
+				goto done;
+			}
+			r->rta_len = skb->tail - (u8*)r;
+			n_i++;
+		}
+	}
+done:
+	read_unlock(&police_lock);
+	if (n_i)
+		cb->args[0] += n_i;
+	return n_i;
+
+rtattr_failure:
+	skb_trim(skb, (u8*)r - skb->data);
+	goto done;
+}
+
+static inline int
+tcf_hash_search(struct tc_action *a, u32 index)
+{
+	struct tcf_police *p = tcf_police_lookup(index);
+
+	if (p != NULL) {
+		a->priv = p;
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+
+#endif
+
 static __inline__ u32 tcf_police_new_index(void)
 {
 	do {
@@ -93,6 +161,269 @@
 	}
 	BUG_TRAP(0);
 }
+
+#ifdef CONFIG_NET_CLS_ACT
+int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,struct tc_action *a, int ovr, int bind)
+{
+	unsigned h;
+	int ret = 0;
+	struct rtattr *tb[TCA_POLICE_MAX];
+	struct tc_police *parm;
+	struct tcf_police *p;
+
+	if (NULL == a) {
+		if (net_ratelimit())
+			printk("BUG: tcf_police_locate called with NULL params\n");
+		return -1;  
+	}
+
+	if (rtattr_parse(tb, TCA_POLICE_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
+		return -1;
+
+	if (tb[TCA_POLICE_TBF-1] == NULL)
+		return -1;
+
+	parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
+
+	if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
+		a->priv = (void *)p;
+		spin_lock(&p->lock);
+		if (bind) {
+			p->bindcnt += 1;
+			p->refcnt += 1;
+		}
+		if (ovr) {
+			goto override;
+		}
+		spin_unlock(&p->lock);
+		return ret; 
+	}
+
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (p == NULL)
+		return -1;
+
+	memset(p, 0, sizeof(*p));
+	ret = 1;
+	p->refcnt = 1;
+	spin_lock_init(&p->lock);
+	p->stats.lock = &p->lock;
+	if (bind)
+		p->bindcnt = 1;
+override:
+	if (parm->rate.rate) {
+		if ((p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1])) == NULL) {
+			goto failure;
+		}
+		if (parm->peakrate.rate &&
+		    (p->P_tab = qdisc_get_rtab(&parm->peakrate, tb[TCA_POLICE_PEAKRATE-1])) == NULL) {
+			goto failure;
+		}
+	}
+	if (tb[TCA_POLICE_RESULT-1])
+		p->result = *(int*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
+#ifdef CONFIG_NET_ESTIMATOR
+	if (tb[TCA_POLICE_AVRATE-1])
+		p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
+#endif
+	p->toks = p->burst = parm->burst;
+	p->mtu = parm->mtu;
+	if (p->mtu == 0) {
+		p->mtu = ~0;
+		if (p->R_tab)
+			p->mtu = 255<<p->R_tab->rate.cell_log;
+	}
+	if (p->P_tab)
+		p->ptoks = L2T_P(p, p->mtu);
+	p->action = parm->action;
+
+	if (ovr) {
+		spin_unlock(&p->lock);
+		return ret;
+	}
+	PSCHED_GET_TIME(p->t_c);
+	p->index = parm->index ? : tcf_police_new_index();
+#ifdef CONFIG_NET_ESTIMATOR
+	if (est)
+		qdisc_new_estimator(&p->stats, est);
+#endif
+	h = tcf_police_hash(p->index);
+	write_lock_bh(&police_lock);
+	p->next = tcf_police_ht[h];
+	tcf_police_ht[h] = p;
+	write_unlock_bh(&police_lock);
+
+	a->priv = (void *)p;
+	return ret;  
+
+failure:
+	if (p->R_tab)
+		qdisc_put_rtab(p->R_tab);
+	if (ovr)
+		spin_unlock(&p->lock);
+	kfree(p);
+	return -1;
+}
+
+int tcf_act_police_cleanup(struct tc_action *a, int bind)
+{
+	struct tcf_police *p;
+	p = PRIV(a);
+	if (NULL != p) 
+		return tcf_police_release(p, bind);
+
+	return 0;
+}
+
+int tcf_act_police_stats(struct sk_buff *skb, struct tc_action *a)
+{
+	struct tcf_police *p;
+	p = PRIV(a);
+	if (NULL != p) 
+		return qdisc_copy_stats(skb, &p->stats);
+
+	return 1;
+}
+
+int tcf_act_police(struct sk_buff **pskb, struct tc_action *a)
+{
+	psched_time_t now;
+	struct sk_buff *skb = *pskb;
+	struct tcf_police *p;
+	long toks;
+	long ptoks = 0;
+
+	p = PRIV(a);
+
+	if (NULL == p) {
+		printk("BUG: tcf_police called with NULL params\n");
+		return -1;  
+	}
+
+	spin_lock(&p->lock);
+
+	p->stats.bytes += skb->len;
+	p->stats.packets++;
+
+#ifdef CONFIG_NET_ESTIMATOR
+	if (p->ewma_rate && p->stats.bps >= p->ewma_rate) {
+		p->stats.overlimits++;
+		spin_unlock(&p->lock);
+		return p->action;
+	}
+#endif
+
+	if (skb->len <= p->mtu) {
+		if (p->R_tab == NULL) {
+			spin_unlock(&p->lock);
+			return p->result;
+		}
+
+		PSCHED_GET_TIME(now);
+
+		toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst, 0);
+
+		if (p->P_tab) {
+			ptoks = toks + p->ptoks;
+			if (ptoks > (long)L2T_P(p, p->mtu))
+				ptoks = (long)L2T_P(p, p->mtu);
+			ptoks -= L2T_P(p, skb->len);
+		}
+		toks += p->toks;
+		if (toks > (long)p->burst)
+			toks = p->burst;
+		toks -= L2T(p, skb->len);
+
+		if ((toks|ptoks) >= 0) {
+			p->t_c = now;
+			p->toks = toks;
+			p->ptoks = ptoks;
+			spin_unlock(&p->lock);
+			return p->result;
+		}
+	}
+
+	p->stats.overlimits++;
+	spin_unlock(&p->lock);
+	return p->action;
+}
+
+int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+	unsigned char	 *b = skb->tail;
+	struct tc_police opt;
+	struct tcf_police *p;
+
+	p = PRIV(a);
+	if (NULL == p) {
+		printk("BUG: tcf_police_dump called with NULL params\n");
+		goto rtattr_failure;
+	}
+
+	opt.index = p->index;
+	opt.action = p->action;
+	opt.mtu = p->mtu;
+	opt.burst = p->burst;
+	opt.refcnt = p->refcnt - ref;
+	opt.bindcnt = p->bindcnt - bind;
+	if (p->R_tab)
+		opt.rate = p->R_tab->rate;
+	else
+		memset(&opt.rate, 0, sizeof(opt.rate));
+	if (p->P_tab)
+		opt.peakrate = p->P_tab->rate;
+	else
+		memset(&opt.peakrate, 0, sizeof(opt.peakrate));
+	RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
+	if (p->result)
+		RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result);
+#ifdef CONFIG_NET_ESTIMATOR
+	if (p->ewma_rate)
+		RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate);
+#endif
+	return skb->len;
+
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+MODULE_AUTHOR("Alexey Kuznetsov");
+MODULE_DESCRIPTION("Policing actions");
+MODULE_LICENSE("GPL");
+
+
+static struct tc_action_ops act_police_ops = {
+	.next		=	NULL,
+	.kind		=	"police",
+	.type		=	TCA_ID_POLICE, 
+	.capab		=	TCA_CAP_NONE, 
+	.owner		=	THIS_MODULE,
+	.act		=	tcf_act_police,
+	.get_stats	=	tcf_act_police_stats,
+	.dump		=	tcf_act_police_dump,
+	.cleanup	=	tcf_act_police_cleanup,
+	.lookup		=	tcf_hash_search,
+	.init		=	tcf_act_police_locate,
+	.walk		=	tcf_generic_walker
+};
+
+static int __init
+police_init_module(void)
+{
+	return tcf_register_action(&act_police_ops);
+}
+
+static void __exit
+police_cleanup_module(void)
+{
+	tcf_unregister_action(&act_police_ops);
+}
+
+module_init(police_init_module);
+module_exit(police_cleanup_module);
+
+#endif
 
 struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
 {
diff -Nru a/net/sched/sch_api.c b/net/sched/sch_api.c
--- a/net/sched/sch_api.c	2004-06-23 19:04:26 -07:00
+++ b/net/sched/sch_api.c	2004-06-23 19:04:26 -07:00
@@ -450,6 +450,9 @@
 	if (!try_module_get(ops->owner))
 		goto err_out;
 
+	/* enqueue is accessed locklessly - make sure it's visible
+	 * before we set a netdevice's qdisc pointer to sch */
+	smp_wmb();
 	if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
 		write_lock(&qdisc_tree_lock);
 		sch->next = dev->qdisc_list;
diff -Nru a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
--- a/net/sched/sch_cbq.c	2004-06-23 19:04:25 -07:00
+++ b/net/sched/sch_cbq.c	2004-06-23 19:04:25 -07:00
@@ -1054,7 +1054,7 @@
 
 	if (sch->q.qlen) {
 		sch->stats.overlimits++;
-		if (q->wd_expires && !netif_queue_stopped(sch->dev)) {
+		if (q->wd_expires) {
 			long delay = PSCHED_US2JIFFIE(q->wd_expires);
 			if (delay <= 0)
 				delay = 1;
diff -Nru a/net/sched/sch_delay.c b/net/sched/sch_delay.c
--- a/net/sched/sch_delay.c	2004-06-23 19:04:25 -07:00
+++ b/net/sched/sch_delay.c	2004-06-23 19:04:25 -07:00
@@ -40,6 +40,7 @@
 struct dly_sched_data {
 	u32	latency;
 	u32	limit;
+	u32	loss;
 	struct timer_list timer;
 	struct Qdisc *qdisc;
 };
@@ -58,6 +59,12 @@
 	struct dly_skb_cb *cb = (struct dly_skb_cb *)skb->cb;
 	int ret;
 
+	/* Random packet drop 0 => none, ~0 => all */
+	if (q->loss >= net_random()) {
+		sch->stats.drops++;
+		return 0;	/* lie about loss so TCP doesn't know */
+	}
+
 	PSCHED_GET_TIME(cb->queuetime);
 
 	/* Queue to underlying scheduler */
@@ -69,7 +76,7 @@
 		sch->stats.bytes += skb->len;
 		sch->stats.packets++;
 	}
-	return 0;
+	return ret;
 }
 
 /* Requeue packets but don't change time stamp */
@@ -104,12 +111,14 @@
 static struct sk_buff *dly_dequeue(struct Qdisc *sch)
 {
 	struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
-	struct sk_buff *skb = q->qdisc->dequeue(q->qdisc);
+	struct sk_buff *skb;
 
+ retry:
+	skb = q->qdisc->dequeue(q->qdisc);
 	if (skb) {
 		struct dly_skb_cb *cb = (struct dly_skb_cb *)skb->cb;
 		psched_time_t now;
-		long diff;
+		long diff, delay;
 
 		PSCHED_GET_TIME(now);
 		diff = q->latency - PSCHED_TDIFF(now, cb->queuetime);
@@ -120,17 +129,17 @@
 			return skb;
 		}
 
-		if (!netif_queue_stopped(sch->dev)) {
-			long delay = PSCHED_US2JIFFIE(diff);
-			if (delay <= 0)
-				delay = 1;
-			mod_timer(&q->timer, jiffies+delay);
-		}
-
 		if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
 			sch->q.qlen--;
 			sch->stats.drops++;
+			goto retry;
 		}
+
+		delay = PSCHED_US2JIFFIE(diff);
+		if (delay <= 0)
+		  delay = 1;
+		mod_timer(&q->timer, jiffies+delay);
+
 		sch->flags |= TCQ_F_THROTTLED;
 	}
 	return NULL;
@@ -195,6 +204,7 @@
 	} else {
 		q->latency = qopt->latency;
 		q->limit = qopt->limit;
+		q->loss = qopt->loss;
 	}
 	return err;
 }
@@ -231,6 +241,7 @@
 
 	qopt.latency = q->latency;
 	qopt.limit = q->limit;
+	qopt.loss = q->loss;
 
 	RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
 
diff -Nru a/net/sched/sch_generic.c b/net/sched/sch_generic.c
--- a/net/sched/sch_generic.c	2004-06-23 19:04:25 -07:00
+++ b/net/sched/sch_generic.c	2004-06-23 19:04:25 -07:00
@@ -30,6 +30,7 @@
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/init.h>
+#include <linux/rcupdate.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 
@@ -387,6 +388,9 @@
 	sch->dev = dev;
 	sch->stats.lock = &dev->queue_lock;
 	atomic_set(&sch->refcnt, 1);
+	/* enqueue is accessed locklessly - make sure it's visible
+	 * before we set a netdevice's qdisc pointer to sch */
+	smp_wmb();
 	if (!ops->init || ops->init(sch, NULL) == 0)
 		return sch;
 
@@ -404,18 +408,36 @@
 		ops->reset(qdisc);
 }
 
+/* this is the rcu callback function to clean up a qdisc when there 
+ * are no further references to it */
+
+static void __qdisc_destroy (void * arg) 
+{
+	struct Qdisc    *qdisc = (struct Qdisc *) arg;
+	struct Qdisc_ops  *ops = qdisc->ops;
+
+#ifdef CONFIG_NET_ESTIMATOR
+	qdisc_kill_estimator(&qdisc->stats);
+#endif
+	if (ops->reset)
+		ops->reset(qdisc);
+	if (ops->destroy)
+		ops->destroy(qdisc);
+	module_put(ops->owner);
+
+	if (!(qdisc->flags&TCQ_F_BUILTIN))
+		kfree(qdisc);
+}
+
 /* Under dev->queue_lock and BH! */
 
 void qdisc_destroy(struct Qdisc *qdisc)
 {
-	struct Qdisc_ops *ops = qdisc->ops;
-	struct net_device *dev;
+	struct net_device *dev = qdisc->dev;
 
 	if (!atomic_dec_and_test(&qdisc->refcnt))
 		return;
 
-	dev = qdisc->dev;
-
 	if (dev) {
 		struct Qdisc *q, **qp;
 		for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) {
@@ -425,16 +447,9 @@
 			}
 		}
 	}
-#ifdef CONFIG_NET_ESTIMATOR
-	qdisc_kill_estimator(&qdisc->stats);
-#endif
-	if (ops->reset)
-		ops->reset(qdisc);
-	if (ops->destroy)
-		ops->destroy(qdisc);
-	module_put(ops->owner);
-	if (!(qdisc->flags&TCQ_F_BUILTIN))
-		kfree(qdisc);
+
+	call_rcu(&qdisc->q_rcu, __qdisc_destroy, qdisc);
+
 }
 
 
diff -Nru a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
--- a/net/sched/sch_hfsc.c	2004-06-23 19:04:25 -07:00
+++ b/net/sched/sch_hfsc.c	2004-06-23 19:04:25 -07:00
@@ -1721,8 +1721,7 @@
 		cl = actlist_get_minvt(&q->root, cur_time);
 		if (cl == NULL) {
 			sch->stats.overlimits++;
-			if (!netif_queue_stopped(sch->dev))
-				hfsc_schedule_watchdog(sch, cur_time);
+			hfsc_schedule_watchdog(sch, cur_time);
 			return NULL;
 		}
 	}
diff -Nru a/net/sched/sch_htb.c b/net/sched/sch_htb.c
--- a/net/sched/sch_htb.c	2004-06-23 19:04:27 -07:00
+++ b/net/sched/sch_htb.c	2004-06-23 19:04:27 -07:00
@@ -1008,7 +1008,6 @@
 static void htb_delay_by(struct Qdisc *sch,long delay)
 {
 	struct htb_sched *q = (struct htb_sched *)sch->data;
-	if (netif_queue_stopped(sch->dev)) return;
 	if (delay <= 0) delay = 1;
 	if (unlikely(delay > 5*HZ)) {
 		if (net_ratelimit())
diff -Nru a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
--- a/net/sched/sch_ingress.c	2004-06-23 19:04:28 -07:00
+++ b/net/sched/sch_ingress.c	2004-06-23 19:04:28 -07:00
@@ -45,7 +45,11 @@
 
 /* Thanks to Doron Oz for this hack
 */
+#ifndef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NETFILTER
 static int nf_registered; 
+#endif
+#endif
 
 struct ingress_qdisc_data {
 	struct Qdisc		*q;
@@ -146,27 +150,52 @@
 	 * Unlike normal "enqueue" functions, ingress_enqueue returns a
 	 * firewall FW_* code.
 	 */
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
+	sch->stats.packets++;
+	sch->stats.bytes += skb->len;
 	switch (result) {
-		case TC_POLICE_SHOT:
-			result = NF_DROP;
+		case TC_ACT_SHOT:
+			result = TC_ACT_SHOT;
 			sch->stats.drops++;
 			break;
+		case TC_ACT_STOLEN:
+		case TC_ACT_QUEUED:
+			result = TC_ACT_STOLEN;
+			break;
+		case TC_ACT_RECLASSIFY: 
+		case TC_ACT_OK:
+		case TC_ACT_UNSPEC:
+		default:
+			skb->tc_index = TC_H_MIN(res.classid);
+			result = TC_ACT_OK;
+			break;
+	};
+/* backward compat */
+#else
+#ifdef	CONFIG_NET_CLS_POLICE  
+	switch (result) {
+		case TC_POLICE_SHOT:
+		result = NF_DROP;
+		sch->stats.drops++;
+		break;
 		case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */
 		case TC_POLICE_OK:
 		case TC_POLICE_UNSPEC:
 		default:
-			sch->stats.packets++;
-			sch->stats.bytes += skb->len;
-			result = NF_ACCEPT;
-			break;
+		sch->stats.packets++;
+		sch->stats.bytes += skb->len;
+		result = NF_ACCEPT;
+		break;
 	};
+
 #else
+	D2PRINTK("Overriding result to ACCEPT\n");
+	result = NF_ACCEPT;
 	sch->stats.packets++;
 	sch->stats.bytes += skb->len;
 #endif
+#endif
 
-	skb->tc_index = TC_H_MIN(res.classid);
 	return result;
 }
 
@@ -199,6 +228,8 @@
 	return 0;
 }
 
+#ifndef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NETFILTER
 static unsigned int
 ing_hook(unsigned int hook, struct sk_buff **pskb,
                              const struct net_device *indev,
@@ -240,10 +271,29 @@
 	.priority       = NF_IP_PRI_FILTER + 1,
 };
 
+#endif
+#endif
+
 int ingress_init(struct Qdisc *sch,struct rtattr *opt)
 {
 	struct ingress_qdisc_data *p = PRIV(sch);
 
+/* Make sure either netfilter or preferably CLS_ACT is
+* compiled in */
+#ifndef CONFIG_NET_CLS_ACT
+#ifndef CONFIG_NETFILTER
+	printk("You MUST compile classifier actions into the kernel\n");
+	goto error;
+#else
+	printk("Ingress scheduler: Classifier actions prefered over netfilter\n");
+#endif
+#endif
+                                                                                
+	if (NULL == p)
+		goto error;
+
+#ifndef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NETFILTER
 	if (!nf_registered) {
 		if (nf_register_hook(&ing_ops) < 0) {
 			printk("ingress qdisc registration error \n");
@@ -251,6 +301,8 @@
 		}
 		nf_registered++;
 	}
+#endif
+#endif
 
 	DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
 	memset(p, 0, sizeof(*p));
@@ -364,8 +416,12 @@
 static void __exit ingress_module_exit(void) 
 {
 	unregister_qdisc(&ingress_qdisc_ops);
+#ifndef CONFIG_NET_CLS_ACT
+#ifdef CONFIG_NETFILTER
 	if (nf_registered)
 		nf_unregister_hook(&ing_ops);
+#endif
+#endif
 }
 module_init(ingress_module_init)
 module_exit(ingress_module_exit)
diff -Nru a/net/sched/sch_prio.c b/net/sched/sch_prio.c
--- a/net/sched/sch_prio.c	2004-06-23 19:04:26 -07:00
+++ b/net/sched/sch_prio.c	2004-06-23 19:04:26 -07:00
@@ -47,60 +47,105 @@
 };
 
 
-static __inline__ unsigned prio_classify(struct sk_buff *skb, struct Qdisc *sch)
+struct Qdisc *prio_classify(struct sk_buff *skb, struct Qdisc *sch,int *r)
 {
 	struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
 	struct tcf_result res;
 	u32 band;
+	int result = 0;
 
 	band = skb->priority;
+
 	if (TC_H_MAJ(skb->priority) != sch->handle) {
+#ifdef CONFIG_NET_CLS_ACT
+		*r = result = tc_classify(skb, q->filter_list, &res);
+
+		switch (result) {
+			case TC_ACT_SHOT:
+			case TC_ACT_STOLEN:
+			case TC_ACT_QUEUED:
+				kfree_skb(skb);
+				return NULL;
+			case TC_ACT_RECLASSIFY:
+			case TC_ACT_OK:
+			case TC_ACT_UNSPEC:
+			default:
+			break;
+		};
+
+		if (!q->filter_list ) {
+#else
 		if (!q->filter_list || tc_classify(skb, q->filter_list, &res)) {
+#endif
 			if (TC_H_MAJ(band))
 				band = 0;
-			return q->prio2band[band&TC_PRIO_MAX];
+			return q->queues[q->prio2band[band&TC_PRIO_MAX]];
 		}
 		band = res.classid;
 	}
 	band = TC_H_MIN(band) - 1;
-	return band < q->bands ? band : q->prio2band[0];
+	if (band > q->bands)
+		return q->queues[q->prio2band[0]];
+
+	return q->queues[band];
 }
 
 static int
 prio_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {
-	struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
 	struct Qdisc *qdisc;
 	int ret;
 
-	qdisc = q->queues[prio_classify(skb, sch)];
+	/* moving these up here changes things from before
+	 * packets counted now include everything that was ever
+	 * seen
+        */
+	sch->stats.bytes += skb->len;
+	sch->stats.packets++;
+	qdisc = prio_classify(skb, sch, &ret);
+	if (NULL == qdisc)
+		goto dropped;
 
 	if ((ret = qdisc->enqueue(skb, qdisc)) == 0) {
-		sch->stats.bytes += skb->len;
-		sch->stats.packets++;
 		sch->q.qlen++;
-		return 0;
+		return NET_XMIT_SUCCESS;
 	}
-	sch->stats.drops++;
-	return ret;
+
+dropped:
+#ifdef CONFIG_NET_CLS_ACT
+	if (TC_ACT_SHOT == ret || NET_XMIT_DROP == ret) {
+#endif
+		sch->stats.drops++;
+		return NET_XMIT_DROP;
+#ifdef CONFIG_NET_CLS_ACT
+	} else {
+		sch->stats.overlimits++; /* abuse, but noone uses it */
+		return NET_XMIT_BYPASS; /* we dont want to confuse TCP */
+	}
+#endif
 }
 
 
 static int
 prio_requeue(struct sk_buff *skb, struct Qdisc* sch)
 {
-	struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
 	struct Qdisc *qdisc;
-	int ret;
+	int ret = NET_XMIT_DROP;
 
-	qdisc = q->queues[prio_classify(skb, sch)];
+#ifdef CONFIG_NET_CLS_ACT
+	sch->stats.reqs++;
+#endif
+	qdisc = prio_classify(skb, sch, &ret);
+	if (qdisc == NULL)
+		goto dropped;
 
 	if ((ret = qdisc->ops->requeue(skb, qdisc)) == 0) {
 		sch->q.qlen++;
 		return 0;
 	}
+dropped:
 	sch->stats.drops++;
-	return ret;
+	return NET_XMIT_DROP;
 }
 
 
diff -Nru a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
--- a/net/sched/sch_tbf.c	2004-06-23 19:04:25 -07:00
+++ b/net/sched/sch_tbf.c	2004-06-23 19:04:25 -07:00
@@ -201,7 +201,7 @@
 
 	if (skb) {
 		psched_time_t now;
-		long toks;
+		long toks, delay;
 		long ptoks = 0;
 		unsigned int len = skb->len;
 
@@ -229,14 +229,12 @@
 			return skb;
 		}
 
-		if (!netif_queue_stopped(sch->dev)) {
-			long delay = PSCHED_US2JIFFIE(max_t(long, -toks, -ptoks));
+		delay = PSCHED_US2JIFFIE(max_t(long, -toks, -ptoks));
 
-			if (delay == 0)
-				delay = 1;
+		if (delay == 0)
+			delay = 1;
 
-			mod_timer(&q->wd_timer, jiffies+delay);
-		}
+		mod_timer(&q->wd_timer, jiffies+delay);
 
 		/* Maybe we have a shorter packet in the queue,
 		   which can be sent now. It sounds cool,
diff -Nru a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
--- a/net/sctp/sm_make_chunk.c	2004-06-23 19:04:25 -07:00
+++ b/net/sctp/sm_make_chunk.c	2004-06-23 19:04:25 -07:00
@@ -1834,23 +1834,28 @@
 	/* Allocate storage for the negotiated streams if it is not a temporary 	 * association.
 	 */
 	if (!asoc->temp) {
-		sctp_assoc_t assoc_id;
+		int assoc_id;
+		int error;
 
 		asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams,
 					       asoc->c.sinit_num_ostreams, gfp);
 		if (!asoc->ssnmap)
 			goto clean_up;
 
-		do {
-			if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
-				goto clean_up;
-			spin_lock_bh(&sctp_assocs_id_lock);
-			assoc_id = (sctp_assoc_t)idr_get_new(&sctp_assocs_id,
-							     (void *)asoc);
-			spin_unlock_bh(&sctp_assocs_id_lock);
-		} while (unlikely((int)assoc_id == -1));
+	retry:
+		if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
+			goto clean_up;
+		spin_lock_bh(&sctp_assocs_id_lock);
+		error = idr_get_new(&sctp_assocs_id,
+				    (void *)asoc,
+				    &assoc_id);
+		spin_unlock_bh(&sctp_assocs_id_lock);
+		if (error == -EAGAIN)
+			goto retry;
+		else if (error)
+			goto clean_up;
 
-		asoc->assoc_id = assoc_id;
+		asoc->assoc_id = (sctp_assoc_t) assoc_id;
 	}
 
 	/* ADDIP Section 4.1 ASCONF Chunk Procedures
diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c
--- a/net/sctp/socket.c	2004-06-23 19:04:29 -07:00
+++ b/net/sctp/socket.c	2004-06-23 19:04:29 -07:00
@@ -990,7 +990,7 @@
  * Note:  This function could use a rewrite especially when explicit
  * connect support comes in.
  */
-/* BUG:  We do not implement the equivalent of wait_for_tcp_memory(). */
+/* BUG:  We do not implement the equivalent of sk_stream_wait_memory(). */
 
 SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *);
 
diff -Nru a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
--- a/net/sunrpc/svcsock.c	2004-06-23 19:04:25 -07:00
+++ b/net/sunrpc/svcsock.c	2004-06-23 19:04:25 -07:00
@@ -125,7 +125,7 @@
 	int wspace;
 
 	if (svsk->sk_sock->type == SOCK_STREAM)
-		wspace = tcp_wspace(svsk->sk_sk);
+		wspace = sk_stream_wspace(svsk->sk_sk);
 	else
 		wspace = sock_wspace(svsk->sk_sk);
 
diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	2004-06-23 19:04:27 -07:00
+++ b/net/sunrpc/xprt.c	2004-06-23 19:04:27 -07:00
@@ -1086,8 +1086,8 @@
 
 	/* Wait until we have enough socket memory */
 	if (xprt->stream) {
-		/* from net/ipv4/tcp.c:tcp_write_space */
-		if (tcp_wspace(sk) < tcp_min_write_space(sk))
+		/* from net/core/stream.c:sk_stream_write_space */
+		if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
 			goto out;
 	} else {
 		/* from net/core/sock.c:sock_def_write_space */
diff -Nru a/net/xfrm/Makefile b/net/xfrm/Makefile
--- a/net/xfrm/Makefile	2004-06-23 19:04:29 -07:00
+++ b/net/xfrm/Makefile	2004-06-23 19:04:29 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the XFRM subsystem.
 #
 
-obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o xfrm_output.o \
+obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o \
 	xfrm_export.o
 obj-$(CONFIG_XFRM_USER) += xfrm_user.o
 
diff -Nru a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c
--- a/net/xfrm/xfrm_export.c	2004-06-23 19:04:27 -07:00
+++ b/net/xfrm/xfrm_export.c	2004-06-23 19:04:27 -07:00
@@ -18,6 +18,7 @@
 EXPORT_SYMBOL(xfrm_state_update);
 EXPORT_SYMBOL(xfrm_state_check_expire);
 EXPORT_SYMBOL(xfrm_state_check_space);
+EXPORT_SYMBOL(xfrm_state_check);
 EXPORT_SYMBOL(xfrm_state_lookup);
 EXPORT_SYMBOL(xfrm_state_register_afinfo);
 EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
@@ -27,7 +28,6 @@
 EXPORT_SYMBOL(xfrm_replay_check);
 EXPORT_SYMBOL(xfrm_replay_advance);
 EXPORT_SYMBOL(xfrm_check_selectors);
-EXPORT_SYMBOL(xfrm_check_output);
 EXPORT_SYMBOL(__secpath_destroy);
 EXPORT_SYMBOL(secpath_dup);
 EXPORT_SYMBOL(xfrm_get_acqseq);
diff -Nru a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
--- a/net/xfrm/xfrm_output.c	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,46 +0,0 @@
-/* 
- * generic xfrm output routines
- *
- * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option) 
- * any later version.
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <net/xfrm.h>
-
-int xfrm_check_output(struct xfrm_state *x,
-                      struct sk_buff *skb, unsigned short family)
-{
-	int err;
-	
-	err = xfrm_state_check_expire(x);
-	if (err)
-		goto out;
-		
-	if (x->props.mode) {
-		switch (family) {
-		case AF_INET:
-			err = xfrm4_tunnel_check_size(skb);
-			break;
-			
-		case AF_INET6:
-			err = xfrm6_tunnel_check_size(skb);
-			break;
-			
-		default:
-			err = -EINVAL;
-		}
-		
-		if (err)
-			goto out;
-	}
-
-	err = xfrm_state_check_space(x, skb);
-out:
-	return err;
-}
diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
--- a/net/xfrm/xfrm_state.c	2004-06-23 19:04:28 -07:00
+++ b/net/xfrm/xfrm_state.c	2004-06-23 19:04:28 -07:00
@@ -531,6 +531,16 @@
 	return 0;
 }
 
+int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int err = xfrm_state_check_expire(x);
+	if (err < 0)
+		goto err;
+	err = xfrm_state_check_space(x, skb);
+err:
+	return err;
+}
+
 struct xfrm_state *
 xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
 		  unsigned short family)
diff -Nru a/scripts/Makefile b/scripts/Makefile
--- a/scripts/Makefile	2004-06-23 19:04:27 -07:00
+++ b/scripts/Makefile	2004-06-23 19:04:27 -07:00
@@ -13,7 +13,7 @@
 subdir-$(CONFIG_MODVERSIONS)	+= genksyms
 
 # Let clean descend into subdirs
-subdir-	+= basic lxdialog kconfig
+subdir-	+= basic lxdialog kconfig package
 
 # dependencies on generated files need to be listed explicitly
 
diff -Nru a/scripts/checkstack.pl b/scripts/checkstack.pl
--- a/scripts/checkstack.pl	2004-06-23 19:04:26 -07:00
+++ b/scripts/checkstack.pl	2004-06-23 19:04:26 -07:00
@@ -23,6 +23,7 @@
 # $1 (first bracket) matches the size of the stack growth
 #
 # use anything else and feel the pain ;)
+my (@stack, $re, $x, $xs);
 {
 	my $arch = shift;
 	if ($arch eq "") {
@@ -31,25 +32,25 @@
 
 	$x	= "[0-9a-f]";	# hex character
 	$xs	= "[0-9a-f ]";	# hex character or space
-	if ($arch =~ /^arm$/) {
+	if ($arch eq 'arm') {
 		#c0008ffc:	e24dd064	sub	sp, sp, #100	; 0x64
 		$re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o;
 	} elsif ($arch =~ /^i[3456]86$/) {
 		#c0105234:       81 ec ac 05 00 00       sub    $0x5ac,%esp
 		$re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%esp$/o;
-	} elsif ($arch =~ /^ia64$/) {
+	} elsif ($arch eq 'ia64') {
 		#e0000000044011fc:       01 0f fc 8c     adds r12=-384,r12
 		$re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o;
-	} elsif ($arch =~ /^mips64$/) {
+	} elsif ($arch eq 'mips64') {
 		#8800402c:       67bdfff0        daddiu  sp,sp,-16
 		$re = qr/.*daddiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;
-	} elsif ($arch =~ /^mips$/) {
+	} elsif ($arch eq 'mips') {
 		#88003254:       27bdffe0        addiu   sp,sp,-32
 		$re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;
-	} elsif ($arch =~ /^ppc$/) {
+	} elsif ($arch eq 'ppc') {
 		#c00029f4:       94 21 ff 30     stwu    r1,-208(r1)
 		$re = qr/.*stwu.*r1,-($x{1,8})\(r1\)/o;
-	} elsif ($arch =~ /^ppc64$/) {
+	} elsif ($arch eq 'ppc64') {
 		#XXX
 		$re = qr/.*stdu.*r1,-($x{1,8})\(r1\)/o;
 	} elsif ($arch =~ /^s390x?$/) {
@@ -62,6 +63,7 @@
 }
 
 sub bysize($) {
+	my ($asize, $bsize);
 	($asize = $a) =~ s/.*	+(.*)$/$1/;
 	($bsize = $b) =~ s/.*	+(.*)$/$1/;
 	$bsize <=> $asize
@@ -70,8 +72,9 @@
 #
 # main()
 #
-$funcre = qr/^$x* \<(.*)\>:$/;
-while ($line = <STDIN>) {
+my $funcre = qr/^$x* <(.*)>:$/;
+my $func;
+while (my $line = <STDIN>) {
 	if ($line =~ m/$funcre/) {
 		$func = $1;
 	}
@@ -85,7 +88,7 @@
 			$size += 0x80000000;
 		}
 
-		$line =~ m/^($xs*).*/;
+		next if $line !~ m/^($xs*)/;
 		my $addr = $1;
 		$addr =~ s/ /0/g;
 		$addr = "0x$addr";
@@ -97,12 +100,8 @@
 			$padlen -= 8;
 		}
 		next if ($size < 100);
-		$stack[@stack] = "$intro$size\n";
+		push @stack, "$intro$size\n";
 	}
 }
 
-@sortedstack = sort bysize @stack;
-
-foreach $i (@sortedstack) {
-	print("$i");
-}
+print sort bysize @stack;
diff -Nru a/scripts/mkspec b/scripts/mkspec
--- a/scripts/mkspec	2004-06-23 19:04:25 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,72 +0,0 @@
-#!/bin/sh
-#
-#	Output a simple RPM spec file that uses no fancy features requring
-#	RPM v4. This is intended to work with any RPM distro.
-#
-#	The only gothic bit here is redefining install_post to avoid 
-#	stripping the symbols from files in the kernel which we want
-#
-#	Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net>
-#
-# That's the voodoo to see if it's a x86.
-ISX86=`echo ${ARCH:=\`arch\`} | grep -ie i.86`
-if [ ! -z $ISX86 ]; then
-	PC=1
-else
-	PC=0
-fi
-# starting to output the spec
-if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then
-	PROVIDES=kernel-drm
-fi
-
-PROVIDES="$PROVIDES kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
-
-echo "Name: kernel"
-echo "Summary: The Linux Kernel"
-echo "Version: "$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION | sed -e "s/-//g"
-# we need to determine the NEXT version number so that uname and
-# rpm -q will agree
-echo "Release: `. $srctree/scripts/mkversion`"
-echo "License: GPL"
-echo "Group: System Environment/Kernel"
-echo "Vendor: The Linux Community"
-echo "URL: http://www.kernel.org"
-echo -n "Source: kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL"
-echo "$EXTRAVERSION.tar.gz" | sed -e "s/-//g"
-echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
-echo "Provides: $PROVIDES"
-echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :"
-echo "%define debug_package %{nil}"
-echo ""
-echo "%description"
-echo "The Linux Kernel, the operating system core itself"
-echo ""
-echo "%prep"
-echo "%setup -q"
-echo ""
-echo "%build"
-echo "make clean all"
-echo ""
-echo "%install"
-echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
-echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install'
-# This is the first disagreement between i386 and most others
-if [ $PC = 1 ]; then
-	echo 'cp arch/i386/boot/bzImage $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
-else
-	echo 'cp vmlinux $RPM_BUILD_ROOT'"/boot/vmlinux-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
-fi
-# Back on track
-echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
-echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
-echo ""
-echo "%clean"
-echo '#echo -rf $RPM_BUILD_ROOT'
-echo ""
-echo "%files"
-echo '%defattr (-, root, root)'
-echo "%dir /lib/modules"
-echo "/lib/modules/$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
-echo "/boot/*"
-echo ""
diff -Nru a/scripts/package/Makefile b/scripts/package/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/scripts/package/Makefile	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,71 @@
+# Makefile for the different targets used to generate full packages of a kernel
+# It uses the generic clean infrastructure of kbuild
+
+# Ignore the following files/directories during tar operation
+TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS
+
+
+# RPM target
+# ---------------------------------------------------------------------------
+# The rpm target generates two rpm files:
+# /usr/src/packages/SRPMS/kernel-2.6.7rc2-1.src.rpm
+# /usr/src/packages/RPMS/i386/kernel-2.6.7rc2-1.<arch>.rpm
+# The src.rpm files includes all source for the kernel being built
+# The <arch>.rpm includes kernel configuration, modules etc.
+#
+# Process to create the rpm files
+# a) clean the kernel
+# b) Generate .spec file
+# c) Build a tar ball, using symlink to make kernel version
+#    first entry in the path
+# d) and pack the result to a tar.gz file
+# e) generate the rpm files, based on kernel.spec
+# - Use /. to avoid tar packing just the symlink
+
+# Do we have rpmbuild, otherwise fall back to the older rpm
+RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \
+	           else echo rpm; fi)
+
+# Remove hyphens since they have special meaning in RPM filenames
+KERNELPATH := kernel-$(subst -,,$(KERNELRELEASE))
+MKSPEC     := $(srctree)/scripts/package/mkspec
+PREV       := set -e; cd ..;
+
+.PHONY: rpm-pkg rpm
+
+$(objtree)/kernel.spec: $(MKSPEC)
+	$(CONFIG_SHELL) $(MKSPEC) > $@
+
+rpm-pkg rpm: $(objtree)/kernel.spec
+	$(MAKE) clean
+	$(PREV) ln -sf $(srctree) $(KERNELPATH)
+	$(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/.
+	$(PREV) rm $(KERNELPATH)
+
+	set -e; \
+	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
+	set -e; \
+	mv -f $(objtree)/.tmp_version $(objtree)/.version
+
+	$(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz
+	rm ../$(KERNELPATH).tar.gz
+
+clean-rule +=  rm -f $(objtree)/kernel.spec
+
+# Deb target
+# ---------------------------------------------------------------------------
+#
+.PHONY: deb-pkg
+deb-pkg:
+	$(MAKE)
+	$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
+
+clean-rule += && rm -rf $(objtree)/debian/
+
+
+# Help text displayed when executing 'make help'
+# ---------------------------------------------------------------------------
+help:
+	@echo  '  rpm-pkg         - Build the kernel as an RPM package'
+	@echo  '  deb-pkg         - Build the kernel as an deb package'
+
diff -Nru a/scripts/package/builddeb b/scripts/package/builddeb
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/scripts/package/builddeb	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# builddeb 1.2
+# Copyright 2003 Wichert Akkerman <wichert@wiggy.net>
+#
+# Simple script to generate a deb package for a Linux kernel. All the
+# complexity of what to do with a kernel after it is installer or removed
+# is left to other scripts and packages: they can install scripts in the
+# /etc/kernel/{pre,post}{inst,rm}.d/ directories that will be called on
+# package install and removal.
+
+set -e
+
+# Some variables and settings used throughout the script
+version="$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+tmpdir="$objtree/debian/tmp"
+
+# Setup the directory structure
+rm -rf "$tmpdir"
+mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot"
+
+# Build and install the kernel
+cp System.map "$tmpdir/boot/System.map-$version"
+cp .config "$tmpdir/boot/config-$version"
+cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
+
+if grep -q '^CONFIG_MODULES=y' .config ; then
+	INSTALL_MOD_PATH="$tmpdir" make modules_install
+fi
+
+# Install the maintainer scripts
+for script in postinst postrm preinst prerm ; do
+	mkdir -p "$tmpdir/etc/kernel/$script.d"
+	cat <<EOF > "$tmpdir/DEBIAN/$script"
+#!/bin/sh
+
+set -e
+
+test -d /etc/kernel/$script.d && run-parts --arg="$version" /etc/kernel/$script.d
+exit 0
+EOF
+	chmod 755 "$tmpdir/DEBIAN/$script"
+done
+
+name="Kernel Compiler <$(id -nu)@$(hostname -f)>"
+# Generate a simple changelog template
+cat <<EOF > debian/changelog
+linux ($version) unstable; urgency=low
+
+  * A standard release
+
+ -- $name  $(date -R)
+EOF
+
+# Generate a control file
+cat <<EOF > debian/control
+Source: linux
+Section: base
+Priority: optional
+Maintainer: $name
+Standards-Version: 3.6.1
+
+Package: linux-$version
+Architecture: any
+Description: Linux kernel, version $version
+ This package contains the Linux kernel, modules and corresponding other
+ files version $version.
+EOF
+
+# Fix some ownership and permissions
+chown -R root:root "$tmpdir"
+chmod -R go-w "$tmpdir"
+
+# Perform the final magic
+dpkg-gencontrol -isp
+dpkg --build "$tmpdir" ..
+
+exit 0
+
diff -Nru a/scripts/package/mkspec b/scripts/package/mkspec
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/scripts/package/mkspec	2004-06-23 19:04:25 -07:00
@@ -0,0 +1,63 @@
+#!/bin/sh
+#
+#	Output a simple RPM spec file that uses no fancy features requring
+#	RPM v4. This is intended to work with any RPM distro.
+#
+#	The only gothic bit here is redefining install_post to avoid
+#	stripping the symbols from files in the kernel which we want
+#
+#	Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net>
+#
+
+# starting to output the spec
+if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then
+	PROVIDES=kernel-drm
+fi
+
+PROVIDES="$PROVIDES kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+
+echo "Name: kernel"
+echo "Summary: The Linux Kernel"
+echo "Version: "$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION | sed -e "s/-//g"
+# we need to determine the NEXT version number so that uname and
+# rpm -q will agree
+echo "Release: `. $srctree/scripts/mkversion`"
+echo "License: GPL"
+echo "Group: System Environment/Kernel"
+echo "Vendor: The Linux Community"
+echo "URL: http://www.kernel.org"
+echo -n "Source: kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL"
+echo "$EXTRAVERSION.tar.gz" | sed -e "s/-//g"
+echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
+echo "Provides: $PROVIDES"
+echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :"
+echo "%define debug_package %{nil}"
+echo ""
+echo "%description"
+echo "The Linux Kernel, the operating system core itself"
+echo ""
+echo "%prep"
+echo "%setup -q"
+echo ""
+echo "%build"
+echo "make clean && make"
+echo ""
+echo "%install"
+echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
+
+echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install'
+echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+
+echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+
+echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo ""
+echo "%clean"
+echo '#echo -rf $RPM_BUILD_ROOT'
+echo ""
+echo "%files"
+echo '%defattr (-, root, root)'
+echo "%dir /lib/modules"
+echo "/lib/modules/$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo "/boot/*"
+echo ""
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	2004-06-23 19:04:25 -07:00
+++ b/security/dummy.c	2004-06-23 19:04:25 -07:00
@@ -720,7 +720,7 @@
 	return 0;
 }
 
-static int dummy_netlink_send (struct sk_buff *skb)
+static int dummy_netlink_send (struct sock *sk, struct sk_buff *skb)
 {
 	if (current->euid == 0)
 		cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN);
diff -Nru a/security/selinux/Makefile b/security/selinux/Makefile
--- a/security/selinux/Makefile	2004-06-23 19:04:25 -07:00
+++ b/security/selinux/Makefile	2004-06-23 19:04:25 -07:00
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
 
-selinux-y := avc.o hooks.o selinuxfs.o netlink.o
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o
 
 selinux-$(CONFIG_SECURITY_NETWORK) += netif.o
 
diff -Nru a/security/selinux/hooks.c b/security/selinux/hooks.c
--- a/security/selinux/hooks.c	2004-06-23 19:04:28 -07:00
+++ b/security/selinux/hooks.c	2004-06-23 19:04:28 -07:00
@@ -71,6 +71,9 @@
 #define XATTR_SELINUX_SUFFIX "selinux"
 #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
 
+extern int policydb_loaded_version;
+extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
+
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
 int selinux_enforcing = 0;
 
@@ -627,7 +630,7 @@
 	return SECCLASS_FILE;
 }
 
-static inline u16 socket_type_to_security_class(int family, int type)
+static inline u16 socket_type_to_security_class(int family, int type, int protocol)
 {
 	switch (family) {
 	case PF_UNIX:
@@ -648,7 +651,28 @@
 			return SECCLASS_RAWIP_SOCKET;
 		}
 	case PF_NETLINK:
-		return SECCLASS_NETLINK_SOCKET;
+		switch (protocol) {
+		case NETLINK_ROUTE:
+			return SECCLASS_NETLINK_ROUTE_SOCKET;
+		case NETLINK_FIREWALL:
+			return SECCLASS_NETLINK_FIREWALL_SOCKET;
+		case NETLINK_TCPDIAG:
+			return SECCLASS_NETLINK_TCPDIAG_SOCKET;
+		case NETLINK_NFLOG:
+			return SECCLASS_NETLINK_NFLOG_SOCKET;
+		case NETLINK_XFRM:
+			return SECCLASS_NETLINK_XFRM_SOCKET;
+		case NETLINK_SELINUX:
+			return SECCLASS_NETLINK_SELINUX_SOCKET;
+		case NETLINK_AUDIT:
+			return SECCLASS_NETLINK_AUDIT_SOCKET;
+		case NETLINK_IP6_FW:
+			return SECCLASS_NETLINK_IP6FW_SOCKET;
+		case NETLINK_DNRTMSG:
+			return SECCLASS_NETLINK_DNRT_SOCKET;
+		default:
+			return SECCLASS_NETLINK_SOCKET;
+		}
 	case PF_PACKET:
 		return SECCLASS_PACKET_SOCKET;
 	case PF_KEY:
@@ -853,7 +877,8 @@
 		struct socket *sock = SOCKET_I(inode);
 		if (sock->sk) {
 			isec->sclass = socket_type_to_security_class(sock->sk->sk_family,
-			                                             sock->sk->sk_type);
+			                                             sock->sk->sk_type,
+			                                             sock->sk->sk_protocol);
 		} else {
 			isec->sclass = SECCLASS_SOCKET;
 		}
@@ -1567,22 +1592,6 @@
 	return -ENOMEM;
 }
 
-static int selinux_netlink_send(struct sk_buff *skb)
-{
-	if (capable(CAP_NET_ADMIN))
-		cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN);
-	else
-		NETLINK_CB(skb).eff_cap = 0;
-	return 0;
-}
-
-static int selinux_netlink_recv(struct sk_buff *skb)
-{
-	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
-		return -EPERM;
-	return 0;
-}
-
 /* binprm security operations */
 
 static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -2918,8 +2927,8 @@
 
 	tsec = current->security;
 	err = avc_has_perm(tsec->sid, tsec->sid,
-			   socket_type_to_security_class(family, type),
-			   SOCKET__CREATE, NULL, NULL);
+			   socket_type_to_security_class(family, type,
+			   protocol), SOCKET__CREATE, NULL, NULL);
 
 out:
 	return err;
@@ -2938,7 +2947,7 @@
 	isec = SOCK_INODE(sock)->i_security;
 
 	tsec = current->security;
-	isec->sclass = socket_type_to_security_class(family, type);
+	isec->sclass = socket_type_to_security_class(family, type, protocol);
 	isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
 
 	return;
@@ -3174,12 +3183,12 @@
 	char *addrp;
 	int len, err = 0;
 	u32 netif_perm, node_perm, node_sid, recv_perm = 0;
+	u32 sock_sid = 0;
+	u16 sock_class = 0;
 	struct socket *sock;
-	struct inode *inode;
 	struct net_device *dev;
 	struct sel_netif *netif;
 	struct netif_security_struct *nsec;
-	struct inode_security_struct *isec;
 	struct avc_audit_data ad;
 
 	family = sk->sk_family;
@@ -3190,15 +3199,21 @@
 	if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
 		family = PF_INET;
 
-	sock = sk->sk_socket;
-	
-	/* TCP control messages don't always have a socket. */
-	if (!sock)
-		goto out;
-
-	inode = SOCK_INODE(sock);
-	if (!inode)
-		goto out;
+ 	read_lock_bh(&sk->sk_callback_lock);
+ 	sock = sk->sk_socket;
+ 	if (sock) {
+ 		struct inode *inode;
+ 		inode = SOCK_INODE(sock);
+ 		if (inode) {
+ 			struct inode_security_struct *isec;
+ 			isec = inode->i_security;
+ 			sock_sid = isec->sid;
+ 			sock_class = isec->sclass;
+ 		}
+ 	}
+ 	read_unlock_bh(&sk->sk_callback_lock);
+ 	if (!sock_sid)
+  		goto out;
 
 	dev = skb->dev;
 	if (!dev)
@@ -3211,9 +3226,8 @@
 	}
 	
 	nsec = &netif->nsec;
-	isec = inode->i_security;
 
-	switch (isec->sclass) {
+	switch (sock_class) {
 	case SECCLASS_UDP_SOCKET:
 		netif_perm = NETIF__UDP_RECV;
 		node_perm = NODE__UDP_RECV;
@@ -3242,7 +3256,7 @@
 		goto out;
 	}
 
-	err = avc_has_perm(isec->sid, nsec->if_sid, SECCLASS_NETIF,
+	err = avc_has_perm(sock_sid, nsec->if_sid, SECCLASS_NETIF,
 	                   netif_perm, &nsec->avcr, &ad);
 	sel_netif_put(netif);
 	if (err)
@@ -3253,7 +3267,7 @@
 	if (err)
 		goto out;
 	
-	err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, NULL, &ad);
+	err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, NULL, &ad);
 	if (err)
 		goto out;
 
@@ -3267,7 +3281,7 @@
 		if (err)
 			goto out;
 
-		err = avc_has_perm(isec->sid, port_sid, isec->sclass,
+		err = avc_has_perm(sock_sid, port_sid, sock_class,
 		                   recv_perm, NULL, &ad);
 	}
 out:	
@@ -3320,6 +3334,55 @@
 static void selinux_sk_free_security(struct sock *sk)
 {
 	sk_free_security(sk);
+}
+
+static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
+{
+	int err = 0;
+	u32 perm;
+	struct nlmsghdr *nlh;
+	struct socket *sock = sk->sk_socket;
+	struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
+	
+	if (skb->len < NLMSG_SPACE(0)) {
+		err = -EINVAL;
+		goto out;
+	}
+	nlh = (struct nlmsghdr *)skb->data;
+	
+	err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
+	if (err) {
+		/* Ignore */
+		if (err == -ENOENT)
+			err = 0;
+		goto out;
+	}
+
+	err = socket_has_perm(current, sock, perm);
+out:
+	return err;
+}
+
+static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
+{
+	int err = 0;
+	
+	if (capable(CAP_NET_ADMIN))
+		cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN);
+	else
+		NETLINK_CB(skb).eff_cap = 0;
+	
+	if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
+		err = selinux_nlmsg_perm(sk, skb);
+	
+	return err;
+}
+
+static int selinux_netlink_recv(struct sk_buff *skb)
+{
+	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
+		return -EPERM;
+	return 0;
 }
 
 #ifdef CONFIG_NETFILTER
diff -Nru a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h
--- a/security/selinux/include/av_inherit.h	2004-06-23 19:04:27 -07:00
+++ b/security/selinux/include/av_inherit.h	2004-06-23 19:04:27 -07:00
@@ -29,6 +29,15 @@
    { SECCLASS_SEM, common_ipc_perm_to_string, 0x00000200UL },
    { SECCLASS_MSGQ, common_ipc_perm_to_string, 0x00000200UL },
    { SECCLASS_SHM, common_ipc_perm_to_string, 0x00000200UL },
+   { SECCLASS_NETLINK_ROUTE_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_NETLINK_FIREWALL_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_NETLINK_TCPDIAG_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_NETLINK_NFLOG_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_NETLINK_XFRM_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_NETLINK_SELINUX_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_NETLINK_AUDIT_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_NETLINK_IP6FW_SOCKET, common_socket_perm_to_string, 0x00400000UL },
+   { SECCLASS_NETLINK_DNRT_SOCKET, common_socket_perm_to_string, 0x00400000UL },
 };
 
 
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	2004-06-23 19:04:28 -07:00
+++ b/security/selinux/include/av_perm_to_string.h	2004-06-23 19:04:28 -07:00
@@ -30,6 +30,9 @@
    { SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto" },
    { SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn" },
    { SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom" },
+   { SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind" },
+   { SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind" },
+   { SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind" },
    { SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv" },
    { SECCLASS_NODE, NODE__TCP_SEND, "tcp_send" },
    { SECCLASS_NODE, NODE__UDP_RECV, "udp_recv" },
@@ -46,9 +49,6 @@
    { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto" },
    { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn" },
    { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom" },
-   { SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind" },
-   { SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind" },
-   { SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind" },
    { SECCLASS_PROCESS, PROCESS__FORK, "fork" },
    { SECCLASS_PROCESS, PROCESS__TRANSITION, "transition" },
    { SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld" },
@@ -121,6 +121,104 @@
    { SECCLASS_PASSWD, PASSWD__PASSWD, "passwd" },
    { SECCLASS_PASSWD, PASSWD__CHFN, "chfn" },
    { SECCLASS_PASSWD, PASSWD__CHSH, "chsh" },
+   { SECCLASS_PASSWD, PASSWD__ROOTOK, "rootok" },
+   { SECCLASS_DRAWABLE, DRAWABLE__CREATE, "create" },
+   { SECCLASS_DRAWABLE, DRAWABLE__DESTROY, "destroy" },
+   { SECCLASS_DRAWABLE, DRAWABLE__DRAW, "draw" },
+   { SECCLASS_DRAWABLE, DRAWABLE__COPY, "copy" },
+   { SECCLASS_DRAWABLE, DRAWABLE__GETATTR, "getattr" },
+   { SECCLASS_GC, GC__CREATE, "create" },
+   { SECCLASS_GC, GC__FREE, "free" },
+   { SECCLASS_GC, GC__GETATTR, "getattr" },
+   { SECCLASS_GC, GC__SETATTR, "setattr" },
+   { SECCLASS_WINDOW, WINDOW__ADDCHILD, "addchild" },
+   { SECCLASS_WINDOW, WINDOW__CREATE, "create" },
+   { SECCLASS_WINDOW, WINDOW__DESTROY, "destroy" },
+   { SECCLASS_WINDOW, WINDOW__MAP, "map" },
+   { SECCLASS_WINDOW, WINDOW__UNMAP, "unmap" },
+   { SECCLASS_WINDOW, WINDOW__CHSTACK, "chstack" },
+   { SECCLASS_WINDOW, WINDOW__CHPROPLIST, "chproplist" },
+   { SECCLASS_WINDOW, WINDOW__CHPROP, "chprop" },
+   { SECCLASS_WINDOW, WINDOW__LISTPROP, "listprop" },
+   { SECCLASS_WINDOW, WINDOW__GETATTR, "getattr" },
+   { SECCLASS_WINDOW, WINDOW__SETATTR, "setattr" },
+   { SECCLASS_WINDOW, WINDOW__SETFOCUS, "setfocus" },
+   { SECCLASS_WINDOW, WINDOW__MOVE, "move" },
+   { SECCLASS_WINDOW, WINDOW__CHSELECTION, "chselection" },
+   { SECCLASS_WINDOW, WINDOW__CHPARENT, "chparent" },
+   { SECCLASS_WINDOW, WINDOW__CTRLLIFE, "ctrllife" },
+   { SECCLASS_WINDOW, WINDOW__ENUMERATE, "enumerate" },
+   { SECCLASS_WINDOW, WINDOW__TRANSPARENT, "transparent" },
+   { SECCLASS_WINDOW, WINDOW__MOUSEMOTION, "mousemotion" },
+   { SECCLASS_WINDOW, WINDOW__CLIENTCOMEVENT, "clientcomevent" },
+   { SECCLASS_WINDOW, WINDOW__INPUTEVENT, "inputevent" },
+   { SECCLASS_WINDOW, WINDOW__DRAWEVENT, "drawevent" },
+   { SECCLASS_WINDOW, WINDOW__WINDOWCHANGEEVENT, "windowchangeevent" },
+   { SECCLASS_WINDOW, WINDOW__WINDOWCHANGEREQUEST, "windowchangerequest" },
+   { SECCLASS_WINDOW, WINDOW__SERVERCHANGEEVENT, "serverchangeevent" },
+   { SECCLASS_WINDOW, WINDOW__EXTENSIONEVENT, "extensionevent" },
+   { SECCLASS_FONT, FONT__LOAD, "load" },
+   { SECCLASS_FONT, FONT__FREE, "free" },
+   { SECCLASS_FONT, FONT__GETATTR, "getattr" },
+   { SECCLASS_FONT, FONT__USE, "use" },
+   { SECCLASS_COLORMAP, COLORMAP__CREATE, "create" },
+   { SECCLASS_COLORMAP, COLORMAP__FREE, "free" },
+   { SECCLASS_COLORMAP, COLORMAP__INSTALL, "install" },
+   { SECCLASS_COLORMAP, COLORMAP__UNINSTALL, "uninstall" },
+   { SECCLASS_COLORMAP, COLORMAP__LIST, "list" },
+   { SECCLASS_COLORMAP, COLORMAP__READ, "read" },
+   { SECCLASS_COLORMAP, COLORMAP__STORE, "store" },
+   { SECCLASS_COLORMAP, COLORMAP__GETATTR, "getattr" },
+   { SECCLASS_COLORMAP, COLORMAP__SETATTR, "setattr" },
+   { SECCLASS_PROPERTY, PROPERTY__CREATE, "create" },
+   { SECCLASS_PROPERTY, PROPERTY__FREE, "free" },
+   { SECCLASS_PROPERTY, PROPERTY__READ, "read" },
+   { SECCLASS_PROPERTY, PROPERTY__WRITE, "write" },
+   { SECCLASS_CURSOR, CURSOR__CREATE, "create" },
+   { SECCLASS_CURSOR, CURSOR__CREATEGLYPH, "createglyph" },
+   { SECCLASS_CURSOR, CURSOR__FREE, "free" },
+   { SECCLASS_CURSOR, CURSOR__ASSIGN, "assign" },
+   { SECCLASS_CURSOR, CURSOR__SETATTR, "setattr" },
+   { SECCLASS_XCLIENT, XCLIENT__KILL, "kill" },
+   { SECCLASS_XINPUT, XINPUT__LOOKUP, "lookup" },
+   { SECCLASS_XINPUT, XINPUT__GETATTR, "getattr" },
+   { SECCLASS_XINPUT, XINPUT__SETATTR, "setattr" },
+   { SECCLASS_XINPUT, XINPUT__SETFOCUS, "setfocus" },
+   { SECCLASS_XINPUT, XINPUT__WARPPOINTER, "warppointer" },
+   { SECCLASS_XINPUT, XINPUT__ACTIVEGRAB, "activegrab" },
+   { SECCLASS_XINPUT, XINPUT__PASSIVEGRAB, "passivegrab" },
+   { SECCLASS_XINPUT, XINPUT__UNGRAB, "ungrab" },
+   { SECCLASS_XINPUT, XINPUT__BELL, "bell" },
+   { SECCLASS_XINPUT, XINPUT__MOUSEMOTION, "mousemotion" },
+   { SECCLASS_XINPUT, XINPUT__RELABELINPUT, "relabelinput" },
+   { SECCLASS_XSERVER, XSERVER__SCREENSAVER, "screensaver" },
+   { SECCLASS_XSERVER, XSERVER__GETHOSTLIST, "gethostlist" },
+   { SECCLASS_XSERVER, XSERVER__SETHOSTLIST, "sethostlist" },
+   { SECCLASS_XSERVER, XSERVER__GETFONTPATH, "getfontpath" },
+   { SECCLASS_XSERVER, XSERVER__SETFONTPATH, "setfontpath" },
+   { SECCLASS_XSERVER, XSERVER__GETATTR, "getattr" },
+   { SECCLASS_XSERVER, XSERVER__GRAB, "grab" },
+   { SECCLASS_XSERVER, XSERVER__UNGRAB, "ungrab" },
+   { SECCLASS_XEXTENSION, XEXTENSION__QUERY, "query" },
+   { SECCLASS_XEXTENSION, XEXTENSION__USE, "use" },
+   { SECCLASS_PAX, PAX__PAGEEXEC, "pageexec" },
+   { SECCLASS_PAX, PAX__EMUTRAMP, "emutramp" },
+   { SECCLASS_PAX, PAX__MPROTECT, "mprotect" },
+   { SECCLASS_PAX, PAX__RANDMMAP, "randmmap" },
+   { SECCLASS_PAX, PAX__RANDEXEC, "randexec" },
+   { SECCLASS_PAX, PAX__SEGMEXEC, "segmexec" },
+   { SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read" },
+   { SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write" },
+   { SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read" },
+   { SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE, "nlmsg_write" },
+   { SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_READ, "nlmsg_read" },
+   { SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE, "nlmsg_write" },
+   { SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_READ, "nlmsg_read" },
+   { SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write" },
+   { SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read" },
+   { SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write" },
+   { SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read" },
+   { SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write" },
 };
 
 
diff -Nru a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
--- a/security/selinux/include/av_permissions.h	2004-06-23 19:04:29 -07:00
+++ b/security/selinux/include/av_permissions.h	2004-06-23 19:04:29 -07:00
@@ -63,23 +63,23 @@
 #define FILESYSTEM__QUOTAMOD                      0x00000100UL
 #define FILESYSTEM__QUOTAGET                      0x00000200UL
 
-#define DIR__EXECUTE                              0x00002000UL
-#define DIR__UNLINK                               0x00000400UL
+#define DIR__IOCTL                                0x00000001UL
+#define DIR__READ                                 0x00000002UL
+#define DIR__WRITE                                0x00000004UL
+#define DIR__CREATE                               0x00000008UL
+#define DIR__GETATTR                              0x00000010UL
 #define DIR__SETATTR                              0x00000020UL
-#define DIR__QUOTAON                              0x00008000UL
+#define DIR__LOCK                                 0x00000040UL
 #define DIR__RELABELFROM                          0x00000080UL
-#define DIR__LINK                                 0x00000800UL
-#define DIR__WRITE                                0x00000004UL
-#define DIR__IOCTL                                0x00000001UL
 #define DIR__RELABELTO                            0x00000100UL
-#define DIR__READ                                 0x00000002UL
-#define DIR__RENAME                               0x00001000UL
 #define DIR__APPEND                               0x00000200UL
-#define DIR__LOCK                                 0x00000040UL
+#define DIR__UNLINK                               0x00000400UL
+#define DIR__LINK                                 0x00000800UL
+#define DIR__RENAME                               0x00001000UL
+#define DIR__EXECUTE                              0x00002000UL
 #define DIR__SWAPON                               0x00004000UL
-#define DIR__GETATTR                              0x00000010UL
+#define DIR__QUOTAON                              0x00008000UL
 #define DIR__MOUNTON                              0x00010000UL
-#define DIR__CREATE                               0x00000008UL
 
 #define DIR__ADD_NAME                             0x00020000UL
 #define DIR__REMOVE_NAME                          0x00040000UL
@@ -87,216 +87,218 @@
 #define DIR__SEARCH                               0x00100000UL
 #define DIR__RMDIR                                0x00200000UL
 
-#define FILE__EXECUTE                             0x00002000UL
-#define FILE__UNLINK                              0x00000400UL
+#define FILE__IOCTL                               0x00000001UL
+#define FILE__READ                                0x00000002UL
+#define FILE__WRITE                               0x00000004UL
+#define FILE__CREATE                              0x00000008UL
+#define FILE__GETATTR                             0x00000010UL
 #define FILE__SETATTR                             0x00000020UL
-#define FILE__QUOTAON                             0x00008000UL
+#define FILE__LOCK                                0x00000040UL
 #define FILE__RELABELFROM                         0x00000080UL
-#define FILE__LINK                                0x00000800UL
-#define FILE__WRITE                               0x00000004UL
-#define FILE__IOCTL                               0x00000001UL
 #define FILE__RELABELTO                           0x00000100UL
-#define FILE__READ                                0x00000002UL
-#define FILE__RENAME                              0x00001000UL
 #define FILE__APPEND                              0x00000200UL
-#define FILE__LOCK                                0x00000040UL
+#define FILE__UNLINK                              0x00000400UL
+#define FILE__LINK                                0x00000800UL
+#define FILE__RENAME                              0x00001000UL
+#define FILE__EXECUTE                             0x00002000UL
 #define FILE__SWAPON                              0x00004000UL
-#define FILE__GETATTR                             0x00000010UL
+#define FILE__QUOTAON                             0x00008000UL
 #define FILE__MOUNTON                             0x00010000UL
-#define FILE__CREATE                              0x00000008UL
 
 #define FILE__EXECUTE_NO_TRANS                    0x00020000UL
 #define FILE__ENTRYPOINT                          0x00040000UL
 
-#define LNK_FILE__EXECUTE                         0x00002000UL
-#define LNK_FILE__UNLINK                          0x00000400UL
+#define LNK_FILE__IOCTL                           0x00000001UL
+#define LNK_FILE__READ                            0x00000002UL
+#define LNK_FILE__WRITE                           0x00000004UL
+#define LNK_FILE__CREATE                          0x00000008UL
+#define LNK_FILE__GETATTR                         0x00000010UL
 #define LNK_FILE__SETATTR                         0x00000020UL
-#define LNK_FILE__QUOTAON                         0x00008000UL
+#define LNK_FILE__LOCK                            0x00000040UL
 #define LNK_FILE__RELABELFROM                     0x00000080UL
-#define LNK_FILE__LINK                            0x00000800UL
-#define LNK_FILE__WRITE                           0x00000004UL
-#define LNK_FILE__IOCTL                           0x00000001UL
 #define LNK_FILE__RELABELTO                       0x00000100UL
-#define LNK_FILE__READ                            0x00000002UL
-#define LNK_FILE__RENAME                          0x00001000UL
 #define LNK_FILE__APPEND                          0x00000200UL
-#define LNK_FILE__LOCK                            0x00000040UL
+#define LNK_FILE__UNLINK                          0x00000400UL
+#define LNK_FILE__LINK                            0x00000800UL
+#define LNK_FILE__RENAME                          0x00001000UL
+#define LNK_FILE__EXECUTE                         0x00002000UL
 #define LNK_FILE__SWAPON                          0x00004000UL
-#define LNK_FILE__GETATTR                         0x00000010UL
+#define LNK_FILE__QUOTAON                         0x00008000UL
 #define LNK_FILE__MOUNTON                         0x00010000UL
-#define LNK_FILE__CREATE                          0x00000008UL
 
-#define CHR_FILE__EXECUTE                         0x00002000UL
-#define CHR_FILE__UNLINK                          0x00000400UL
+#define CHR_FILE__IOCTL                           0x00000001UL
+#define CHR_FILE__READ                            0x00000002UL
+#define CHR_FILE__WRITE                           0x00000004UL
+#define CHR_FILE__CREATE                          0x00000008UL
+#define CHR_FILE__GETATTR                         0x00000010UL
 #define CHR_FILE__SETATTR                         0x00000020UL
-#define CHR_FILE__QUOTAON                         0x00008000UL
+#define CHR_FILE__LOCK                            0x00000040UL
 #define CHR_FILE__RELABELFROM                     0x00000080UL
-#define CHR_FILE__LINK                            0x00000800UL
-#define CHR_FILE__WRITE                           0x00000004UL
-#define CHR_FILE__IOCTL                           0x00000001UL
 #define CHR_FILE__RELABELTO                       0x00000100UL
-#define CHR_FILE__READ                            0x00000002UL
-#define CHR_FILE__RENAME                          0x00001000UL
 #define CHR_FILE__APPEND                          0x00000200UL
-#define CHR_FILE__LOCK                            0x00000040UL
+#define CHR_FILE__UNLINK                          0x00000400UL
+#define CHR_FILE__LINK                            0x00000800UL
+#define CHR_FILE__RENAME                          0x00001000UL
+#define CHR_FILE__EXECUTE                         0x00002000UL
 #define CHR_FILE__SWAPON                          0x00004000UL
-#define CHR_FILE__GETATTR                         0x00000010UL
+#define CHR_FILE__QUOTAON                         0x00008000UL
 #define CHR_FILE__MOUNTON                         0x00010000UL
-#define CHR_FILE__CREATE                          0x00000008UL
 
-#define BLK_FILE__EXECUTE                         0x00002000UL
-#define BLK_FILE__UNLINK                          0x00000400UL
+#define BLK_FILE__IOCTL                           0x00000001UL
+#define BLK_FILE__READ                            0x00000002UL
+#define BLK_FILE__WRITE                           0x00000004UL
+#define BLK_FILE__CREATE                          0x00000008UL
+#define BLK_FILE__GETATTR                         0x00000010UL
 #define BLK_FILE__SETATTR                         0x00000020UL
-#define BLK_FILE__QUOTAON                         0x00008000UL
+#define BLK_FILE__LOCK                            0x00000040UL
 #define BLK_FILE__RELABELFROM                     0x00000080UL
-#define BLK_FILE__LINK                            0x00000800UL
-#define BLK_FILE__WRITE                           0x00000004UL
-#define BLK_FILE__IOCTL                           0x00000001UL
 #define BLK_FILE__RELABELTO                       0x00000100UL
-#define BLK_FILE__READ                            0x00000002UL
-#define BLK_FILE__RENAME                          0x00001000UL
 #define BLK_FILE__APPEND                          0x00000200UL
-#define BLK_FILE__LOCK                            0x00000040UL
+#define BLK_FILE__UNLINK                          0x00000400UL
+#define BLK_FILE__LINK                            0x00000800UL
+#define BLK_FILE__RENAME                          0x00001000UL
+#define BLK_FILE__EXECUTE                         0x00002000UL
 #define BLK_FILE__SWAPON                          0x00004000UL
-#define BLK_FILE__GETATTR                         0x00000010UL
+#define BLK_FILE__QUOTAON                         0x00008000UL
 #define BLK_FILE__MOUNTON                         0x00010000UL
-#define BLK_FILE__CREATE                          0x00000008UL
 
-#define SOCK_FILE__EXECUTE                        0x00002000UL
-#define SOCK_FILE__UNLINK                         0x00000400UL
+#define SOCK_FILE__IOCTL                          0x00000001UL
+#define SOCK_FILE__READ                           0x00000002UL
+#define SOCK_FILE__WRITE                          0x00000004UL
+#define SOCK_FILE__CREATE                         0x00000008UL
+#define SOCK_FILE__GETATTR                        0x00000010UL
 #define SOCK_FILE__SETATTR                        0x00000020UL
-#define SOCK_FILE__QUOTAON                        0x00008000UL
+#define SOCK_FILE__LOCK                           0x00000040UL
 #define SOCK_FILE__RELABELFROM                    0x00000080UL
-#define SOCK_FILE__LINK                           0x00000800UL
-#define SOCK_FILE__WRITE                          0x00000004UL
-#define SOCK_FILE__IOCTL                          0x00000001UL
 #define SOCK_FILE__RELABELTO                      0x00000100UL
-#define SOCK_FILE__READ                           0x00000002UL
-#define SOCK_FILE__RENAME                         0x00001000UL
 #define SOCK_FILE__APPEND                         0x00000200UL
-#define SOCK_FILE__LOCK                           0x00000040UL
+#define SOCK_FILE__UNLINK                         0x00000400UL
+#define SOCK_FILE__LINK                           0x00000800UL
+#define SOCK_FILE__RENAME                         0x00001000UL
+#define SOCK_FILE__EXECUTE                        0x00002000UL
 #define SOCK_FILE__SWAPON                         0x00004000UL
-#define SOCK_FILE__GETATTR                        0x00000010UL
+#define SOCK_FILE__QUOTAON                        0x00008000UL
 #define SOCK_FILE__MOUNTON                        0x00010000UL
-#define SOCK_FILE__CREATE                         0x00000008UL
 
-#define FIFO_FILE__EXECUTE                        0x00002000UL
-#define FIFO_FILE__UNLINK                         0x00000400UL
+#define FIFO_FILE__IOCTL                          0x00000001UL
+#define FIFO_FILE__READ                           0x00000002UL
+#define FIFO_FILE__WRITE                          0x00000004UL
+#define FIFO_FILE__CREATE                         0x00000008UL
+#define FIFO_FILE__GETATTR                        0x00000010UL
 #define FIFO_FILE__SETATTR                        0x00000020UL
-#define FIFO_FILE__QUOTAON                        0x00008000UL
+#define FIFO_FILE__LOCK                           0x00000040UL
 #define FIFO_FILE__RELABELFROM                    0x00000080UL
-#define FIFO_FILE__LINK                           0x00000800UL
-#define FIFO_FILE__WRITE                          0x00000004UL
-#define FIFO_FILE__IOCTL                          0x00000001UL
 #define FIFO_FILE__RELABELTO                      0x00000100UL
-#define FIFO_FILE__READ                           0x00000002UL
-#define FIFO_FILE__RENAME                         0x00001000UL
 #define FIFO_FILE__APPEND                         0x00000200UL
-#define FIFO_FILE__LOCK                           0x00000040UL
+#define FIFO_FILE__UNLINK                         0x00000400UL
+#define FIFO_FILE__LINK                           0x00000800UL
+#define FIFO_FILE__RENAME                         0x00001000UL
+#define FIFO_FILE__EXECUTE                        0x00002000UL
 #define FIFO_FILE__SWAPON                         0x00004000UL
-#define FIFO_FILE__GETATTR                        0x00000010UL
+#define FIFO_FILE__QUOTAON                        0x00008000UL
 #define FIFO_FILE__MOUNTON                        0x00010000UL
-#define FIFO_FILE__CREATE                         0x00000008UL
 
 #define FD__USE                                   0x00000001UL
 
-#define SOCKET__RELABELTO                         0x00000100UL
-#define SOCKET__RECV_MSG                          0x00080000UL
+#define SOCKET__IOCTL                             0x00000001UL
+#define SOCKET__READ                              0x00000002UL
+#define SOCKET__WRITE                             0x00000004UL
+#define SOCKET__CREATE                            0x00000008UL
+#define SOCKET__GETATTR                           0x00000010UL
+#define SOCKET__SETATTR                           0x00000020UL
+#define SOCKET__LOCK                              0x00000040UL
 #define SOCKET__RELABELFROM                       0x00000080UL
-#define SOCKET__SETOPT                            0x00008000UL
+#define SOCKET__RELABELTO                         0x00000100UL
 #define SOCKET__APPEND                            0x00000200UL
-#define SOCKET__SETATTR                           0x00000020UL
-#define SOCKET__SENDTO                            0x00040000UL
-#define SOCKET__GETOPT                            0x00004000UL
-#define SOCKET__READ                              0x00000002UL
-#define SOCKET__SHUTDOWN                          0x00010000UL
-#define SOCKET__LISTEN                            0x00001000UL
 #define SOCKET__BIND                              0x00000400UL
-#define SOCKET__WRITE                             0x00000004UL
-#define SOCKET__ACCEPT                            0x00002000UL
 #define SOCKET__CONNECT                           0x00000800UL
-#define SOCKET__LOCK                              0x00000040UL
-#define SOCKET__IOCTL                             0x00000001UL
-#define SOCKET__CREATE                            0x00000008UL
-#define SOCKET__NAME_BIND                         0x00200000UL
-#define SOCKET__SEND_MSG                          0x00100000UL
+#define SOCKET__LISTEN                            0x00001000UL
+#define SOCKET__ACCEPT                            0x00002000UL
+#define SOCKET__GETOPT                            0x00004000UL
+#define SOCKET__SETOPT                            0x00008000UL
+#define SOCKET__SHUTDOWN                          0x00010000UL
 #define SOCKET__RECVFROM                          0x00020000UL
-#define SOCKET__GETATTR                           0x00000010UL
+#define SOCKET__SENDTO                            0x00040000UL
+#define SOCKET__RECV_MSG                          0x00080000UL
+#define SOCKET__SEND_MSG                          0x00100000UL
+#define SOCKET__NAME_BIND                         0x00200000UL
 
-#define TCP_SOCKET__RELABELTO                     0x00000100UL
-#define TCP_SOCKET__RECV_MSG                      0x00080000UL
+#define TCP_SOCKET__IOCTL                         0x00000001UL
+#define TCP_SOCKET__READ                          0x00000002UL
+#define TCP_SOCKET__WRITE                         0x00000004UL
+#define TCP_SOCKET__CREATE                        0x00000008UL
+#define TCP_SOCKET__GETATTR                       0x00000010UL
+#define TCP_SOCKET__SETATTR                       0x00000020UL
+#define TCP_SOCKET__LOCK                          0x00000040UL
 #define TCP_SOCKET__RELABELFROM                   0x00000080UL
-#define TCP_SOCKET__SETOPT                        0x00008000UL
+#define TCP_SOCKET__RELABELTO                     0x00000100UL
 #define TCP_SOCKET__APPEND                        0x00000200UL
-#define TCP_SOCKET__SETATTR                       0x00000020UL
-#define TCP_SOCKET__SENDTO                        0x00040000UL
-#define TCP_SOCKET__GETOPT                        0x00004000UL
-#define TCP_SOCKET__READ                          0x00000002UL
-#define TCP_SOCKET__SHUTDOWN                      0x00010000UL
-#define TCP_SOCKET__LISTEN                        0x00001000UL
 #define TCP_SOCKET__BIND                          0x00000400UL
-#define TCP_SOCKET__WRITE                         0x00000004UL
-#define TCP_SOCKET__ACCEPT                        0x00002000UL
 #define TCP_SOCKET__CONNECT                       0x00000800UL
-#define TCP_SOCKET__LOCK                          0x00000040UL
-#define TCP_SOCKET__IOCTL                         0x00000001UL
-#define TCP_SOCKET__CREATE                        0x00000008UL
-#define TCP_SOCKET__NAME_BIND                     0x00200000UL
-#define TCP_SOCKET__SEND_MSG                      0x00100000UL
+#define TCP_SOCKET__LISTEN                        0x00001000UL
+#define TCP_SOCKET__ACCEPT                        0x00002000UL
+#define TCP_SOCKET__GETOPT                        0x00004000UL
+#define TCP_SOCKET__SETOPT                        0x00008000UL
+#define TCP_SOCKET__SHUTDOWN                      0x00010000UL
 #define TCP_SOCKET__RECVFROM                      0x00020000UL
-#define TCP_SOCKET__GETATTR                       0x00000010UL
+#define TCP_SOCKET__SENDTO                        0x00040000UL
+#define TCP_SOCKET__RECV_MSG                      0x00080000UL
+#define TCP_SOCKET__SEND_MSG                      0x00100000UL
+#define TCP_SOCKET__NAME_BIND                     0x00200000UL
 
 #define TCP_SOCKET__CONNECTTO                     0x00400000UL
 #define TCP_SOCKET__NEWCONN                       0x00800000UL
 #define TCP_SOCKET__ACCEPTFROM                    0x01000000UL
 #define TCP_SOCKET__NODE_BIND                     0x02000000UL
 
-#define UDP_SOCKET__RELABELTO                     0x00000100UL
-#define UDP_SOCKET__RECV_MSG                      0x00080000UL
+#define UDP_SOCKET__IOCTL                         0x00000001UL
+#define UDP_SOCKET__READ                          0x00000002UL
+#define UDP_SOCKET__WRITE                         0x00000004UL
+#define UDP_SOCKET__CREATE                        0x00000008UL
+#define UDP_SOCKET__GETATTR                       0x00000010UL
+#define UDP_SOCKET__SETATTR                       0x00000020UL
+#define UDP_SOCKET__LOCK                          0x00000040UL
 #define UDP_SOCKET__RELABELFROM                   0x00000080UL
-#define UDP_SOCKET__SETOPT                        0x00008000UL
+#define UDP_SOCKET__RELABELTO                     0x00000100UL
 #define UDP_SOCKET__APPEND                        0x00000200UL
-#define UDP_SOCKET__SETATTR                       0x00000020UL
-#define UDP_SOCKET__SENDTO                        0x00040000UL
-#define UDP_SOCKET__GETOPT                        0x00004000UL
-#define UDP_SOCKET__READ                          0x00000002UL
-#define UDP_SOCKET__SHUTDOWN                      0x00010000UL
-#define UDP_SOCKET__LISTEN                        0x00001000UL
 #define UDP_SOCKET__BIND                          0x00000400UL
-#define UDP_SOCKET__WRITE                         0x00000004UL
-#define UDP_SOCKET__ACCEPT                        0x00002000UL
 #define UDP_SOCKET__CONNECT                       0x00000800UL
-#define UDP_SOCKET__LOCK                          0x00000040UL
-#define UDP_SOCKET__IOCTL                         0x00000001UL
-#define UDP_SOCKET__CREATE                        0x00000008UL
-#define UDP_SOCKET__NAME_BIND                     0x00200000UL
-#define UDP_SOCKET__SEND_MSG                      0x00100000UL
+#define UDP_SOCKET__LISTEN                        0x00001000UL
+#define UDP_SOCKET__ACCEPT                        0x00002000UL
+#define UDP_SOCKET__GETOPT                        0x00004000UL
+#define UDP_SOCKET__SETOPT                        0x00008000UL
+#define UDP_SOCKET__SHUTDOWN                      0x00010000UL
 #define UDP_SOCKET__RECVFROM                      0x00020000UL
-#define UDP_SOCKET__GETATTR                       0x00000010UL
+#define UDP_SOCKET__SENDTO                        0x00040000UL
+#define UDP_SOCKET__RECV_MSG                      0x00080000UL
+#define UDP_SOCKET__SEND_MSG                      0x00100000UL
+#define UDP_SOCKET__NAME_BIND                     0x00200000UL
+
 #define UDP_SOCKET__NODE_BIND                     0x00400000UL
 
-#define RAWIP_SOCKET__RELABELTO                   0x00000100UL
-#define RAWIP_SOCKET__RECV_MSG                    0x00080000UL
+#define RAWIP_SOCKET__IOCTL                       0x00000001UL
+#define RAWIP_SOCKET__READ                        0x00000002UL
+#define RAWIP_SOCKET__WRITE                       0x00000004UL
+#define RAWIP_SOCKET__CREATE                      0x00000008UL
+#define RAWIP_SOCKET__GETATTR                     0x00000010UL
+#define RAWIP_SOCKET__SETATTR                     0x00000020UL
+#define RAWIP_SOCKET__LOCK                        0x00000040UL
 #define RAWIP_SOCKET__RELABELFROM                 0x00000080UL
-#define RAWIP_SOCKET__SETOPT                      0x00008000UL
+#define RAWIP_SOCKET__RELABELTO                   0x00000100UL
 #define RAWIP_SOCKET__APPEND                      0x00000200UL
-#define RAWIP_SOCKET__SETATTR                     0x00000020UL
-#define RAWIP_SOCKET__SENDTO                      0x00040000UL
-#define RAWIP_SOCKET__GETOPT                      0x00004000UL
-#define RAWIP_SOCKET__READ                        0x00000002UL
-#define RAWIP_SOCKET__SHUTDOWN                    0x00010000UL
-#define RAWIP_SOCKET__LISTEN                      0x00001000UL
 #define RAWIP_SOCKET__BIND                        0x00000400UL
-#define RAWIP_SOCKET__WRITE                       0x00000004UL
-#define RAWIP_SOCKET__ACCEPT                      0x00002000UL
 #define RAWIP_SOCKET__CONNECT                     0x00000800UL
-#define RAWIP_SOCKET__LOCK                        0x00000040UL
-#define RAWIP_SOCKET__IOCTL                       0x00000001UL
-#define RAWIP_SOCKET__CREATE                      0x00000008UL
-#define RAWIP_SOCKET__NAME_BIND                   0x00200000UL
-#define RAWIP_SOCKET__SEND_MSG                    0x00100000UL
+#define RAWIP_SOCKET__LISTEN                      0x00001000UL
+#define RAWIP_SOCKET__ACCEPT                      0x00002000UL
+#define RAWIP_SOCKET__GETOPT                      0x00004000UL
+#define RAWIP_SOCKET__SETOPT                      0x00008000UL
+#define RAWIP_SOCKET__SHUTDOWN                    0x00010000UL
 #define RAWIP_SOCKET__RECVFROM                    0x00020000UL
-#define RAWIP_SOCKET__GETATTR                     0x00000010UL
+#define RAWIP_SOCKET__SENDTO                      0x00040000UL
+#define RAWIP_SOCKET__RECV_MSG                    0x00080000UL
+#define RAWIP_SOCKET__SEND_MSG                    0x00100000UL
+#define RAWIP_SOCKET__NAME_BIND                   0x00200000UL
+
 #define RAWIP_SOCKET__NODE_BIND                   0x00400000UL
 
 #define NODE__TCP_RECV                            0x00000001UL
@@ -314,124 +316,124 @@
 #define NETIF__RAWIP_RECV                         0x00000010UL
 #define NETIF__RAWIP_SEND                         0x00000020UL
 
-#define NETLINK_SOCKET__RELABELTO                 0x00000100UL
-#define NETLINK_SOCKET__RECV_MSG                  0x00080000UL
+#define NETLINK_SOCKET__IOCTL                     0x00000001UL
+#define NETLINK_SOCKET__READ                      0x00000002UL
+#define NETLINK_SOCKET__WRITE                     0x00000004UL
+#define NETLINK_SOCKET__CREATE                    0x00000008UL
+#define NETLINK_SOCKET__GETATTR                   0x00000010UL
+#define NETLINK_SOCKET__SETATTR                   0x00000020UL
+#define NETLINK_SOCKET__LOCK                      0x00000040UL
 #define NETLINK_SOCKET__RELABELFROM               0x00000080UL
-#define NETLINK_SOCKET__SETOPT                    0x00008000UL
+#define NETLINK_SOCKET__RELABELTO                 0x00000100UL
 #define NETLINK_SOCKET__APPEND                    0x00000200UL
-#define NETLINK_SOCKET__SETATTR                   0x00000020UL
-#define NETLINK_SOCKET__SENDTO                    0x00040000UL
-#define NETLINK_SOCKET__GETOPT                    0x00004000UL
-#define NETLINK_SOCKET__READ                      0x00000002UL
-#define NETLINK_SOCKET__SHUTDOWN                  0x00010000UL
-#define NETLINK_SOCKET__LISTEN                    0x00001000UL
 #define NETLINK_SOCKET__BIND                      0x00000400UL
-#define NETLINK_SOCKET__WRITE                     0x00000004UL
-#define NETLINK_SOCKET__ACCEPT                    0x00002000UL
 #define NETLINK_SOCKET__CONNECT                   0x00000800UL
-#define NETLINK_SOCKET__LOCK                      0x00000040UL
-#define NETLINK_SOCKET__IOCTL                     0x00000001UL
-#define NETLINK_SOCKET__CREATE                    0x00000008UL
-#define NETLINK_SOCKET__NAME_BIND                 0x00200000UL
-#define NETLINK_SOCKET__SEND_MSG                  0x00100000UL
+#define NETLINK_SOCKET__LISTEN                    0x00001000UL
+#define NETLINK_SOCKET__ACCEPT                    0x00002000UL
+#define NETLINK_SOCKET__GETOPT                    0x00004000UL
+#define NETLINK_SOCKET__SETOPT                    0x00008000UL
+#define NETLINK_SOCKET__SHUTDOWN                  0x00010000UL
 #define NETLINK_SOCKET__RECVFROM                  0x00020000UL
-#define NETLINK_SOCKET__GETATTR                   0x00000010UL
+#define NETLINK_SOCKET__SENDTO                    0x00040000UL
+#define NETLINK_SOCKET__RECV_MSG                  0x00080000UL
+#define NETLINK_SOCKET__SEND_MSG                  0x00100000UL
+#define NETLINK_SOCKET__NAME_BIND                 0x00200000UL
 
-#define PACKET_SOCKET__RELABELTO                  0x00000100UL
-#define PACKET_SOCKET__RECV_MSG                   0x00080000UL
+#define PACKET_SOCKET__IOCTL                      0x00000001UL
+#define PACKET_SOCKET__READ                       0x00000002UL
+#define PACKET_SOCKET__WRITE                      0x00000004UL
+#define PACKET_SOCKET__CREATE                     0x00000008UL
+#define PACKET_SOCKET__GETATTR                    0x00000010UL
+#define PACKET_SOCKET__SETATTR                    0x00000020UL
+#define PACKET_SOCKET__LOCK                       0x00000040UL
 #define PACKET_SOCKET__RELABELFROM                0x00000080UL
-#define PACKET_SOCKET__SETOPT                     0x00008000UL
+#define PACKET_SOCKET__RELABELTO                  0x00000100UL
 #define PACKET_SOCKET__APPEND                     0x00000200UL
-#define PACKET_SOCKET__SETATTR                    0x00000020UL
-#define PACKET_SOCKET__SENDTO                     0x00040000UL
-#define PACKET_SOCKET__GETOPT                     0x00004000UL
-#define PACKET_SOCKET__READ                       0x00000002UL
-#define PACKET_SOCKET__SHUTDOWN                   0x00010000UL
-#define PACKET_SOCKET__LISTEN                     0x00001000UL
 #define PACKET_SOCKET__BIND                       0x00000400UL
-#define PACKET_SOCKET__WRITE                      0x00000004UL
-#define PACKET_SOCKET__ACCEPT                     0x00002000UL
 #define PACKET_SOCKET__CONNECT                    0x00000800UL
-#define PACKET_SOCKET__LOCK                       0x00000040UL
-#define PACKET_SOCKET__IOCTL                      0x00000001UL
-#define PACKET_SOCKET__CREATE                     0x00000008UL
-#define PACKET_SOCKET__NAME_BIND                  0x00200000UL
-#define PACKET_SOCKET__SEND_MSG                   0x00100000UL
+#define PACKET_SOCKET__LISTEN                     0x00001000UL
+#define PACKET_SOCKET__ACCEPT                     0x00002000UL
+#define PACKET_SOCKET__GETOPT                     0x00004000UL
+#define PACKET_SOCKET__SETOPT                     0x00008000UL
+#define PACKET_SOCKET__SHUTDOWN                   0x00010000UL
 #define PACKET_SOCKET__RECVFROM                   0x00020000UL
-#define PACKET_SOCKET__GETATTR                    0x00000010UL
+#define PACKET_SOCKET__SENDTO                     0x00040000UL
+#define PACKET_SOCKET__RECV_MSG                   0x00080000UL
+#define PACKET_SOCKET__SEND_MSG                   0x00100000UL
+#define PACKET_SOCKET__NAME_BIND                  0x00200000UL
 
-#define KEY_SOCKET__RELABELTO                     0x00000100UL
-#define KEY_SOCKET__RECV_MSG                      0x00080000UL
+#define KEY_SOCKET__IOCTL                         0x00000001UL
+#define KEY_SOCKET__READ                          0x00000002UL
+#define KEY_SOCKET__WRITE                         0x00000004UL
+#define KEY_SOCKET__CREATE                        0x00000008UL
+#define KEY_SOCKET__GETATTR                       0x00000010UL
+#define KEY_SOCKET__SETATTR                       0x00000020UL
+#define KEY_SOCKET__LOCK                          0x00000040UL
 #define KEY_SOCKET__RELABELFROM                   0x00000080UL
-#define KEY_SOCKET__SETOPT                        0x00008000UL
+#define KEY_SOCKET__RELABELTO                     0x00000100UL
 #define KEY_SOCKET__APPEND                        0x00000200UL
-#define KEY_SOCKET__SETATTR                       0x00000020UL
-#define KEY_SOCKET__SENDTO                        0x00040000UL
-#define KEY_SOCKET__GETOPT                        0x00004000UL
-#define KEY_SOCKET__READ                          0x00000002UL
-#define KEY_SOCKET__SHUTDOWN                      0x00010000UL
-#define KEY_SOCKET__LISTEN                        0x00001000UL
 #define KEY_SOCKET__BIND                          0x00000400UL
-#define KEY_SOCKET__WRITE                         0x00000004UL
-#define KEY_SOCKET__ACCEPT                        0x00002000UL
 #define KEY_SOCKET__CONNECT                       0x00000800UL
-#define KEY_SOCKET__LOCK                          0x00000040UL
-#define KEY_SOCKET__IOCTL                         0x00000001UL
-#define KEY_SOCKET__CREATE                        0x00000008UL
-#define KEY_SOCKET__NAME_BIND                     0x00200000UL
-#define KEY_SOCKET__SEND_MSG                      0x00100000UL
+#define KEY_SOCKET__LISTEN                        0x00001000UL
+#define KEY_SOCKET__ACCEPT                        0x00002000UL
+#define KEY_SOCKET__GETOPT                        0x00004000UL
+#define KEY_SOCKET__SETOPT                        0x00008000UL
+#define KEY_SOCKET__SHUTDOWN                      0x00010000UL
 #define KEY_SOCKET__RECVFROM                      0x00020000UL
-#define KEY_SOCKET__GETATTR                       0x00000010UL
+#define KEY_SOCKET__SENDTO                        0x00040000UL
+#define KEY_SOCKET__RECV_MSG                      0x00080000UL
+#define KEY_SOCKET__SEND_MSG                      0x00100000UL
+#define KEY_SOCKET__NAME_BIND                     0x00200000UL
 
-#define UNIX_STREAM_SOCKET__RELABELTO             0x00000100UL
-#define UNIX_STREAM_SOCKET__RECV_MSG              0x00080000UL
+#define UNIX_STREAM_SOCKET__IOCTL                 0x00000001UL
+#define UNIX_STREAM_SOCKET__READ                  0x00000002UL
+#define UNIX_STREAM_SOCKET__WRITE                 0x00000004UL
+#define UNIX_STREAM_SOCKET__CREATE                0x00000008UL
+#define UNIX_STREAM_SOCKET__GETATTR               0x00000010UL
+#define UNIX_STREAM_SOCKET__SETATTR               0x00000020UL
+#define UNIX_STREAM_SOCKET__LOCK                  0x00000040UL
 #define UNIX_STREAM_SOCKET__RELABELFROM           0x00000080UL
-#define UNIX_STREAM_SOCKET__SETOPT                0x00008000UL
+#define UNIX_STREAM_SOCKET__RELABELTO             0x00000100UL
 #define UNIX_STREAM_SOCKET__APPEND                0x00000200UL
-#define UNIX_STREAM_SOCKET__SETATTR               0x00000020UL
-#define UNIX_STREAM_SOCKET__SENDTO                0x00040000UL
-#define UNIX_STREAM_SOCKET__GETOPT                0x00004000UL
-#define UNIX_STREAM_SOCKET__READ                  0x00000002UL
-#define UNIX_STREAM_SOCKET__SHUTDOWN              0x00010000UL
-#define UNIX_STREAM_SOCKET__LISTEN                0x00001000UL
 #define UNIX_STREAM_SOCKET__BIND                  0x00000400UL
-#define UNIX_STREAM_SOCKET__WRITE                 0x00000004UL
-#define UNIX_STREAM_SOCKET__ACCEPT                0x00002000UL
 #define UNIX_STREAM_SOCKET__CONNECT               0x00000800UL
-#define UNIX_STREAM_SOCKET__LOCK                  0x00000040UL
-#define UNIX_STREAM_SOCKET__IOCTL                 0x00000001UL
-#define UNIX_STREAM_SOCKET__CREATE                0x00000008UL
-#define UNIX_STREAM_SOCKET__NAME_BIND             0x00200000UL
-#define UNIX_STREAM_SOCKET__SEND_MSG              0x00100000UL
+#define UNIX_STREAM_SOCKET__LISTEN                0x00001000UL
+#define UNIX_STREAM_SOCKET__ACCEPT                0x00002000UL
+#define UNIX_STREAM_SOCKET__GETOPT                0x00004000UL
+#define UNIX_STREAM_SOCKET__SETOPT                0x00008000UL
+#define UNIX_STREAM_SOCKET__SHUTDOWN              0x00010000UL
 #define UNIX_STREAM_SOCKET__RECVFROM              0x00020000UL
-#define UNIX_STREAM_SOCKET__GETATTR               0x00000010UL
+#define UNIX_STREAM_SOCKET__SENDTO                0x00040000UL
+#define UNIX_STREAM_SOCKET__RECV_MSG              0x00080000UL
+#define UNIX_STREAM_SOCKET__SEND_MSG              0x00100000UL
+#define UNIX_STREAM_SOCKET__NAME_BIND             0x00200000UL
 
 #define UNIX_STREAM_SOCKET__CONNECTTO             0x00400000UL
 #define UNIX_STREAM_SOCKET__NEWCONN               0x00800000UL
 #define UNIX_STREAM_SOCKET__ACCEPTFROM            0x01000000UL
 
-#define UNIX_DGRAM_SOCKET__RELABELTO              0x00000100UL
-#define UNIX_DGRAM_SOCKET__RECV_MSG               0x00080000UL
+#define UNIX_DGRAM_SOCKET__IOCTL                  0x00000001UL
+#define UNIX_DGRAM_SOCKET__READ                   0x00000002UL
+#define UNIX_DGRAM_SOCKET__WRITE                  0x00000004UL
+#define UNIX_DGRAM_SOCKET__CREATE                 0x00000008UL
+#define UNIX_DGRAM_SOCKET__GETATTR                0x00000010UL
+#define UNIX_DGRAM_SOCKET__SETATTR                0x00000020UL
+#define UNIX_DGRAM_SOCKET__LOCK                   0x00000040UL
 #define UNIX_DGRAM_SOCKET__RELABELFROM            0x00000080UL
-#define UNIX_DGRAM_SOCKET__SETOPT                 0x00008000UL
+#define UNIX_DGRAM_SOCKET__RELABELTO              0x00000100UL
 #define UNIX_DGRAM_SOCKET__APPEND                 0x00000200UL
-#define UNIX_DGRAM_SOCKET__SETATTR                0x00000020UL
-#define UNIX_DGRAM_SOCKET__SENDTO                 0x00040000UL
-#define UNIX_DGRAM_SOCKET__GETOPT                 0x00004000UL
-#define UNIX_DGRAM_SOCKET__READ                   0x00000002UL
-#define UNIX_DGRAM_SOCKET__SHUTDOWN               0x00010000UL
-#define UNIX_DGRAM_SOCKET__LISTEN                 0x00001000UL
 #define UNIX_DGRAM_SOCKET__BIND                   0x00000400UL
-#define UNIX_DGRAM_SOCKET__WRITE                  0x00000004UL
-#define UNIX_DGRAM_SOCKET__ACCEPT                 0x00002000UL
 #define UNIX_DGRAM_SOCKET__CONNECT                0x00000800UL
-#define UNIX_DGRAM_SOCKET__LOCK                   0x00000040UL
-#define UNIX_DGRAM_SOCKET__IOCTL                  0x00000001UL
-#define UNIX_DGRAM_SOCKET__CREATE                 0x00000008UL
-#define UNIX_DGRAM_SOCKET__NAME_BIND              0x00200000UL
-#define UNIX_DGRAM_SOCKET__SEND_MSG               0x00100000UL
+#define UNIX_DGRAM_SOCKET__LISTEN                 0x00001000UL
+#define UNIX_DGRAM_SOCKET__ACCEPT                 0x00002000UL
+#define UNIX_DGRAM_SOCKET__GETOPT                 0x00004000UL
+#define UNIX_DGRAM_SOCKET__SETOPT                 0x00008000UL
+#define UNIX_DGRAM_SOCKET__SHUTDOWN               0x00010000UL
 #define UNIX_DGRAM_SOCKET__RECVFROM               0x00020000UL
-#define UNIX_DGRAM_SOCKET__GETATTR                0x00000010UL
+#define UNIX_DGRAM_SOCKET__SENDTO                 0x00040000UL
+#define UNIX_DGRAM_SOCKET__RECV_MSG               0x00080000UL
+#define UNIX_DGRAM_SOCKET__SEND_MSG               0x00100000UL
+#define UNIX_DGRAM_SOCKET__NAME_BIND              0x00200000UL
 
 #define PROCESS__FORK                             0x00000001UL
 #define PROCESS__TRANSITION                       0x00000002UL
@@ -457,50 +459,50 @@
 #define PROCESS__SETRLIMIT                        0x00200000UL
 #define PROCESS__RLIMITINH                        0x00400000UL
 
+#define IPC__CREATE                               0x00000001UL
+#define IPC__DESTROY                              0x00000002UL
+#define IPC__GETATTR                              0x00000004UL
 #define IPC__SETATTR                              0x00000008UL
 #define IPC__READ                                 0x00000010UL
+#define IPC__WRITE                                0x00000020UL
 #define IPC__ASSOCIATE                            0x00000040UL
-#define IPC__DESTROY                              0x00000002UL
-#define IPC__UNIX_WRITE                           0x00000100UL
-#define IPC__CREATE                               0x00000001UL
 #define IPC__UNIX_READ                            0x00000080UL
-#define IPC__GETATTR                              0x00000004UL
-#define IPC__WRITE                                0x00000020UL
+#define IPC__UNIX_WRITE                           0x00000100UL
 
+#define SEM__CREATE                               0x00000001UL
+#define SEM__DESTROY                              0x00000002UL
+#define SEM__GETATTR                              0x00000004UL
 #define SEM__SETATTR                              0x00000008UL
 #define SEM__READ                                 0x00000010UL
+#define SEM__WRITE                                0x00000020UL
 #define SEM__ASSOCIATE                            0x00000040UL
-#define SEM__DESTROY                              0x00000002UL
-#define SEM__UNIX_WRITE                           0x00000100UL
-#define SEM__CREATE                               0x00000001UL
 #define SEM__UNIX_READ                            0x00000080UL
-#define SEM__GETATTR                              0x00000004UL
-#define SEM__WRITE                                0x00000020UL
+#define SEM__UNIX_WRITE                           0x00000100UL
 
+#define MSGQ__CREATE                              0x00000001UL
+#define MSGQ__DESTROY                             0x00000002UL
+#define MSGQ__GETATTR                             0x00000004UL
 #define MSGQ__SETATTR                             0x00000008UL
 #define MSGQ__READ                                0x00000010UL
+#define MSGQ__WRITE                               0x00000020UL
 #define MSGQ__ASSOCIATE                           0x00000040UL
-#define MSGQ__DESTROY                             0x00000002UL
-#define MSGQ__UNIX_WRITE                          0x00000100UL
-#define MSGQ__CREATE                              0x00000001UL
 #define MSGQ__UNIX_READ                           0x00000080UL
-#define MSGQ__GETATTR                             0x00000004UL
-#define MSGQ__WRITE                               0x00000020UL
+#define MSGQ__UNIX_WRITE                          0x00000100UL
 
 #define MSGQ__ENQUEUE                             0x00000200UL
 
 #define MSG__SEND                                 0x00000001UL
 #define MSG__RECEIVE                              0x00000002UL
 
+#define SHM__CREATE                               0x00000001UL
+#define SHM__DESTROY                              0x00000002UL
+#define SHM__GETATTR                              0x00000004UL
 #define SHM__SETATTR                              0x00000008UL
 #define SHM__READ                                 0x00000010UL
+#define SHM__WRITE                                0x00000020UL
 #define SHM__ASSOCIATE                            0x00000040UL
-#define SHM__DESTROY                              0x00000002UL
-#define SHM__UNIX_WRITE                           0x00000100UL
-#define SHM__CREATE                               0x00000001UL
 #define SHM__UNIX_READ                            0x00000080UL
-#define SHM__GETATTR                              0x00000004UL
-#define SHM__WRITE                                0x00000020UL
+#define SHM__UNIX_WRITE                           0x00000100UL
 
 #define SHM__LOCK                                 0x00000200UL
 
@@ -552,6 +554,327 @@
 #define PASSWD__PASSWD                            0x00000001UL
 #define PASSWD__CHFN                              0x00000002UL
 #define PASSWD__CHSH                              0x00000004UL
+#define PASSWD__ROOTOK                            0x00000008UL
 
+#define DRAWABLE__CREATE                          0x00000001UL
+#define DRAWABLE__DESTROY                         0x00000002UL
+#define DRAWABLE__DRAW                            0x00000004UL
+#define DRAWABLE__COPY                            0x00000008UL
+#define DRAWABLE__GETATTR                         0x00000010UL
+
+#define GC__CREATE                                0x00000001UL
+#define GC__FREE                                  0x00000002UL
+#define GC__GETATTR                               0x00000004UL
+#define GC__SETATTR                               0x00000008UL
+
+#define WINDOW__ADDCHILD                          0x00000001UL
+#define WINDOW__CREATE                            0x00000002UL
+#define WINDOW__DESTROY                           0x00000004UL
+#define WINDOW__MAP                               0x00000008UL
+#define WINDOW__UNMAP                             0x00000010UL
+#define WINDOW__CHSTACK                           0x00000020UL
+#define WINDOW__CHPROPLIST                        0x00000040UL
+#define WINDOW__CHPROP                            0x00000080UL
+#define WINDOW__LISTPROP                          0x00000100UL
+#define WINDOW__GETATTR                           0x00000200UL
+#define WINDOW__SETATTR                           0x00000400UL
+#define WINDOW__SETFOCUS                          0x00000800UL
+#define WINDOW__MOVE                              0x00001000UL
+#define WINDOW__CHSELECTION                       0x00002000UL
+#define WINDOW__CHPARENT                          0x00004000UL
+#define WINDOW__CTRLLIFE                          0x00008000UL
+#define WINDOW__ENUMERATE                         0x00010000UL
+#define WINDOW__TRANSPARENT                       0x00020000UL
+#define WINDOW__MOUSEMOTION                       0x00040000UL
+#define WINDOW__CLIENTCOMEVENT                    0x00080000UL
+#define WINDOW__INPUTEVENT                        0x00100000UL
+#define WINDOW__DRAWEVENT                         0x00200000UL
+#define WINDOW__WINDOWCHANGEEVENT                 0x00400000UL
+#define WINDOW__WINDOWCHANGEREQUEST               0x00800000UL
+#define WINDOW__SERVERCHANGEEVENT                 0x01000000UL
+#define WINDOW__EXTENSIONEVENT                    0x02000000UL
+
+#define FONT__LOAD                                0x00000001UL
+#define FONT__FREE                                0x00000002UL
+#define FONT__GETATTR                             0x00000004UL
+#define FONT__USE                                 0x00000008UL
+
+#define COLORMAP__CREATE                          0x00000001UL
+#define COLORMAP__FREE                            0x00000002UL
+#define COLORMAP__INSTALL                         0x00000004UL
+#define COLORMAP__UNINSTALL                       0x00000008UL
+#define COLORMAP__LIST                            0x00000010UL
+#define COLORMAP__READ                            0x00000020UL
+#define COLORMAP__STORE                           0x00000040UL
+#define COLORMAP__GETATTR                         0x00000080UL
+#define COLORMAP__SETATTR                         0x00000100UL
+
+#define PROPERTY__CREATE                          0x00000001UL
+#define PROPERTY__FREE                            0x00000002UL
+#define PROPERTY__READ                            0x00000004UL
+#define PROPERTY__WRITE                           0x00000008UL
+
+#define CURSOR__CREATE                            0x00000001UL
+#define CURSOR__CREATEGLYPH                       0x00000002UL
+#define CURSOR__FREE                              0x00000004UL
+#define CURSOR__ASSIGN                            0x00000008UL
+#define CURSOR__SETATTR                           0x00000010UL
+
+#define XCLIENT__KILL                             0x00000001UL
+
+#define XINPUT__LOOKUP                            0x00000001UL
+#define XINPUT__GETATTR                           0x00000002UL
+#define XINPUT__SETATTR                           0x00000004UL
+#define XINPUT__SETFOCUS                          0x00000008UL
+#define XINPUT__WARPPOINTER                       0x00000010UL
+#define XINPUT__ACTIVEGRAB                        0x00000020UL
+#define XINPUT__PASSIVEGRAB                       0x00000040UL
+#define XINPUT__UNGRAB                            0x00000080UL
+#define XINPUT__BELL                              0x00000100UL
+#define XINPUT__MOUSEMOTION                       0x00000200UL
+#define XINPUT__RELABELINPUT                      0x00000400UL
+
+#define XSERVER__SCREENSAVER                      0x00000001UL
+#define XSERVER__GETHOSTLIST                      0x00000002UL
+#define XSERVER__SETHOSTLIST                      0x00000004UL
+#define XSERVER__GETFONTPATH                      0x00000008UL
+#define XSERVER__SETFONTPATH                      0x00000010UL
+#define XSERVER__GETATTR                          0x00000020UL
+#define XSERVER__GRAB                             0x00000040UL
+#define XSERVER__UNGRAB                           0x00000080UL
+
+#define XEXTENSION__QUERY                         0x00000001UL
+#define XEXTENSION__USE                           0x00000002UL
+
+#define PAX__PAGEEXEC                             0x00000001UL
+#define PAX__EMUTRAMP                             0x00000002UL
+#define PAX__MPROTECT                             0x00000004UL
+#define PAX__RANDMMAP                             0x00000008UL
+#define PAX__RANDEXEC                             0x00000010UL
+#define PAX__SEGMEXEC                             0x00000020UL
+
+#define NETLINK_ROUTE_SOCKET__IOCTL               0x00000001UL
+#define NETLINK_ROUTE_SOCKET__READ                0x00000002UL
+#define NETLINK_ROUTE_SOCKET__WRITE               0x00000004UL
+#define NETLINK_ROUTE_SOCKET__CREATE              0x00000008UL
+#define NETLINK_ROUTE_SOCKET__GETATTR             0x00000010UL
+#define NETLINK_ROUTE_SOCKET__SETATTR             0x00000020UL
+#define NETLINK_ROUTE_SOCKET__LOCK                0x00000040UL
+#define NETLINK_ROUTE_SOCKET__RELABELFROM         0x00000080UL
+#define NETLINK_ROUTE_SOCKET__RELABELTO           0x00000100UL
+#define NETLINK_ROUTE_SOCKET__APPEND              0x00000200UL
+#define NETLINK_ROUTE_SOCKET__BIND                0x00000400UL
+#define NETLINK_ROUTE_SOCKET__CONNECT             0x00000800UL
+#define NETLINK_ROUTE_SOCKET__LISTEN              0x00001000UL
+#define NETLINK_ROUTE_SOCKET__ACCEPT              0x00002000UL
+#define NETLINK_ROUTE_SOCKET__GETOPT              0x00004000UL
+#define NETLINK_ROUTE_SOCKET__SETOPT              0x00008000UL
+#define NETLINK_ROUTE_SOCKET__SHUTDOWN            0x00010000UL
+#define NETLINK_ROUTE_SOCKET__RECVFROM            0x00020000UL
+#define NETLINK_ROUTE_SOCKET__SENDTO              0x00040000UL
+#define NETLINK_ROUTE_SOCKET__RECV_MSG            0x00080000UL
+#define NETLINK_ROUTE_SOCKET__SEND_MSG            0x00100000UL
+#define NETLINK_ROUTE_SOCKET__NAME_BIND           0x00200000UL
+
+#define NETLINK_ROUTE_SOCKET__NLMSG_READ          0x00400000UL
+#define NETLINK_ROUTE_SOCKET__NLMSG_WRITE         0x00800000UL
+
+#define NETLINK_FIREWALL_SOCKET__IOCTL            0x00000001UL
+#define NETLINK_FIREWALL_SOCKET__READ             0x00000002UL
+#define NETLINK_FIREWALL_SOCKET__WRITE            0x00000004UL
+#define NETLINK_FIREWALL_SOCKET__CREATE           0x00000008UL
+#define NETLINK_FIREWALL_SOCKET__GETATTR          0x00000010UL
+#define NETLINK_FIREWALL_SOCKET__SETATTR          0x00000020UL
+#define NETLINK_FIREWALL_SOCKET__LOCK             0x00000040UL
+#define NETLINK_FIREWALL_SOCKET__RELABELFROM      0x00000080UL
+#define NETLINK_FIREWALL_SOCKET__RELABELTO        0x00000100UL
+#define NETLINK_FIREWALL_SOCKET__APPEND           0x00000200UL
+#define NETLINK_FIREWALL_SOCKET__BIND             0x00000400UL
+#define NETLINK_FIREWALL_SOCKET__CONNECT          0x00000800UL
+#define NETLINK_FIREWALL_SOCKET__LISTEN           0x00001000UL
+#define NETLINK_FIREWALL_SOCKET__ACCEPT           0x00002000UL
+#define NETLINK_FIREWALL_SOCKET__GETOPT           0x00004000UL
+#define NETLINK_FIREWALL_SOCKET__SETOPT           0x00008000UL
+#define NETLINK_FIREWALL_SOCKET__SHUTDOWN         0x00010000UL
+#define NETLINK_FIREWALL_SOCKET__RECVFROM         0x00020000UL
+#define NETLINK_FIREWALL_SOCKET__SENDTO           0x00040000UL
+#define NETLINK_FIREWALL_SOCKET__RECV_MSG         0x00080000UL
+#define NETLINK_FIREWALL_SOCKET__SEND_MSG         0x00100000UL
+#define NETLINK_FIREWALL_SOCKET__NAME_BIND        0x00200000UL
+
+#define NETLINK_FIREWALL_SOCKET__NLMSG_READ       0x00400000UL
+#define NETLINK_FIREWALL_SOCKET__NLMSG_WRITE      0x00800000UL
+
+#define NETLINK_TCPDIAG_SOCKET__IOCTL             0x00000001UL
+#define NETLINK_TCPDIAG_SOCKET__READ              0x00000002UL
+#define NETLINK_TCPDIAG_SOCKET__WRITE             0x00000004UL
+#define NETLINK_TCPDIAG_SOCKET__CREATE            0x00000008UL
+#define NETLINK_TCPDIAG_SOCKET__GETATTR           0x00000010UL
+#define NETLINK_TCPDIAG_SOCKET__SETATTR           0x00000020UL
+#define NETLINK_TCPDIAG_SOCKET__LOCK              0x00000040UL
+#define NETLINK_TCPDIAG_SOCKET__RELABELFROM       0x00000080UL
+#define NETLINK_TCPDIAG_SOCKET__RELABELTO         0x00000100UL
+#define NETLINK_TCPDIAG_SOCKET__APPEND            0x00000200UL
+#define NETLINK_TCPDIAG_SOCKET__BIND              0x00000400UL
+#define NETLINK_TCPDIAG_SOCKET__CONNECT           0x00000800UL
+#define NETLINK_TCPDIAG_SOCKET__LISTEN            0x00001000UL
+#define NETLINK_TCPDIAG_SOCKET__ACCEPT            0x00002000UL
+#define NETLINK_TCPDIAG_SOCKET__GETOPT            0x00004000UL
+#define NETLINK_TCPDIAG_SOCKET__SETOPT            0x00008000UL
+#define NETLINK_TCPDIAG_SOCKET__SHUTDOWN          0x00010000UL
+#define NETLINK_TCPDIAG_SOCKET__RECVFROM          0x00020000UL
+#define NETLINK_TCPDIAG_SOCKET__SENDTO            0x00040000UL
+#define NETLINK_TCPDIAG_SOCKET__RECV_MSG          0x00080000UL
+#define NETLINK_TCPDIAG_SOCKET__SEND_MSG          0x00100000UL
+#define NETLINK_TCPDIAG_SOCKET__NAME_BIND         0x00200000UL
+
+#define NETLINK_TCPDIAG_SOCKET__NLMSG_READ        0x00400000UL
+#define NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE       0x00800000UL
+
+#define NETLINK_NFLOG_SOCKET__IOCTL               0x00000001UL
+#define NETLINK_NFLOG_SOCKET__READ                0x00000002UL
+#define NETLINK_NFLOG_SOCKET__WRITE               0x00000004UL
+#define NETLINK_NFLOG_SOCKET__CREATE              0x00000008UL
+#define NETLINK_NFLOG_SOCKET__GETATTR             0x00000010UL
+#define NETLINK_NFLOG_SOCKET__SETATTR             0x00000020UL
+#define NETLINK_NFLOG_SOCKET__LOCK                0x00000040UL
+#define NETLINK_NFLOG_SOCKET__RELABELFROM         0x00000080UL
+#define NETLINK_NFLOG_SOCKET__RELABELTO           0x00000100UL
+#define NETLINK_NFLOG_SOCKET__APPEND              0x00000200UL
+#define NETLINK_NFLOG_SOCKET__BIND                0x00000400UL
+#define NETLINK_NFLOG_SOCKET__CONNECT             0x00000800UL
+#define NETLINK_NFLOG_SOCKET__LISTEN              0x00001000UL
+#define NETLINK_NFLOG_SOCKET__ACCEPT              0x00002000UL
+#define NETLINK_NFLOG_SOCKET__GETOPT              0x00004000UL
+#define NETLINK_NFLOG_SOCKET__SETOPT              0x00008000UL
+#define NETLINK_NFLOG_SOCKET__SHUTDOWN            0x00010000UL
+#define NETLINK_NFLOG_SOCKET__RECVFROM            0x00020000UL
+#define NETLINK_NFLOG_SOCKET__SENDTO              0x00040000UL
+#define NETLINK_NFLOG_SOCKET__RECV_MSG            0x00080000UL
+#define NETLINK_NFLOG_SOCKET__SEND_MSG            0x00100000UL
+#define NETLINK_NFLOG_SOCKET__NAME_BIND           0x00200000UL
+
+#define NETLINK_XFRM_SOCKET__IOCTL                0x00000001UL
+#define NETLINK_XFRM_SOCKET__READ                 0x00000002UL
+#define NETLINK_XFRM_SOCKET__WRITE                0x00000004UL
+#define NETLINK_XFRM_SOCKET__CREATE               0x00000008UL
+#define NETLINK_XFRM_SOCKET__GETATTR              0x00000010UL
+#define NETLINK_XFRM_SOCKET__SETATTR              0x00000020UL
+#define NETLINK_XFRM_SOCKET__LOCK                 0x00000040UL
+#define NETLINK_XFRM_SOCKET__RELABELFROM          0x00000080UL
+#define NETLINK_XFRM_SOCKET__RELABELTO            0x00000100UL
+#define NETLINK_XFRM_SOCKET__APPEND               0x00000200UL
+#define NETLINK_XFRM_SOCKET__BIND                 0x00000400UL
+#define NETLINK_XFRM_SOCKET__CONNECT              0x00000800UL
+#define NETLINK_XFRM_SOCKET__LISTEN               0x00001000UL
+#define NETLINK_XFRM_SOCKET__ACCEPT               0x00002000UL
+#define NETLINK_XFRM_SOCKET__GETOPT               0x00004000UL
+#define NETLINK_XFRM_SOCKET__SETOPT               0x00008000UL
+#define NETLINK_XFRM_SOCKET__SHUTDOWN             0x00010000UL
+#define NETLINK_XFRM_SOCKET__RECVFROM             0x00020000UL
+#define NETLINK_XFRM_SOCKET__SENDTO               0x00040000UL
+#define NETLINK_XFRM_SOCKET__RECV_MSG             0x00080000UL
+#define NETLINK_XFRM_SOCKET__SEND_MSG             0x00100000UL
+#define NETLINK_XFRM_SOCKET__NAME_BIND            0x00200000UL
+
+#define NETLINK_XFRM_SOCKET__NLMSG_READ           0x00400000UL
+#define NETLINK_XFRM_SOCKET__NLMSG_WRITE          0x00800000UL
+
+#define NETLINK_SELINUX_SOCKET__IOCTL             0x00000001UL
+#define NETLINK_SELINUX_SOCKET__READ              0x00000002UL
+#define NETLINK_SELINUX_SOCKET__WRITE             0x00000004UL
+#define NETLINK_SELINUX_SOCKET__CREATE            0x00000008UL
+#define NETLINK_SELINUX_SOCKET__GETATTR           0x00000010UL
+#define NETLINK_SELINUX_SOCKET__SETATTR           0x00000020UL
+#define NETLINK_SELINUX_SOCKET__LOCK              0x00000040UL
+#define NETLINK_SELINUX_SOCKET__RELABELFROM       0x00000080UL
+#define NETLINK_SELINUX_SOCKET__RELABELTO         0x00000100UL
+#define NETLINK_SELINUX_SOCKET__APPEND            0x00000200UL
+#define NETLINK_SELINUX_SOCKET__BIND              0x00000400UL
+#define NETLINK_SELINUX_SOCKET__CONNECT           0x00000800UL
+#define NETLINK_SELINUX_SOCKET__LISTEN            0x00001000UL
+#define NETLINK_SELINUX_SOCKET__ACCEPT            0x00002000UL
+#define NETLINK_SELINUX_SOCKET__GETOPT            0x00004000UL
+#define NETLINK_SELINUX_SOCKET__SETOPT            0x00008000UL
+#define NETLINK_SELINUX_SOCKET__SHUTDOWN          0x00010000UL
+#define NETLINK_SELINUX_SOCKET__RECVFROM          0x00020000UL
+#define NETLINK_SELINUX_SOCKET__SENDTO            0x00040000UL
+#define NETLINK_SELINUX_SOCKET__RECV_MSG          0x00080000UL
+#define NETLINK_SELINUX_SOCKET__SEND_MSG          0x00100000UL
+#define NETLINK_SELINUX_SOCKET__NAME_BIND         0x00200000UL
+
+#define NETLINK_AUDIT_SOCKET__IOCTL               0x00000001UL
+#define NETLINK_AUDIT_SOCKET__READ                0x00000002UL
+#define NETLINK_AUDIT_SOCKET__WRITE               0x00000004UL
+#define NETLINK_AUDIT_SOCKET__CREATE              0x00000008UL
+#define NETLINK_AUDIT_SOCKET__GETATTR             0x00000010UL
+#define NETLINK_AUDIT_SOCKET__SETATTR             0x00000020UL
+#define NETLINK_AUDIT_SOCKET__LOCK                0x00000040UL
+#define NETLINK_AUDIT_SOCKET__RELABELFROM         0x00000080UL
+#define NETLINK_AUDIT_SOCKET__RELABELTO           0x00000100UL
+#define NETLINK_AUDIT_SOCKET__APPEND              0x00000200UL
+#define NETLINK_AUDIT_SOCKET__BIND                0x00000400UL
+#define NETLINK_AUDIT_SOCKET__CONNECT             0x00000800UL
+#define NETLINK_AUDIT_SOCKET__LISTEN              0x00001000UL
+#define NETLINK_AUDIT_SOCKET__ACCEPT              0x00002000UL
+#define NETLINK_AUDIT_SOCKET__GETOPT              0x00004000UL
+#define NETLINK_AUDIT_SOCKET__SETOPT              0x00008000UL
+#define NETLINK_AUDIT_SOCKET__SHUTDOWN            0x00010000UL
+#define NETLINK_AUDIT_SOCKET__RECVFROM            0x00020000UL
+#define NETLINK_AUDIT_SOCKET__SENDTO              0x00040000UL
+#define NETLINK_AUDIT_SOCKET__RECV_MSG            0x00080000UL
+#define NETLINK_AUDIT_SOCKET__SEND_MSG            0x00100000UL
+#define NETLINK_AUDIT_SOCKET__NAME_BIND           0x00200000UL
+
+#define NETLINK_AUDIT_SOCKET__NLMSG_READ          0x00400000UL
+#define NETLINK_AUDIT_SOCKET__NLMSG_WRITE         0x00800000UL
+
+#define NETLINK_IP6FW_SOCKET__IOCTL               0x00000001UL
+#define NETLINK_IP6FW_SOCKET__READ                0x00000002UL
+#define NETLINK_IP6FW_SOCKET__WRITE               0x00000004UL
+#define NETLINK_IP6FW_SOCKET__CREATE              0x00000008UL
+#define NETLINK_IP6FW_SOCKET__GETATTR             0x00000010UL
+#define NETLINK_IP6FW_SOCKET__SETATTR             0x00000020UL
+#define NETLINK_IP6FW_SOCKET__LOCK                0x00000040UL
+#define NETLINK_IP6FW_SOCKET__RELABELFROM         0x00000080UL
+#define NETLINK_IP6FW_SOCKET__RELABELTO           0x00000100UL
+#define NETLINK_IP6FW_SOCKET__APPEND              0x00000200UL
+#define NETLINK_IP6FW_SOCKET__BIND                0x00000400UL
+#define NETLINK_IP6FW_SOCKET__CONNECT             0x00000800UL
+#define NETLINK_IP6FW_SOCKET__LISTEN              0x00001000UL
+#define NETLINK_IP6FW_SOCKET__ACCEPT              0x00002000UL
+#define NETLINK_IP6FW_SOCKET__GETOPT              0x00004000UL
+#define NETLINK_IP6FW_SOCKET__SETOPT              0x00008000UL
+#define NETLINK_IP6FW_SOCKET__SHUTDOWN            0x00010000UL
+#define NETLINK_IP6FW_SOCKET__RECVFROM            0x00020000UL
+#define NETLINK_IP6FW_SOCKET__SENDTO              0x00040000UL
+#define NETLINK_IP6FW_SOCKET__RECV_MSG            0x00080000UL
+#define NETLINK_IP6FW_SOCKET__SEND_MSG            0x00100000UL
+#define NETLINK_IP6FW_SOCKET__NAME_BIND           0x00200000UL
+
+#define NETLINK_IP6FW_SOCKET__NLMSG_READ          0x00400000UL
+#define NETLINK_IP6FW_SOCKET__NLMSG_WRITE         0x00800000UL
+
+#define NETLINK_DNRT_SOCKET__IOCTL                0x00000001UL
+#define NETLINK_DNRT_SOCKET__READ                 0x00000002UL
+#define NETLINK_DNRT_SOCKET__WRITE                0x00000004UL
+#define NETLINK_DNRT_SOCKET__CREATE               0x00000008UL
+#define NETLINK_DNRT_SOCKET__GETATTR              0x00000010UL
+#define NETLINK_DNRT_SOCKET__SETATTR              0x00000020UL
+#define NETLINK_DNRT_SOCKET__LOCK                 0x00000040UL
+#define NETLINK_DNRT_SOCKET__RELABELFROM          0x00000080UL
+#define NETLINK_DNRT_SOCKET__RELABELTO            0x00000100UL
+#define NETLINK_DNRT_SOCKET__APPEND               0x00000200UL
+#define NETLINK_DNRT_SOCKET__BIND                 0x00000400UL
+#define NETLINK_DNRT_SOCKET__CONNECT              0x00000800UL
+#define NETLINK_DNRT_SOCKET__LISTEN               0x00001000UL
+#define NETLINK_DNRT_SOCKET__ACCEPT               0x00002000UL
+#define NETLINK_DNRT_SOCKET__GETOPT               0x00004000UL
+#define NETLINK_DNRT_SOCKET__SETOPT               0x00008000UL
+#define NETLINK_DNRT_SOCKET__SHUTDOWN             0x00010000UL
+#define NETLINK_DNRT_SOCKET__RECVFROM             0x00020000UL
+#define NETLINK_DNRT_SOCKET__SENDTO               0x00040000UL
+#define NETLINK_DNRT_SOCKET__RECV_MSG             0x00080000UL
+#define NETLINK_DNRT_SOCKET__SEND_MSG             0x00100000UL
 
 /* FLASK */
diff -Nru a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
--- a/security/selinux/include/class_to_string.h	2004-06-23 19:04:25 -07:00
+++ b/security/selinux/include/class_to_string.h	2004-06-23 19:04:25 -07:00
@@ -35,5 +35,26 @@
     "shm",
     "ipc",
     "passwd",
+    "drawable",
+    "window",
+    "gc",
+    "font",
+    "colormap",
+    "property",
+    "cursor",
+    "xclient",
+    "xinput",
+    "xserver",
+    "xextension",
+    "pax",
+    "netlink_route_socket",
+    "netlink_firewall_socket",
+    "netlink_tcpdiag_socket",
+    "netlink_nflog_socket",
+    "netlink_xfrm_socket",
+    "netlink_selinux_socket",
+    "netlink_audit_socket",
+    "netlink_ip6fw_socket",
+    "netlink_dnrt_socket",
 };
 
diff -Nru a/security/selinux/include/flask.h b/security/selinux/include/flask.h
--- a/security/selinux/include/flask.h	2004-06-23 19:04:27 -07:00
+++ b/security/selinux/include/flask.h	2004-06-23 19:04:27 -07:00
@@ -35,6 +35,27 @@
 #define SECCLASS_SHM                                     28
 #define SECCLASS_IPC                                     29
 #define SECCLASS_PASSWD                                  30
+#define SECCLASS_DRAWABLE                                31
+#define SECCLASS_WINDOW                                  32
+#define SECCLASS_GC                                      33
+#define SECCLASS_FONT                                    34
+#define SECCLASS_COLORMAP                                35
+#define SECCLASS_PROPERTY                                36
+#define SECCLASS_CURSOR                                  37
+#define SECCLASS_XCLIENT                                 38
+#define SECCLASS_XINPUT                                  39
+#define SECCLASS_XSERVER                                 40
+#define SECCLASS_XEXTENSION                              41
+#define SECCLASS_PAX                                     42
+#define SECCLASS_NETLINK_ROUTE_SOCKET                    43
+#define SECCLASS_NETLINK_FIREWALL_SOCKET                 44
+#define SECCLASS_NETLINK_TCPDIAG_SOCKET                  45
+#define SECCLASS_NETLINK_NFLOG_SOCKET                    46
+#define SECCLASS_NETLINK_XFRM_SOCKET                     47
+#define SECCLASS_NETLINK_SELINUX_SOCKET                  48
+#define SECCLASS_NETLINK_AUDIT_SOCKET                    49
+#define SECCLASS_NETLINK_IP6FW_SOCKET                    50
+#define SECCLASS_NETLINK_DNRT_SOCKET                     51
 
 /*
  * Security identifier indices for initial entities
diff -Nru a/security/selinux/include/security.h b/security/selinux/include/security.h
--- a/security/selinux/include/security.h	2004-06-23 19:04:25 -07:00
+++ b/security/selinux/include/security.h	2004-06-23 19:04:25 -07:00
@@ -17,13 +17,14 @@
 #define SELINUX_MAGIC 0xf97cff8c
 
 /* Identify specific policy version changes */
-#define POLICYDB_VERSION_BASE  15
-#define POLICYDB_VERSION_BOOL  16
-#define POLICYDB_VERSION_IPV6  17
+#define POLICYDB_VERSION_BASE		15
+#define POLICYDB_VERSION_BOOL		16
+#define POLICYDB_VERSION_IPV6		17
+#define POLICYDB_VERSION_NLCLASS	18
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_IPV6
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_NLCLASS
 
 #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
 extern int selinux_enabled;
diff -Nru a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/security/selinux/nlmsgtab.c	2004-06-23 19:04:29 -07:00
@@ -0,0 +1,153 @@
+/*
+ * Netlink message type permission tables, for user generated messages.
+ *
+ * Author: James Morris <jmorris@redhat.com>
+ *
+ * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/if.h>
+#include <linux/netfilter_ipv4/ip_queue.h>
+#include <linux/tcp_diag.h>
+#include <linux/xfrm.h>
+#include <linux/audit.h>
+
+#include "flask.h"
+#include "av_permissions.h"
+
+struct nlmsg_perm
+{
+	u16	nlmsg_type;
+	u32	perm;
+};
+
+static struct nlmsg_perm nlmsg_route_perms[] =
+{
+	{ RTM_NEWLINK,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_DELLINK,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_GETLINK,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_SETLINK,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_NEWADDR,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_DELADDR,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_GETADDR,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_NEWROUTE,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_DELROUTE,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_GETROUTE,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_NEWNEIGH,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_DELNEIGH,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_GETNEIGH,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_NEWRULE,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_DELRULE,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_GETRULE,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_NEWQDISC,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_DELQDISC,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_GETQDISC,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_NEWTCLASS,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_DELTCLASS,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_GETTCLASS,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_NEWTFILTER,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_DELTFILTER,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_GETTFILTER,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_NEWPREFIX,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+	{ RTM_GETPREFIX,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_GETMULTICAST,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_GETANYCAST,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+};
+
+static struct nlmsg_perm nlmsg_firewall_perms[] =
+{
+	{ IPQM_MODE,		NETLINK_FIREWALL_SOCKET__NLMSG_WRITE },
+	{ IPQM_VERDICT,		NETLINK_FIREWALL_SOCKET__NLMSG_WRITE },
+};
+
+static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
+{
+	{ TCPDIAG_GETSOCK,	NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
+};
+
+static struct nlmsg_perm nlmsg_xfrm_perms[] =
+{
+	{ XFRM_MSG_NEWSA,	NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+	{ XFRM_MSG_DELSA,	NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+	{ XFRM_MSG_GETSA,	NETLINK_XFRM_SOCKET__NLMSG_READ  },
+	{ XFRM_MSG_NEWPOLICY,	NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+	{ XFRM_MSG_DELPOLICY,	NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+	{ XFRM_MSG_GETPOLICY,	NETLINK_XFRM_SOCKET__NLMSG_READ  },
+	{ XFRM_MSG_ALLOCSPI,	NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+	{ XFRM_MSG_UPDPOLICY,	NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+	{ XFRM_MSG_UPDSA,	NETLINK_XFRM_SOCKET__NLMSG_WRITE },
+};
+
+static struct nlmsg_perm nlmsg_audit_perms[] =
+{
+	{ AUDIT_GET,		NETLINK_AUDIT_SOCKET__NLMSG_READ  },
+	{ AUDIT_SET,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+	{ AUDIT_LIST,		NETLINK_AUDIT_SOCKET__NLMSG_READ  },
+	{ AUDIT_ADD,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+	{ AUDIT_DEL,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+	{ AUDIT_USER,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+	{ AUDIT_LOGIN,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+};
+
+
+static int nlmsg_perm(u16 nlmsg_type, u32 *perm, struct nlmsg_perm *tab, size_t tabsize)
+{
+	int i, err = -EINVAL;
+
+	for (i = 0; i < tabsize/sizeof(struct nlmsg_perm); i++)
+		if (nlmsg_type == tab[i].nlmsg_type) {
+			*perm = tab[i].perm;
+			err = 0;
+			break;
+		}
+
+	return err;
+}
+
+int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
+{
+	int err = 0;
+
+	switch (sclass) {
+	case SECCLASS_NETLINK_ROUTE_SOCKET:
+		err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
+				 sizeof(nlmsg_route_perms));
+		break;
+
+	case SECCLASS_NETLINK_FIREWALL_SOCKET:
+	case NETLINK_IP6_FW:
+		err = nlmsg_perm(nlmsg_type, perm, nlmsg_firewall_perms,
+				 sizeof(nlmsg_firewall_perms));
+		break;
+
+	case SECCLASS_NETLINK_TCPDIAG_SOCKET:
+		err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms,
+				 sizeof(nlmsg_tcpdiag_perms));
+		break;
+
+	case SECCLASS_NETLINK_XFRM_SOCKET:
+		err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms,
+				 sizeof(nlmsg_xfrm_perms));
+		break;
+
+	case SECCLASS_NETLINK_AUDIT_SOCKET:
+		err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
+				 sizeof(nlmsg_audit_perms));
+		break;
+
+	/* No messaging from userspace, or class unknown/unhandled */
+	default:
+		err = -ENOENT;
+		break;
+	}
+
+	return err;
+}
diff -Nru a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
--- a/security/selinux/ss/policydb.c	2004-06-23 19:04:26 -07:00
+++ b/security/selinux/ss/policydb.c	2004-06-23 19:04:26 -07:00
@@ -38,6 +38,8 @@
 };
 #endif
 
+int policydb_loaded_version;
+
 static unsigned int symtab_sizes[SYM_NUM] = {
 	2,
 	32,
@@ -71,6 +73,11 @@
 		.sym_num        = SYM_NUM,
 		.ocon_num       = OCON_NUM,
 	},
+	{
+		.version        = POLICYDB_VERSION_NLCLASS,
+		.sym_num        = SYM_NUM,
+		.ocon_num       = OCON_NUM,
+	},
 };
 
 static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -1125,7 +1132,7 @@
 	struct role_trans *tr, *ltr;
 	struct ocontext *l, *c, *newc;
 	struct genfs *genfs_p, *genfs, *newgenfs;
-	int i, j, rc, r_policyvers;
+	int i, j, rc, r_policyvers = 0;
 	u32 *buf, len, len2, config, nprim, nel, nel2;
 	char *policydb_str;
 	struct policydb_compat_info *info;
@@ -1546,6 +1553,7 @@
 	if (rc)
 		goto bad;
 out:
+	policydb_loaded_version = r_policyvers;
 	return rc;
 bad_newc:
 	ocontext_destroy(newc,OCON_FSUSE);
diff -Nru a/security/selinux/ss/services.c b/security/selinux/ss/services.c
--- a/security/selinux/ss/services.c	2004-06-23 19:04:28 -07:00
+++ b/security/selinux/ss/services.c	2004-06-23 19:04:28 -07:00
@@ -40,6 +40,7 @@
 #include "mls.h"
 
 extern void selnl_notify_policyload(u32 seqno);
+extern int policydb_loaded_version;
 
 static rwlock_t policy_rwlock = RW_LOCK_UNLOCKED;
 #define POLICY_RDLOCK read_lock(&policy_rwlock)
@@ -202,6 +203,17 @@
 	struct avtab_key avkey;
 	struct avtab_datum *avdatum;
 	struct class_datum *tclass_datum;
+
+	/*
+	 * 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_compute_av:  unrecognized class %d\n",
diff -Nru a/sound/core/seq/Makefile b/sound/core/seq/Makefile
--- a/sound/core/seq/Makefile	2004-06-23 19:04:28 -07:00
+++ b/sound/core/seq/Makefile	2004-06-23 19:04:28 -07:00
@@ -51,7 +51,6 @@
 obj-$(call sequencer,$(CONFIG_SND_CS4231)) += $(RAWMIDI_OBJS)
 obj-$(call sequencer,$(CONFIG_SND_CS4232)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
 obj-$(call sequencer,$(CONFIG_SND_CS4236)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_PC98_CS4232)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
 obj-$(call sequencer,$(CONFIG_SND_ES1688)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
 obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
 obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
diff -Nru a/sound/core/seq/instr/Makefile b/sound/core/seq/instr/Makefile
--- a/sound/core/seq/instr/Makefile	2004-06-23 19:04:28 -07:00
+++ b/sound/core/seq/instr/Makefile	2004-06-23 19:04:28 -07:00
@@ -26,7 +26,6 @@
 obj-$(call sequencer,$(CONFIG_SND_AD1816A)) += snd-ainstr-fm.o
 obj-$(call sequencer,$(CONFIG_SND_CS4232)) += snd-ainstr-fm.o
 obj-$(call sequencer,$(CONFIG_SND_CS4236)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_PC98_CS4232)) += snd-ainstr-fm.o
 obj-$(call sequencer,$(CONFIG_SND_ES1688)) += snd-ainstr-fm.o
 obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
 obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
diff -Nru a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
--- a/sound/drivers/mpu401/mpu401.c	2004-06-23 19:04:27 -07:00
+++ b/sound/drivers/mpu401/mpu401.c	2004-06-23 19:04:27 -07:00
@@ -52,9 +52,6 @@
 #endif
 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* MPU-401 port number */
 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* MPU-401 IRQ */
-#ifdef CONFIG_X86_PC9800
-static int pc98ii[SNDRV_CARDS];				/* PC98-II dauther board */
-#endif
 static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
@@ -77,11 +74,6 @@
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
 MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
-#ifdef CONFIG_X86_PC9800
-module_param_array(pc98ii, bool, boot_devs, 0444);
-MODULE_PARM_DESC(pc98ii, "Roland MPU-PC98II support.");
-MODULE_PARM_SYNTAX(pc98ii, SNDRV_BOOLEAN_FALSE_DESC);
-#endif
 
 #ifndef CONFIG_ACPI_BUS
 struct acpi_device;
@@ -188,9 +180,6 @@
 	}
 #endif
 	if (snd_mpu401_uart_new(card, 0,
-#ifdef CONFIG_X86_PC9800
-				pc98ii[dev] ? MPU401_HW_PC98II :
-#endif
 				MPU401_HW_MPU401,
 				port[dev], 0,
 				irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) {
diff -Nru a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
--- a/sound/drivers/opl3/opl3_lib.c	2004-06-23 19:04:25 -07:00
+++ b/sound/drivers/opl3/opl3_lib.c	2004-06-23 19:04:25 -07:00
@@ -416,26 +416,6 @@
 	case OPL3_HW_OPL3_FM801:
 		opl3->command = &snd_opl3_command;
 		break;
-	case OPL3_HW_OPL3_PC98:
-		opl3->command = &snd_opl3_command;
-
-		/* Initialize? */
-		opl3->command(opl3, OPL3_RIGHT | 0x05, 0x05);
-		opl3->command(opl3, OPL3_RIGHT | 0x08, 0x04);
-		opl3->command(opl3, OPL3_RIGHT | 0x08, 0x00);
-		opl3->command(opl3, OPL3_LEFT | 0xf7, 0x00);
-		opl3->command(opl3, OPL3_LEFT | 0x04, 0x60);
-		opl3->command(opl3, OPL3_LEFT | 0x04, 0x80);
-		inb(opl3->l_port);
-		
-		opl3->command(opl3, OPL3_LEFT | 0x02, 0xff);
-		opl3->command(opl3, OPL3_LEFT | 0x04, 0x21);
-		inb(opl3->l_port);
-		
-		opl3->command(opl3, OPL3_LEFT | 0x04, 0x60);
-		opl3->command(opl3, OPL3_LEFT | 0x04, 0x80);
-
-		break;
 	case OPL3_HW_OPL3_CS4281:
 		opl3->command = &snd_opl3_cs4281_command;
 		break;
diff -Nru a/sound/isa/Kconfig b/sound/isa/Kconfig
--- a/sound/isa/Kconfig	2004-06-23 19:04:28 -07:00
+++ b/sound/isa/Kconfig	2004-06-23 19:04:28 -07:00
@@ -51,16 +51,6 @@
 	  Say 'Y' or 'M' to include support for CS4235,CS4236,CS4237B,CS4238B,CS4239
 	  chips from Cirrus Logic - Crystal Semiconductors.
 
-config SND_PC98_CS4232
-	tristate "NEC PC9800 CS4232 driver"
-	depends on SND && X86_PC9800
-	select SND_OPL3_LIB
-	select SND_MPU401_UART
-	select SND_PCM
-	help
-	  Say 'Y' or 'M' to include support for NEC PC-9801/PC-9821 on-board
-	  soundchip based on CS4232.
-
 config SND_ES968
 	tristate "Generic ESS ES968 driver"
 	depends on SND && ISAPNP
diff -Nru a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile
--- a/sound/isa/cs423x/Makefile	2004-06-23 19:04:28 -07:00
+++ b/sound/isa/cs423x/Makefile	2004-06-23 19:04:28 -07:00
@@ -8,7 +8,6 @@
 snd-cs4231-objs := cs4231.o
 snd-cs4232-objs := cs4232.o
 snd-cs4236-objs := cs4236.o
-snd-pc98-cs4232-objs := pc98.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_AZT2320) += snd-cs4231-lib.o
@@ -22,6 +21,5 @@
 obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-cs4231-lib.o
 obj-$(CONFIG_SND_WAVEFRONT) += snd-cs4231-lib.o
 obj-$(CONFIG_SND_SSCAPE) += snd-cs4231-lib.o
-obj-$(CONFIG_SND_PC98_CS4232) += snd-pc98-cs4232.o snd-cs4231-lib.o
 
 obj-m := $(sort $(obj-m))
diff -Nru a/sound/isa/cs423x/pc98.c b/sound/isa/cs423x/pc98.c
--- a/sound/isa/cs423x/pc98.c	2004-06-23 19:04:26 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,438 +0,0 @@
-/*
- *  Driver for CS4232 on NEC PC9800 series
- *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- *                   Osamu Tomita <tomita@cinet.co.jp>
- *                   Takashi Iwai <tiwai@suse.de>
- *                   Hideaki Okubo <okubo@msh.biglobe.ne.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 <sound/driver.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/moduleparam.h>
-#include <sound/core.h>
-#include <sound/cs4231.h>
-#include <sound/mpu401.h>
-#include <sound/opl3.h>
-#include <sound/initval.h>
-#include "sound_pc9800.h"
-
-#define chip_t cs4231_t
-
-MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
-MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DESCRIPTION("NEC PC9800 CS4232");
-MODULE_DEVICES("{{NEC,PC9800}}");
-
-#define IDENT "PC98-CS4232"
-
-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_ISAPNP; /* Enable this card */
-static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
-#if 0 /* NOT USED */
-static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
-#endif
-static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* PnP setup */
-static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
-static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 5,7,9,11,12,15 */
-static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 9,11,12,15 */
-static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
-static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
-static int pc98ii[SNDRV_CARDS];				/* PC98II */
-static int boot_devs;
-
-module_param_array(index, int, boot_devs, 0444);
-MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
-module_param_array(id, charp, boot_devs, 0444);
-MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
-module_param_array(enable, bool, boot_devs, 0444);
-MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-module_param_array(port, long, boot_devs, 0444);
-MODULE_PARM_DESC(port, "Port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
-#if 0 /* NOT USED */
-module_param_array(cport, long, boot_devs, 0444);
-MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(cport, SNDRV_PORT12_DESC);
-#endif
-module_param_array(mpu_port, long, boot_devs, 0444);
-MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
-module_param_array(fm_port, long, boot_devs, 0444);
-MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
-module_param_array(irq, int, boot_devs, 0444);
-MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
-module_param_array(mpu_irq, int, boot_devs, 0444);
-MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
-module_param_array(dma1, int, boot_devs, 0444);
-MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
-module_param_array(dma2, int, boot_devs, 0444);
-MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
-module_param_array(pc98ii, bool, boot_devs, 0444);
-MODULE_PARM_DESC(pc98ii, "Roland MPU-PC98II support.");
-MODULE_PARM_SYNTAX(pc98ii, SNDRV_BOOLEAN_FALSE_DESC);
-
-
-static snd_card_t *snd_pc98_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
-/*
- * initialize MPU401-UART
- */
-
-static int __init pc98_mpu401_init(int irq)
-{
-#include "pc9801_118_magic.h"
-#define outp118(reg,data) outb((reg),0x148e);outb((data),0x148f)
-#define WAIT118 outb(0x00,0x5f)
-	int	mpu_intr, count;
-#ifdef OOKUBO_ORIGINAL
-	int	err = 0;
-#endif /* OOKUBO_ORIGINAL */
-
-	switch (irq) {
-	case 3:
-		mpu_intr = 3;
-		break;
-	case 5:
-		mpu_intr = 2;
-		break;
-	case 6:
-		mpu_intr = 1;
-		break;
-	case 10:
-		mpu_intr = 0;
-		break;
-	default:
-		snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq);
-		return -EINVAL;
-	}
-
-	outp118(0x21, mpu_intr);
-	WAIT118;
-	outb(0x00, 0x148e);
-	if (inb(0x148f) & 0x08) {
-		snd_printk(KERN_INFO IDENT ": No MIDI daughter board found\n");
-		return 0;
-	}
-
-	outp118(0x20, 0x00);
-	outp118(0x05, 0x04);
-	for (count = 0; count < 35000; count ++)
-		WAIT118;
-	outb(0x05, 0x148e);
-	for (count = 0; count < 65000; count ++)
-		if (inb(0x148f) == 0x04)
-			goto set_mode_118;
-	snd_printk(KERN_ERR IDENT ": MIDI daughter board initialize failed at stage1\n\n");
-	return -EINVAL;
-
- set_mode_118:
-	outp118(0x05, 0x0c);
-	outb(0xaa, 0x485);
-	outb(0x99, 0x485);
-	outb(0x2a, 0x485);
-	for (count = 0; count < sizeof(Data0485_99); count ++) {
-		outb(Data0485_99[count], 0x485);
-		WAIT118;
-	}
-
-	outb(0x00, 0x486);
-	outb(0xaa, 0x485);
-	outb(0x9e, 0x485);
-	outb(0x2a, 0x485);
-	for (count = 0; count < sizeof(Data0485_9E); count ++)
-		if (inb(0x485) != Data0485_9E[count]) {
-#ifdef OOKUBO_ORIGINAL
-			err = 1;
-#endif /* OOKUBO_ORIGINAL */
-			break;
-		}
-	outb(0x00, 0x486);
-	for (count = 0; count < 2000; count ++)
-		WAIT118;
-#ifdef OOKUBO_ORIGINAL
-	if (!err) {
-		outb(0xaa, 0x485);
-		outb(0x36, 0x485);
-		outb(0x28, 0x485);
-		for (count = 0; count < sizeof(Data0485_36); count ++)
-			outb(Data0485_36[count], 0x485);
-		outb(0x00, 0x486);
-		for (count = 0; count < 1500; count ++)
-			WAIT118;
-		outp118(0x05, inb(0x148f) | 0x08);
-		outb(0xff, 0x148c);
-		outp118(0x05, inb(0x148f) & 0xf7);
-		for (count = 0; count < 1500; count ++)
-			WAIT118;
-	}
-#endif /* OOKUBO_ORIGINAL */
-
-	outb(0xaa, 0x485);
-	outb(0xa9, 0x485);
-	outb(0x21, 0x485);
-	for (count = 0; count < sizeof(Data0485_A9); count ++) {
-		outb(Data0485_A9[count], 0x485);
-		WAIT118;
-	}
-
-	outb(0x00, 0x486);
-	outb(0xaa, 0x485);
-	outb(0x0c, 0x485);
-	outb(0x20, 0x485);
-	for (count = 0; count < sizeof(Data0485_0C); count ++) {
-		outb(Data0485_0C[count], 0x485);
-		WAIT118;
-	}
-
-	outb(0x00, 0x486);
-	outb(0xaa, 0x485);
-	outb(0x66, 0x485);
-	outb(0x20, 0x485);
-	for (count = 0; count < sizeof(Data0485_66); count ++) {
-		outb(Data0485_66[count], 0x485);
-		WAIT118;
-	}
-
-	outb(0x00, 0x486);
-	outb(0xaa, 0x485);
-	outb(0x60, 0x485);
-	outb(0x20, 0x485);
-	for (count = 0; count < sizeof(Data0485_60); count ++) {
-		outb(Data0485_60[count], 0x485);
-		WAIT118;
-	}
-
-	outb(0x00, 0x486);
-	outp118(0x05, 0x04);
-	outp118(0x05, 0x00);
-	for (count = 0; count < 35000; count ++)
-		WAIT118;
-	outb(0x05, 0x148e);
-	for (count = 0; count < 65000; count ++)
-		if (inb(0x148f) == 0x00)
-			goto end_mode_118;
-	snd_printk(KERN_ERR IDENT ": MIDI daughter board initialize failed at stage2\n");
-	return -EINVAL;
-
- end_mode_118:
-	outb(0x3f, 0x148d);
-	snd_printk(KERN_INFO IDENT ": MIDI daughter board initialized\n");
-	return 0;
-}
-
-static int __init pc98_cs4231_chip_init(int dev)
-{
-	int intr_bits, intr_bits2, dma_bits;
-
-	switch (irq[dev]) {
-	case 3:
-		intr_bits = 0x08;
-		intr_bits2 = 0x03;
-		break;
-	case 5:
-		intr_bits = 0x10;
-		intr_bits2 = 0x08;
-		break;
-	case 10:
-		intr_bits = 0x18;
-		intr_bits2 = 0x02;
-		break;
-	case 12:
-		intr_bits = 0x20;
-		intr_bits2 = 0x00;
-		break;
-	default:
-		snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq[dev]);
-		return -EINVAL;
-	}
-
-	switch (dma1[dev]) {
-	case 0:
-		dma_bits = 0x01;
-		break;
-	case 1:
-		dma_bits = 0x02;
-		break;
-	case 3:
-		dma_bits = 0x03;
-		break;
-	default:
-		snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma1[dev]);
-		return -EINVAL;
-	}
-
-	if (dma2[dev] >= 2) {
-		snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma2[dev]);
-		return -EINVAL;
-	}
-
-	outb(dma1[dev], 0x29);		/* dma1 boundary 64KB */
-	if (dma1[dev] != dma2[dev] && dma2[dev] >= 0) {
-		outb(0, 0x5f);		/* wait */
-		outb(dma2[dev], 0x29);	/* dma2 boundary 64KB */
-		intr_bits |= 0x04;
-	}
-
-	if (PC9800_SOUND_ID() == PC9800_SOUND_ID_118) {
-		/* Set up CanBe control registers. */
-		snd_printd(KERN_INFO "Setting up CanBe Sound System\n");
-		outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID);
-		outb(0x01, 0x0f4a);
-		outb(intr_bits2, 0x0f4b);
-	}
-
-	outb(intr_bits | dma_bits, 0xf40);
-	return 0;
-}
-
-
-static int __init snd_card_pc98_probe(int dev)
-{
-	snd_card_t *card;
-	snd_pcm_t *pcm = NULL;
-	cs4231_t *chip;
-	opl3_t *opl3;
-	int err;
-
-	if (port[dev] == SNDRV_AUTO_PORT) {
-		snd_printk(KERN_ERR IDENT ": specify port\n");
-		return -EINVAL;
-	}
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
-
-	if ((err = pc98_cs4231_chip_init(dev)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-
-	if ((err = snd_cs4231_create(card,
-				     port[dev],
-				     -1,
-				     irq[dev],
-				     dma1[dev],
-				     dma2[dev],
-				     CS4231_HW_DETECT,
-				     0,
-				     &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_mixer(chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-
-	if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-
-	if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
-		/* ??? */
-		outb(0x00, fm_port[dev] + 6);
-		inb(fm_port[dev] + 7);
-		/* Enable OPL-3 Function */
-		outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID);
-		if (snd_opl3_create(card,
-				    fm_port[dev], fm_port[dev] + 2,
-				    OPL3_HW_OPL3_PC98, 0, &opl3) < 0) {
-			printk(KERN_ERR IDENT ": OPL3 not detected\n");
-		} else {
-			if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
-				snd_card_free(card);
-				return err;
-			}
-		}
-	}
-
-	if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
-		err = pc98_mpu401_init(mpu_irq[dev]);
-		if (! err) {
-			err = snd_mpu401_uart_new(card, 0,
-						  pc98ii[dev] ? MPU401_HW_PC98II : MPU401_HW_MPU401,
-						  mpu_port[dev], 0,
-						  mpu_irq[dev], SA_INTERRUPT, NULL);
-			if (err < 0)
-				snd_printk(KERN_INFO IDENT ": MPU401 not detected\n");
-		}
-	}
-
-	strcpy(card->driver, pcm->name);
-	strcpy(card->shortname, pcm->name);
-	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i",
-		pcm->name,
-		chip->port,
-		irq[dev],
-		dma1[dev]);
-	if (dma2[dev] >= 0)
-		sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	snd_pc98_cards[dev] = card;
-	return 0;
-}
-
-static int __init alsa_card_pc98_init(void)
-{
-	int dev, cards = 0;
-
-	for (dev = 0; dev < SNDRV_CARDS; dev++) {
-		if (!enable[dev])
-			continue;
-		if (snd_card_pc98_probe(dev) >= 0)
-			cards++;
-	}
-	if (!cards) {
-#ifdef MODULE
-		printk(KERN_ERR IDENT " soundcard not found or device busy\n");
-#endif
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static void __exit alsa_card_pc98_exit(void)
-{
-	int idx;
-
-	for (idx = 0; idx < SNDRV_CARDS; idx++)
-		snd_card_free(snd_pc98_cards[idx]);
-}
-
-module_init(alsa_card_pc98_init)
-module_exit(alsa_card_pc98_exit)
diff -Nru a/sound/isa/cs423x/pc9801_118_magic.h b/sound/isa/cs423x/pc9801_118_magic.h
--- a/sound/isa/cs423x/pc9801_118_magic.h	2004-06-23 19:04:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,411 +0,0 @@
-		static unsigned char	Data0485_A9[] = {
-		0x12, 0x03, 0x90, 0xc2, 0x2a, 0x75, 0x1e, 0x20,
-		0xe4, 0x12, 0x2b, 0x9b, 0x22, 0xa9, 0x16, 0x77,
-		0x33, 0xe9, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf5,
-		0x16, 0xc2, 0x2f, 0x22, 0xa9, 0x16, 0x77, 0x42,
-		0xe9, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf9, 0x77,
-		0xf8, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf5, 0x16,
-		0xc2, 0x2f, 0x22, 0x90, 0x25, 0x9f, 0x30, 0x04,
-		0x05, 0xc2, 0x04, 0x12, 0x1f, 0x62, 0x30, 0x00,
-		0x05, 0xc2, 0x00, 0x12, 0x15, 0xe6, 0x30, 0x01,
-		0x05, 0xc2, 0x01, 0x12, 0x29, 0xaf, 0x30, 0x02,
-		0x05, 0xc2, 0x02, 0x12, 0x29, 0xaf, 0x30, 0x05,
-		0x05, 0xc2, 0x05, 0x12, 0x16, 0x65, 0x30, 0x06,
-		0x08, 0xc2, 0x06, 0x12, 0x16, 0xb1, 0x12, 0x29,
-		0xaf, 0x30, 0x07, 0x08, 0xc2, 0x07, 0x12, 0x16,
-		0xe9, 0x12, 0x29, 0xaf, 0x22, 0x20, 0x97, 0x09,
-		0x53, 0xa8, 0xfb, 0x12, 0x04, 0x2c, 0x43, 0xa8,
-		0x04, 0x22, 0x71, 0xb8, 0x71, 0xb8, 0x71, 0xb8,
-		0x22, 0x20, 0x4b, 0x04, 0x75, 0x4e, 0x02, 0x22,
-		0xe5, 0x35, 0x24, 0xff, 0xf5, 0x35, 0xe5, 0x36,
-		0x34, 0xff, 0xf5, 0x36, 0x75, 0x4e, 0x02, 0x22,
-		0x10, 0x19, 0x02, 0x80, 0x08, 0x78, 0x00, 0xe2,
-		0x78, 0x07, 0xf2, 0x61, 0x9b, 0x78, 0x11, 0xe2,
-		0xc0, 0x01, 0xc0, 0xf0, 0xc0, 0xd0, 0xc0, 0x02,
-		0x71, 0x14, 0xe5, 0x30, 0xb4, 0x01, 0x02, 0x61,
-		0x93, 0x43, 0x08, 0x40, 0x12, 0x2a, 0x53, 0x61,
-		0x93, 0x79, 0x03, 0xe3, 0xa2, 0xe2, 0x92, 0x26,
-		0xa2, 0xe3, 0x92, 0x27, 0x22, 0xad, 0x2b, 0xbd,
-		0x04, 0x07, 0xf5, 0x72, 0x78, 0x27, 0x02, 0x11,
-		0x76, 0x02, 0x11, 0x30, 0x00, 0x00, 0x00, 0x12,
-		0x28, 0xba, 0x79, 0x01, 0xe3, 0x75, 0x21, 0x3f,
-		0x75, 0x49, 0x11, 0x75, 0x4c, 0x11, 0x31, 0xdc,
-		0x75, 0x1a, 0x80, 0x51, 0x72, 0x75, 0x81, 0xe3,
-		0x12, 0x25, 0xc9, 0x43, 0xa8, 0x01, 0x00, 0x53,
-		0xa8, 0xfe, 0x10, 0x50, 0x02, 0x80, 0x03, 0x12,
-		0x1a, 0x8d, 0xd1, 0x28, 0x12, 0x03, 0xd9, 0xd1,
-		0xf2, 0x12, 0x2d, 0xf0, 0xb0, 0x11, 0x92, 0xe0,
-		0xa2, 0x2a, 0xa0, 0xb5, 0x82, 0xe0, 0x50, 0x03,
-		0x79, 0x0f, 0xe3, 0x71, 0xca, 0x51, 0x1e, 0x91,
-		0xe4, 0x53, 0xa8, 0xfb, 0x10, 0x10, 0x02, 0x80,
-		0x26, 0xc2, 0x8e, 0xd2, 0xab, 0xa2, 0x1c, 0x40,
-		0x13, 0xa2, 0x1d, 0x50, 0x0a, 0x43, 0x08, 0x40,
-		0x12, 0x1a, 0x01, 0xd1, 0xd7, 0x80, 0x0b, 0x12,
-		0x26, 0x04, 0x61, 0x08, 0x43, 0x08, 0x40, 0x12,
-		0x1a, 0x01, 0xd2, 0x1f, 0x12, 0x17, 0x7f, 0x43,
-		0xa8, 0x04, 0x51, 0x1e, 0x91, 0xe4, 0x12, 0x13,
-		0x34, 0x80, 0x98, 0xa2, 0x17, 0x72, 0x16, 0x72,
-		0x15, 0x72, 0x2d, 0x50, 0x06, 0xfa, 0x12, 0x13,
-		0x66, 0x80, 0x25, 0xc2, 0x13, 0x30, 0x28, 0x05,
-		0x12, 0x02, 0xbe, 0x80, 0x1b, 0xb4, 0x10, 0x12,
-		0x78, 0x00, 0xf2, 0xe5, 0x30, 0xb4, 0x01, 0x06,
-		0x12, 0x03, 0x90, 0xd2, 0x19, 0x22, 0x12, 0x00,
-		0xdd, 0x22, 0x75, 0x30, 0x00, 0x12, 0x00, 0xa1,
-		0x22, 0x00, 0x00, 0x75, 0x1e, 0x00, 0x74, 0x0c,
-		0x12, 0x2b, 0x9b, 0x74, 0x40, 0x79, 0x05, 0xf3,
-		0x74, 0x49, 0x12, 0x2b, 0x9b, 0x74, 0x04, 0x79,
-		0x05, 0xf3, 0x75, 0x15, 0x04, 0x74, 0x10, 0x12,
-		0x2b, 0x9b, 0x74, 0x00, 0x79, 0x05, 0xf3, 0x74,
-		0x17, 0x12, 0x2b, 0x9b, 0x74, 0x00, 0x79, 0x05,
-		0xf3, 0x74, 0x1a, 0x12, 0x2b, 0x9b, 0x74, 0x00,
-		0x79, 0x05, 0xf3, 0x74, 0x0a, 0x12, 0x2b, 0x9b,
-		0x74, 0x20, 0x79, 0x05, 0xf3, 0x79, 0xe0, 0x77,
-		0x20, 0x22, 0xd0, 0x02, 0xd0, 0xd0, 0xd0, 0xf0,
-		0xd0, 0x01, 0xe5, 0x5f, 0xd0, 0xa8, 0x22, 0x00,
-		0x00, 0x90, 0x25, 0x9f, 0x75, 0x26, 0xff, 0x75,
-		0x27, 0xff, 0x75, 0x28, 0x03, 0x75, 0x13, 0xff,
-		0x75, 0x1f, 0x00, 0x75, 0x14, 0xff, 0x22, 0x79,
-		0x06, 0xe5, 0x29, 0x60, 0x0b, 0xe3, 0x30, 0xe1,
-		0xf8, 0xe5, 0x4f, 0x64, 0x80, 0x79, 0x07, 0xf3,
-		0x22, 0x10, 0x4c, 0x01, 0x22, 0x30, 0x4b, 0x0a,
-		0xc2, 0x4b, 0xe5, 0x4d, 0x64, 0x80, 0xf5, 0x4f,
-		0x80, 0x1d, 0xe5, 0x15, 0xa2, 0xe0, 0x82, 0xe6,
-		0x40, 0x02, 0x80, 0x35, 0x30, 0x4a, 0x04, 0xb1,
-		0xe6, 0x80, 0x0c, 0x30, 0x49, 0x04, 0x51, 0x2b,
-		0x80, 0x05, 0x30, 0x48, 0x24, 0x91, 0x7e, 0x79,
-		0x06, 0xe3, 0x30, 0xe0, 0x1a, 0x79, 0x06, 0xf3,
-		0xe5, 0x4e, 0x24, 0xff, 0x50, 0x04, 0xf5, 0x4e,
-		0x80, 0x0d, 0x79, 0x0f, 0xf3, 0x20, 0x2a, 0x07,
-		0x12, 0x2b, 0x32, 0x75, 0x29, 0x00, 0x22, 0x91,
-		0x1b, 0x22, 0x79, 0x0f, 0xe3, 0xc0, 0xa8, 0x75,
-		0xa8, 0x00, 0x30, 0x2b, 0x03, 0xd0, 0xa8, 0x22,
-		0x79, 0x0e, 0xf3, 0xd0, 0xa8, 0x22, 0x8a, 0xf0,
-		0xe5, 0x50, 0x10, 0xf3, 0x10, 0x23, 0x23, 0x23,
-		0x25, 0xf0, 0x12, 0x2c, 0xb8, 0xa2, 0xe7, 0x92,
-		0xe4, 0xc2, 0xe7, 0x80, 0x08, 0x23, 0x23, 0x23,
-		0x25, 0xf0, 0x12, 0x2c, 0x19, 0x25, 0x4f, 0x20,
-		0xd2, 0x04, 0xf5, 0x4f, 0x80, 0x0a, 0x40, 0x05,
-		0x75, 0x4f, 0x7f, 0x80, 0x03, 0x75, 0x4f, 0xff,
-		0xea, 0x12, 0x2c, 0x3c, 0x25, 0x50, 0x20, 0xe7,
-		0x05, 0xb4, 0x03, 0x07, 0x80, 0x0c, 0x75, 0x50,
-		0x00, 0x80, 0x09, 0x40, 0x05, 0x75, 0x50, 0x03,
-		0x80, 0x02, 0xf5, 0x50, 0x22, 0xe5, 0x4d, 0xc4,
-		0x54, 0x0c, 0x03, 0x03, 0xfa, 0x91, 0xa9, 0x71,
-		0xb8, 0xe5, 0x4d, 0xc4, 0x54, 0x03, 0xfa, 0x91,
-		0xa9, 0x71, 0xb8, 0xe5, 0x4d, 0x54, 0x0c, 0x03,
-		0x03, 0xfa, 0x91, 0xa9, 0x71, 0xb8, 0xe5, 0x4d,
-		0x54, 0x03, 0xfa, 0x91, 0xa9, 0x71, 0xb8, 0x22,
-		0x8a, 0xf0, 0xe5, 0x50, 0x23, 0x23, 0x25, 0xf0,
-		0x12, 0x2b, 0xf6, 0x25, 0x4f, 0x20, 0xd2, 0x04,
-		0xf5, 0x4f, 0x80, 0x0a, 0x40, 0x05, 0x75, 0x4f,
-		0x7f, 0x80, 0x03, 0x75, 0x4f, 0xff, 0xea, 0x12,
-		0x2c, 0x40, 0x25, 0x50, 0x20, 0xe7, 0x05, 0xb4,
-		0x05, 0x07, 0x80, 0x0c, 0x75, 0x50, 0x00, 0x80,
-		0x09, 0x40, 0x05, 0x75, 0x50, 0x05, 0x80, 0x02,
-		0xf5, 0x50, 0x22, 0x30, 0x26, 0x03, 0x12, 0x1e,
-		0xf5, 0x30, 0x27, 0x03, 0x12, 0x1f, 0x37, 0x30,
-		0x25, 0x09, 0x12, 0x1f, 0x4e, 0x30, 0x23, 0x03,
-		0x12, 0x1f, 0x1e, 0x10, 0x22, 0x02, 0x80, 0x0a,
-		0xe5, 0x3b, 0xb4, 0xff, 0x02, 0xc2, 0x20, 0x12,
-		0x1e, 0x79, 0x22, 0x78, 0x11, 0xe2, 0x20, 0xe0,
-		0x07, 0xc0, 0x01, 0x12, 0x28, 0xba, 0xd0, 0x01,
-		0x78, 0x00, 0xf2, 0x61, 0x9b, 0x12, 0x2b, 0x32,
-		0x12, 0x17, 0x7f, 0x78, 0x00, 0xf2, 0xaa, 0x35,
-		0xab, 0x36, 0xea, 0x24, 0xff, 0xfa, 0xeb, 0x34,
-		0xff, 0xfb, 0x50, 0x03, 0xd2, 0x10, 0x22, 0x75,
-		0x37, 0x01, 0x75, 0x38, 0x00, 0x75, 0x39, 0x00,
-		0x12, 0x04, 0x04, 0xd2, 0x8e, 0x22, 0xa8, 0x2b,
-		0xb8, 0x00, 0x02, 0x80, 0x03, 0x02, 0x11, 0xbd,
-		0xf5, 0x74, 0x78, 0x2a, 0x12, 0x11, 0xec, 0xe5,
-		0x74, 0x78, 0x29, 0x12, 0x11, 0xec, 0x22, 0xfa,
-		0xe5, 0x2b, 0x60, 0x01, 0x22, 0xea, 0x78, 0x2b,
-		0xf5, 0x75, 0x12, 0x11, 0xec, 0x22, 0x74, 0x10,
-		0x12, 0x2b, 0x9b, 0x74, 0x20, 0x78, 0x05, 0xf2,
-		0x74, 0x09, 0x12, 0x17, 0x75, 0xe5, 0x15, 0x44,
-		0x80, 0x79, 0x05, 0xf3, 0xf5, 0x15, 0x12, 0x17,
-		0x7f, 0x22, 0x12, 0x03, 0x84, 0x79, 0x0f, 0xe3,
-		0x78, 0x00, 0xf2, 0x12, 0x2b, 0x28, 0xe5, 0x81,
-		0x24, 0xfc, 0xf5, 0x81, 0x61, 0x93, 0xd2, 0x07,
-		0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x4c, 0xc2,
-		0x0f, 0x12, 0x29, 0xa3, 0x61, 0x93, 0x02, 0x1b,
-		0x77, 0x00, 0xe1, 0x81, 0xe1, 0x9a, 0xd2, 0x2c,
-		0xa1, 0x0c, 0x20, 0x20, 0x02, 0xd2, 0x26, 0x02,
-		0x1e, 0x35, 0x02, 0x1e, 0x61, 0x02, 0x1d, 0x8f,
-		0xc2, 0x8e, 0x75, 0xa8, 0x9e, 0x22, 0x41, 0x49,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x02, 0x29, 0x91, 0x00, 0x00, 0x00, 0xa1, 0xbb,
-		0xa1, 0xc3, 0x02, 0x1e, 0x6b, 0xe5, 0x4d, 0xc4,
-		0x54, 0x0f, 0xfa, 0x91, 0x2f, 0x71, 0xb8, 0xe5,
-		0x4d, 0x54, 0x0f, 0xfa, 0x91, 0x2f, 0x71, 0xb8,
-		0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xc6,
-		0x02, 0x1d, 0x8f, 0xc2, 0x8e, 0xd2, 0xab, 0xc2,
-		0x10, 0x79, 0x0f, 0xf3, 0x22, 0x00, 0x02, 0x2a,
-		0x84, 0x00, 0xe1, 0xbc, 0xe1, 0xc8, 0x02, 0x1e,
-		0x27, 0x00, 0x78, 0x00, 0xf2, 0x78, 0x0b, 0xe2,
-		0xf4, 0xf5, 0x4d, 0xd2, 0x4c, 0x61, 0x9b, 0x30,
-		0xb5, 0x02, 0xc2, 0x11, 0x22, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x79, 0xbd, 0xf1, 0x3d, 0x83,
-		0x22, 0xdd, 0xbd, 0xbd, 0xbd, 0x61, 0xbd, 0x8d,
-		0x7a, 0xbd, 0xbd, 0xbd, 0xbd, 0x30, 0xbd, 0xbd,
-		0xbd, 0x55, 0xbd, 0xbd, 0xbd, 0x52, 0xbd, 0xb6,
-		0xb6, 0xbd, 0xbd, 0xbd, 0xbd, 0x00, 0xbd, 0xbd,
-		0xbd, 0xe8, 0xda, 0xbd, 0xbd, 0xcf, 0xb9, 0xbd,
-		0xc4, 0xf1, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
-		0xbd, 0x7b, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
-		0xbd, 0x70, 0x6a, 0x57, 0x47, 0x34, 0xbd, 0xbd,
-		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x29, 0xbd,
-		0xbd, 0xbd, 0xb6, 0xb6, 0xbd, 0xbd, 0xbd, 0xbd,
-		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x2e, 0x25,
-		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xfe, 0xf5,
-		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x19, 0xbd,
-		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x21, 0x8f,
-		0x09, 0xbd, 0xf9, 0x86, 0xbd, 0xbd, 0xbd, 0xd7,
-		0xbd, 0xa9, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x9b,
-		0xd1, 0x9d, 0xbd, 0xae, 0xbd, 0xbd, 0xbd, 0xcb,
-		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
-		0xb6, 0xa5, 0xbd, 0xc5, 0xbd, 0xbd, 0xbd, 0xc3,
-		0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x74, 0x10,
-		0x12, 0x2b, 0x9b, 0xe4, 0x78, 0x05, 0xf2, 0x74,
-		0x09, 0x12, 0x17, 0x75, 0xe5, 0x15, 0x54, 0x7f,
-		0x79, 0x05, 0xf3, 0xf5, 0x15, 0x12, 0x17, 0x7f,
-		0x22, 0x30, 0x51, 0x01, 0x22, 0x53, 0xa8, 0xfb,
-		0x12, 0x2d, 0xf0, 0x50, 0x22, 0x79, 0x03, 0xe3,
-		0x20, 0xe4, 0x1c, 0xaa, 0x35, 0xab, 0x36, 0xea,
-		0x24, 0xf0, 0xfa, 0xeb, 0x34, 0xff, 0xfb, 0x50,
-		0x0e, 0x10, 0x1f, 0x02, 0x80, 0x09, 0x20, 0x2a,
-		0x03, 0x12, 0x2b, 0x32, 0x12, 0x2d, 0xd6, 0x43,
-		0xa8, 0x04, 0x22, 0xa2, 0x1c, 0x72, 0x1d, 0x40,
-		0x07, 0x53, 0x08, 0xbf, 0x78, 0x00, 0xf2, 0x22,
-		0xb1, 0x1e, 0x22, 0x00, 0x79, 0x02, 0x12, 0x27,
-		0x3d, 0x02, 0x2d, 0x37, 0x14, 0x54, 0xf0, 0x60,
-		0x21, 0xe5, 0xf0, 0x24, 0xb6, 0xe5, 0xf0, 0x50,
-		0x16, 0x24, 0x8b, 0x50, 0x15, 0xe5, 0xf0, 0x24,
-		0x56, 0xe5, 0xf0, 0x50, 0x08, 0x24, 0x2f, 0x50,
-		0x09, 0xe5, 0xf0, 0x24, 0xd9, 0x24, 0xd5, 0x24,
-		0xf0, 0x22, 0x15, 0x81, 0x15, 0x81, 0xe9, 0x22,
-		0x78, 0x13, 0x74, 0x00, 0xf2, 0x75, 0x2e, 0x01,
-		0xd2, 0x6a, 0xc2, 0x69, 0xc2, 0x68, 0xc2, 0x6c,
-		0x90, 0x25, 0x9f, 0x75, 0xb8, 0x07, 0x41, 0xa4,
-		0xc0, 0x01, 0xc0, 0xf0, 0xc0, 0xd0, 0xc0, 0x02,
-		0xe5, 0x3d, 0x54, 0x7d, 0x03, 0x10, 0xe5, 0x05,
-		0x90, 0x28, 0x4b, 0x80, 0x03, 0x90, 0x2b, 0x7c,
-		0x73, 0xe5, 0x3d, 0x30, 0xe5, 0x07, 0x74, 0xfd,
-		0x78, 0x00, 0xf2, 0x61, 0x9b, 0x90, 0x1a, 0x97,
-		0x74, 0xb6, 0xc0, 0xe0, 0x74, 0x27, 0xc0, 0xe0,
-		0xc0, 0xa8, 0x02, 0x1b, 0xab, 0x90, 0x25, 0x9f,
-		0xd0, 0xa8, 0x22, 0x90, 0x27, 0xb6, 0xc0, 0x82,
-		0xc0, 0x83, 0xc0, 0xa8, 0x02, 0x1d, 0xa6, 0x90,
-		0x27, 0xb6, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0xa8,
-		0x02, 0x1e, 0x0a, 0xea, 0x24, 0xf0, 0xfa, 0xeb,
-		0x34, 0xff, 0xfb, 0x50, 0x2e, 0x20, 0x0b, 0x05,
-		0x85, 0x44, 0xe0, 0x80, 0x03, 0x75, 0xe0, 0x00,
-		0x30, 0xe1, 0x20, 0xe5, 0x35, 0x24, 0xff, 0xf5,
-		0x35, 0xe5, 0x36, 0x34, 0xff, 0xf5, 0x36, 0xc3,
-		0xe5, 0x36, 0x13, 0xf5, 0x36, 0xe5, 0x35, 0x13,
-		0xf5, 0x35, 0x75, 0x3a, 0x10, 0x12, 0x1a, 0x77,
-		0x02, 0x18, 0x77, 0x75, 0x3a, 0x00, 0x12, 0x1a,
-		0x77, 0x02, 0x18, 0x1b, 0x20, 0x4b, 0x04, 0x75,
-		0x4e, 0x03, 0x22, 0xe5, 0x35, 0x24, 0xff, 0xf5,
-		0x35, 0xe5, 0x36, 0x34, 0xff, 0xf5, 0x36, 0x75,
-		0x4e, 0x03, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x2c,
-		0x70, 0xd2, 0x00, 0x78, 0x11, 0xe2, 0x44, 0x11,
-		0xf5, 0x3f, 0xc2, 0x08, 0x12, 0x29, 0xa3, 0x02,
-		0x23, 0x93, 0x21, 0x62, 0x61, 0x40, 0x01, 0x3a,
-		0x01, 0x73, 0x21, 0x76, 0x61, 0xa8, 0x21, 0x39,
-		0x21, 0x4a, 0x02, 0x2a, 0x7b, 0x79, 0x06, 0xf3,
-		0xc0, 0xd0, 0x12, 0x03, 0xd9, 0x78, 0x00, 0xf2,
-		0xd0, 0xd0, 0x22, 0x00, 0x00, 0x00, 0x00, 0x02,
-		0x2c, 0xb4, 0x78, 0x11, 0xe2, 0x44, 0x11, 0x54,
-		0x0f, 0xf8, 0xc4, 0x48, 0xd2, 0x05, 0xf5, 0x48,
-		0xc2, 0x0d, 0x31, 0xa3, 0x02, 0x23, 0x93, 0x20,
-		0x4b, 0x04, 0x75, 0x4e, 0x01, 0x22, 0xe5, 0x35,
-		0x24, 0xff, 0xf5, 0x35, 0xe5, 0x36, 0x34, 0xff,
-		0xf5, 0x36, 0x75, 0x4e, 0x01, 0x22, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x79, 0xd0, 0x77, 0x1b, 0x79, 0xd1, 0x77, 0x18,
-		0x79, 0xd2, 0x77, 0x77, 0x79, 0xd3, 0x77, 0x18,
-		0x22, 0x75, 0x29, 0x00, 0x75, 0x25, 0x00, 0x75,
-		0x34, 0x03, 0x75, 0x22, 0x00, 0x75, 0x23, 0x05,
-		0x75, 0x4f, 0x00, 0x75, 0x50, 0x00, 0x75, 0x30,
-		0x00, 0x79, 0xdc, 0x77, 0x03, 0xc2, 0x8e, 0x75,
-		0x17, 0xa8, 0x75, 0x16, 0xa8, 0x74, 0xaa, 0x79,
-		0x01, 0xf3, 0x79, 0xd7, 0x77, 0x74, 0x79, 0xd8,
-		0x77, 0xff, 0x79, 0xd9, 0x77, 0x07, 0x79, 0xda,
-		0x77, 0x00, 0x12, 0x25, 0x6f, 0x43, 0x08, 0x40,
-		0x71, 0x32, 0x79, 0x0e, 0xe3, 0x10, 0x51, 0x1c,
-		0x74, 0x06, 0x71, 0x9b, 0xe5, 0x11, 0x44, 0x80,
-		0x79, 0x05, 0xf3, 0xf5, 0x11, 0x74, 0x07, 0x71,
-		0x9b, 0xe5, 0x12, 0x44, 0x80, 0x79, 0x05, 0xf3,
-		0xf5, 0x12, 0x80, 0x18, 0x53, 0x27, 0xa0, 0x53,
-		0x28, 0x01, 0x75, 0x20, 0xf7, 0x12, 0x23, 0x4c,
-		0x75, 0x11, 0x80, 0x75, 0x12, 0x80, 0x12, 0x1f,
-		0xc0, 0x12, 0x21, 0xdc, 0x79, 0x06, 0xf3, 0x22,
-		0xd2, 0x02, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5,
-		0x43, 0xc2, 0x0a, 0x12, 0x29, 0xa3, 0x02, 0x23,
-		0x93, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x44,
-		0xc2, 0x0b, 0x12, 0x29, 0xa3, 0x02, 0x23, 0x93,
-		0x78, 0x00, 0xe2, 0x90, 0x25, 0x9f, 0x02, 0x23,
-		0x93, 0x78, 0x11, 0xe2, 0x75, 0x20, 0xf7, 0x75,
-		0x21, 0x3f, 0x75, 0x49, 0x11, 0x75, 0x4c, 0x11,
-		0x31, 0xa3, 0x02, 0x23, 0x93, 0x78, 0x11, 0xe2,
-		0x44, 0x11, 0x54, 0x0f, 0xf8, 0xc4, 0x48, 0xf8,
-		0xe5, 0x49, 0x45, 0x3f, 0x58, 0xf5, 0x49, 0xd2,
-		0x06, 0xc2, 0x0e, 0x31, 0xa3, 0x02, 0x23, 0x93,
-		0xc0, 0x01, 0x20, 0x2a, 0x04, 0x71, 0x32, 0xc2,
-		0x11, 0x11, 0x5e, 0xc2, 0x1f, 0xd0, 0x01, 0x02,
-		0x23, 0x9b, 0x12, 0x21, 0xdc, 0x78, 0x00, 0xf2,
-		0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xda,
-		0xe7, 0x70, 0x2b, 0x20, 0x0a, 0x05, 0x85, 0x43,
-		0xe0, 0x80, 0x03, 0x75, 0xe0, 0x00, 0x30, 0xe1,
-		0x1d, 0x20, 0xe2, 0x1f, 0x74, 0xe0, 0xca, 0x74,
-		0x00, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3, 0xf5,
-		0x09, 0xca, 0x74, 0x01, 0x71, 0x9b, 0xca, 0x79,
-		0x05, 0xf3, 0xf5, 0x0a, 0x80, 0x43, 0x12, 0x15,
-		0x3e, 0x80, 0x3e, 0xe5, 0x0b, 0xb4, 0x17, 0x02,
-		0x80, 0x0b, 0x50, 0x09, 0x74, 0x17, 0xc3, 0x95,
-		0x0b, 0x44, 0x60, 0x80, 0x02, 0x74, 0x60, 0xca,
-		0x74, 0x00, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3,
-		0xf5, 0x09, 0xe5, 0x0c, 0xb4, 0x17, 0x02, 0x80,
-		0x0b, 0x50, 0x09, 0x74, 0x17, 0xc3, 0x95, 0x0c,
-		0x44, 0x60, 0x80, 0x02, 0x74, 0x60, 0xca, 0x74,
-		0x01, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3, 0xf5,
-		0x0a, 0x22, 0xd2, 0x04, 0x78, 0x11, 0xe2, 0x44,
-		0x11, 0xf5, 0x46, 0xc2, 0x0c, 0x31, 0xa3, 0x02,
-		0x23, 0x93, 0xd2, 0x05, 0x78, 0x11, 0xe2, 0x44,
-		0x11, 0xf5, 0x48, 0xc2, 0x0d, 0x31, 0xa3, 0x02,
-		0x23, 0x93, 0xd2, 0x06, 0x78, 0x11, 0xe2, 0x44,
-		0x11, 0xf5, 0x49, 0xc2, 0x0e, 0x31, 0xa3, 0x02,
-		0x23, 0x93, 0x30, 0x1c, 0x21, 0x20, 0x4d, 0x1e,
-		0xe5, 0x29, 0x60, 0x1a, 0xc2, 0x1c, 0x12, 0x19,
-		0xec, 0x12, 0x13, 0xcf, 0xd2, 0x4d, 0x12, 0x17,
-		0x7f, 0x78, 0x00, 0xf2, 0x79, 0x06, 0xf3, 0x43,
-		0xa8, 0x04, 0x12, 0x24, 0x1b, 0x22, 0x12, 0x27,
-		0x24, 0x22, 0x78, 0x00, 0xe2, 0x90, 0x25, 0x9f,
-		0x02, 0x23, 0x93, 0x78, 0x00, 0xe2, 0xa2, 0xe7,
-		0x72, 0xe3, 0x92, 0xe7, 0x02, 0x1d, 0x85, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x79, 0x04, 0xe3, 0x54, 0x80, 0x70, 0xf9, 0x22,
-		0xe5, 0x29, 0x79, 0xde, 0xf7, 0x75, 0x29, 0x00,
-		0x70, 0x12, 0xe5, 0x15, 0x79, 0xdd, 0xf7, 0x12,
-		0x2d, 0xf0, 0x40, 0x08, 0x20, 0x1c, 0x07, 0x20,
-		0x1d, 0x04, 0x80, 0x02, 0x71, 0x32, 0x30, 0xb5,
-		0x0c, 0x79, 0x06, 0xf3, 0x20, 0x2a, 0x06, 0x79,
-		0xdd, 0xe7, 0x54, 0xfc, 0xf7, 0xd2, 0x2b, 0x12,
-		0x25, 0x6f, 0x22, 0x00, 0x00, 0x00, 0x00, 0xe5,
-		0x15, 0xa2, 0xe0, 0xb0, 0xe6, 0x40, 0x31, 0xa2,
-		0xe1, 0xb0, 0xe7, 0x40, 0x38, 0x10, 0x2b, 0x02,
-		0x80, 0x26, 0x79, 0xde, 0xe7, 0x70, 0x0b, 0x79,
-		0xdd, 0xe7, 0x20, 0xe0, 0x12, 0x20, 0xe1, 0x28,
-		0x80, 0x16, 0xf5, 0x29, 0x30, 0x4d, 0x11, 0x20,
-		0x4c, 0x0e, 0x12, 0x24, 0x1b, 0x80, 0x09, 0x43,
-		0x08, 0x40, 0x12, 0x13, 0xcf, 0x12, 0x17, 0x7f,
-		0xe5, 0x13, 0x20, 0xe4, 0x05, 0x12, 0x18, 0x1b,
-		0x80, 0x03, 0x12, 0x18, 0x77, 0xc2, 0x2b, 0x22,
-		0x12, 0x26, 0xd7, 0x12, 0x13, 0xb7, 0x22, 0x78,
-		0x04, 0x79, 0x00, 0xd9, 0xfe, 0xd8, 0xfa, 0x22,
-		0x00, 0x74, 0x09, 0x71, 0x9b, 0xe5, 0x15, 0x54,
-		0xfc, 0x79, 0x05, 0xf3, 0xf5, 0x15, 0x22, 0x78,
-		0x11, 0xe2, 0x44, 0x11, 0x54, 0x0f, 0xf8, 0xc4,
-		0x48, 0xf5, 0x46, 0xc2, 0x0c, 0xd2, 0x04, 0x31,
-		0xa3, 0x02, 0x23, 0x93, 0x12, 0x26, 0xd7, 0x12,
-		0x00, 0xb7, 0x22, 0x00, 0x79, 0x06, 0xf3, 0x74,
-		0x0a, 0x71, 0x9b, 0x79, 0xe0, 0xe7, 0x44, 0x02,
-		0xf7, 0x79, 0x05, 0xf3, 0x22, 0x74, 0x0a, 0x71,
-		0x9b, 0x79, 0xe0, 0xe7, 0x54, 0xfd, 0xf7, 0x79,
-		0x05, 0xf3, 0x22, 0x21, 0x59, 0x41, 0x23, 0x21,
-		0x59, 0x41, 0x33, 0x41, 0x43, 0x21, 0x59, 0x21,
-		0x59, 0x02, 0x25, 0x9f, 0x00, 0x74, 0x0d, 0x71,
-		0x9b, 0x74, 0x4d, 0x79, 0x05, 0xf3, 0xd2, 0x52,
-		0x22, 0x00, 0x53, 0x08, 0x40, 0x45, 0x08, 0x45,
-		0x1e, 0x79, 0x04, 0xf3, 0xf5, 0x08, 0x22, 0xd2,
-		0x01, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x42,
-		0xc2, 0x09, 0x31, 0xa3, 0x02, 0x23, 0x93, 0x00,
-		0x00, 0x00, 0x00, 0x71, 0x6e, 0x74, 0x09, 0x12,
-		0x17, 0x75, 0xe5, 0x15, 0x44, 0x40, 0x79, 0x05,
-		0xf3, 0xf5, 0x15, 0x75, 0x3a, 0x00, 0x12, 0x1a,
-		0x77, 0x02, 0x18, 0x1b, 0xf5, 0x38, 0xe5, 0x37,
-		0x24, 0x01, 0xf5, 0x37, 0xe5, 0x38, 0x34, 0x00,
-		0xf5, 0x38, 0x40, 0x05, 0x75, 0x39, 0x00, 0x80,
-		0x03, 0x75, 0x39, 0x01, 0x12, 0x04, 0x04, 0xd2,
-		0x8e, 0x02, 0x03, 0x8d, 0x00, 0xb4, 0x0d, 0x03,
-		0x74, 0x14, 0x22, 0x04, 0x83, 0x22, 0x00, 0x02,
-		0xff, 0x01, 0x00, 0x05, 0xfe, 0xff, 0x00, 0x0a,
-		0xfc, 0xfe, 0x00, 0xc0, 0xf8, 0xfc, 0x00, 0x28,
-		0xf0, 0xf8, 0x00, 0x30, 0xe0, 0xd0, 0x01, 0x88,
-		0x04, 0x83, 0x22, 0x00, 0xff, 0xfe, 0xfd, 0xfc,
-		0xfc, 0xfb, 0xfa, 0xfe, 0xfd, 0xfb, 0xf9, 0xf7,
-		0xf7, 0xf5, 0xf3, 0xfc, 0xfa, 0xf6, 0xf2, 0xee,
-		0xee, 0xea, 0xe6, 0xf8, 0xf4, 0xec, 0xe4, 0xdc,
-		0xd4, 0xcc, 0xc4, 0x24, 0x21, 0x83, 0x22, 0x04,
-		0x83, 0x22, 0xff, 0x01, 0xff, 0x01, 0x00, 0x00,
-		0x00, 0x02, 0x22, 0x32, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-		0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xff,
-		0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x83,
-		0x22, 0x8a, 0x01, 0x20, 0x01, 0x0b, 0xea, 0xf3,
-		0xf9, 0x8b, 0x7e, 0x6b, 0xd5, 0x01, 0x00, 0x01,
-		0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x01, 0x3a, 0x01, 0x38, 0x01, 0x4b, 0x01,
-		0x49, 0x01, 0x5c, 0x01, 0x5a, 0x01, 0x08, 0x08,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x01, 0x15, 0x24, 0x48, 0x83, 0x22, 0x04,
-		0x83, 0x22, 0x00, 0x01, 0x02, 0x03, 0x04, 0x06,
-		0x07, 0x08, 0x00, 0x03, 0x05, 0x07, 0x09, 0x0d,
-		0x0f, 0x81, 0x00, 0x06, 0x0a, 0x0e, 0x82, 0x8a,
-		0x8e, 0x22, 0x00, 0x0c, 0x84, 0x8c, 0x24, 0x2c,
-		0xa4, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0xaa, 0x35, 0xab, 0x36,
-		0x02, 0x27, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-		0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x25,
-		0x03, 0x03, 0x2b, 0x03, 0x00, 0x03, 0x00, 0x03,
-		0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x22,
-		0x00, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
-		0x2b, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
-		0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01,
-		0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-		0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-		0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
-		0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02,
-		0x21, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00,
-		0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x21,
-		0x01, 0x02, 0x21, 0x02, 0x02, 0x02, 0x00, 0x02,
-		0x02, 0x02, 0x02, 0x02, 0x02, 0x20, 0xb5, 0x05,
-		0x79, 0x0f, 0xf3, 0xc2, 0x11, 0x22, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5,
-		0x15, 0xa2, 0xe0, 0xb0, 0xe6, 0x50, 0x01, 0x22,
-		0xa2, 0xe1, 0xb0, 0xe7, 0x22, 0x02, 0x00};
-		static unsigned char	Data0485_0C[] = {
-		0x02, 0x27, 0x69};
-		static unsigned char	Data0485_66[] = {
-		0x02, 0x25, 0x47, 0x02, 0x25, 0x60};
-		static unsigned char	Data0485_60[] = {
-		0x02, 0x22, 0x7e};
-		static unsigned char	Data0485_99[] = {
-		0xc2, 0x53, 0x02, 0x12, 0x86};
-		static unsigned char	Data0485_9E[] = {
-		0x70, 0xf9, 0x22};
-#ifdef OOKUBO_ORIGINAL
-		static unsigned char	Data0485_36[] = {
-		0x78, 0x00, 0xf2, 0xc2, 0x53, 0x74, 0x86, 0xc0,
-		0xe0, 0x74, 0x12, 0xc0,	0xe0, 0x32};
-#endif /* OOKUBO_ORIGINAL */
diff -Nru a/sound/isa/cs423x/sound_pc9800.h b/sound/isa/cs423x/sound_pc9800.h
--- a/sound/isa/cs423x/sound_pc9800.h	2004-06-23 19:04:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,23 +0,0 @@
-#ifndef _SOUND_PC9800_H_
-#define _SOUND_PC9800_H_
-
-#include <asm/io.h>
-
-#define PC9800_SOUND_IO_ID	0xa460
-
-/* Sound Functions ID. */
-#define PC9800_SOUND_ID()	((inb(PC9800_SOUND_IO_ID) >> 4) & 0x0f)
-
-#define PC9800_SOUND_ID_DO	0x0	/* PC-98DO+ Internal */
-#define PC9800_SOUND_ID_GS	0x1	/* PC-98GS Internal */
-#define PC9800_SOUND_ID_73	0x2	/* PC-9801-73 (base 0x18x) */
-#define PC9800_SOUND_ID_73A	0x3	/* PC-9801-73/76 (base 0x28x) */
-#define PC9800_SOUND_ID_86	0x4	/* PC-9801-86 and compatible (base 0x18x) */
-#define PC9800_SOUND_ID_86A	0x5	/* PC-9801-86 (base 0x28x) */
-#define PC9800_SOUND_ID_NF	0x6	/* PC-9821Nf/Np Internal */
-#define PC9800_SOUND_ID_XMATE	0x7	/* X-Mate Internal and compatible */
-#define PC9800_SOUND_ID_118	0x8	/* PC-9801-118 and compatible(CanBe Internal, etc.) */
-
-#define PC9800_SOUND_ID_UNKNOWN	0xf	/* Unknown (No Sound System or PC-9801-26) */
-
-#endif
diff -Nru a/sound/oss/cmpci.c b/sound/oss/cmpci.c
--- a/sound/oss/cmpci.c	2004-06-23 19:04:27 -07:00
+++ b/sound/oss/cmpci.c	2004-06-23 19:04:27 -07:00
@@ -3280,7 +3280,7 @@
 MODULE_DESCRIPTION("CM8x38 Audio Driver");
 MODULE_LICENSE("GPL");
 
-static void __devinit cm_remove(struct pci_dev *dev)
+static void __devexit cm_remove(struct pci_dev *dev)
 {
 	struct cm_state *s = pci_get_drvdata(dev);
 
@@ -3337,7 +3337,7 @@
        .name	 = "cmpci",
        .id_table = id_table,
        .probe	 = cm_probe,
-       .remove	 = cm_remove
+       .remove	 = __devexit_p(cm_remove)
 };
 
 static int __init init_cmpci(void)
diff -Nru a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
--- a/sound/oss/dmasound/dmasound_atari.c	2004-06-23 19:04:26 -07:00
+++ b/sound/oss/dmasound/dmasound_atari.c	2004-06-23 19:04:26 -07:00
@@ -22,7 +22,6 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 
-#include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/atariints.h>
 #include <asm/atari_stram.h>
diff -Nru a/sound/oss/sb_card.c b/sound/oss/sb_card.c
--- a/sound/oss/sb_card.c	2004-06-23 19:04:27 -07:00
+++ b/sound/oss/sb_card.c	2004-06-23 19:04:27 -07:00
@@ -309,7 +309,13 @@
 
 	/* If either PnP or Legacy registered a card then return
 	 * success */
-	return (pres > 0 || lres > 0) ? 0 : -ENODEV;
+	if (pres <= 0 && lres <= 0) {
+#ifdef CONFIG_PNP
+		pnp_unregister_card_driver(&sb_pnp_driver);
+#endif
+		return -ENODEV;
+	}
+	return 0;
 }
 
 static void __exit sb_exit(void)
diff -Nru a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c	2004-06-23 19:04:28 -07:00
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c	2004-06-23 19:04:28 -07:00
@@ -246,6 +246,12 @@
 		if ((entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name, 
 							ins->proc_dsp_dir)) != NULL) {
 			scb_info = kmalloc(sizeof(proc_scb_info_t), GFP_KERNEL);
+			if (!scb_info) {
+				snd_info_free_entry(entry);
+				entry = NULL;
+				goto out;
+			}
+
 			scb_info->chip = chip;
 			scb_info->scb_desc = scb;
       
@@ -262,7 +268,7 @@
 				entry = NULL;
 			}
 		}
-
+out:
 		scb->proc_info = entry;
 	}
 }
diff -Nru a/sound/ppc/pmac.c b/sound/ppc/pmac.c
--- a/sound/ppc/pmac.c	2004-06-23 19:04:29 -07:00
+++ b/sound/ppc/pmac.c	2004-06-23 19:04:29 -07:00
@@ -931,6 +931,13 @@
 		chip->freq_table = tumbler_freqs;
 		chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
 	}
+	if (device_is_compatible(sound, "AOAKeylargo")) {
+		/* Seems to support the stock AWACS frequencies, but has
+		   a snapper mixer */
+		chip->model = PMAC_SNAPPER;
+		// chip->can_byte_swap = 0; /* FIXME: check this */
+		chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
+	}
 	prop = (unsigned int *)get_property(sound, "device-id", 0);
 	if (prop)
 		chip->device_id = *prop;
